1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2008, 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 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
69 -- File suffix for object files
71 type Name_Location is record
72 Name : File_Name_Type;
73 Location : Source_Ptr;
74 Source : Source_Id := No_Source;
75 Except : Boolean := False;
76 Found : Boolean := False;
78 -- Information about file names found in string list attribute
79 -- Source_Files or in a source list file, stored in hash table
80 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
82 No_Name_Location : constant Name_Location :=
84 Location => No_Location,
89 package Source_Names is new GNAT.HTable.Simple_HTable
90 (Header_Num => Header_Num,
91 Element => Name_Location,
92 No_Element => No_Name_Location,
93 Key => File_Name_Type,
96 -- Hash table to store file names found in string list attribute
97 -- Source_Files or in a source list file, stored in hash table
98 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
100 -- More documentation needed on what unit exceptions are about ???
102 type Unit_Exception is record
104 Spec : File_Name_Type;
105 Impl : File_Name_Type;
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
122 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
123 (Header_Num => Header_Num,
129 -- Hash table to store recursive source directories, to avoid looking
130 -- several times, and to avoid cycles that may be introduced by symbolic
133 type Ada_Naming_Exception_Id is new Nat;
134 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
136 type Unit_Info is record
139 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
141 -- No_Unit : constant Unit_Info :=
142 -- (Specification, No_Name, No_Ada_Naming_Exception);
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
149 Table_Increment => 100,
150 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
152 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
153 (Header_Num => Header_Num,
154 Element => Ada_Naming_Exception_Id,
155 No_Element => No_Ada_Naming_Exception,
156 Key => File_Name_Type,
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 type File_Found is record
163 File : File_Name_Type := No_File;
164 Found : Boolean := False;
165 Location : Source_Ptr := No_Location;
167 No_File_Found : constant File_Found := (No_File, False, No_Location);
169 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
170 (Header_Num => Header_Num,
171 Element => File_Found,
172 No_Element => No_File_Found,
173 Key => File_Name_Type,
176 -- A hash table to store the excluded files, if any. This is filled by
177 -- Find_Excluded_Sources below.
179 procedure Find_Excluded_Sources
180 (In_Tree : Project_Tree_Ref;
181 Data : Project_Data);
182 -- Find the list of files that should not be considered as source files
183 -- for this project. Sets the list in the Excluded_Sources_Htable.
185 function Hash (Unit : Unit_Info) return Header_Num;
187 type Name_And_Index is record
188 Name : Name_Id := No_Name;
191 No_Name_And_Index : constant Name_And_Index :=
192 (Name => No_Name, Index => 0);
194 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
195 (Header_Num => Header_Num,
196 Element => Name_And_Index,
197 No_Element => No_Name_And_Index,
201 -- A table to check if a unit with an exceptional name will hide a source
202 -- with a file name following the naming convention.
206 Data : in out Project_Data;
207 In_Tree : Project_Tree_Ref;
208 Project : Project_Id;
210 Lang_Id : Language_Index;
212 File_Name : File_Name_Type;
213 Display_File : File_Name_Type;
214 Lang_Kind : Language_Kind;
215 Naming_Exception : Boolean := False;
216 Path : Path_Name_Type := No_Path;
217 Display_Path : Path_Name_Type := No_Path;
218 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
219 Other_Part : Source_Id := No_Source;
220 Unit : Name_Id := No_Name;
222 Source_To_Replace : Source_Id := No_Source);
223 -- Add a new source to the different lists: list of all sources in the
224 -- project tree, list of source of a project and list of sources of a
226 -- If Path is specified, the file is also added to Source_Paths_HT.
227 -- If Source_To_Replace is specified, it points to the source in the
228 -- extended project that the new file is overriding.
230 function ALI_File_Name (Source : String) return String;
231 -- Return the ALI file name corresponding to a source
233 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
234 -- Check that a name is a valid Ada unit name
236 procedure Check_Naming_Schemes
237 (Data : in out Project_Data;
238 Project : Project_Id;
239 In_Tree : Project_Tree_Ref);
240 -- Check the naming scheme part of Data
242 procedure Check_Ada_Naming_Scheme_Validity
243 (Project : Project_Id;
244 In_Tree : Project_Tree_Ref;
245 Naming : Naming_Data);
246 -- Check that the package Naming is correct
248 procedure Check_Configuration
249 (Project : Project_Id;
250 In_Tree : Project_Tree_Ref;
251 Data : in out Project_Data);
252 -- Check the configuration attributes for the project
254 procedure Check_For_Source
255 (File_Name : File_Name_Type;
256 Path_Name : Path_Name_Type;
257 Project : Project_Id;
258 In_Tree : Project_Tree_Ref;
259 Data : in out Project_Data;
260 Location : Source_Ptr;
261 Language : Language_Index;
263 Naming_Exception : Boolean);
264 -- Check if a file, with name File_Name and path Path_Name, in a source
265 -- directory is a source for language Language in project Project of
266 -- project tree In_Tree. ???
268 procedure Check_If_Externally_Built
269 (Project : Project_Id;
270 In_Tree : Project_Tree_Ref;
271 Data : in out Project_Data);
272 -- Check attribute Externally_Built of project Project in project tree
273 -- In_Tree and modify its data Data if it has the value "true".
275 procedure Check_Library_Attributes
276 (Project : Project_Id;
277 In_Tree : Project_Tree_Ref;
278 Current_Dir : String;
279 Data : in out Project_Data);
280 -- Check the library attributes of project Project in project tree In_Tree
281 -- and modify its data Data accordingly.
282 -- Current_Dir should represent the current directory, and is passed for
283 -- efficiency to avoid system calls to recompute it.
285 procedure Check_Package_Naming
286 (Project : Project_Id;
287 In_Tree : Project_Tree_Ref;
288 Data : in out Project_Data);
289 -- Check package Naming of project Project in project tree In_Tree and
290 -- modify its data Data accordingly.
292 procedure Check_Programming_Languages
293 (In_Tree : Project_Tree_Ref;
294 Project : Project_Id;
295 Data : in out Project_Data);
296 -- Check attribute Languages for the project with data Data in project
297 -- tree In_Tree and set the components of Data for all the programming
298 -- languages indicated in attribute Languages, if any.
300 function Check_Project
302 Root_Project : Project_Id;
303 In_Tree : Project_Tree_Ref;
304 Extending : Boolean) return Boolean;
305 -- Returns True if P is Root_Project or, if Extending is True, a project
306 -- extended by Root_Project.
308 procedure Check_Stand_Alone_Library
309 (Project : Project_Id;
310 In_Tree : Project_Tree_Ref;
311 Data : in out Project_Data;
312 Current_Dir : String;
313 Extending : Boolean);
314 -- Check if project Project in project tree In_Tree is a Stand-Alone
315 -- Library project, and modify its data Data accordingly if it is one.
316 -- Current_Dir should represent the current directory, and is passed for
317 -- efficiency to avoid system calls to recompute it.
319 procedure Get_Path_Names_And_Record_Ada_Sources
320 (Project : Project_Id;
321 In_Tree : Project_Tree_Ref;
322 Data : in out Project_Data;
323 Current_Dir : String);
324 -- Find the path names of the source files in the Source_Names table
325 -- in the source directories and record those that are Ada sources.
327 function Compute_Directory_Last (Dir : String) return Natural;
328 -- Return the index of the last significant character in Dir. This is used
329 -- to avoid duplicate '/' (slash) characters at the end of directory names.
332 (Project : Project_Id;
333 In_Tree : Project_Tree_Ref;
335 Flag_Location : Source_Ptr);
336 -- Output an error message. If Error_Report is null, simply call
337 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
340 procedure Find_Ada_Sources
341 (Project : Project_Id;
342 In_Tree : Project_Tree_Ref;
343 Data : in out Project_Data;
344 Current_Dir : String);
345 -- Find all the Ada sources in all of the source directories of a project
346 -- Current_Dir should represent the current directory, and is passed for
347 -- efficiency to avoid system calls to recompute it.
349 procedure Find_Sources
350 (Project : Project_Id;
351 In_Tree : Project_Tree_Ref;
352 Data : in out Project_Data;
353 For_Language : Language_Index;
354 Current_Dir : String);
355 -- Find all the sources in all of the source directories of a project for
356 -- a specified language.
358 procedure Search_Directories
359 (Project : Project_Id;
360 In_Tree : Project_Tree_Ref;
361 Data : in out Project_Data;
362 For_All_Sources : Boolean);
363 -- Search the source directories to find the sources.
364 -- If For_All_Sources is True, check each regular file name against the
365 -- naming schemes of the different languages. Otherwise consider only the
366 -- file names in the hash table Source_Names.
369 (Project : Project_Id;
370 In_Tree : Project_Tree_Ref;
371 Data : in out Project_Data;
373 File_Name : File_Name_Type;
374 Display_File_Name : File_Name_Type;
375 Source_Directory : String;
376 For_All_Sources : Boolean);
377 -- Check if file File_Name is a valid source of the project. This is used
378 -- in multi-language mode only.
379 -- When the file matches one of the naming schemes, it is added to
380 -- various htables through Add_Source and to Source_Paths_Htable.
382 -- Name is the name of the candidate file. It hasn't been normalized yet
383 -- and is the direct result of readdir().
385 -- File_Name is the same as Name, but has been normalized.
386 -- Display_File_Name, however, has not been normalized.
388 -- Source_Directory is the directory in which the file
389 -- was found. It hasn't been normalized (nor has had links resolved).
390 -- It should not end with a directory separator, to avoid duplicates
393 -- If For_All_Sources is True, then all possible file names are analyzed
394 -- otherwise only those currently set in the Source_Names htable.
396 procedure Check_Naming_Schemes
397 (In_Tree : Project_Tree_Ref;
398 Data : in out Project_Data;
400 File_Name : File_Name_Type;
401 Alternate_Languages : out Alternate_Language_Id;
402 Language : out Language_Index;
403 Language_Name : out Name_Id;
404 Display_Language_Name : out Name_Id;
406 Lang_Kind : out Language_Kind;
407 Kind : out Source_Kind);
408 -- Check if the file name File_Name conforms to one of the naming
409 -- schemes of the project.
410 -- If the file does not match one of the naming schemes, set Language
411 -- to No_Language_Index.
412 -- Filename is the name of the file being investigated. It has been
413 -- normalized (case-folded). File_Name is the same value.
415 procedure Free_Ada_Naming_Exceptions;
416 -- Free the internal hash tables used for checking naming exceptions
418 procedure Get_Directories
419 (Project : Project_Id;
420 In_Tree : Project_Tree_Ref;
421 Current_Dir : String;
422 Data : in out Project_Data);
423 -- Get the object directory, the exec directory and the source directories
425 -- Current_Dir should represent the current directory, and is passed for
426 -- efficiency to avoid system calls to recompute it.
429 (Project : Project_Id;
430 In_Tree : Project_Tree_Ref;
431 Data : in out Project_Data);
432 -- Get the mains of a project from attribute Main, if it exists, and put
433 -- them in the project data.
435 procedure Get_Sources_From_File
437 Location : Source_Ptr;
438 Project : Project_Id;
439 In_Tree : Project_Tree_Ref);
440 -- Get the list of sources from a text file and put them in hash table
443 procedure Find_Explicit_Sources
444 (Lang : Language_Index;
445 Current_Dir : String;
446 Project : Project_Id;
447 In_Tree : Project_Tree_Ref;
448 Data : in out Project_Data);
449 -- Process the Source_Files and Source_List_File attributes, and store
450 -- the list of source files into the Source_Names htable.
451 -- Lang indicates which language is being processed when in Ada_Only mode
452 -- (all languages are processed anyway when in Multi_Language mode).
455 (In_Tree : Project_Tree_Ref;
456 Canonical_File_Name : File_Name_Type;
457 Naming : Naming_Data;
458 Exception_Id : out Ada_Naming_Exception_Id;
459 Unit_Name : out Name_Id;
460 Unit_Kind : out Spec_Or_Body;
461 Needs_Pragma : out Boolean);
462 -- Find out, from a file name, the unit name, the unit kind and if a
463 -- specific SFN pragma is needed. If the file name corresponds to no unit,
464 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
465 -- exception to the naming scheme, then Exception_Id is set to the unit or
466 -- units that the source contains.
468 function Is_Illegal_Suffix
470 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
471 -- Returns True if the string Suffix cannot be used as a spec suffix, a
472 -- body suffix or a separate suffix.
474 procedure Locate_Directory
475 (Project : Project_Id;
476 In_Tree : Project_Tree_Ref;
477 Name : File_Name_Type;
478 Parent : Path_Name_Type;
479 Dir : out Path_Name_Type;
480 Display : out Path_Name_Type;
481 Create : String := "";
482 Current_Dir : String;
483 Location : Source_Ptr := No_Location);
484 -- Locate a directory. Name is the directory name. Parent is the root
485 -- directory, if Name a relative path name. Dir is set to the canonical
486 -- case path name of the directory, and Display is the directory path name
487 -- for display purposes. If the directory does not exist and Project_Setup
488 -- is True and Create is a non null string, an attempt is made to create
489 -- the directory. If the directory does not exist and Project_Setup is
490 -- false, then Dir and Display are set to No_Name.
491 -- Current_Dir should represent the current directory, and is passed for
492 -- efficiency to avoid system calls to recompute it.
494 procedure Look_For_Sources
495 (Project : Project_Id;
496 In_Tree : Project_Tree_Ref;
497 Data : in out Project_Data;
498 Current_Dir : String);
499 -- Find all the sources of project Project in project tree In_Tree and
500 -- update its Data accordingly.
501 -- Current_Dir should represent the current directory, and is passed for
502 -- efficiency to avoid system calls to recompute it.
504 function Path_Name_Of
505 (File_Name : File_Name_Type;
506 Directory : Path_Name_Type) return String;
507 -- Returns the path name of a (non project) file.
508 -- Returns an empty string if file cannot be found.
510 procedure Prepare_Ada_Naming_Exceptions
511 (List : Array_Element_Id;
512 In_Tree : Project_Tree_Ref;
513 Kind : Spec_Or_Body);
514 -- Prepare the internal hash tables used for checking naming exceptions
515 -- for Ada. Insert all elements of List in the tables.
517 function Project_Extends
518 (Extending : Project_Id;
519 Extended : Project_Id;
520 In_Tree : Project_Tree_Ref) return Boolean;
521 -- Returns True if Extending is extending Extended either directly or
524 procedure Record_Ada_Source
525 (File_Name : File_Name_Type;
526 Path_Name : Path_Name_Type;
527 Project : Project_Id;
528 In_Tree : Project_Tree_Ref;
529 Data : in out Project_Data;
530 Location : Source_Ptr;
531 Current_Source : in out String_List_Id;
532 Source_Recorded : in out Boolean;
533 Current_Dir : String);
534 -- Put a unit in the list of units of a project, if the file name
535 -- corresponds to a valid unit name.
536 -- Current_Dir should represent the current directory, and is passed for
537 -- efficiency to avoid system calls to recompute it.
539 procedure Record_Other_Sources
540 (Project : Project_Id;
541 In_Tree : Project_Tree_Ref;
542 Data : in out Project_Data;
543 Language : Language_Index;
544 Naming_Exceptions : Boolean);
545 -- Record the sources of a language in a project.
546 -- When Naming_Exceptions is True, mark the found sources as such, to
547 -- later remove those that are not named in a list of sources.
549 procedure Remove_Source
551 Replaced_By : Source_Id;
552 Project : Project_Id;
553 Data : in out Project_Data;
554 In_Tree : Project_Tree_Ref);
557 procedure Report_No_Sources
558 (Project : Project_Id;
560 In_Tree : Project_Tree_Ref;
561 Location : Source_Ptr);
562 -- Report an error or a warning depending on the value of When_No_Sources
563 -- when there are no sources for language Lang_Name.
565 procedure Show_Source_Dirs
566 (Data : Project_Data; In_Tree : Project_Tree_Ref);
567 -- List all the source directories of a project
570 (Language : Language_Index;
571 Naming : Naming_Data;
572 In_Tree : Project_Tree_Ref) return File_Name_Type;
573 -- Get the suffix for the source of a language from a package naming.
574 -- If not specified, return the default for the language.
576 procedure Warn_If_Not_Sources
577 (Project : Project_Id;
578 In_Tree : Project_Tree_Ref;
579 Conventions : Array_Element_Id;
581 Extending : Boolean);
582 -- Check that individual naming conventions apply to immediate sources of
583 -- the project. If not, issue a warning.
591 Data : in out Project_Data;
592 In_Tree : Project_Tree_Ref;
593 Project : Project_Id;
595 Lang_Id : Language_Index;
597 File_Name : File_Name_Type;
598 Display_File : File_Name_Type;
599 Lang_Kind : Language_Kind;
600 Naming_Exception : Boolean := False;
601 Path : Path_Name_Type := No_Path;
602 Display_Path : Path_Name_Type := No_Path;
603 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
604 Other_Part : Source_Id := No_Source;
605 Unit : Name_Id := No_Name;
607 Source_To_Replace : Source_Id := No_Source)
609 Source : constant Source_Id := Data.Last_Source;
610 Src_Data : Source_Data := No_Source_Data;
613 -- This is a new source so create an entry for it in the Sources table
615 Source_Data_Table.Increment_Last (In_Tree.Sources);
616 Id := Source_Data_Table.Last (In_Tree.Sources);
618 if Current_Verbosity = High then
619 Write_Str ("Adding source #");
621 Write_Str (", File : ");
622 Write_Str (Get_Name_String (File_Name));
624 if Lang_Kind = Unit_Based then
625 Write_Str (", Unit : ");
626 Write_Str (Get_Name_String (Unit));
632 Src_Data.Project := Project;
633 Src_Data.Language_Name := Lang;
634 Src_Data.Language := Lang_Id;
635 Src_Data.Lang_Kind := Lang_Kind;
636 Src_Data.Compiled := In_Tree.Languages_Data.Table
637 (Lang_Id).Config.Compiler_Driver /=
639 Src_Data.Kind := Kind;
640 Src_Data.Alternate_Languages := Alternate_Languages;
641 Src_Data.Other_Part := Other_Part;
642 Src_Data.Unit := Unit;
643 Src_Data.Index := Index;
644 Src_Data.File := File_Name;
645 Src_Data.Display_File := Display_File;
646 Src_Data.Dependency := In_Tree.Languages_Data.Table
647 (Lang_Id).Config.Dependency_Kind;
648 Src_Data.Naming_Exception := Naming_Exception;
650 if Src_Data.Compiled then
651 Src_Data.Object := Object_Name (File_Name);
653 Dependency_Name (File_Name, Src_Data.Dependency);
654 Src_Data.Switches := Switches_Name (File_Name);
657 if Path /= No_Path then
658 Src_Data.Path := Path;
659 Src_Data.Display_Path := Display_Path;
660 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
663 -- Add the source to the global list
665 Src_Data.Next_In_Sources := In_Tree.First_Source;
666 In_Tree.First_Source := Id;
668 -- Add the source to the project list
670 if Source = No_Source then
671 Data.First_Source := Id;
673 In_Tree.Sources.Table (Source).Next_In_Project := Id;
676 Data.Last_Source := Id;
678 -- Add the source to the language list
680 Src_Data.Next_In_Lang :=
681 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
682 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
684 In_Tree.Sources.Table (Id) := Src_Data;
686 if Source_To_Replace /= No_Source then
687 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
695 function ALI_File_Name (Source : String) return String is
697 -- If the source name has an extension, then replace it with
700 for Index in reverse Source'First + 1 .. Source'Last loop
701 if Source (Index) = '.' then
702 return Source (Source'First .. Index - 1) & ALI_Suffix;
706 -- If there is no dot, or if it is the first character, just add the
709 return Source & ALI_Suffix;
717 (Project : Project_Id;
718 In_Tree : Project_Tree_Ref;
719 Report_Error : Put_Line_Access;
720 When_No_Sources : Error_Warning;
721 Current_Dir : String)
723 Data : Project_Data := In_Tree.Projects.Table (Project);
724 Extending : Boolean := False;
727 Nmsc.When_No_Sources := When_No_Sources;
728 Error_Report := Report_Error;
730 Recursive_Dirs.Reset;
732 Check_If_Externally_Built (Project, In_Tree, Data);
734 -- Object, exec and source directories
736 Get_Directories (Project, In_Tree, Current_Dir, Data);
738 -- Get the programming languages
740 Check_Programming_Languages (In_Tree, Project, Data);
742 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
746 "an abstract project need to have no language, no sources or no " &
747 "source directories",
751 -- Check configuration in multi language mode
753 if Must_Check_Configuration then
754 Check_Configuration (Project, In_Tree, Data);
757 -- Library attributes
759 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
761 if Current_Verbosity = High then
762 Show_Source_Dirs (Data, In_Tree);
765 Check_Package_Naming (Project, In_Tree, Data);
767 Extending := Data.Extends /= No_Project;
769 Check_Naming_Schemes (Data, Project, In_Tree);
771 if Get_Mode = Ada_Only then
772 Prepare_Ada_Naming_Exceptions
773 (Data.Naming.Bodies, In_Tree, Body_Part);
774 Prepare_Ada_Naming_Exceptions
775 (Data.Naming.Specs, In_Tree, Specification);
780 if Data.Source_Dirs /= Nil_String then
781 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
783 if Get_Mode = Ada_Only then
785 -- Check that all individual naming conventions apply to sources
786 -- of this project file.
789 (Project, In_Tree, Data.Naming.Bodies,
791 Extending => Extending);
793 (Project, In_Tree, Data.Naming.Specs,
795 Extending => Extending);
797 elsif Get_Mode = Multi_Language and then
798 (not Data.Externally_Built) and then
802 Language : Language_Index;
804 Src_Data : Source_Data;
805 Alt_Lang : Alternate_Language_Id;
806 Alt_Lang_Data : Alternate_Language_Data;
809 Language := Data.First_Language_Processing;
810 while Language /= No_Language_Index loop
811 Source := Data.First_Source;
812 Source_Loop : while Source /= No_Source loop
813 Src_Data := In_Tree.Sources.Table (Source);
815 exit Source_Loop when Src_Data.Language = Language;
817 Alt_Lang := Src_Data.Alternate_Languages;
820 while Alt_Lang /= No_Alternate_Language loop
822 In_Tree.Alt_Langs.Table (Alt_Lang);
824 when Alt_Lang_Data.Language = Language;
825 Alt_Lang := Alt_Lang_Data.Next;
826 end loop Alternate_Loop;
828 Source := Src_Data.Next_In_Project;
829 end loop Source_Loop;
831 if Source = No_Source then
835 (In_Tree.Languages_Data.Table
836 (Language).Display_Name),
841 Language := In_Tree.Languages_Data.Table (Language).Next;
847 -- If it is a library project file, check if it is a standalone library
850 Check_Stand_Alone_Library
851 (Project, In_Tree, Data, Current_Dir, Extending);
854 -- Put the list of Mains, if any, in the project data
856 Get_Mains (Project, In_Tree, Data);
858 -- Update the project data in the Projects table
860 In_Tree.Projects.Table (Project) := Data;
862 Free_Ada_Naming_Exceptions;
869 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
870 The_Name : String := Name;
872 Need_Letter : Boolean := True;
873 Last_Underscore : Boolean := False;
874 OK : Boolean := The_Name'Length > 0;
877 function Is_Reserved (Name : Name_Id) return Boolean;
878 function Is_Reserved (S : String) return Boolean;
879 -- Check that the given name is not an Ada 95 reserved word. The reason
880 -- for the Ada 95 here is that we do not want to exclude the case of an
881 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
882 -- name would be rejected anyway by the compiler. That means there is no
883 -- requirement that the project file parser reject this.
889 function Is_Reserved (S : String) return Boolean is
892 Add_Str_To_Name_Buffer (S);
893 return Is_Reserved (Name_Find);
900 function Is_Reserved (Name : Name_Id) return Boolean is
902 if Get_Name_Table_Byte (Name) /= 0
903 and then Name /= Name_Project
904 and then Name /= Name_Extends
905 and then Name /= Name_External
906 and then Name not in Ada_2005_Reserved_Words
910 if Current_Verbosity = High then
911 Write_Str (The_Name);
912 Write_Line (" is an Ada reserved word.");
922 -- Start of processing for Check_Ada_Name
927 Name_Len := The_Name'Length;
928 Name_Buffer (1 .. Name_Len) := The_Name;
930 -- Special cases of children of packages A, G, I and S on VMS
933 and then Name_Len > 3
934 and then Name_Buffer (2 .. 3) = "__"
936 ((Name_Buffer (1) = 'a') or else
937 (Name_Buffer (1) = 'g') or else
938 (Name_Buffer (1) = 'i') or else
939 (Name_Buffer (1) = 's'))
941 Name_Buffer (2) := '.';
942 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
943 Name_Len := Name_Len - 1;
946 Real_Name := Name_Find;
948 if Is_Reserved (Real_Name) then
952 First := The_Name'First;
954 for Index in The_Name'Range loop
957 -- We need a letter (at the beginning, and following a dot),
958 -- but we don't have one.
960 if Is_Letter (The_Name (Index)) then
961 Need_Letter := False;
966 if Current_Verbosity = High then
967 Write_Int (Types.Int (Index));
969 Write_Char (The_Name (Index));
970 Write_Line ("' is not a letter.");
976 elsif Last_Underscore
977 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
979 -- Two underscores are illegal, and a dot cannot follow
984 if Current_Verbosity = High then
985 Write_Int (Types.Int (Index));
987 Write_Char (The_Name (Index));
988 Write_Line ("' is illegal here.");
993 elsif The_Name (Index) = '.' then
995 -- First, check if the name before the dot is not a reserved word
996 if Is_Reserved (The_Name (First .. Index - 1)) then
1002 -- We need a letter after a dot
1004 Need_Letter := True;
1006 elsif The_Name (Index) = '_' then
1007 Last_Underscore := True;
1010 -- We need an letter or a digit
1012 Last_Underscore := False;
1014 if not Is_Alphanumeric (The_Name (Index)) then
1017 if Current_Verbosity = High then
1018 Write_Int (Types.Int (Index));
1020 Write_Char (The_Name (Index));
1021 Write_Line ("' is not alphanumeric.");
1029 -- Cannot end with an underscore or a dot
1031 OK := OK and then not Need_Letter and then not Last_Underscore;
1034 if First /= Name'First and then
1035 Is_Reserved (The_Name (First .. The_Name'Last))
1043 -- Signal a problem with No_Name
1049 --------------------------------------
1050 -- Check_Ada_Naming_Scheme_Validity --
1051 --------------------------------------
1053 procedure Check_Ada_Naming_Scheme_Validity
1054 (Project : Project_Id;
1055 In_Tree : Project_Tree_Ref;
1056 Naming : Naming_Data)
1059 -- Only check if we are not using the Default naming scheme
1061 if Naming /= In_Tree.Private_Part.Default_Naming then
1063 Dot_Replacement : constant String :=
1065 (Naming.Dot_Replacement);
1067 Spec_Suffix : constant String :=
1068 Spec_Suffix_Of (In_Tree, "ada", Naming);
1070 Body_Suffix : constant String :=
1071 Body_Suffix_Of (In_Tree, "ada", Naming);
1073 Separate_Suffix : constant String :=
1075 (Naming.Separate_Suffix);
1078 -- Dot_Replacement cannot
1081 -- - start or end with an alphanumeric
1082 -- - be a single '_'
1083 -- - start with an '_' followed by an alphanumeric
1084 -- - contain a '.' except if it is "."
1086 if Dot_Replacement'Length = 0
1087 or else Is_Alphanumeric
1088 (Dot_Replacement (Dot_Replacement'First))
1089 or else Is_Alphanumeric
1090 (Dot_Replacement (Dot_Replacement'Last))
1091 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1093 (Dot_Replacement'Length = 1
1096 (Dot_Replacement (Dot_Replacement'First + 1))))
1097 or else (Dot_Replacement'Length > 1
1099 Index (Source => Dot_Replacement,
1100 Pattern => ".") /= 0)
1104 '"' & Dot_Replacement &
1105 """ is illegal for Dot_Replacement.",
1106 Naming.Dot_Repl_Loc);
1112 if Is_Illegal_Suffix
1113 (Spec_Suffix, Dot_Replacement = ".")
1115 Err_Vars.Error_Msg_File_1 :=
1116 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1119 "{ is illegal for Spec_Suffix",
1120 Naming.Ada_Spec_Suffix_Loc);
1123 if Is_Illegal_Suffix
1124 (Body_Suffix, Dot_Replacement = ".")
1126 Err_Vars.Error_Msg_File_1 :=
1127 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1130 "{ is illegal for Body_Suffix",
1131 Naming.Ada_Body_Suffix_Loc);
1134 if Body_Suffix /= Separate_Suffix then
1135 if Is_Illegal_Suffix
1136 (Separate_Suffix, Dot_Replacement = ".")
1138 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1141 "{ is illegal for Separate_Suffix",
1142 Naming.Sep_Suffix_Loc);
1146 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1147 -- since that would cause a clear ambiguity. Note that we do
1148 -- allow a Spec_Suffix to have the same termination as one of
1149 -- these, which causes a potential ambiguity, but we resolve
1150 -- that my matching the longest possible suffix.
1152 if Spec_Suffix = Body_Suffix then
1157 """) cannot be the same as Spec_Suffix.",
1158 Naming.Ada_Body_Suffix_Loc);
1161 if Body_Suffix /= Separate_Suffix
1162 and then Spec_Suffix = Separate_Suffix
1166 "Separate_Suffix (""" &
1168 """) cannot be the same as Spec_Suffix.",
1169 Naming.Sep_Suffix_Loc);
1173 end Check_Ada_Naming_Scheme_Validity;
1175 -------------------------
1176 -- Check_Configuration --
1177 -------------------------
1179 procedure Check_Configuration
1180 (Project : Project_Id;
1181 In_Tree : Project_Tree_Ref;
1182 Data : in out Project_Data)
1184 Dot_Replacement : File_Name_Type := No_File;
1185 Casing : Casing_Type := All_Lower_Case;
1186 Separate_Suffix : File_Name_Type := No_File;
1188 Lang_Index : Language_Index := No_Language_Index;
1189 -- The index of the language data being checked
1191 Prev_Index : Language_Index := No_Language_Index;
1192 -- The index of the previous language
1194 Current_Language : Name_Id := No_Name;
1195 -- The name of the language
1197 Lang_Data : Language_Data;
1198 -- The data of the language being checked
1200 procedure Get_Language_Index_Of (Language : Name_Id);
1201 -- Get the language index of Language, if Language is one of the
1202 -- languages of the project.
1204 procedure Process_Project_Level_Simple_Attributes;
1205 -- Process the simple attributes at the project level
1207 procedure Process_Project_Level_Array_Attributes;
1208 -- Process the associate array attributes at the project level
1210 procedure Process_Packages;
1211 -- Read the packages of the project
1213 ---------------------------
1214 -- Get_Language_Index_Of --
1215 ---------------------------
1217 procedure Get_Language_Index_Of (Language : Name_Id) is
1218 Real_Language : Name_Id;
1221 Get_Name_String (Language);
1222 To_Lower (Name_Buffer (1 .. Name_Len));
1223 Real_Language := Name_Find;
1225 -- Nothing to do if the language is the same as the current language
1227 if Current_Language /= Real_Language then
1228 Lang_Index := Data.First_Language_Processing;
1229 while Lang_Index /= No_Language_Index loop
1230 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1233 In_Tree.Languages_Data.Table (Lang_Index).Next;
1236 if Lang_Index = No_Language_Index then
1237 Current_Language := No_Name;
1239 Current_Language := Real_Language;
1242 end Get_Language_Index_Of;
1244 ----------------------
1245 -- Process_Packages --
1246 ----------------------
1248 procedure Process_Packages is
1249 Packages : Package_Id;
1250 Element : Package_Element;
1252 procedure Process_Binder (Arrays : Array_Id);
1253 -- Process the associate array attributes of package Binder
1255 procedure Process_Builder (Attributes : Variable_Id);
1256 -- Process the simple attributes of package Builder
1258 procedure Process_Compiler (Arrays : Array_Id);
1259 -- Process the associate array attributes of package Compiler
1261 procedure Process_Naming (Attributes : Variable_Id);
1262 -- Process the simple attributes of package Naming
1264 procedure Process_Naming (Arrays : Array_Id);
1265 -- Process the associate array attributes of package Naming
1267 procedure Process_Linker (Attributes : Variable_Id);
1268 -- Process the simple attributes of package Linker of a
1269 -- configuration project.
1271 --------------------
1272 -- Process_Binder --
1273 --------------------
1275 procedure Process_Binder (Arrays : Array_Id) is
1276 Current_Array_Id : Array_Id;
1277 Current_Array : Array_Data;
1278 Element_Id : Array_Element_Id;
1279 Element : Array_Element;
1282 -- Process the associative array attribute of package Binder
1284 Current_Array_Id := Arrays;
1285 while Current_Array_Id /= No_Array loop
1286 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1288 Element_Id := Current_Array.Value;
1289 while Element_Id /= No_Array_Element loop
1290 Element := In_Tree.Array_Elements.Table (Element_Id);
1292 -- Get the name of the language
1294 Get_Language_Index_Of (Element.Index);
1296 if Lang_Index /= No_Language_Index then
1297 case Current_Array.Name is
1300 -- Attribute Driver (<language>)
1302 In_Tree.Languages_Data.Table
1303 (Lang_Index).Config.Binder_Driver :=
1304 File_Name_Type (Element.Value.Value);
1306 when Name_Required_Switches =>
1308 In_Tree.Languages_Data.Table
1309 (Lang_Index).Config.Binder_Required_Switches,
1310 From_List => Element.Value.Values,
1311 In_Tree => In_Tree);
1315 -- Attribute Prefix (<language>)
1317 In_Tree.Languages_Data.Table
1318 (Lang_Index).Config.Binder_Prefix :=
1319 Element.Value.Value;
1321 when Name_Objects_Path =>
1323 -- Attribute Objects_Path (<language>)
1325 In_Tree.Languages_Data.Table
1326 (Lang_Index).Config.Objects_Path :=
1327 Element.Value.Value;
1329 when Name_Objects_Path_File =>
1331 -- Attribute Objects_Path (<language>)
1333 In_Tree.Languages_Data.Table
1334 (Lang_Index).Config.Objects_Path_File :=
1335 Element.Value.Value;
1342 Element_Id := Element.Next;
1345 Current_Array_Id := Current_Array.Next;
1349 ---------------------
1350 -- Process_Builder --
1351 ---------------------
1353 procedure Process_Builder (Attributes : Variable_Id) is
1354 Attribute_Id : Variable_Id;
1355 Attribute : Variable;
1358 -- Process non associated array attribute from package Builder
1360 Attribute_Id := Attributes;
1361 while Attribute_Id /= No_Variable loop
1363 In_Tree.Variable_Elements.Table (Attribute_Id);
1365 if not Attribute.Value.Default then
1366 if Attribute.Name = Name_Executable_Suffix then
1368 -- Attribute Executable_Suffix: the suffix of the
1371 Data.Config.Executable_Suffix :=
1372 Attribute.Value.Value;
1376 Attribute_Id := Attribute.Next;
1378 end Process_Builder;
1380 ----------------------
1381 -- Process_Compiler --
1382 ----------------------
1384 procedure Process_Compiler (Arrays : Array_Id) is
1385 Current_Array_Id : Array_Id;
1386 Current_Array : Array_Data;
1387 Element_Id : Array_Element_Id;
1388 Element : Array_Element;
1389 List : String_List_Id;
1392 -- Process the associative array attribute of package Compiler
1394 Current_Array_Id := Arrays;
1395 while Current_Array_Id /= No_Array loop
1396 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1398 Element_Id := Current_Array.Value;
1399 while Element_Id /= No_Array_Element loop
1400 Element := In_Tree.Array_Elements.Table (Element_Id);
1402 -- Get the name of the language
1404 Get_Language_Index_Of (Element.Index);
1406 if Lang_Index /= No_Language_Index then
1407 case Current_Array.Name is
1408 when Name_Dependency_Switches =>
1410 -- Attribute Dependency_Switches (<language>)
1412 if In_Tree.Languages_Data.Table
1413 (Lang_Index).Config.Dependency_Kind = None
1415 In_Tree.Languages_Data.Table
1416 (Lang_Index).Config.Dependency_Kind :=
1420 List := Element.Value.Values;
1422 if List /= Nil_String then
1424 In_Tree.Languages_Data.Table
1425 (Lang_Index).Config.Dependency_Option,
1427 In_Tree => In_Tree);
1430 when Name_Dependency_Driver =>
1432 -- Attribute Dependency_Driver (<language>)
1434 if In_Tree.Languages_Data.Table
1435 (Lang_Index).Config.Dependency_Kind = None
1437 In_Tree.Languages_Data.Table
1438 (Lang_Index).Config.Dependency_Kind :=
1442 List := Element.Value.Values;
1444 if List /= Nil_String then
1446 In_Tree.Languages_Data.Table
1447 (Lang_Index).Config.Compute_Dependency,
1449 In_Tree => In_Tree);
1452 when Name_Include_Switches =>
1454 -- Attribute Include_Switches (<language>)
1456 List := Element.Value.Values;
1458 if List = Nil_String then
1462 "include option cannot be null",
1463 Element.Value.Location);
1467 In_Tree.Languages_Data.Table
1468 (Lang_Index).Config.Include_Option,
1470 In_Tree => In_Tree);
1472 when Name_Include_Path =>
1474 -- Attribute Include_Path (<language>)
1476 In_Tree.Languages_Data.Table
1477 (Lang_Index).Config.Include_Path :=
1478 Element.Value.Value;
1480 when Name_Include_Path_File =>
1482 -- Attribute Include_Path_File (<language>)
1484 In_Tree.Languages_Data.Table
1485 (Lang_Index).Config.Include_Path_File :=
1486 Element.Value.Value;
1490 -- Attribute Driver (<language>)
1492 Get_Name_String (Element.Value.Value);
1494 In_Tree.Languages_Data.Table
1495 (Lang_Index).Config.Compiler_Driver :=
1496 File_Name_Type (Element.Value.Value);
1498 when Name_Required_Switches =>
1500 In_Tree.Languages_Data.Table
1501 (Lang_Index).Config.
1502 Compiler_Required_Switches,
1503 From_List => Element.Value.Values,
1504 In_Tree => In_Tree);
1506 when Name_Pic_Option =>
1508 -- Attribute Compiler_Pic_Option (<language>)
1510 List := Element.Value.Values;
1512 if List = Nil_String then
1516 "compiler PIC option cannot be null",
1517 Element.Value.Location);
1521 In_Tree.Languages_Data.Table
1522 (Lang_Index).Config.Compilation_PIC_Option,
1524 In_Tree => In_Tree);
1526 when Name_Mapping_File_Switches =>
1528 -- Attribute Mapping_File_Switches (<language>)
1530 List := Element.Value.Values;
1532 if List = Nil_String then
1536 "mapping file switches cannot be null",
1537 Element.Value.Location);
1541 In_Tree.Languages_Data.Table
1542 (Lang_Index).Config.Mapping_File_Switches,
1544 In_Tree => In_Tree);
1546 when Name_Mapping_Spec_Suffix =>
1548 -- Attribute Mapping_Spec_Suffix (<language>)
1550 In_Tree.Languages_Data.Table
1551 (Lang_Index).Config.Mapping_Spec_Suffix :=
1552 File_Name_Type (Element.Value.Value);
1554 when Name_Mapping_Body_Suffix =>
1556 -- Attribute Mapping_Body_Suffix (<language>)
1558 In_Tree.Languages_Data.Table
1559 (Lang_Index).Config.Mapping_Body_Suffix :=
1560 File_Name_Type (Element.Value.Value);
1562 when Name_Config_File_Switches =>
1564 -- Attribute Config_File_Switches (<language>)
1566 List := Element.Value.Values;
1568 if List = Nil_String then
1572 "config file switches cannot be null",
1573 Element.Value.Location);
1577 In_Tree.Languages_Data.Table
1578 (Lang_Index).Config.Config_File_Switches,
1580 In_Tree => In_Tree);
1582 when Name_Objects_Path =>
1584 -- Attribute Objects_Path (<language>)
1586 In_Tree.Languages_Data.Table
1587 (Lang_Index).Config.Objects_Path :=
1588 Element.Value.Value;
1590 when Name_Objects_Path_File =>
1592 -- Attribute Objects_Path_File (<language>)
1594 In_Tree.Languages_Data.Table
1595 (Lang_Index).Config.Objects_Path_File :=
1596 Element.Value.Value;
1598 when Name_Config_Body_File_Name =>
1600 -- Attribute Config_Body_File_Name (<language>)
1602 In_Tree.Languages_Data.Table
1603 (Lang_Index).Config.Config_Body :=
1604 Element.Value.Value;
1606 when Name_Config_Body_File_Name_Pattern =>
1608 -- Attribute Config_Body_File_Name_Pattern
1611 In_Tree.Languages_Data.Table
1612 (Lang_Index).Config.Config_Body_Pattern :=
1613 Element.Value.Value;
1615 when Name_Config_Spec_File_Name =>
1617 -- Attribute Config_Spec_File_Name (<language>)
1619 In_Tree.Languages_Data.Table
1620 (Lang_Index).Config.Config_Spec :=
1621 Element.Value.Value;
1623 when Name_Config_Spec_File_Name_Pattern =>
1625 -- Attribute Config_Spec_File_Name_Pattern
1628 In_Tree.Languages_Data.Table
1629 (Lang_Index).Config.Config_Spec_Pattern :=
1630 Element.Value.Value;
1632 when Name_Config_File_Unique =>
1634 -- Attribute Config_File_Unique (<language>)
1637 In_Tree.Languages_Data.Table
1638 (Lang_Index).Config.Config_File_Unique :=
1640 (Get_Name_String (Element.Value.Value));
1642 when Constraint_Error =>
1646 "illegal value for Config_File_Unique",
1647 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
1676 In_Tree.Variable_Elements.Table (Attribute_Id);
1678 if not Attribute.Value.Default then
1679 if Attribute.Name = Name_Separate_Suffix then
1681 -- Attribute Separate_Suffix
1683 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1685 elsif Attribute.Name = Name_Casing then
1691 Value (Get_Name_String (Attribute.Value.Value));
1694 when Constraint_Error =>
1698 "invalid value for Casing",
1699 Attribute.Value.Location);
1702 elsif Attribute.Name = Name_Dot_Replacement then
1704 -- Attribute Dot_Replacement
1706 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1711 Attribute_Id := Attribute.Next;
1715 procedure Process_Naming (Arrays : Array_Id) is
1716 Current_Array_Id : Array_Id;
1717 Current_Array : Array_Data;
1718 Element_Id : Array_Element_Id;
1719 Element : Array_Element;
1721 -- Process the associative array attribute of package Naming
1723 Current_Array_Id := Arrays;
1724 while Current_Array_Id /= No_Array loop
1725 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1727 Element_Id := Current_Array.Value;
1728 while Element_Id /= No_Array_Element loop
1729 Element := In_Tree.Array_Elements.Table (Element_Id);
1731 -- Get the name of the language
1733 Get_Language_Index_Of (Element.Index);
1735 if Lang_Index /= No_Language_Index then
1736 case Current_Array.Name is
1737 when Name_Specification_Suffix | Name_Spec_Suffix =>
1739 -- Attribute Spec_Suffix (<language>)
1741 In_Tree.Languages_Data.Table
1742 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1743 File_Name_Type (Element.Value.Value);
1745 when Name_Implementation_Suffix | Name_Body_Suffix =>
1747 -- Attribute Body_Suffix (<language>)
1749 In_Tree.Languages_Data.Table
1750 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1751 File_Name_Type (Element.Value.Value);
1753 In_Tree.Languages_Data.Table
1754 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1755 File_Name_Type (Element.Value.Value);
1762 Element_Id := Element.Next;
1765 Current_Array_Id := Current_Array.Next;
1769 --------------------
1770 -- Process_Linker --
1771 --------------------
1773 procedure Process_Linker (Attributes : Variable_Id) is
1774 Attribute_Id : Variable_Id;
1775 Attribute : Variable;
1778 -- Process non associated array attribute from package Linker
1780 Attribute_Id := Attributes;
1781 while Attribute_Id /= No_Variable loop
1783 In_Tree.Variable_Elements.Table (Attribute_Id);
1785 if not Attribute.Value.Default then
1786 if Attribute.Name = Name_Driver then
1788 -- Attribute Linker'Driver: the default linker to use
1790 Data.Config.Linker :=
1791 Path_Name_Type (Attribute.Value.Value);
1794 Attribute.Name = Name_Required_Switches
1797 -- Attribute Required_Switches: the minimum
1798 -- options to use when invoking the linker
1801 Data.Config.Minimum_Linker_Options,
1802 From_List => Attribute.Value.Values,
1803 In_Tree => In_Tree);
1808 Attribute_Id := Attribute.Next;
1812 -- Start of processing for Process_Packages
1815 Packages := Data.Decl.Packages;
1816 while Packages /= No_Package loop
1817 Element := In_Tree.Packages.Table (Packages);
1819 case Element.Name is
1822 -- Process attributes of package Binder
1824 Process_Binder (Element.Decl.Arrays);
1826 when Name_Builder =>
1828 -- Process attributes of package Builder
1830 Process_Builder (Element.Decl.Attributes);
1832 when Name_Compiler =>
1834 -- Process attributes of package Compiler
1836 Process_Compiler (Element.Decl.Arrays);
1840 -- Process attributes of package Linker
1842 Process_Linker (Element.Decl.Attributes);
1846 -- Process attributes of package Naming
1848 Process_Naming (Element.Decl.Attributes);
1849 Process_Naming (Element.Decl.Arrays);
1855 Packages := Element.Next;
1857 end Process_Packages;
1859 ---------------------------------------------
1860 -- Process_Project_Level_Simple_Attributes --
1861 ---------------------------------------------
1863 procedure Process_Project_Level_Simple_Attributes is
1864 Attribute_Id : Variable_Id;
1865 Attribute : Variable;
1866 List : String_List_Id;
1869 -- Process non associated array attribute at project level
1871 Attribute_Id := Data.Decl.Attributes;
1872 while Attribute_Id /= No_Variable loop
1874 In_Tree.Variable_Elements.Table (Attribute_Id);
1876 if not Attribute.Value.Default then
1877 if Attribute.Name = Name_Library_Builder then
1879 -- Attribute Library_Builder: the application to invoke
1880 -- to build libraries.
1882 Data.Config.Library_Builder :=
1883 Path_Name_Type (Attribute.Value.Value);
1885 elsif Attribute.Name = Name_Archive_Builder then
1887 -- Attribute Archive_Builder: the archive builder
1888 -- (usually "ar") and its minimum options (usually "cr").
1890 List := Attribute.Value.Values;
1892 if List = Nil_String then
1896 "archive builder cannot be null",
1897 Attribute.Value.Location);
1900 Put (Into_List => Data.Config.Archive_Builder,
1902 In_Tree => In_Tree);
1904 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1906 -- Attribute Archive_Builder: the archive builder
1907 -- (usually "ar") and its minimum options (usually "cr").
1909 List := Attribute.Value.Values;
1911 if List /= Nil_String then
1913 (Into_List => Data.Config.Archive_Builder_Append_Option,
1915 In_Tree => In_Tree);
1918 elsif Attribute.Name = Name_Archive_Indexer then
1920 -- Attribute Archive_Indexer: the optional archive
1921 -- indexer (usually "ranlib") with its minimum options
1924 List := Attribute.Value.Values;
1926 if List = Nil_String then
1930 "archive indexer cannot be null",
1931 Attribute.Value.Location);
1934 Put (Into_List => Data.Config.Archive_Indexer,
1936 In_Tree => In_Tree);
1938 elsif Attribute.Name = Name_Library_Partial_Linker then
1940 -- Attribute Library_Partial_Linker: the optional linker
1941 -- driver with its minimum options, to partially link
1944 List := Attribute.Value.Values;
1946 if List = Nil_String then
1950 "partial linker cannot be null",
1951 Attribute.Value.Location);
1954 Put (Into_List => Data.Config.Lib_Partial_Linker,
1956 In_Tree => In_Tree);
1958 elsif Attribute.Name = Name_Archive_Suffix then
1959 Data.Config.Archive_Suffix :=
1960 File_Name_Type (Attribute.Value.Value);
1962 elsif Attribute.Name = Name_Linker_Executable_Option then
1964 -- Attribute Linker_Executable_Option: optional options
1965 -- to specify an executable name. Defaults to "-o".
1967 List := Attribute.Value.Values;
1969 if List = Nil_String then
1973 "linker executable option cannot be null",
1974 Attribute.Value.Location);
1977 Put (Into_List => Data.Config.Linker_Executable_Option,
1979 In_Tree => In_Tree);
1981 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
1983 -- Attribute Linker_Lib_Dir_Option: optional options
1984 -- to specify a library search directory. Defaults to
1987 Get_Name_String (Attribute.Value.Value);
1989 if Name_Len = 0 then
1993 "linker library directory option cannot be empty",
1994 Attribute.Value.Location);
1997 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
1999 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2001 -- Attribute Linker_Lib_Name_Option: optional options
2002 -- to specify the name of a library to be linked in.
2003 -- Defaults to "-l".
2005 Get_Name_String (Attribute.Value.Value);
2007 if Name_Len = 0 then
2011 "linker library name option cannot be empty",
2012 Attribute.Value.Location);
2015 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2017 elsif Attribute.Name = Name_Run_Path_Option then
2019 -- Attribute Run_Path_Option: optional options to
2020 -- specify a path for libraries.
2022 List := Attribute.Value.Values;
2024 if List /= Nil_String then
2025 Put (Into_List => Data.Config.Run_Path_Option,
2027 In_Tree => In_Tree);
2030 elsif Attribute.Name = Name_Library_Support then
2032 pragma Unsuppress (All_Checks);
2034 Data.Config.Lib_Support :=
2035 Library_Support'Value (Get_Name_String
2036 (Attribute.Value.Value));
2038 when Constraint_Error =>
2042 "invalid value """ &
2043 Get_Name_String (Attribute.Value.Value) &
2044 """ for Library_Support",
2045 Attribute.Value.Location);
2048 elsif Attribute.Name = Name_Shared_Library_Prefix then
2049 Data.Config.Shared_Lib_Prefix :=
2050 File_Name_Type (Attribute.Value.Value);
2052 elsif Attribute.Name = Name_Shared_Library_Suffix then
2053 Data.Config.Shared_Lib_Suffix :=
2054 File_Name_Type (Attribute.Value.Value);
2056 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2058 pragma Unsuppress (All_Checks);
2060 Data.Config.Symbolic_Link_Supported :=
2061 Boolean'Value (Get_Name_String
2062 (Attribute.Value.Value));
2064 when Constraint_Error =>
2069 & Get_Name_String (Attribute.Value.Value)
2070 & """ for Symbolic_Link_Supported",
2071 Attribute.Value.Location);
2075 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2078 pragma Unsuppress (All_Checks);
2080 Data.Config.Lib_Maj_Min_Id_Supported :=
2081 Boolean'Value (Get_Name_String
2082 (Attribute.Value.Value));
2084 when Constraint_Error =>
2088 "invalid value """ &
2089 Get_Name_String (Attribute.Value.Value) &
2090 """ for Library_Major_Minor_Id_Supported",
2091 Attribute.Value.Location);
2094 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2096 pragma Unsuppress (All_Checks);
2098 Data.Config.Auto_Init_Supported :=
2099 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2101 when Constraint_Error =>
2106 & Get_Name_String (Attribute.Value.Value)
2107 & """ for Library_Auto_Init_Supported",
2108 Attribute.Value.Location);
2111 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2112 List := Attribute.Value.Values;
2114 if List /= Nil_String then
2115 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2117 In_Tree => In_Tree);
2120 elsif Attribute.Name = Name_Library_Version_Switches then
2121 List := Attribute.Value.Values;
2123 if List /= Nil_String then
2124 Put (Into_List => Data.Config.Lib_Version_Options,
2126 In_Tree => In_Tree);
2131 Attribute_Id := Attribute.Next;
2133 end Process_Project_Level_Simple_Attributes;
2135 --------------------------------------------
2136 -- Process_Project_Level_Array_Attributes --
2137 --------------------------------------------
2139 procedure Process_Project_Level_Array_Attributes is
2140 Current_Array_Id : Array_Id;
2141 Current_Array : Array_Data;
2142 Element_Id : Array_Element_Id;
2143 Element : Array_Element;
2144 List : String_List_Id;
2147 -- Process the associative array attributes at project level
2149 Current_Array_Id := Data.Decl.Arrays;
2150 while Current_Array_Id /= No_Array loop
2151 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2153 Element_Id := Current_Array.Value;
2154 while Element_Id /= No_Array_Element loop
2155 Element := In_Tree.Array_Elements.Table (Element_Id);
2157 -- Get the name of the language
2159 Get_Language_Index_Of (Element.Index);
2161 if Lang_Index /= No_Language_Index then
2162 case Current_Array.Name is
2163 when Name_Inherit_Source_Path =>
2164 List := Element.Value.Values;
2166 if List /= Nil_String then
2169 In_Tree.Languages_Data.Table (Lang_Index).
2170 Config.Include_Compatible_Languages,
2173 Lower_Case => True);
2176 when Name_Toolchain_Description =>
2178 -- Attribute Toolchain_Description (<language>)
2180 In_Tree.Languages_Data.Table
2181 (Lang_Index).Config.Toolchain_Description :=
2182 Element.Value.Value;
2184 when Name_Toolchain_Version =>
2186 -- Attribute Toolchain_Version (<language>)
2188 In_Tree.Languages_Data.Table
2189 (Lang_Index).Config.Toolchain_Version :=
2190 Element.Value.Value;
2192 when Name_Runtime_Library_Dir =>
2194 -- Attribute Runtime_Library_Dir (<language>)
2196 In_Tree.Languages_Data.Table
2197 (Lang_Index).Config.Runtime_Library_Dir :=
2198 Element.Value.Value;
2205 Element_Id := Element.Next;
2208 Current_Array_Id := Current_Array.Next;
2210 end Process_Project_Level_Array_Attributes;
2213 Process_Project_Level_Simple_Attributes;
2214 Process_Project_Level_Array_Attributes;
2217 -- For unit based languages, set Casing, Dot_Replacement and
2218 -- Separate_Suffix in Naming_Data.
2220 Lang_Index := Data.First_Language_Processing;
2221 while Lang_Index /= No_Language_Index loop
2222 if In_Tree.Languages_Data.Table
2223 (Lang_Index).Name = Name_Ada
2225 In_Tree.Languages_Data.Table
2226 (Lang_Index).Config.Naming_Data.Casing := Casing;
2227 In_Tree.Languages_Data.Table
2228 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2231 if Separate_Suffix /= No_File then
2232 In_Tree.Languages_Data.Table
2233 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2240 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2243 -- Give empty names to various prefixes/suffixes, if they have not
2244 -- been specified in the configuration.
2246 if Data.Config.Archive_Suffix = No_File then
2247 Data.Config.Archive_Suffix := Empty_File;
2250 if Data.Config.Shared_Lib_Prefix = No_File then
2251 Data.Config.Shared_Lib_Prefix := Empty_File;
2254 if Data.Config.Shared_Lib_Suffix = No_File then
2255 Data.Config.Shared_Lib_Suffix := Empty_File;
2258 Lang_Index := Data.First_Language_Processing;
2259 while Lang_Index /= No_Language_Index loop
2260 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2262 Current_Language := Lang_Data.Display_Name;
2264 -- For all languages, Compiler_Driver needs to be specified
2266 if Lang_Data.Config.Compiler_Driver = No_File then
2267 Error_Msg_Name_1 := Current_Language;
2271 "?no compiler specified for language %%" &
2272 ", ignoring all its sources",
2275 if Lang_Index = Data.First_Language_Processing then
2276 Data.First_Language_Processing :=
2279 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2283 elsif Lang_Data.Name = Name_Ada then
2284 Prev_Index := Lang_Index;
2286 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2287 -- Body_Suffix need to be specified.
2289 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2293 "Dot_Replacement not specified for Ada",
2297 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2301 "Spec_Suffix not specified for Ada",
2305 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2309 "Body_Suffix not specified for Ada",
2314 Prev_Index := Lang_Index;
2316 -- For file based languages, either Spec_Suffix or Body_Suffix
2317 -- need to be specified.
2319 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2320 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2322 Error_Msg_Name_1 := Current_Language;
2326 "no suffixes specified for %%",
2331 Lang_Index := Lang_Data.Next;
2333 end Check_Configuration;
2335 ----------------------
2336 -- Check_For_Source --
2337 ----------------------
2339 procedure Check_For_Source
2340 (File_Name : File_Name_Type;
2341 Path_Name : Path_Name_Type;
2342 Project : Project_Id;
2343 In_Tree : Project_Tree_Ref;
2344 Data : in out Project_Data;
2345 Location : Source_Ptr;
2346 Language : Language_Index;
2348 Naming_Exception : Boolean)
2350 Name : String := Get_Name_String (File_Name);
2351 Real_Location : Source_Ptr := Location;
2354 Canonical_Case_File_Name (Name);
2356 -- A file is a source of a language if Naming_Exception is True (case
2357 -- of naming exceptions) or if its file name ends with the suffix.
2361 (Name'Length > Suffix'Length
2363 Name (Name'Last - Suffix'Length + 1 .. Name'Last) = Suffix)
2365 if Real_Location = No_Location then
2366 Real_Location := Data.Location;
2370 Path_Id : Path_Name_Type;
2371 C_Path_Id : Path_Name_Type;
2372 -- The path name id (in canonical case)
2374 File_Id : File_Name_Type;
2375 -- The file name id (in canonical case)
2377 Obj_Id : File_Name_Type;
2378 -- The object file name
2380 Obj_Path_Id : Path_Name_Type;
2381 -- The object path name
2383 Dep_Id : File_Name_Type;
2384 -- The dependency file name
2386 Dep_Path_Id : Path_Name_Type;
2387 -- The dependency path name
2389 Dot_Pos : Natural := 0;
2390 -- Position of the last dot in Name
2392 Source : Other_Source;
2393 Source_Id : Other_Source_Id := Data.First_Other_Source;
2396 -- Get the file name id
2398 if Osint.File_Names_Case_Sensitive then
2399 File_Id := File_Name;
2401 Name_Len := Name'Length;
2402 Name_Buffer (1 .. Name_Len) := Name;
2403 File_Id := Name_Find;
2406 -- Get the path name id
2408 Path_Id := Path_Name;
2410 if Osint.File_Names_Case_Sensitive then
2411 C_Path_Id := Path_Name;
2414 C_Path : String := Get_Name_String (Path_Name);
2416 Canonical_Case_File_Name (C_Path);
2417 Name_Len := C_Path'Length;
2418 Name_Buffer (1 .. Name_Len) := C_Path;
2419 C_Path_Id := Name_Find;
2423 -- Find the position of the last dot
2425 for J in reverse Name'Range loop
2426 if Name (J) = '.' then
2432 if Dot_Pos <= Name'First then
2433 Dot_Pos := Name'Last + 1;
2436 -- Compute the object file name
2438 Get_Name_String (File_Id);
2439 Name_Len := Dot_Pos - Name'First;
2441 for J in Object_Suffix'Range loop
2442 Name_Len := Name_Len + 1;
2443 Name_Buffer (Name_Len) := Object_Suffix (J);
2446 Obj_Id := Name_Find;
2448 -- Compute the object path name
2450 Get_Name_String (Data.Display_Object_Dir);
2452 if Name_Buffer (Name_Len) /= Directory_Separator
2453 and then Name_Buffer (Name_Len) /= '/'
2455 Name_Len := Name_Len + 1;
2456 Name_Buffer (Name_Len) := Directory_Separator;
2459 Add_Str_To_Name_Buffer (Get_Name_String (Obj_Id));
2460 Obj_Path_Id := Name_Find;
2462 -- Compute the dependency file name
2464 Get_Name_String (File_Id);
2465 Name_Len := Dot_Pos - Name'First + 1;
2466 Name_Buffer (Name_Len) := '.';
2467 Name_Len := Name_Len + 1;
2468 Name_Buffer (Name_Len) := 'd';
2469 Dep_Id := Name_Find;
2471 -- Compute the dependency path name
2473 Get_Name_String (Data.Display_Object_Dir);
2475 if Name_Buffer (Name_Len) /= Directory_Separator
2476 and then Name_Buffer (Name_Len) /= '/'
2478 Name_Len := Name_Len + 1;
2479 Name_Buffer (Name_Len) := Directory_Separator;
2482 Add_Str_To_Name_Buffer (Get_Name_String (Dep_Id));
2483 Dep_Path_Id := Name_Find;
2485 -- Check if source is already in the list of source for this
2486 -- project: it may have already been specified as a naming
2487 -- exception for the same language or an other language, or
2488 -- they may be two identical file names in different source
2491 while Source_Id /= No_Other_Source loop
2492 Source := In_Tree.Other_Sources.Table (Source_Id);
2494 if Source.File_Name = File_Id then
2495 -- Two sources of different languages cannot have the same
2498 if Source.Language /= Language then
2499 Error_Msg_File_1 := File_Name;
2502 "{ cannot be a source of several languages",
2506 -- No problem if a file has already been specified as
2507 -- a naming exception of this language.
2509 elsif Source.Path_Name = C_Path_Id then
2511 -- Reset the naming exception flag, if this is not a
2512 -- naming exception.
2514 if not Naming_Exception then
2515 In_Tree.Other_Sources.Table
2516 (Source_Id).Naming_Exception := False;
2521 -- There are several files with the same names, but the
2522 -- order of the source directories is known (no /**):
2523 -- only the first one encountered is kept, the other ones
2526 elsif Data.Known_Order_Of_Source_Dirs then
2529 -- But it is an error if the order of the source directories
2533 Error_Msg_File_1 := File_Name;
2536 "{ is found in several source directories",
2541 -- Two sources with different file names cannot have the same
2542 -- object file name.
2544 elsif Source.Object_Name = Obj_Id then
2545 Error_Msg_File_1 := File_Id;
2546 Error_Msg_File_2 := Source.File_Name;
2547 Error_Msg_File_3 := Obj_Id;
2550 "{ and { have the same object file {",
2555 Source_Id := Source.Next;
2558 if Current_Verbosity = High then
2559 Write_Str (" found ");
2560 Display_Language_Name (Language);
2561 Write_Str (" source """);
2562 Write_Str (Get_Name_String (File_Name));
2564 Write_Str (" object path = ");
2565 Write_Line (Get_Name_String (Obj_Path_Id));
2568 -- Create the Other_Source record
2571 (Language => Language,
2572 File_Name => File_Id,
2573 Path_Name => Path_Id,
2574 Source_TS => File_Stamp (Path_Id),
2575 Object_Name => Obj_Id,
2576 Object_Path => Obj_Path_Id,
2577 Object_TS => File_Stamp (Obj_Path_Id),
2579 Dep_Path => Dep_Path_Id,
2580 Dep_TS => File_Stamp (Dep_Path_Id),
2581 Naming_Exception => Naming_Exception,
2582 Next => No_Other_Source);
2584 -- And add it to the Other_Sources table
2586 Other_Source_Table.Increment_Last (In_Tree.Other_Sources);
2587 In_Tree.Other_Sources.Table
2588 (Other_Source_Table.Last (In_Tree.Other_Sources)) := Source;
2590 -- There are sources of languages other than Ada in this project
2592 Data.Other_Sources_Present := True;
2594 -- And there are sources of this language in this project
2596 Set (Language, True, Data, In_Tree);
2598 -- Add this source to the list of sources of languages other than
2599 -- Ada of the project.
2601 if Data.First_Other_Source = No_Other_Source then
2602 Data.First_Other_Source :=
2603 Other_Source_Table.Last (In_Tree.Other_Sources);
2606 In_Tree.Other_Sources.Table (Data.Last_Other_Source).Next :=
2607 Other_Source_Table.Last (In_Tree.Other_Sources);
2610 Data.Last_Other_Source :=
2611 Other_Source_Table.Last (In_Tree.Other_Sources);
2614 end Check_For_Source;
2616 -------------------------------
2617 -- Check_If_Externally_Built --
2618 -------------------------------
2620 procedure Check_If_Externally_Built
2621 (Project : Project_Id;
2622 In_Tree : Project_Tree_Ref;
2623 Data : in out Project_Data)
2625 Externally_Built : constant Variable_Value :=
2627 (Name_Externally_Built,
2628 Data.Decl.Attributes, In_Tree);
2631 if not Externally_Built.Default then
2632 Get_Name_String (Externally_Built.Value);
2633 To_Lower (Name_Buffer (1 .. Name_Len));
2635 if Name_Buffer (1 .. Name_Len) = "true" then
2636 Data.Externally_Built := True;
2638 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2639 Error_Msg (Project, In_Tree,
2640 "Externally_Built may only be true or false",
2641 Externally_Built.Location);
2645 -- A virtual project extending an externally built project is itself
2646 -- externally built.
2648 if Data.Virtual and then Data.Extends /= No_Project then
2649 Data.Externally_Built :=
2650 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2653 if Current_Verbosity = High then
2654 Write_Str ("Project is ");
2656 if not Data.Externally_Built then
2660 Write_Line ("externally built.");
2662 end Check_If_Externally_Built;
2664 --------------------------
2665 -- Check_Naming_Schemes --
2666 --------------------------
2668 procedure Check_Naming_Schemes
2669 (Data : in out Project_Data;
2670 Project : Project_Id;
2671 In_Tree : Project_Tree_Ref)
2673 Naming_Id : constant Package_Id :=
2674 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2675 Naming : Package_Element;
2677 procedure Check_Unit_Names (List : Array_Element_Id);
2678 -- Check that a list of unit names contains only valid names
2680 procedure Get_Exceptions (Kind : Source_Kind);
2682 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2684 ----------------------
2685 -- Check_Unit_Names --
2686 ----------------------
2688 procedure Check_Unit_Names (List : Array_Element_Id) is
2689 Current : Array_Element_Id;
2690 Element : Array_Element;
2691 Unit_Name : Name_Id;
2694 -- Loop through elements of the string list
2697 while Current /= No_Array_Element loop
2698 Element := In_Tree.Array_Elements.Table (Current);
2700 -- Put file name in canonical case
2702 if not Osint.File_Names_Case_Sensitive then
2703 Get_Name_String (Element.Value.Value);
2704 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2705 Element.Value.Value := Name_Find;
2708 -- Check that it contains a valid unit name
2710 Get_Name_String (Element.Index);
2711 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2713 if Unit_Name = No_Name then
2714 Err_Vars.Error_Msg_Name_1 := Element.Index;
2717 "%% is not a valid unit name.",
2718 Element.Value.Location);
2721 if Current_Verbosity = High then
2722 Write_Str (" Unit (""");
2723 Write_Str (Get_Name_String (Unit_Name));
2727 Element.Index := Unit_Name;
2728 In_Tree.Array_Elements.Table (Current) := Element;
2731 Current := Element.Next;
2733 end Check_Unit_Names;
2735 --------------------
2736 -- Get_Exceptions --
2737 --------------------
2739 procedure Get_Exceptions (Kind : Source_Kind) is
2740 Exceptions : Array_Element_Id;
2741 Exception_List : Variable_Value;
2742 Element_Id : String_List_Id;
2743 Element : String_Element;
2744 File_Name : File_Name_Type;
2745 Lang_Id : Language_Index;
2747 Lang_Kind : Language_Kind;
2754 (Name_Implementation_Exceptions,
2755 In_Arrays => Naming.Decl.Arrays,
2756 In_Tree => In_Tree);
2761 (Name_Specification_Exceptions,
2762 In_Arrays => Naming.Decl.Arrays,
2763 In_Tree => In_Tree);
2766 Lang_Id := Data.First_Language_Processing;
2767 while Lang_Id /= No_Language_Index loop
2768 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2771 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2773 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2775 Exception_List := Value_Of
2777 In_Array => Exceptions,
2778 In_Tree => In_Tree);
2780 if Exception_List /= Nil_Variable_Value then
2781 Element_Id := Exception_List.Values;
2782 while Element_Id /= Nil_String loop
2783 Element := In_Tree.String_Elements.Table (Element_Id);
2785 if Osint.File_Names_Case_Sensitive then
2786 File_Name := File_Name_Type (Element.Value);
2788 Get_Name_String (Element.Value);
2789 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2790 File_Name := Name_Find;
2793 Source := Data.First_Source;
2794 while Source /= No_Source
2796 In_Tree.Sources.Table (Source).File /= File_Name
2799 In_Tree.Sources.Table (Source).Next_In_Project;
2802 if Source = No_Source then
2811 File_Name => File_Name,
2812 Display_File => File_Name_Type (Element.Value),
2813 Naming_Exception => True,
2814 Lang_Kind => Lang_Kind);
2817 -- Check if the file name is already recorded for
2818 -- another language or another kind.
2821 In_Tree.Sources.Table (Source).Language /= Lang_Id
2826 "the same file cannot be a source " &
2830 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2834 "the same file cannot be a source " &
2839 -- If the file is already recorded for the same
2840 -- language and the same kind, it means that the file
2841 -- name appears several times in the *_Exceptions
2842 -- attribute; so there is nothing to do.
2846 Element_Id := Element.Next;
2851 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2855 -------------------------
2856 -- Get_Unit_Exceptions --
2857 -------------------------
2859 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2860 Exceptions : Array_Element_Id;
2861 Element : Array_Element;
2864 File_Name : File_Name_Type;
2865 Lang_Id : constant Language_Index :=
2866 Data.Unit_Based_Language_Index;
2867 Lang : constant Name_Id :=
2868 Data.Unit_Based_Language_Name;
2871 Source_To_Replace : Source_Id := No_Source;
2873 Other_Project : Project_Id;
2874 Other_Part : Source_Id := No_Source;
2877 if Lang_Id = No_Language_Index or else Lang = No_Name then
2882 Exceptions := Value_Of
2884 In_Arrays => Naming.Decl.Arrays,
2885 In_Tree => In_Tree);
2887 if Exceptions = No_Array_Element then
2890 (Name_Implementation,
2891 In_Arrays => Naming.Decl.Arrays,
2892 In_Tree => In_Tree);
2899 In_Arrays => Naming.Decl.Arrays,
2900 In_Tree => In_Tree);
2902 if Exceptions = No_Array_Element then
2903 Exceptions := Value_Of
2904 (Name_Specification,
2905 In_Arrays => Naming.Decl.Arrays,
2906 In_Tree => In_Tree);
2911 while Exceptions /= No_Array_Element loop
2912 Element := In_Tree.Array_Elements.Table (Exceptions);
2914 if Osint.File_Names_Case_Sensitive then
2915 File_Name := File_Name_Type (Element.Value.Value);
2917 Get_Name_String (Element.Value.Value);
2918 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2919 File_Name := Name_Find;
2922 Get_Name_String (Element.Index);
2923 To_Lower (Name_Buffer (1 .. Name_Len));
2926 Index := Element.Value.Index;
2928 -- For Ada, check if it is a valid unit name
2930 if Lang = Name_Ada then
2931 Get_Name_String (Element.Index);
2932 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2934 if Unit = No_Name then
2935 Err_Vars.Error_Msg_Name_1 := Element.Index;
2938 "%% is not a valid unit name.",
2939 Element.Value.Location);
2943 if Unit /= No_Name then
2945 -- Check if the source already exists
2947 Source := In_Tree.First_Source;
2948 Source_To_Replace := No_Source;
2950 while Source /= No_Source and then
2951 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2952 In_Tree.Sources.Table (Source).Index /= Index)
2954 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2957 if Source /= No_Source then
2958 if In_Tree.Sources.Table (Source).Kind /= Kind then
2959 Other_Part := Source;
2963 In_Tree.Sources.Table (Source).Next_In_Sources;
2965 exit when Source = No_Source or else
2966 (In_Tree.Sources.Table (Source).Unit = Unit
2968 In_Tree.Sources.Table (Source).Index = Index);
2972 if Source /= No_Source then
2973 Other_Project := In_Tree.Sources.Table (Source).Project;
2975 if Is_Extending (Project, Other_Project, In_Tree) then
2977 In_Tree.Sources.Table (Source).Other_Part;
2979 -- Record the source to be removed
2981 Source_To_Replace := Source;
2982 Source := No_Source;
2985 Error_Msg_Name_1 := Unit;
2987 In_Tree.Projects.Table (Other_Project).Name;
2991 "%% is already a source of project %%",
2992 Element.Value.Location);
2997 if Source = No_Source then
3006 File_Name => File_Name,
3007 Display_File => File_Name_Type (Element.Value.Value),
3008 Lang_Kind => Unit_Based,
3009 Other_Part => Other_Part,
3012 Naming_Exception => True,
3013 Source_To_Replace => Source_To_Replace);
3017 Exceptions := Element.Next;
3020 end Get_Unit_Exceptions;
3022 -- Start of processing for Check_Naming_Schemes
3025 if Get_Mode = Ada_Only then
3027 -- If there is a package Naming, we will put in Data.Naming what is
3028 -- in this package Naming.
3030 if Naming_Id /= No_Package then
3031 Naming := In_Tree.Packages.Table (Naming_Id);
3033 if Current_Verbosity = High then
3034 Write_Line ("Checking ""Naming"" for Ada.");
3038 Bodies : constant Array_Element_Id :=
3040 (Name_Body, Naming.Decl.Arrays, In_Tree);
3042 Specs : constant Array_Element_Id :=
3044 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3047 if Bodies /= No_Array_Element then
3049 -- We have elements in the array Body_Part
3051 if Current_Verbosity = High then
3052 Write_Line ("Found Bodies.");
3055 Data.Naming.Bodies := Bodies;
3056 Check_Unit_Names (Bodies);
3059 if Current_Verbosity = High then
3060 Write_Line ("No Bodies.");
3064 if Specs /= No_Array_Element then
3066 -- We have elements in the array Specs
3068 if Current_Verbosity = High then
3069 Write_Line ("Found Specs.");
3072 Data.Naming.Specs := Specs;
3073 Check_Unit_Names (Specs);
3076 if Current_Verbosity = High then
3077 Write_Line ("No Specs.");
3082 -- We are now checking if variables Dot_Replacement, Casing,
3083 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3085 -- For each variable, if it does not exist, we do nothing,
3086 -- because we already have the default.
3088 -- Check Dot_Replacement
3091 Dot_Replacement : constant Variable_Value :=
3093 (Name_Dot_Replacement,
3094 Naming.Decl.Attributes, In_Tree);
3097 pragma Assert (Dot_Replacement.Kind = Single,
3098 "Dot_Replacement is not a single string");
3100 if not Dot_Replacement.Default then
3101 Get_Name_String (Dot_Replacement.Value);
3103 if Name_Len = 0 then
3106 "Dot_Replacement cannot be empty",
3107 Dot_Replacement.Location);
3110 if Osint.File_Names_Case_Sensitive then
3111 Data.Naming.Dot_Replacement :=
3112 File_Name_Type (Dot_Replacement.Value);
3114 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3115 Data.Naming.Dot_Replacement := Name_Find;
3117 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3122 if Current_Verbosity = High then
3123 Write_Str (" Dot_Replacement = """);
3124 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3132 Casing_String : constant Variable_Value :=
3135 Naming.Decl.Attributes,
3139 pragma Assert (Casing_String.Kind = Single,
3140 "Casing is not a single string");
3142 if not Casing_String.Default then
3144 Casing_Image : constant String :=
3145 Get_Name_String (Casing_String.Value);
3148 Casing_Value : constant Casing_Type :=
3149 Value (Casing_Image);
3151 Data.Naming.Casing := Casing_Value;
3155 when Constraint_Error =>
3156 if Casing_Image'Length = 0 then
3159 "Casing cannot be an empty string",
3160 Casing_String.Location);
3163 Name_Len := Casing_Image'Length;
3164 Name_Buffer (1 .. Name_Len) := Casing_Image;
3165 Err_Vars.Error_Msg_Name_1 := Name_Find;
3168 "%% is not a correct Casing",
3169 Casing_String.Location);
3175 if Current_Verbosity = High then
3176 Write_Str (" Casing = ");
3177 Write_Str (Image (Data.Naming.Casing));
3182 -- Check Spec_Suffix
3185 Ada_Spec_Suffix : constant Variable_Value :=
3189 In_Array => Data.Naming.Spec_Suffix,
3190 In_Tree => In_Tree);
3193 if Ada_Spec_Suffix.Kind = Single
3194 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3196 Get_Name_String (Ada_Spec_Suffix.Value);
3197 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3198 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3199 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3206 Default_Ada_Spec_Suffix);
3210 if Current_Verbosity = High then
3211 Write_Str (" Spec_Suffix = """);
3212 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3217 -- Check Body_Suffix
3220 Ada_Body_Suffix : constant Variable_Value :=
3224 In_Array => Data.Naming.Body_Suffix,
3225 In_Tree => In_Tree);
3228 if Ada_Body_Suffix.Kind = Single
3229 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3231 Get_Name_String (Ada_Body_Suffix.Value);
3232 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3233 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3234 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3241 Default_Ada_Body_Suffix);
3245 if Current_Verbosity = High then
3246 Write_Str (" Body_Suffix = """);
3247 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3252 -- Check Separate_Suffix
3255 Ada_Sep_Suffix : constant Variable_Value :=
3257 (Variable_Name => Name_Separate_Suffix,
3258 In_Variables => Naming.Decl.Attributes,
3259 In_Tree => In_Tree);
3262 if Ada_Sep_Suffix.Default then
3263 Data.Naming.Separate_Suffix :=
3264 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3267 Get_Name_String (Ada_Sep_Suffix.Value);
3269 if Name_Len = 0 then
3272 "Separate_Suffix cannot be empty",
3273 Ada_Sep_Suffix.Location);
3276 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3277 Data.Naming.Separate_Suffix := Name_Find;
3278 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3283 if Current_Verbosity = High then
3284 Write_Str (" Separate_Suffix = """);
3285 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3290 -- Check if Data.Naming is valid
3292 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3295 elsif not In_Configuration then
3297 -- Look into package Naming, if there is one
3299 if Naming_Id /= No_Package then
3300 Naming := In_Tree.Packages.Table (Naming_Id);
3302 if Current_Verbosity = High then
3303 Write_Line ("Checking package Naming.");
3306 -- We are now checking if attribute Dot_Replacement, Casing,
3307 -- and/or Separate_Suffix exist.
3309 -- For each attribute, if it does not exist, we do nothing,
3310 -- because we already have the default.
3311 -- Otherwise, for all unit-based languages, we put the declared
3312 -- value in the language config.
3315 Dot_Repl : constant Variable_Value :=
3317 (Name_Dot_Replacement,
3318 Naming.Decl.Attributes, In_Tree);
3319 Dot_Replacement : File_Name_Type := No_File;
3321 Casing_String : constant Variable_Value :=
3324 Naming.Decl.Attributes,
3326 Casing : Casing_Type;
3327 Casing_Defined : Boolean := False;
3329 Sep_Suffix : constant Variable_Value :=
3331 (Variable_Name => Name_Separate_Suffix,
3332 In_Variables => Naming.Decl.Attributes,
3333 In_Tree => In_Tree);
3334 Separate_Suffix : File_Name_Type := No_File;
3336 Lang_Id : Language_Index;
3338 -- Check attribute Dot_Replacement
3340 if not Dot_Repl.Default then
3341 Get_Name_String (Dot_Repl.Value);
3343 if Name_Len = 0 then
3346 "Dot_Replacement cannot be empty",
3350 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3351 Dot_Replacement := Name_Find;
3353 if Current_Verbosity = High then
3354 Write_Str (" Dot_Replacement = """);
3355 Write_Str (Get_Name_String (Dot_Replacement));
3362 -- Check attribute Casing
3364 if not Casing_String.Default then
3366 Casing_Image : constant String :=
3367 Get_Name_String (Casing_String.Value);
3370 Casing_Value : constant Casing_Type :=
3371 Value (Casing_Image);
3373 Casing := Casing_Value;
3374 Casing_Defined := True;
3376 if Current_Verbosity = High then
3377 Write_Str (" Casing = ");
3378 Write_Str (Image (Casing));
3385 when Constraint_Error =>
3386 if Casing_Image'Length = 0 then
3389 "Casing cannot be an empty string",
3390 Casing_String.Location);
3393 Name_Len := Casing_Image'Length;
3394 Name_Buffer (1 .. Name_Len) := Casing_Image;
3395 Err_Vars.Error_Msg_Name_1 := Name_Find;
3398 "%% is not a correct Casing",
3399 Casing_String.Location);
3404 if not Sep_Suffix.Default then
3405 Get_Name_String (Sep_Suffix.Value);
3407 if Name_Len = 0 then
3410 "Separate_Suffix cannot be empty",
3411 Sep_Suffix.Location);
3414 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3415 Separate_Suffix := Name_Find;
3417 if Current_Verbosity = High then
3418 Write_Str (" Separate_Suffix = """);
3419 Write_Str (Get_Name_String (Separate_Suffix));
3426 -- For all unit based languages, if any, set the specified
3427 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3429 if Dot_Replacement /= No_File
3430 or else Casing_Defined
3431 or else Separate_Suffix /= No_File
3433 Lang_Id := Data.First_Language_Processing;
3434 while Lang_Id /= No_Language_Index loop
3435 if In_Tree.Languages_Data.Table
3436 (Lang_Id).Config.Kind = Unit_Based
3438 if Dot_Replacement /= No_File then
3439 In_Tree.Languages_Data.Table
3440 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3444 if Casing_Defined then
3445 In_Tree.Languages_Data.Table
3446 (Lang_Id).Config.Naming_Data.Casing := Casing;
3449 if Separate_Suffix /= No_File then
3450 In_Tree.Languages_Data.Table
3451 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3457 In_Tree.Languages_Data.Table (Lang_Id).Next;
3462 -- Next, get the spec and body suffixes
3465 Suffix : Variable_Value;
3466 Lang_Id : Language_Index;
3470 Lang_Id := Data.First_Language_Processing;
3471 while Lang_Id /= No_Language_Index loop
3472 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3478 Attribute_Or_Array_Name => Name_Spec_Suffix,
3479 In_Package => Naming_Id,
3480 In_Tree => In_Tree);
3482 if Suffix = Nil_Variable_Value then
3485 Attribute_Or_Array_Name => Name_Specification_Suffix,
3486 In_Package => Naming_Id,
3487 In_Tree => In_Tree);
3490 if Suffix /= Nil_Variable_Value then
3491 In_Tree.Languages_Data.Table (Lang_Id).
3492 Config.Naming_Data.Spec_Suffix :=
3493 File_Name_Type (Suffix.Value);
3500 Attribute_Or_Array_Name => Name_Body_Suffix,
3501 In_Package => Naming_Id,
3502 In_Tree => In_Tree);
3504 if Suffix = Nil_Variable_Value then
3507 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3508 In_Package => Naming_Id,
3509 In_Tree => In_Tree);
3512 if Suffix /= Nil_Variable_Value then
3513 In_Tree.Languages_Data.Table (Lang_Id).
3514 Config.Naming_Data.Body_Suffix :=
3515 File_Name_Type (Suffix.Value);
3518 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3522 -- Get the exceptions for file based languages
3524 Get_Exceptions (Spec);
3525 Get_Exceptions (Impl);
3527 -- Get the exceptions for unit based languages
3529 Get_Unit_Exceptions (Spec);
3530 Get_Unit_Exceptions (Impl);
3534 end Check_Naming_Schemes;
3536 ------------------------------
3537 -- Check_Library_Attributes --
3538 ------------------------------
3540 procedure Check_Library_Attributes
3541 (Project : Project_Id;
3542 In_Tree : Project_Tree_Ref;
3543 Current_Dir : String;
3544 Data : in out Project_Data)
3546 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3548 Lib_Dir : constant Prj.Variable_Value :=
3550 (Snames.Name_Library_Dir, Attributes, In_Tree);
3552 Lib_Name : constant Prj.Variable_Value :=
3554 (Snames.Name_Library_Name, Attributes, In_Tree);
3556 Lib_Version : constant Prj.Variable_Value :=
3558 (Snames.Name_Library_Version, Attributes, In_Tree);
3560 Lib_ALI_Dir : constant Prj.Variable_Value :=
3562 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3564 The_Lib_Kind : constant Prj.Variable_Value :=
3566 (Snames.Name_Library_Kind, Attributes, In_Tree);
3568 Imported_Project_List : Project_List := Empty_Project_List;
3570 Continuation : String_Access := No_Continuation_String'Access;
3572 Support_For_Libraries : Library_Support;
3574 Library_Directory_Present : Boolean;
3576 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3577 -- Check if an imported or extended project if also a library project
3583 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3584 Proj_Data : Project_Data;
3589 if Proj /= No_Project then
3590 Proj_Data := In_Tree.Projects.Table (Proj);
3592 if not Proj_Data.Library then
3594 -- The only not library projects that are OK are those that
3595 -- have no sources. However, header files from non-Ada
3596 -- languages are OK, as there is nothing to compile.
3598 Src_Id := Proj_Data.First_Source;
3599 while Src_Id /= No_Source loop
3600 Src := In_Tree.Sources.Table (Src_Id);
3602 exit when Src.Lang_Kind /= File_Based
3603 or else Src.Kind /= Spec;
3605 Src_Id := Src.Next_In_Project;
3608 if Src_Id /= No_Source then
3609 Error_Msg_Name_1 := Data.Name;
3610 Error_Msg_Name_2 := Proj_Data.Name;
3616 "library project %% cannot extend project %% " &
3617 "that is not a library project",
3624 "library project %% cannot import project %% " &
3625 "that is not a library project",
3629 Continuation := Continuation_String'Access;
3632 elsif Data.Library_Kind /= Static and then
3633 Proj_Data.Library_Kind = Static
3635 Error_Msg_Name_1 := Data.Name;
3636 Error_Msg_Name_2 := Proj_Data.Name;
3642 "shared library project %% cannot extend static " &
3643 "library project %%",
3650 "shared library project %% cannot import static " &
3651 "library project %%",
3655 Continuation := Continuation_String'Access;
3660 -- Start of processing for Check_Library_Attributes
3663 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3665 -- Special case of extending project
3667 if Data.Extends /= No_Project then
3669 Extended_Data : constant Project_Data :=
3670 In_Tree.Projects.Table (Data.Extends);
3673 -- If the project extended is a library project, we inherit the
3674 -- library name, if it is not redefined; we check that the library
3675 -- directory is specified.
3677 if Extended_Data.Library then
3678 if Data.Qualifier = Standard then
3681 "a standard project cannot extend a library project",
3685 if Lib_Name.Default then
3686 Data.Library_Name := Extended_Data.Library_Name;
3689 if Lib_Dir.Default then
3690 if not Data.Virtual then
3693 "a project extending a library project must " &
3694 "specify an attribute Library_Dir",
3698 -- For a virtual project extending a library project,
3699 -- inherit library directory.
3701 Data.Library_Dir := Extended_Data.Library_Dir;
3702 Data.Display_Library_Dir :=
3703 Extended_Data.Display_Library_Dir;
3704 Library_Directory_Present := True;
3712 pragma Assert (Lib_Name.Kind = Single);
3714 if Lib_Name.Value = Empty_String then
3715 if Current_Verbosity = High
3716 and then Data.Library_Name = No_Name
3718 Write_Line ("No library name");
3722 -- There is no restriction on the syntax of library names
3724 Data.Library_Name := Lib_Name.Value;
3727 if Data.Library_Name /= No_Name then
3728 if Current_Verbosity = High then
3729 Write_Str ("Library name = """);
3730 Write_Str (Get_Name_String (Data.Library_Name));
3734 pragma Assert (Lib_Dir.Kind = Single);
3736 if not Library_Directory_Present then
3737 if Current_Verbosity = High then
3738 Write_Line ("No library directory");
3742 -- Find path name (unless inherited), check that it is a directory
3744 if Data.Library_Dir = No_Path then
3748 File_Name_Type (Lib_Dir.Value),
3749 Data.Display_Directory,
3751 Data.Display_Library_Dir,
3752 Create => "library",
3753 Current_Dir => Current_Dir,
3754 Location => Lib_Dir.Location);
3757 if Data.Library_Dir = No_Path then
3759 -- Get the absolute name of the library directory that
3760 -- does not exist, to report an error.
3763 Dir_Name : constant String :=
3764 Get_Name_String (Lib_Dir.Value);
3767 if Is_Absolute_Path (Dir_Name) then
3768 Err_Vars.Error_Msg_File_1 :=
3769 File_Name_Type (Lib_Dir.Value);
3772 Get_Name_String (Data.Display_Directory);
3774 if Name_Buffer (Name_Len) /= Directory_Separator then
3775 Name_Len := Name_Len + 1;
3776 Name_Buffer (Name_Len) := Directory_Separator;
3780 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3782 Name_Len := Name_Len + Dir_Name'Length;
3783 Err_Vars.Error_Msg_File_1 := Name_Find;
3790 "library directory { does not exist",
3794 -- The library directory cannot be the same as the Object
3797 elsif Data.Library_Dir = Data.Object_Directory then
3800 "library directory cannot be the same " &
3801 "as object directory",
3803 Data.Library_Dir := No_Path;
3804 Data.Display_Library_Dir := No_Path;
3808 OK : Boolean := True;
3809 Dirs_Id : String_List_Id;
3810 Dir_Elem : String_Element;
3813 -- The library directory cannot be the same as a source
3814 -- directory of the current project.
3816 Dirs_Id := Data.Source_Dirs;
3817 while Dirs_Id /= Nil_String loop
3818 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3819 Dirs_Id := Dir_Elem.Next;
3821 if Data.Library_Dir = Path_Name_Type (Dir_Elem.Value) then
3822 Err_Vars.Error_Msg_File_1 :=
3823 File_Name_Type (Dir_Elem.Value);
3826 "library directory cannot be the same " &
3827 "as source directory {",
3836 -- The library directory cannot be the same as a source
3837 -- directory of another project either.
3840 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3841 if Pid /= Project then
3842 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3844 Dir_Loop : while Dirs_Id /= Nil_String loop
3846 In_Tree.String_Elements.Table (Dirs_Id);
3847 Dirs_Id := Dir_Elem.Next;
3849 if Data.Library_Dir =
3850 Path_Name_Type (Dir_Elem.Value)
3852 Err_Vars.Error_Msg_File_1 :=
3853 File_Name_Type (Dir_Elem.Value);
3854 Err_Vars.Error_Msg_Name_1 :=
3855 In_Tree.Projects.Table (Pid).Name;
3859 "library directory cannot be the same " &
3860 "as source directory { of project %%",
3867 end loop Project_Loop;
3871 Data.Library_Dir := No_Path;
3872 Data.Display_Library_Dir := No_Path;
3874 elsif Current_Verbosity = High then
3876 -- Display the Library directory in high verbosity
3878 Write_Str ("Library directory =""");
3879 Write_Str (Get_Name_String (Data.Display_Library_Dir));
3889 Data.Library_Dir /= No_Path
3891 Data.Library_Name /= No_Name;
3893 if Data.Extends = No_Project then
3894 case Data.Qualifier is
3896 if Data.Library then
3899 "a standard project cannot be a library project",
3904 if not Data.Library then
3907 "not a library project",
3917 if Data.Library then
3918 if Get_Mode = Multi_Language then
3919 Support_For_Libraries := Data.Config.Lib_Support;
3922 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3925 if Support_For_Libraries = Prj.None then
3928 "?libraries are not supported on this platform",
3930 Data.Library := False;
3933 if Lib_ALI_Dir.Value = Empty_String then
3934 if Current_Verbosity = High then
3935 Write_Line ("No library ALI directory specified");
3937 Data.Library_ALI_Dir := Data.Library_Dir;
3938 Data.Display_Library_ALI_Dir := Data.Display_Library_Dir;
3941 -- Find path name, check that it is a directory
3946 File_Name_Type (Lib_ALI_Dir.Value),
3947 Data.Display_Directory,
3948 Data.Library_ALI_Dir,
3949 Data.Display_Library_ALI_Dir,
3950 Create => "library ALI",
3951 Current_Dir => Current_Dir,
3952 Location => Lib_ALI_Dir.Location);
3954 if Data.Library_ALI_Dir = No_Path then
3956 -- Get the absolute name of the library ALI directory that
3957 -- does not exist, to report an error.
3960 Dir_Name : constant String :=
3961 Get_Name_String (Lib_ALI_Dir.Value);
3964 if Is_Absolute_Path (Dir_Name) then
3965 Err_Vars.Error_Msg_File_1 :=
3966 File_Name_Type (Lib_Dir.Value);
3969 Get_Name_String (Data.Display_Directory);
3971 if Name_Buffer (Name_Len) /= Directory_Separator then
3972 Name_Len := Name_Len + 1;
3973 Name_Buffer (Name_Len) := Directory_Separator;
3977 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3979 Name_Len := Name_Len + Dir_Name'Length;
3980 Err_Vars.Error_Msg_File_1 := Name_Find;
3987 "library 'A'L'I directory { does not exist",
3988 Lib_ALI_Dir.Location);
3992 if Data.Library_ALI_Dir /= Data.Library_Dir then
3994 -- The library ALI directory cannot be the same as the
3995 -- Object directory.
3997 if Data.Library_ALI_Dir = Data.Object_Directory then
4000 "library 'A'L'I directory cannot be the same " &
4001 "as object directory",
4002 Lib_ALI_Dir.Location);
4003 Data.Library_ALI_Dir := No_Path;
4004 Data.Display_Library_ALI_Dir := No_Path;
4008 OK : Boolean := True;
4009 Dirs_Id : String_List_Id;
4010 Dir_Elem : String_Element;
4013 -- The library ALI directory cannot be the same as
4014 -- a source directory of the current project.
4016 Dirs_Id := Data.Source_Dirs;
4017 while Dirs_Id /= Nil_String loop
4018 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4019 Dirs_Id := Dir_Elem.Next;
4021 if Data.Library_ALI_Dir =
4022 Path_Name_Type (Dir_Elem.Value)
4024 Err_Vars.Error_Msg_File_1 :=
4025 File_Name_Type (Dir_Elem.Value);
4028 "library 'A'L'I directory cannot be " &
4029 "the same as source directory {",
4030 Lib_ALI_Dir.Location);
4038 -- The library ALI directory cannot be the same as
4039 -- a source directory of another project either.
4043 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4045 if Pid /= Project then
4047 In_Tree.Projects.Table (Pid).Source_Dirs;
4050 while Dirs_Id /= Nil_String loop
4052 In_Tree.String_Elements.Table (Dirs_Id);
4053 Dirs_Id := Dir_Elem.Next;
4055 if Data.Library_ALI_Dir =
4056 Path_Name_Type (Dir_Elem.Value)
4058 Err_Vars.Error_Msg_File_1 :=
4059 File_Name_Type (Dir_Elem.Value);
4060 Err_Vars.Error_Msg_Name_1 :=
4061 In_Tree.Projects.Table (Pid).Name;
4065 "library 'A'L'I directory cannot " &
4066 "be the same as source directory " &
4068 Lib_ALI_Dir.Location);
4070 exit ALI_Project_Loop;
4072 end loop ALI_Dir_Loop;
4074 end loop ALI_Project_Loop;
4078 Data.Library_ALI_Dir := No_Path;
4079 Data.Display_Library_ALI_Dir := No_Path;
4081 elsif Current_Verbosity = High then
4083 -- Display the Library ALI directory in high
4086 Write_Str ("Library ALI directory =""");
4088 (Get_Name_String (Data.Display_Library_ALI_Dir));
4096 pragma Assert (Lib_Version.Kind = Single);
4098 if Lib_Version.Value = Empty_String then
4099 if Current_Verbosity = High then
4100 Write_Line ("No library version specified");
4104 Data.Lib_Internal_Name := Lib_Version.Value;
4107 pragma Assert (The_Lib_Kind.Kind = Single);
4109 if The_Lib_Kind.Value = Empty_String then
4110 if Current_Verbosity = High then
4111 Write_Line ("No library kind specified");
4115 Get_Name_String (The_Lib_Kind.Value);
4118 Kind_Name : constant String :=
4119 To_Lower (Name_Buffer (1 .. Name_Len));
4121 OK : Boolean := True;
4124 if Kind_Name = "static" then
4125 Data.Library_Kind := Static;
4127 elsif Kind_Name = "dynamic" then
4128 Data.Library_Kind := Dynamic;
4130 elsif Kind_Name = "relocatable" then
4131 Data.Library_Kind := Relocatable;
4136 "illegal value for Library_Kind",
4137 The_Lib_Kind.Location);
4141 if Current_Verbosity = High and then OK then
4142 Write_Str ("Library kind = ");
4143 Write_Line (Kind_Name);
4146 if Data.Library_Kind /= Static and then
4147 Support_For_Libraries = Prj.Static_Only
4151 "only static libraries are supported " &
4153 The_Lib_Kind.Location);
4154 Data.Library := False;
4159 if Data.Library then
4160 if Current_Verbosity = High then
4161 Write_Line ("This is a library project file");
4164 if Get_Mode = Multi_Language then
4165 Check_Library (Data.Extends, Extends => True);
4167 Imported_Project_List := Data.Imported_Projects;
4168 while Imported_Project_List /= Empty_Project_List loop
4170 (In_Tree.Project_Lists.Table
4171 (Imported_Project_List).Project,
4173 Imported_Project_List :=
4174 In_Tree.Project_Lists.Table
4175 (Imported_Project_List).Next;
4183 if Data.Extends /= No_Project then
4184 In_Tree.Projects.Table (Data.Extends).Library := False;
4186 end Check_Library_Attributes;
4188 --------------------------
4189 -- Check_Package_Naming --
4190 --------------------------
4192 procedure Check_Package_Naming
4193 (Project : Project_Id;
4194 In_Tree : Project_Tree_Ref;
4195 Data : in out Project_Data)
4197 Naming_Id : constant Package_Id :=
4198 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4200 Naming : Package_Element;
4203 -- If there is a package Naming, we will put in Data.Naming
4204 -- what is in this package Naming.
4206 if Naming_Id /= No_Package then
4207 Naming := In_Tree.Packages.Table (Naming_Id);
4209 if Current_Verbosity = High then
4210 Write_Line ("Checking ""Naming"".");
4213 -- Check Spec_Suffix
4216 Spec_Suffixs : Array_Element_Id :=
4222 Suffix : Array_Element_Id;
4223 Element : Array_Element;
4224 Suffix2 : Array_Element_Id;
4227 -- If some suffixes have been specified, we make sure that
4228 -- for each language for which a default suffix has been
4229 -- specified, there is a suffix specified, either the one
4230 -- in the project file or if there were none, the default.
4232 if Spec_Suffixs /= No_Array_Element then
4233 Suffix := Data.Naming.Spec_Suffix;
4235 while Suffix /= No_Array_Element loop
4237 In_Tree.Array_Elements.Table (Suffix);
4238 Suffix2 := Spec_Suffixs;
4240 while Suffix2 /= No_Array_Element loop
4241 exit when In_Tree.Array_Elements.Table
4242 (Suffix2).Index = Element.Index;
4243 Suffix2 := In_Tree.Array_Elements.Table
4247 -- There is a registered default suffix, but no
4248 -- suffix specified in the project file.
4249 -- Add the default to the array.
4251 if Suffix2 = No_Array_Element then
4252 Array_Element_Table.Increment_Last
4253 (In_Tree.Array_Elements);
4254 In_Tree.Array_Elements.Table
4255 (Array_Element_Table.Last
4256 (In_Tree.Array_Elements)) :=
4257 (Index => Element.Index,
4258 Src_Index => Element.Src_Index,
4259 Index_Case_Sensitive => False,
4260 Value => Element.Value,
4261 Next => Spec_Suffixs);
4262 Spec_Suffixs := Array_Element_Table.Last
4263 (In_Tree.Array_Elements);
4266 Suffix := Element.Next;
4269 -- Put the resulting array as the specification suffixes
4271 Data.Naming.Spec_Suffix := Spec_Suffixs;
4276 Current : Array_Element_Id;
4277 Element : Array_Element;
4280 Current := Data.Naming.Spec_Suffix;
4281 while Current /= No_Array_Element loop
4282 Element := In_Tree.Array_Elements.Table (Current);
4283 Get_Name_String (Element.Value.Value);
4285 if Name_Len = 0 then
4288 "Spec_Suffix cannot be empty",
4289 Element.Value.Location);
4292 In_Tree.Array_Elements.Table (Current) := Element;
4293 Current := Element.Next;
4297 -- Check Body_Suffix
4300 Impl_Suffixs : Array_Element_Id :=
4306 Suffix : Array_Element_Id;
4307 Element : Array_Element;
4308 Suffix2 : Array_Element_Id;
4311 -- If some suffixes have been specified, we make sure that
4312 -- for each language for which a default suffix has been
4313 -- specified, there is a suffix specified, either the one
4314 -- in the project file or if there were none, the default.
4316 if Impl_Suffixs /= No_Array_Element then
4317 Suffix := Data.Naming.Body_Suffix;
4318 while Suffix /= No_Array_Element loop
4320 In_Tree.Array_Elements.Table (Suffix);
4322 Suffix2 := Impl_Suffixs;
4323 while Suffix2 /= No_Array_Element loop
4324 exit when In_Tree.Array_Elements.Table
4325 (Suffix2).Index = Element.Index;
4326 Suffix2 := In_Tree.Array_Elements.Table
4330 -- There is a registered default suffix, but no suffix was
4331 -- specified in the project file. Add default to the array.
4333 if Suffix2 = No_Array_Element then
4334 Array_Element_Table.Increment_Last
4335 (In_Tree.Array_Elements);
4336 In_Tree.Array_Elements.Table
4337 (Array_Element_Table.Last
4338 (In_Tree.Array_Elements)) :=
4339 (Index => Element.Index,
4340 Src_Index => Element.Src_Index,
4341 Index_Case_Sensitive => False,
4342 Value => Element.Value,
4343 Next => Impl_Suffixs);
4344 Impl_Suffixs := Array_Element_Table.Last
4345 (In_Tree.Array_Elements);
4348 Suffix := Element.Next;
4351 -- Put the resulting array as the implementation suffixes
4353 Data.Naming.Body_Suffix := Impl_Suffixs;
4358 Current : Array_Element_Id;
4359 Element : Array_Element;
4362 Current := Data.Naming.Body_Suffix;
4363 while Current /= No_Array_Element loop
4364 Element := In_Tree.Array_Elements.Table (Current);
4365 Get_Name_String (Element.Value.Value);
4367 if Name_Len = 0 then
4370 "Body_Suffix cannot be empty",
4371 Element.Value.Location);
4374 In_Tree.Array_Elements.Table (Current) := Element;
4375 Current := Element.Next;
4379 -- Get the exceptions, if any
4381 Data.Naming.Specification_Exceptions :=
4383 (Name_Specification_Exceptions,
4384 In_Arrays => Naming.Decl.Arrays,
4385 In_Tree => In_Tree);
4387 Data.Naming.Implementation_Exceptions :=
4389 (Name_Implementation_Exceptions,
4390 In_Arrays => Naming.Decl.Arrays,
4391 In_Tree => In_Tree);
4393 end Check_Package_Naming;
4395 ---------------------------------
4396 -- Check_Programming_Languages --
4397 ---------------------------------
4399 procedure Check_Programming_Languages
4400 (In_Tree : Project_Tree_Ref;
4401 Project : Project_Id;
4402 Data : in out Project_Data)
4404 Languages : Variable_Value := Nil_Variable_Value;
4405 Def_Lang : Variable_Value := Nil_Variable_Value;
4406 Def_Lang_Id : Name_Id;
4409 Data.First_Language_Processing := No_Language_Index;
4411 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4414 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4415 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4416 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4418 if Data.Source_Dirs /= Nil_String then
4420 -- Check if languages are specified in this project
4422 if Languages.Default then
4424 -- Attribute Languages is not specified. So, it defaults to
4425 -- a project of the default language only.
4427 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4428 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4430 -- In Ada_Only mode, the default language is Ada
4432 if Get_Mode = Ada_Only then
4433 In_Tree.Name_Lists.Table (Data.Languages) :=
4434 (Name => Name_Ada, Next => No_Name_List);
4436 -- Attribute Languages is not specified. So, it defaults to
4437 -- a project of language Ada only.
4439 Data.Langs (Ada_Language_Index) := True;
4441 -- No sources of languages other than Ada
4443 Data.Other_Sources_Present := False;
4446 -- If the configuration file does not define a language either
4448 if Def_Lang.Default then
4449 if not Default_Language_Is_Ada then
4453 "no languages defined for this project",
4455 Def_Lang_Id := No_Name;
4457 Def_Lang_Id := Name_Ada;
4461 -- ??? Are we supporting a single default language in the
4462 -- configuration file ?
4463 Get_Name_String (Def_Lang.Value);
4464 To_Lower (Name_Buffer (1 .. Name_Len));
4465 Def_Lang_Id := Name_Find;
4468 if Def_Lang_Id /= No_Name then
4469 In_Tree.Name_Lists.Table (Data.Languages) :=
4470 (Name => Def_Lang_Id, Next => No_Name_List);
4472 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4474 Data.First_Language_Processing :=
4475 Language_Data_Table.Last (In_Tree.Languages_Data);
4476 In_Tree.Languages_Data.Table
4477 (Data.First_Language_Processing) := No_Language_Data;
4478 In_Tree.Languages_Data.Table
4479 (Data.First_Language_Processing).Name := Def_Lang_Id;
4480 Get_Name_String (Def_Lang_Id);
4481 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4482 In_Tree.Languages_Data.Table
4483 (Data.First_Language_Processing).Display_Name := Name_Find;
4485 if Def_Lang_Id = Name_Ada then
4486 In_Tree.Languages_Data.Table
4487 (Data.First_Language_Processing).Config.Kind
4489 In_Tree.Languages_Data.Table
4490 (Data.First_Language_Processing).Config.Dependency_Kind
4492 Data.Unit_Based_Language_Name := Name_Ada;
4493 Data.Unit_Based_Language_Index :=
4494 Data.First_Language_Processing;
4496 In_Tree.Languages_Data.Table
4497 (Data.First_Language_Processing).Config.Kind
4505 Current : String_List_Id := Languages.Values;
4506 Element : String_Element;
4507 Lang_Name : Name_Id;
4508 Index : Language_Index;
4509 Lang_Data : Language_Data;
4510 NL_Id : Name_List_Index := No_Name_List;
4513 if Get_Mode = Ada_Only then
4515 -- Assume that there is no language specified yet
4517 Data.Other_Sources_Present := False;
4518 Data.Ada_Sources_Present := False;
4521 -- If there are no languages declared, there are no sources
4523 if Current = Nil_String then
4524 Data.Source_Dirs := Nil_String;
4526 if Data.Qualifier = Standard then
4530 "a standard project cannot have no language declared",
4531 Languages.Location);
4535 -- Look through all the languages specified in attribute
4538 while Current /= Nil_String loop
4540 In_Tree.String_Elements.Table (Current);
4541 Get_Name_String (Element.Value);
4542 To_Lower (Name_Buffer (1 .. Name_Len));
4543 Lang_Name := Name_Find;
4545 NL_Id := Data.Languages;
4546 while NL_Id /= No_Name_List loop
4548 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4549 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4552 if NL_Id = No_Name_List then
4553 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4555 if Data.Languages = No_Name_List then
4557 Name_List_Table.Last (In_Tree.Name_Lists);
4560 NL_Id := Data.Languages;
4561 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4564 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4567 In_Tree.Name_Lists.Table (NL_Id).Next :=
4568 Name_List_Table.Last (In_Tree.Name_Lists);
4571 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4572 In_Tree.Name_Lists.Table (NL_Id) :=
4573 (Lang_Name, No_Name_List);
4575 if Get_Mode = Ada_Only then
4576 Index := Language_Indexes.Get (Lang_Name);
4578 if Index = No_Language_Index then
4579 Add_Language_Name (Lang_Name);
4580 Index := Last_Language_Index;
4583 Set (Index, True, Data, In_Tree);
4584 Set (Language_Processing =>
4585 Default_Language_Processing_Data,
4586 For_Language => Index,
4588 In_Tree => In_Tree);
4590 if Index = Ada_Language_Index then
4591 Data.Ada_Sources_Present := True;
4594 Data.Other_Sources_Present := True;
4598 Language_Data_Table.Increment_Last
4599 (In_Tree.Languages_Data);
4601 Language_Data_Table.Last (In_Tree.Languages_Data);
4602 Lang_Data.Name := Lang_Name;
4603 Lang_Data.Display_Name := Element.Value;
4604 Lang_Data.Next := Data.First_Language_Processing;
4606 if Lang_Name = Name_Ada then
4607 Lang_Data.Config.Kind := Unit_Based;
4608 Lang_Data.Config.Dependency_Kind := ALI_File;
4609 Data.Unit_Based_Language_Name := Name_Ada;
4610 Data.Unit_Based_Language_Index := Index;
4613 Lang_Data.Config.Kind := File_Based;
4614 Lang_Data.Config.Dependency_Kind := None;
4617 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4618 Data.First_Language_Processing := Index;
4622 Current := Element.Next;
4628 end Check_Programming_Languages;
4634 function Check_Project
4636 Root_Project : Project_Id;
4637 In_Tree : Project_Tree_Ref;
4638 Extending : Boolean) return Boolean
4641 if P = Root_Project then
4644 elsif Extending then
4646 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4649 while Data.Extends /= No_Project loop
4650 if P = Data.Extends then
4654 Data := In_Tree.Projects.Table (Data.Extends);
4662 -------------------------------
4663 -- Check_Stand_Alone_Library --
4664 -------------------------------
4666 procedure Check_Stand_Alone_Library
4667 (Project : Project_Id;
4668 In_Tree : Project_Tree_Ref;
4669 Data : in out Project_Data;
4670 Current_Dir : String;
4671 Extending : Boolean)
4673 Lib_Interfaces : constant Prj.Variable_Value :=
4675 (Snames.Name_Library_Interface,
4676 Data.Decl.Attributes,
4679 Lib_Auto_Init : constant Prj.Variable_Value :=
4681 (Snames.Name_Library_Auto_Init,
4682 Data.Decl.Attributes,
4685 Lib_Src_Dir : constant Prj.Variable_Value :=
4687 (Snames.Name_Library_Src_Dir,
4688 Data.Decl.Attributes,
4691 Lib_Symbol_File : constant Prj.Variable_Value :=
4693 (Snames.Name_Library_Symbol_File,
4694 Data.Decl.Attributes,
4697 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4699 (Snames.Name_Library_Symbol_Policy,
4700 Data.Decl.Attributes,
4703 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4705 (Snames.Name_Library_Reference_Symbol_File,
4706 Data.Decl.Attributes,
4709 Auto_Init_Supported : Boolean;
4710 OK : Boolean := True;
4712 Next_Proj : Project_Id;
4715 if Get_Mode = Multi_Language then
4716 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4718 Auto_Init_Supported :=
4719 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4722 pragma Assert (Lib_Interfaces.Kind = List);
4724 -- It is a stand-alone library project file if attribute
4725 -- Library_Interface is defined.
4727 if not Lib_Interfaces.Default then
4728 SAL_Library : declare
4729 Interfaces : String_List_Id := Lib_Interfaces.Values;
4730 Interface_ALIs : String_List_Id := Nil_String;
4732 The_Unit_Id : Unit_Index;
4733 The_Unit_Data : Unit_Data;
4735 procedure Add_ALI_For (Source : File_Name_Type);
4736 -- Add an ALI file name to the list of Interface ALIs
4742 procedure Add_ALI_For (Source : File_Name_Type) is
4744 Get_Name_String (Source);
4747 ALI : constant String :=
4748 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4749 ALI_Name_Id : Name_Id;
4752 Name_Len := ALI'Length;
4753 Name_Buffer (1 .. Name_Len) := ALI;
4754 ALI_Name_Id := Name_Find;
4756 String_Element_Table.Increment_Last
4757 (In_Tree.String_Elements);
4758 In_Tree.String_Elements.Table
4759 (String_Element_Table.Last
4760 (In_Tree.String_Elements)) :=
4761 (Value => ALI_Name_Id,
4763 Display_Value => ALI_Name_Id,
4765 In_Tree.String_Elements.Table
4766 (Interfaces).Location,
4768 Next => Interface_ALIs);
4769 Interface_ALIs := String_Element_Table.Last
4770 (In_Tree.String_Elements);
4774 -- Start of processing for SAL_Library
4777 Data.Standalone_Library := True;
4779 -- Library_Interface cannot be an empty list
4781 if Interfaces = Nil_String then
4784 "Library_Interface cannot be an empty list",
4785 Lib_Interfaces.Location);
4788 -- Process each unit name specified in the attribute
4789 -- Library_Interface.
4791 while Interfaces /= Nil_String loop
4793 (In_Tree.String_Elements.Table (Interfaces).Value);
4794 To_Lower (Name_Buffer (1 .. Name_Len));
4796 if Name_Len = 0 then
4799 "an interface cannot be an empty string",
4800 In_Tree.String_Elements.Table (Interfaces).Location);
4804 Error_Msg_Name_1 := Unit;
4806 if Get_Mode = Ada_Only then
4808 Units_Htable.Get (In_Tree.Units_HT, Unit);
4810 if The_Unit_Id = No_Unit_Index then
4814 In_Tree.String_Elements.Table
4815 (Interfaces).Location);
4818 -- Check that the unit is part of the project
4821 In_Tree.Units.Table (The_Unit_Id);
4823 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4824 and then The_Unit_Data.File_Names (Body_Part).Path /=
4828 (The_Unit_Data.File_Names (Body_Part).Project,
4829 Project, In_Tree, Extending)
4831 -- There is a body for this unit.
4832 -- If there is no spec, we need to check
4833 -- that it is not a subunit.
4835 if The_Unit_Data.File_Names
4836 (Specification).Name = No_File
4839 Src_Ind : Source_File_Index;
4842 Src_Ind := Sinput.P.Load_Project_File
4844 (The_Unit_Data.File_Names
4847 if Sinput.P.Source_File_Is_Subunit
4852 "%% is a subunit; " &
4853 "it cannot be an interface",
4855 String_Elements.Table
4856 (Interfaces).Location);
4861 -- The unit is not a subunit, so we add
4862 -- to the Interface ALIs the ALI file
4863 -- corresponding to the body.
4866 (The_Unit_Data.File_Names (Body_Part).Name);
4871 "%% is not an unit of this project",
4872 In_Tree.String_Elements.Table
4873 (Interfaces).Location);
4876 elsif The_Unit_Data.File_Names
4877 (Specification).Name /= No_File
4878 and then The_Unit_Data.File_Names
4879 (Specification).Path /= Slash
4880 and then Check_Project
4881 (The_Unit_Data.File_Names
4882 (Specification).Project,
4883 Project, In_Tree, Extending)
4886 -- The unit is part of the project, it has
4887 -- a spec, but no body. We add to the Interface
4888 -- ALIs the ALI file corresponding to the spec.
4891 (The_Unit_Data.File_Names (Specification).Name);
4896 "%% is not an unit of this project",
4897 In_Tree.String_Elements.Table
4898 (Interfaces).Location);
4903 -- Multi_Language mode
4905 Next_Proj := Data.Extends;
4906 Source := Data.First_Source;
4909 while Source /= No_Source and then
4910 In_Tree.Sources.Table (Source).Unit /= Unit
4913 In_Tree.Sources.Table (Source).Next_In_Project;
4916 exit when Source /= No_Source or else
4917 Next_Proj = No_Project;
4920 In_Tree.Projects.Table (Next_Proj).First_Source;
4922 In_Tree.Projects.Table (Next_Proj).Extends;
4925 if Source /= No_Source then
4926 if In_Tree.Sources.Table (Source).Kind = Sep then
4927 Source := No_Source;
4929 elsif In_Tree.Sources.Table (Source).Kind = Spec
4931 In_Tree.Sources.Table (Source).Other_Part /=
4934 Source := In_Tree.Sources.Table (Source).Other_Part;
4938 if Source /= No_Source then
4939 if In_Tree.Sources.Table (Source).Project /= Project
4943 In_Tree.Sources.Table (Source).Project,
4946 Source := No_Source;
4950 if Source = No_Source then
4953 "%% is not an unit of this project",
4954 In_Tree.String_Elements.Table
4955 (Interfaces).Location);
4958 if In_Tree.Sources.Table (Source).Kind = Spec and then
4959 In_Tree.Sources.Table (Source).Other_Part /=
4963 In_Tree.Sources.Table (Source).Other_Part;
4966 String_Element_Table.Increment_Last
4967 (In_Tree.String_Elements);
4968 In_Tree.String_Elements.Table
4969 (String_Element_Table.Last
4970 (In_Tree.String_Elements)) :=
4972 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4975 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4977 In_Tree.String_Elements.Table
4978 (Interfaces).Location,
4980 Next => Interface_ALIs);
4981 Interface_ALIs := String_Element_Table.Last
4982 (In_Tree.String_Elements);
4990 In_Tree.String_Elements.Table (Interfaces).Next;
4993 -- Put the list of Interface ALIs in the project data
4995 Data.Lib_Interface_ALIs := Interface_ALIs;
4997 -- Check value of attribute Library_Auto_Init and set
4998 -- Lib_Auto_Init accordingly.
5000 if Lib_Auto_Init.Default then
5002 -- If no attribute Library_Auto_Init is declared, then set auto
5003 -- init only if it is supported.
5005 Data.Lib_Auto_Init := Auto_Init_Supported;
5008 Get_Name_String (Lib_Auto_Init.Value);
5009 To_Lower (Name_Buffer (1 .. Name_Len));
5011 if Name_Buffer (1 .. Name_Len) = "false" then
5012 Data.Lib_Auto_Init := False;
5014 elsif Name_Buffer (1 .. Name_Len) = "true" then
5015 if Auto_Init_Supported then
5016 Data.Lib_Auto_Init := True;
5019 -- Library_Auto_Init cannot be "true" if auto init is not
5024 "library auto init not supported " &
5026 Lib_Auto_Init.Location);
5032 "invalid value for attribute Library_Auto_Init",
5033 Lib_Auto_Init.Location);
5038 -- If attribute Library_Src_Dir is defined and not the empty string,
5039 -- check if the directory exist and is not the object directory or
5040 -- one of the source directories. This is the directory where copies
5041 -- of the interface sources will be copied. Note that this directory
5042 -- may be the library directory.
5044 if Lib_Src_Dir.Value /= Empty_String then
5046 Dir_Id : constant File_Name_Type :=
5047 File_Name_Type (Lib_Src_Dir.Value);
5054 Data.Display_Directory,
5055 Data.Library_Src_Dir,
5056 Data.Display_Library_Src_Dir,
5057 Create => "library source copy",
5058 Current_Dir => Current_Dir,
5059 Location => Lib_Src_Dir.Location);
5061 -- If directory does not exist, report an error
5063 if Data.Library_Src_Dir = No_Path then
5065 -- Get the absolute name of the library directory that does
5066 -- not exist, to report an error.
5069 Dir_Name : constant String :=
5070 Get_Name_String (Dir_Id);
5073 if Is_Absolute_Path (Dir_Name) then
5074 Err_Vars.Error_Msg_File_1 := Dir_Id;
5077 Get_Name_String (Data.Directory);
5079 if Name_Buffer (Name_Len) /=
5082 Name_Len := Name_Len + 1;
5083 Name_Buffer (Name_Len) :=
5084 Directory_Separator;
5089 Name_Len + Dir_Name'Length) :=
5091 Name_Len := Name_Len + Dir_Name'Length;
5092 Err_Vars.Error_Msg_Name_1 := Name_Find;
5097 Error_Msg_File_1 := Dir_Id;
5100 "Directory { does not exist",
5101 Lib_Src_Dir.Location);
5104 -- Report error if it is the same as the object directory
5106 elsif Data.Library_Src_Dir = Data.Object_Directory then
5109 "directory to copy interfaces cannot be " &
5110 "the object directory",
5111 Lib_Src_Dir.Location);
5112 Data.Library_Src_Dir := No_Path;
5116 Src_Dirs : String_List_Id;
5117 Src_Dir : String_Element;
5120 -- Interface copy directory cannot be one of the source
5121 -- directory of the current project.
5123 Src_Dirs := Data.Source_Dirs;
5124 while Src_Dirs /= Nil_String loop
5125 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5127 -- Report error if it is one of the source directories
5129 if Data.Library_Src_Dir =
5130 Path_Name_Type (Src_Dir.Value)
5134 "directory to copy interfaces cannot " &
5135 "be one of the source directories",
5136 Lib_Src_Dir.Location);
5137 Data.Library_Src_Dir := No_Path;
5141 Src_Dirs := Src_Dir.Next;
5144 if Data.Library_Src_Dir /= No_Path then
5146 -- It cannot be a source directory of any other
5149 Project_Loop : for Pid in 1 ..
5150 Project_Table.Last (In_Tree.Projects)
5153 In_Tree.Projects.Table (Pid).Source_Dirs;
5154 Dir_Loop : while Src_Dirs /= Nil_String loop
5156 In_Tree.String_Elements.Table (Src_Dirs);
5158 -- Report error if it is one of the source
5161 if Data.Library_Src_Dir =
5162 Path_Name_Type (Src_Dir.Value)
5165 File_Name_Type (Src_Dir.Value);
5167 In_Tree.Projects.Table (Pid).Name;
5170 "directory to copy interfaces cannot " &
5171 "be the same as source directory { of " &
5173 Lib_Src_Dir.Location);
5174 Data.Library_Src_Dir := No_Path;
5178 Src_Dirs := Src_Dir.Next;
5180 end loop Project_Loop;
5184 -- In high verbosity, if there is a valid Library_Src_Dir,
5185 -- display its path name.
5187 if Data.Library_Src_Dir /= No_Path
5188 and then Current_Verbosity = High
5190 Write_Str ("Directory to copy interfaces =""");
5191 Write_Str (Get_Name_String (Data.Library_Src_Dir));
5198 -- Check the symbol related attributes
5200 -- First, the symbol policy
5202 if not Lib_Symbol_Policy.Default then
5204 Value : constant String :=
5206 (Get_Name_String (Lib_Symbol_Policy.Value));
5209 -- Symbol policy must hove one of a limited number of values
5211 if Value = "autonomous" or else Value = "default" then
5212 Data.Symbol_Data.Symbol_Policy := Autonomous;
5214 elsif Value = "compliant" then
5215 Data.Symbol_Data.Symbol_Policy := Compliant;
5217 elsif Value = "controlled" then
5218 Data.Symbol_Data.Symbol_Policy := Controlled;
5220 elsif Value = "restricted" then
5221 Data.Symbol_Data.Symbol_Policy := Restricted;
5223 elsif Value = "direct" then
5224 Data.Symbol_Data.Symbol_Policy := Direct;
5229 "illegal value for Library_Symbol_Policy",
5230 Lib_Symbol_Policy.Location);
5235 -- If attribute Library_Symbol_File is not specified, symbol policy
5236 -- cannot be Restricted.
5238 if Lib_Symbol_File.Default then
5239 if Data.Symbol_Data.Symbol_Policy = Restricted then
5242 "Library_Symbol_File needs to be defined when " &
5243 "symbol policy is Restricted",
5244 Lib_Symbol_Policy.Location);
5248 -- Library_Symbol_File is defined
5250 Data.Symbol_Data.Symbol_File :=
5251 Path_Name_Type (Lib_Symbol_File.Value);
5253 Get_Name_String (Lib_Symbol_File.Value);
5255 if Name_Len = 0 then
5258 "symbol file name cannot be an empty string",
5259 Lib_Symbol_File.Location);
5262 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5265 for J in 1 .. Name_Len loop
5266 if Name_Buffer (J) = '/'
5267 or else Name_Buffer (J) = Directory_Separator
5276 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5279 "symbol file name { is illegal. " &
5280 "Name cannot include directory info.",
5281 Lib_Symbol_File.Location);
5286 -- If attribute Library_Reference_Symbol_File is not defined,
5287 -- symbol policy cannot be Compliant or Controlled.
5289 if Lib_Ref_Symbol_File.Default then
5290 if Data.Symbol_Data.Symbol_Policy = Compliant
5291 or else Data.Symbol_Data.Symbol_Policy = Controlled
5295 "a reference symbol file need to be defined",
5296 Lib_Symbol_Policy.Location);
5300 -- Library_Reference_Symbol_File is defined, check file exists
5302 Data.Symbol_Data.Reference :=
5303 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5305 Get_Name_String (Lib_Ref_Symbol_File.Value);
5307 if Name_Len = 0 then
5310 "reference symbol file name cannot be an empty string",
5311 Lib_Symbol_File.Location);
5314 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5316 Add_Str_To_Name_Buffer (Get_Name_String (Data.Directory));
5317 Add_Char_To_Name_Buffer (Directory_Separator);
5318 Add_Str_To_Name_Buffer
5319 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5320 Data.Symbol_Data.Reference := Name_Find;
5323 if not Is_Regular_File
5324 (Get_Name_String (Data.Symbol_Data.Reference))
5327 File_Name_Type (Lib_Ref_Symbol_File.Value);
5329 -- For controlled and direct symbol policies, it is an error
5330 -- if the reference symbol file does not exist. For other
5331 -- symbol policies, this is just a warning
5334 Data.Symbol_Data.Symbol_Policy /= Controlled
5335 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5339 "<library reference symbol file { does not exist",
5340 Lib_Ref_Symbol_File.Location);
5342 -- In addition in the non-controlled case, if symbol policy
5343 -- is Compliant, it is changed to Autonomous, because there
5344 -- is no reference to check against, and we don't want to
5345 -- fail in this case.
5347 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5348 if Data.Symbol_Data.Symbol_Policy = Compliant then
5349 Data.Symbol_Data.Symbol_Policy := Autonomous;
5354 -- If both the reference symbol file and the symbol file are
5355 -- defined, then check that they are not the same file.
5357 if Data.Symbol_Data.Symbol_File /= No_Path then
5358 Get_Name_String (Data.Symbol_Data.Symbol_File);
5360 if Name_Len > 0 then
5362 Symb_Path : constant String :=
5365 (Data.Object_Directory) &
5366 Directory_Separator &
5367 Name_Buffer (1 .. Name_Len),
5368 Directory => Current_Dir,
5370 Opt.Follow_Links_For_Files);
5371 Ref_Path : constant String :=
5374 (Data.Symbol_Data.Reference),
5375 Directory => Current_Dir,
5377 Opt.Follow_Links_For_Files);
5379 if Symb_Path = Ref_Path then
5382 "library reference symbol file and library" &
5383 " symbol file cannot be the same file",
5384 Lib_Ref_Symbol_File.Location);
5392 end Check_Stand_Alone_Library;
5394 ----------------------------
5395 -- Compute_Directory_Last --
5396 ----------------------------
5398 function Compute_Directory_Last (Dir : String) return Natural is
5401 and then (Dir (Dir'Last - 1) = Directory_Separator
5402 or else Dir (Dir'Last - 1) = '/')
5404 return Dir'Last - 1;
5408 end Compute_Directory_Last;
5415 (Project : Project_Id;
5416 In_Tree : Project_Tree_Ref;
5418 Flag_Location : Source_Ptr)
5420 Real_Location : Source_Ptr := Flag_Location;
5421 Error_Buffer : String (1 .. 5_000);
5422 Error_Last : Natural := 0;
5423 Name_Number : Natural := 0;
5424 File_Number : Natural := 0;
5425 First : Positive := Msg'First;
5428 procedure Add (C : Character);
5429 -- Add a character to the buffer
5431 procedure Add (S : String);
5432 -- Add a string to the buffer
5435 -- Add a name to the buffer
5438 -- Add a file name to the buffer
5444 procedure Add (C : Character) is
5446 Error_Last := Error_Last + 1;
5447 Error_Buffer (Error_Last) := C;
5450 procedure Add (S : String) is
5452 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5453 Error_Last := Error_Last + S'Length;
5460 procedure Add_File is
5461 File : File_Name_Type;
5465 File_Number := File_Number + 1;
5469 File := Err_Vars.Error_Msg_File_1;
5471 File := Err_Vars.Error_Msg_File_2;
5473 File := Err_Vars.Error_Msg_File_3;
5478 Get_Name_String (File);
5479 Add (Name_Buffer (1 .. Name_Len));
5487 procedure Add_Name is
5492 Name_Number := Name_Number + 1;
5496 Name := Err_Vars.Error_Msg_Name_1;
5498 Name := Err_Vars.Error_Msg_Name_2;
5500 Name := Err_Vars.Error_Msg_Name_3;
5505 Get_Name_String (Name);
5506 Add (Name_Buffer (1 .. Name_Len));
5510 -- Start of processing for Error_Msg
5513 -- If location of error is unknown, use the location of the project
5515 if Real_Location = No_Location then
5516 Real_Location := In_Tree.Projects.Table (Project).Location;
5519 if Error_Report = null then
5520 Prj.Err.Error_Msg (Msg, Real_Location);
5524 -- Ignore continuation character
5526 if Msg (First) = '\' then
5529 -- Warning character is always the first one in this package
5530 -- this is an undocumented kludge???
5532 elsif Msg (First) = '?' then
5536 elsif Msg (First) = '<' then
5539 if Err_Vars.Error_Msg_Warn then
5545 while Index <= Msg'Last loop
5546 if Msg (Index) = '{' then
5549 elsif Msg (Index) = '%' then
5550 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5562 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5565 ----------------------
5566 -- Find_Ada_Sources --
5567 ----------------------
5569 procedure Find_Ada_Sources
5570 (Project : Project_Id;
5571 In_Tree : Project_Tree_Ref;
5572 Data : in out Project_Data;
5573 Current_Dir : String)
5575 Source_Dir : String_List_Id := Data.Source_Dirs;
5576 Element : String_Element;
5578 Current_Source : String_List_Id := Nil_String;
5579 Source_Recorded : Boolean := False;
5582 if Current_Verbosity = High then
5583 Write_Line ("Looking for sources:");
5586 -- For each subdirectory
5588 while Source_Dir /= Nil_String loop
5590 Source_Recorded := False;
5591 Element := In_Tree.String_Elements.Table (Source_Dir);
5592 if Element.Value /= No_Name then
5593 Get_Name_String (Element.Display_Value);
5596 Source_Directory : constant String :=
5597 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5598 Dir_Last : constant Natural :=
5599 Compute_Directory_Last (Source_Directory);
5602 if Current_Verbosity = High then
5603 Write_Str ("Source_Dir = ");
5604 Write_Line (Source_Directory);
5607 -- We look at every entry in the source directory
5610 Source_Directory (Source_Directory'First .. Dir_Last));
5613 Read (Dir, Name_Buffer, Name_Len);
5615 if Current_Verbosity = High then
5616 Write_Str (" Checking ");
5617 Write_Line (Name_Buffer (1 .. Name_Len));
5620 exit when Name_Len = 0;
5623 File_Name : constant File_Name_Type := Name_Find;
5625 -- ??? We could probably optimize the following call:
5626 -- we need to resolve links only once for the
5627 -- directory itself, and then do a single call to
5628 -- readlink() for each file. Unfortunately that would
5629 -- require a change in Normalize_Pathname so that it
5630 -- has the option of not resolving links for its
5631 -- Directory parameter, only for Name.
5633 Path : constant String :=
5635 (Name => Name_Buffer (1 .. Name_Len),
5638 (Source_Directory'First .. Dir_Last),
5640 Opt.Follow_Links_For_Files,
5641 Case_Sensitive => True);
5643 Path_Name : Path_Name_Type;
5646 Name_Len := Path'Length;
5647 Name_Buffer (1 .. Name_Len) := Path;
5648 Path_Name := Name_Find;
5650 -- We attempt to register it as a source. However,
5651 -- there is no error if the file does not contain a
5652 -- valid source. But there is an error if we have a
5653 -- duplicate unit name.
5656 (File_Name => File_Name,
5657 Path_Name => Path_Name,
5661 Location => No_Location,
5662 Current_Source => Current_Source,
5663 Source_Recorded => Source_Recorded,
5664 Current_Dir => Current_Dir);
5673 when Directory_Error =>
5677 if Source_Recorded then
5678 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5682 Source_Dir := Element.Next;
5685 if Current_Verbosity = High then
5686 Write_Line ("end Looking for sources.");
5689 end Find_Ada_Sources;
5695 procedure Find_Sources
5696 (Project : Project_Id;
5697 In_Tree : Project_Tree_Ref;
5698 Data : in out Project_Data;
5699 For_Language : Language_Index;
5700 Current_Dir : String)
5702 Source_Dir : String_List_Id;
5703 Element : String_Element;
5705 Current_Source : String_List_Id := Nil_String;
5706 Source_Recorded : Boolean := False;
5709 if Current_Verbosity = High then
5710 Write_Line ("Looking for sources:");
5713 -- Loop through subdirectories
5715 Source_Dir := Data.Source_Dirs;
5716 while Source_Dir /= Nil_String loop
5718 Source_Recorded := False;
5719 Element := In_Tree.String_Elements.Table (Source_Dir);
5721 if Element.Value /= No_Name then
5722 Get_Name_String (Element.Display_Value);
5725 Source_Directory : constant String :=
5726 Name_Buffer (1 .. Name_Len) &
5727 Directory_Separator;
5729 Dir_Last : constant Natural :=
5730 Compute_Directory_Last (Source_Directory);
5733 if Current_Verbosity = High then
5734 Write_Str ("Source_Dir = ");
5735 Write_Line (Source_Directory);
5738 -- We look to every entry in the source directory
5740 Open (Dir, Source_Directory
5741 (Source_Directory'First .. Dir_Last));
5744 Read (Dir, Name_Buffer, Name_Len);
5746 if Current_Verbosity = High then
5747 Write_Str (" Checking ");
5748 Write_Line (Name_Buffer (1 .. Name_Len));
5751 exit when Name_Len = 0;
5754 File_Name : constant File_Name_Type := Name_Find;
5755 Path : constant String :=
5757 (Name => Name_Buffer (1 .. Name_Len),
5758 Directory => Source_Directory
5759 (Source_Directory'First .. Dir_Last),
5760 Resolve_Links => Opt.Follow_Links_For_Files,
5761 Case_Sensitive => True);
5762 Path_Name : Path_Name_Type;
5765 Name_Len := Path'Length;
5766 Name_Buffer (1 .. Name_Len) := Path;
5767 Path_Name := Name_Find;
5769 if For_Language = Ada_Language_Index then
5771 -- We attempt to register it as a source. However,
5772 -- there is no error if the file does not contain
5773 -- a valid source. But there is an error if we have
5774 -- a duplicate unit name.
5777 (File_Name => File_Name,
5778 Path_Name => Path_Name,
5782 Location => No_Location,
5783 Current_Source => Current_Source,
5784 Source_Recorded => Source_Recorded,
5785 Current_Dir => Current_Dir);
5789 (File_Name => File_Name,
5790 Path_Name => Path_Name,
5794 Location => No_Location,
5795 Language => For_Language,
5797 Body_Suffix_Of (For_Language, Data, In_Tree),
5798 Naming_Exception => False);
5808 when Directory_Error =>
5812 if Source_Recorded then
5813 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5817 Source_Dir := Element.Next;
5820 if Current_Verbosity = High then
5821 Write_Line ("end Looking for sources.");
5824 if For_Language = Ada_Language_Index then
5826 -- If we have looked for sources and found none, then it is an error,
5827 -- except if it is an extending project. If a non extending project
5828 -- is not supposed to contain any source files, then never call
5831 if Current_Source /= Nil_String then
5832 Data.Ada_Sources_Present := True;
5834 elsif Data.Extends = No_Project then
5835 Report_No_Sources (Project, "Ada", In_Tree, Data.Location);
5840 --------------------------------
5841 -- Free_Ada_Naming_Exceptions --
5842 --------------------------------
5844 procedure Free_Ada_Naming_Exceptions is
5846 Ada_Naming_Exception_Table.Set_Last (0);
5847 Ada_Naming_Exceptions.Reset;
5848 Reverse_Ada_Naming_Exceptions.Reset;
5849 end Free_Ada_Naming_Exceptions;
5851 ---------------------
5852 -- Get_Directories --
5853 ---------------------
5855 procedure Get_Directories
5856 (Project : Project_Id;
5857 In_Tree : Project_Tree_Ref;
5858 Current_Dir : String;
5859 Data : in out Project_Data)
5861 Object_Dir : constant Variable_Value :=
5863 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5865 Exec_Dir : constant Variable_Value :=
5867 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5869 Source_Dirs : constant Variable_Value :=
5871 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5873 Excluded_Source_Dirs : constant Variable_Value :=
5875 (Name_Excluded_Source_Dirs,
5876 Data.Decl.Attributes,
5879 Source_Files : constant Variable_Value :=
5881 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5883 Last_Source_Dir : String_List_Id := Nil_String;
5885 procedure Find_Source_Dirs
5886 (From : File_Name_Type;
5887 Location : Source_Ptr;
5888 Removed : Boolean := False);
5889 -- Find one or several source directories, and add (or remove, if
5890 -- Removed is True) them to list of source directories of the project.
5892 ----------------------
5893 -- Find_Source_Dirs --
5894 ----------------------
5896 procedure Find_Source_Dirs
5897 (From : File_Name_Type;
5898 Location : Source_Ptr;
5899 Removed : Boolean := False)
5901 Directory : constant String := Get_Name_String (From);
5902 Element : String_Element;
5904 procedure Recursive_Find_Dirs (Path : Name_Id);
5905 -- Find all the subdirectories (recursively) of Path and add them
5906 -- to the list of source directories of the project.
5908 -------------------------
5909 -- Recursive_Find_Dirs --
5910 -------------------------
5912 procedure Recursive_Find_Dirs (Path : Name_Id) is
5914 Name : String (1 .. 250);
5916 List : String_List_Id;
5917 Prev : String_List_Id;
5918 Element : String_Element;
5919 Found : Boolean := False;
5921 Non_Canonical_Path : Name_Id := No_Name;
5922 Canonical_Path : Name_Id := No_Name;
5924 The_Path : constant String :=
5926 (Get_Name_String (Path),
5927 Directory => Current_Dir,
5928 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5929 Directory_Separator;
5931 The_Path_Last : constant Natural :=
5932 Compute_Directory_Last (The_Path);
5935 Name_Len := The_Path_Last - The_Path'First + 1;
5936 Name_Buffer (1 .. Name_Len) :=
5937 The_Path (The_Path'First .. The_Path_Last);
5938 Non_Canonical_Path := Name_Find;
5940 if Osint.File_Names_Case_Sensitive then
5941 Canonical_Path := Non_Canonical_Path;
5943 Get_Name_String (Non_Canonical_Path);
5944 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5945 Canonical_Path := Name_Find;
5948 -- To avoid processing the same directory several times, check
5949 -- if the directory is already in Recursive_Dirs. If it is, then
5950 -- there is nothing to do, just return. If it is not, put it there
5951 -- and continue recursive processing.
5954 if Recursive_Dirs.Get (Canonical_Path) then
5957 Recursive_Dirs.Set (Canonical_Path, True);
5961 -- Check if directory is already in list
5963 List := Data.Source_Dirs;
5965 while List /= Nil_String loop
5966 Element := In_Tree.String_Elements.Table (List);
5968 if Element.Value /= No_Name then
5969 Found := Element.Value = Canonical_Path;
5974 List := Element.Next;
5977 -- If directory is not already in list, put it there
5979 if (not Removed) and (not Found) then
5980 if Current_Verbosity = High then
5982 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5985 String_Element_Table.Increment_Last
5986 (In_Tree.String_Elements);
5988 (Value => Canonical_Path,
5989 Display_Value => Non_Canonical_Path,
5990 Location => No_Location,
5995 -- Case of first source directory
5997 if Last_Source_Dir = Nil_String then
5998 Data.Source_Dirs := String_Element_Table.Last
5999 (In_Tree.String_Elements);
6001 -- Here we already have source directories
6004 -- Link the previous last to the new one
6006 In_Tree.String_Elements.Table
6007 (Last_Source_Dir).Next :=
6008 String_Element_Table.Last
6009 (In_Tree.String_Elements);
6012 -- And register this source directory as the new last
6014 Last_Source_Dir := String_Element_Table.Last
6015 (In_Tree.String_Elements);
6016 In_Tree.String_Elements.Table (Last_Source_Dir) :=
6019 elsif Removed and Found then
6020 if Prev = Nil_String then
6022 In_Tree.String_Elements.Table (List).Next;
6024 In_Tree.String_Elements.Table (Prev).Next :=
6025 In_Tree.String_Elements.Table (List).Next;
6029 -- Now look for subdirectories. We do that even when this
6030 -- directory is already in the list, because some of its
6031 -- subdirectories may not be in the list yet.
6033 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
6036 Read (Dir, Name, Last);
6039 if Name (1 .. Last) /= "."
6040 and then Name (1 .. Last) /= ".."
6042 -- Avoid . and .. directories
6044 if Current_Verbosity = High then
6045 Write_Str (" Checking ");
6046 Write_Line (Name (1 .. Last));
6050 Path_Name : constant String :=
6052 (Name => Name (1 .. Last),
6054 The_Path (The_Path'First .. The_Path_Last),
6055 Resolve_Links => Opt.Follow_Links_For_Dirs,
6056 Case_Sensitive => True);
6059 if Is_Directory (Path_Name) then
6060 -- We have found a new subdirectory, call self
6062 Name_Len := Path_Name'Length;
6063 Name_Buffer (1 .. Name_Len) := Path_Name;
6064 Recursive_Find_Dirs (Name_Find);
6073 when Directory_Error =>
6075 end Recursive_Find_Dirs;
6077 -- Start of processing for Find_Source_Dirs
6080 if Current_Verbosity = High and then not Removed then
6081 Write_Str ("Find_Source_Dirs (""");
6082 Write_Str (Directory);
6086 -- First, check if we are looking for a directory tree, indicated
6087 -- by "/**" at the end.
6089 if Directory'Length >= 3
6090 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
6091 and then (Directory (Directory'Last - 2) = '/'
6093 Directory (Directory'Last - 2) = Directory_Separator)
6096 Data.Known_Order_Of_Source_Dirs := False;
6099 Name_Len := Directory'Length - 3;
6101 if Name_Len = 0 then
6103 -- Case of "/**": all directories in file system
6106 Name_Buffer (1) := Directory (Directory'First);
6109 Name_Buffer (1 .. Name_Len) :=
6110 Directory (Directory'First .. Directory'Last - 3);
6113 if Current_Verbosity = High then
6114 Write_Str ("Looking for all subdirectories of """);
6115 Write_Str (Name_Buffer (1 .. Name_Len));
6120 Base_Dir : constant File_Name_Type := Name_Find;
6121 Root_Dir : constant String :=
6123 (Name => Get_Name_String (Base_Dir),
6125 Get_Name_String (Data.Display_Directory),
6126 Resolve_Links => False,
6127 Case_Sensitive => True);
6130 if Root_Dir'Length = 0 then
6131 Err_Vars.Error_Msg_File_1 := Base_Dir;
6133 if Location = No_Location then
6136 "{ is not a valid directory.",
6141 "{ is not a valid directory.",
6146 -- We have an existing directory, we register it and all of
6147 -- its subdirectories.
6149 if Current_Verbosity = High then
6150 Write_Line ("Looking for source directories:");
6153 Name_Len := Root_Dir'Length;
6154 Name_Buffer (1 .. Name_Len) := Root_Dir;
6155 Recursive_Find_Dirs (Name_Find);
6157 if Current_Verbosity = High then
6158 Write_Line ("End of looking for source directories.");
6163 -- We have a single directory
6167 Path_Name : Path_Name_Type;
6168 Display_Path_Name : Path_Name_Type;
6169 List : String_List_Id;
6170 Prev : String_List_Id;
6174 (Project => Project,
6177 Parent => Data.Display_Directory,
6179 Display => Display_Path_Name,
6180 Current_Dir => Current_Dir);
6182 if Path_Name = No_Path then
6183 Err_Vars.Error_Msg_File_1 := From;
6185 if Location = No_Location then
6188 "{ is not a valid directory",
6193 "{ is not a valid directory",
6199 Path : constant String :=
6200 Get_Name_String (Path_Name) &
6201 Directory_Separator;
6202 Last_Path : constant Natural :=
6203 Compute_Directory_Last (Path);
6205 Display_Path : constant String :=
6207 (Display_Path_Name) &
6208 Directory_Separator;
6209 Last_Display_Path : constant Natural :=
6210 Compute_Directory_Last
6212 Display_Path_Id : Name_Id;
6216 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6217 Path_Id := Name_Find;
6219 Add_Str_To_Name_Buffer
6221 (Display_Path'First .. Last_Display_Path));
6222 Display_Path_Id := Name_Find;
6226 -- As it is an existing directory, we add it to the
6227 -- list of directories.
6229 String_Element_Table.Increment_Last
6230 (In_Tree.String_Elements);
6234 Display_Value => Display_Path_Id,
6235 Location => No_Location,
6237 Next => Nil_String);
6239 if Last_Source_Dir = Nil_String then
6241 -- This is the first source directory
6243 Data.Source_Dirs := String_Element_Table.Last
6244 (In_Tree.String_Elements);
6247 -- We already have source directories, link the
6248 -- previous last to the new one.
6250 In_Tree.String_Elements.Table
6251 (Last_Source_Dir).Next :=
6252 String_Element_Table.Last
6253 (In_Tree.String_Elements);
6256 -- And register this source directory as the new last
6258 Last_Source_Dir := String_Element_Table.Last
6259 (In_Tree.String_Elements);
6260 In_Tree.String_Elements.Table
6261 (Last_Source_Dir) := Element;
6264 -- Remove source dir, if present
6266 List := Data.Source_Dirs;
6269 -- Look for source dir in current list
6271 while List /= Nil_String loop
6272 Element := In_Tree.String_Elements.Table (List);
6273 exit when Element.Value = Path_Id;
6275 List := Element.Next;
6278 if List /= Nil_String then
6279 -- Source dir was found, remove it from the list
6281 if Prev = Nil_String then
6283 In_Tree.String_Elements.Table (List).Next;
6286 In_Tree.String_Elements.Table (Prev).Next :=
6287 In_Tree.String_Elements.Table (List).Next;
6295 end Find_Source_Dirs;
6297 -- Start of processing for Get_Directories
6300 if Current_Verbosity = High then
6301 Write_Line ("Starting to look for directories");
6304 -- Check the object directory
6306 pragma Assert (Object_Dir.Kind = Single,
6307 "Object_Dir is not a single string");
6309 -- We set the object directory to its default
6311 Data.Object_Directory := Data.Directory;
6312 Data.Display_Object_Dir := Data.Display_Directory;
6314 if Object_Dir.Value /= Empty_String then
6315 Get_Name_String (Object_Dir.Value);
6317 if Name_Len = 0 then
6320 "Object_Dir cannot be empty",
6321 Object_Dir.Location);
6324 -- We check that the specified object directory does exist
6329 File_Name_Type (Object_Dir.Value),
6330 Data.Display_Directory,
6331 Data.Object_Directory,
6332 Data.Display_Object_Dir,
6334 Location => Object_Dir.Location,
6335 Current_Dir => Current_Dir);
6337 if Data.Object_Directory = No_Path then
6339 -- The object directory does not exist, report an error if the
6340 -- project is not externally built.
6342 if not Data.Externally_Built then
6343 Err_Vars.Error_Msg_File_1 :=
6344 File_Name_Type (Object_Dir.Value);
6347 "the object directory { cannot be found",
6351 -- Do not keep a nil Object_Directory. Set it to the specified
6352 -- (relative or absolute) path. This is for the benefit of
6353 -- tools that recover from errors; for example, these tools
6354 -- could create the non existent directory.
6356 Data.Display_Object_Dir := Path_Name_Type (Object_Dir.Value);
6358 if Osint.File_Names_Case_Sensitive then
6359 Data.Object_Directory := Path_Name_Type (Object_Dir.Value);
6361 Get_Name_String (Object_Dir.Value);
6362 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6363 Data.Object_Directory := Name_Find;
6368 elsif Subdirs /= null then
6370 Name_Buffer (1) := '.';
6375 Data.Display_Directory,
6376 Data.Object_Directory,
6377 Data.Display_Object_Dir,
6379 Location => Object_Dir.Location,
6380 Current_Dir => Current_Dir);
6383 if Current_Verbosity = High then
6384 if Data.Object_Directory = No_Path then
6385 Write_Line ("No object directory");
6387 Write_Str ("Object directory: """);
6388 Write_Str (Get_Name_String (Data.Display_Object_Dir));
6393 -- Check the exec directory
6395 pragma Assert (Exec_Dir.Kind = Single,
6396 "Exec_Dir is not a single string");
6398 -- We set the object directory to its default
6400 Data.Exec_Directory := Data.Object_Directory;
6401 Data.Display_Exec_Dir := Data.Display_Object_Dir;
6403 if Exec_Dir.Value /= Empty_String then
6404 Get_Name_String (Exec_Dir.Value);
6406 if Name_Len = 0 then
6409 "Exec_Dir cannot be empty",
6413 -- We check that the specified exec directory does exist
6418 File_Name_Type (Exec_Dir.Value),
6419 Data.Display_Directory,
6420 Data.Exec_Directory,
6421 Data.Display_Exec_Dir,
6423 Location => Exec_Dir.Location,
6424 Current_Dir => Current_Dir);
6426 if Data.Exec_Directory = No_Path then
6427 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6430 "the exec directory { cannot be found",
6436 if Current_Verbosity = High then
6437 if Data.Exec_Directory = No_Path then
6438 Write_Line ("No exec directory");
6440 Write_Str ("Exec directory: """);
6441 Write_Str (Get_Name_String (Data.Display_Exec_Dir));
6446 -- Look for the source directories
6448 if Current_Verbosity = High then
6449 Write_Line ("Starting to look for source directories");
6452 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6454 if (not Source_Files.Default) and then
6455 Source_Files.Values = Nil_String
6457 Data.Source_Dirs := Nil_String;
6459 if Data.Qualifier = Standard then
6463 "a standard project cannot have no sources",
6464 Source_Files.Location);
6467 if Data.Extends = No_Project
6468 and then Data.Object_Directory = Data.Directory
6470 Data.Object_Directory := No_Path;
6473 elsif Source_Dirs.Default then
6475 -- No Source_Dirs specified: the single source directory is the one
6476 -- containing the project file
6478 String_Element_Table.Increment_Last
6479 (In_Tree.String_Elements);
6480 Data.Source_Dirs := String_Element_Table.Last
6481 (In_Tree.String_Elements);
6482 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6483 (Value => Name_Id (Data.Directory),
6484 Display_Value => Name_Id (Data.Display_Directory),
6485 Location => No_Location,
6490 if Current_Verbosity = High then
6491 Write_Line ("Single source directory:");
6493 Write_Str (Get_Name_String (Data.Display_Directory));
6497 elsif Source_Dirs.Values = Nil_String then
6498 if Data.Qualifier = Standard then
6502 "a standard project cannot have no source directories",
6503 Source_Dirs.Location);
6506 -- If Source_Dirs is an empty string list, this means that this
6507 -- project contains no source. For projects that don't extend other
6508 -- projects, this also means that there is no need for an object
6509 -- directory, if not specified.
6511 if Data.Extends = No_Project
6512 and then Data.Object_Directory = Data.Directory
6514 Data.Object_Directory := No_Path;
6517 Data.Source_Dirs := Nil_String;
6521 Source_Dir : String_List_Id;
6522 Element : String_Element;
6525 -- Process the source directories for each element of the list
6527 Source_Dir := Source_Dirs.Values;
6528 while Source_Dir /= Nil_String loop
6530 In_Tree.String_Elements.Table (Source_Dir);
6532 (File_Name_Type (Element.Value), Element.Location);
6533 Source_Dir := Element.Next;
6538 if not Excluded_Source_Dirs.Default
6539 and then Excluded_Source_Dirs.Values /= Nil_String
6542 Source_Dir : String_List_Id;
6543 Element : String_Element;
6546 -- Process the source directories for each element of the list
6548 Source_Dir := Excluded_Source_Dirs.Values;
6549 while Source_Dir /= Nil_String loop
6551 In_Tree.String_Elements.Table (Source_Dir);
6553 (File_Name_Type (Element.Value),
6556 Source_Dir := Element.Next;
6561 if Current_Verbosity = High then
6562 Write_Line ("Putting source directories in canonical cases");
6566 Current : String_List_Id := Data.Source_Dirs;
6567 Element : String_Element;
6570 while Current /= Nil_String loop
6571 Element := In_Tree.String_Elements.Table (Current);
6572 if Element.Value /= No_Name then
6573 if not Osint.File_Names_Case_Sensitive then
6574 Get_Name_String (Element.Value);
6575 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6576 Element.Value := Name_Find;
6579 In_Tree.String_Elements.Table (Current) := Element;
6582 Current := Element.Next;
6586 end Get_Directories;
6593 (Project : Project_Id;
6594 In_Tree : Project_Tree_Ref;
6595 Data : in out Project_Data)
6597 Mains : constant Variable_Value :=
6598 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6601 Data.Mains := Mains.Values;
6603 -- If no Mains were specified, and if we are an extending project,
6604 -- inherit the Mains from the project we are extending.
6606 if Mains.Default then
6607 if Data.Extends /= No_Project then
6609 In_Tree.Projects.Table (Data.Extends).Mains;
6612 -- In a library project file, Main cannot be specified
6614 elsif Data.Library then
6617 "a library project file cannot have Main specified",
6622 ---------------------------
6623 -- Get_Sources_From_File --
6624 ---------------------------
6626 procedure Get_Sources_From_File
6628 Location : Source_Ptr;
6629 Project : Project_Id;
6630 In_Tree : Project_Tree_Ref)
6632 File : Prj.Util.Text_File;
6633 Line : String (1 .. 250);
6635 Source_Name : File_Name_Type;
6636 Name_Loc : Name_Location;
6639 if Get_Mode = Ada_Only then
6643 if Current_Verbosity = High then
6644 Write_Str ("Opening """);
6651 Prj.Util.Open (File, Path);
6653 if not Prj.Util.Is_Valid (File) then
6654 Error_Msg (Project, In_Tree, "file does not exist", Location);
6656 -- Read the lines one by one
6658 while not Prj.Util.End_Of_File (File) loop
6659 Prj.Util.Get_Line (File, Line, Last);
6661 -- A non empty, non comment line should contain a file name
6664 and then (Last = 1 or else Line (1 .. 2) /= "--")
6667 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6668 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6669 Source_Name := Name_Find;
6671 -- Check that there is no directory information
6673 for J in 1 .. Last loop
6674 if Line (J) = '/' or else Line (J) = Directory_Separator then
6675 Error_Msg_File_1 := Source_Name;
6679 "file name cannot include directory information ({)",
6685 Name_Loc := Source_Names.Get (Source_Name);
6687 if Name_Loc = No_Name_Location then
6689 (Name => Source_Name,
6690 Location => Location,
6691 Source => No_Source,
6696 Source_Names.Set (Source_Name, Name_Loc);
6700 Prj.Util.Close (File);
6703 end Get_Sources_From_File;
6710 (In_Tree : Project_Tree_Ref;
6711 Canonical_File_Name : File_Name_Type;
6712 Naming : Naming_Data;
6713 Exception_Id : out Ada_Naming_Exception_Id;
6714 Unit_Name : out Name_Id;
6715 Unit_Kind : out Spec_Or_Body;
6716 Needs_Pragma : out Boolean)
6718 Info_Id : Ada_Naming_Exception_Id :=
6719 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6720 VMS_Name : File_Name_Type;
6723 if Info_Id = No_Ada_Naming_Exception then
6724 if Hostparm.OpenVMS then
6725 VMS_Name := Canonical_File_Name;
6726 Get_Name_String (VMS_Name);
6728 if Name_Buffer (Name_Len) = '.' then
6729 Name_Len := Name_Len - 1;
6730 VMS_Name := Name_Find;
6733 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6738 if Info_Id /= No_Ada_Naming_Exception then
6739 Exception_Id := Info_Id;
6740 Unit_Name := No_Name;
6741 Unit_Kind := Specification;
6742 Needs_Pragma := True;
6746 Needs_Pragma := False;
6747 Exception_Id := No_Ada_Naming_Exception;
6749 Get_Name_String (Canonical_File_Name);
6751 -- How about some comments and a name for this declare block ???
6752 -- In fact the whole code below needs more comments ???
6755 File : String := Name_Buffer (1 .. Name_Len);
6756 First : constant Positive := File'First;
6757 Last : Natural := File'Last;
6758 Standard_GNAT : Boolean;
6759 Spec : constant File_Name_Type :=
6760 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6761 Body_Suff : constant File_Name_Type :=
6762 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6765 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6766 and then Body_Suff = Default_Ada_Body_Suffix;
6769 Spec_Suffix : constant String := Get_Name_String (Spec);
6770 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6771 Sep_Suffix : constant String :=
6772 Get_Name_String (Naming.Separate_Suffix);
6774 May_Be_Spec : Boolean;
6775 May_Be_Body : Boolean;
6776 May_Be_Sep : Boolean;
6780 File'Length > Spec_Suffix'Length
6782 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6785 File'Length > Body_Suffix'Length
6787 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6790 File'Length > Sep_Suffix'Length
6792 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6794 -- If two May_Be_ booleans are True, always choose the longer one
6797 if May_Be_Body and then
6798 Spec_Suffix'Length < Body_Suffix'Length
6800 Unit_Kind := Body_Part;
6802 if May_Be_Sep and then
6803 Body_Suffix'Length < Sep_Suffix'Length
6805 Last := Last - Sep_Suffix'Length;
6806 May_Be_Body := False;
6809 Last := Last - Body_Suffix'Length;
6810 May_Be_Sep := False;
6813 elsif May_Be_Sep and then
6814 Spec_Suffix'Length < Sep_Suffix'Length
6816 Unit_Kind := Body_Part;
6817 Last := Last - Sep_Suffix'Length;
6820 Unit_Kind := Specification;
6821 Last := Last - Spec_Suffix'Length;
6824 elsif May_Be_Body then
6825 Unit_Kind := Body_Part;
6827 if May_Be_Sep and then
6828 Body_Suffix'Length < Sep_Suffix'Length
6830 Last := Last - Sep_Suffix'Length;
6831 May_Be_Body := False;
6833 Last := Last - Body_Suffix'Length;
6834 May_Be_Sep := False;
6837 elsif May_Be_Sep then
6838 Unit_Kind := Body_Part;
6839 Last := Last - Sep_Suffix'Length;
6847 -- This is not a source file
6849 Unit_Name := No_Name;
6850 Unit_Kind := Specification;
6852 if Current_Verbosity = High then
6853 Write_Line (" Not a valid file name.");
6858 elsif Current_Verbosity = High then
6860 when Specification =>
6861 Write_Str (" Specification: ");
6862 Write_Line (File (First .. Last + Spec_Suffix'Length));
6866 Write_Str (" Body: ");
6867 Write_Line (File (First .. Last + Body_Suffix'Length));
6870 Write_Str (" Separate: ");
6871 Write_Line (File (First .. Last + Sep_Suffix'Length));
6877 Get_Name_String (Naming.Dot_Replacement);
6879 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6881 if Name_Buffer (1 .. Name_Len) /= "." then
6883 -- If Dot_Replacement is not a single dot, then there should not
6884 -- be any dot in the name.
6886 for Index in First .. Last loop
6887 if File (Index) = '.' then
6888 if Current_Verbosity = High then
6890 (" Not a valid file name (some dot not replaced).");
6893 Unit_Name := No_Name;
6899 -- Replace the substring Dot_Replacement with dots
6902 Index : Positive := First;
6905 while Index <= Last - Name_Len + 1 loop
6907 if File (Index .. Index + Name_Len - 1) =
6908 Name_Buffer (1 .. Name_Len)
6910 File (Index) := '.';
6912 if Name_Len > 1 and then Index < Last then
6913 File (Index + 1 .. Last - Name_Len + 1) :=
6914 File (Index + Name_Len .. Last);
6917 Last := Last - Name_Len + 1;
6925 -- Check if the casing is right
6928 Src : String := File (First .. Last);
6929 Src_Last : Positive := Last;
6932 case Naming.Casing is
6933 when All_Lower_Case =>
6936 Mapping => Lower_Case_Map);
6938 when All_Upper_Case =>
6941 Mapping => Upper_Case_Map);
6943 when Mixed_Case | Unknown =>
6947 if Src /= File (First .. Last) then
6948 if Current_Verbosity = High then
6949 Write_Line (" Not a valid file name (casing).");
6952 Unit_Name := No_Name;
6956 -- We put the name in lower case
6960 Mapping => Lower_Case_Map);
6962 -- In the standard GNAT naming scheme, check for special cases:
6963 -- children or separates of A, G, I or S, and run time sources.
6965 if Standard_GNAT and then Src'Length >= 3 then
6967 S1 : constant Character := Src (Src'First);
6968 S2 : constant Character := Src (Src'First + 1);
6969 S3 : constant Character := Src (Src'First + 2);
6977 -- Children or separates of packages A, G, I or S. These
6978 -- names are x__ ... or x~... (where x is a, g, i, or s).
6979 -- Both versions (x__... and x~...) are allowed in all
6980 -- platforms, because it is not possible to know the
6981 -- platform before processing of the project files.
6983 if S2 = '_' and then S3 = '_' then
6984 Src (Src'First + 1) := '.';
6985 Src_Last := Src_Last - 1;
6986 Src (Src'First + 2 .. Src_Last) :=
6987 Src (Src'First + 3 .. Src_Last + 1);
6990 Src (Src'First + 1) := '.';
6992 -- If it is potentially a run time source, disable
6993 -- filling of the mapping file to avoid warnings.
6996 Set_Mapping_File_Initial_State_To_Empty;
7002 if Current_Verbosity = High then
7004 Write_Line (Src (Src'First .. Src_Last));
7007 -- Now, we check if this name is a valid unit name
7010 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
7020 function Hash (Unit : Unit_Info) return Header_Num is
7022 return Header_Num (Unit.Unit mod 2048);
7025 -----------------------
7026 -- Is_Illegal_Suffix --
7027 -----------------------
7029 function Is_Illegal_Suffix
7031 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
7034 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
7038 -- If dot replacement is a single dot, and first character of suffix is
7041 if Dot_Replacement_Is_A_Single_Dot
7042 and then Suffix (Suffix'First) = '.'
7044 for Index in Suffix'First + 1 .. Suffix'Last loop
7046 -- If there is another dot
7048 if Suffix (Index) = '.' then
7050 -- It is illegal to have a letter following the initial dot
7052 return Is_Letter (Suffix (Suffix'First + 1));
7060 end Is_Illegal_Suffix;
7062 ----------------------
7063 -- Locate_Directory --
7064 ----------------------
7066 procedure Locate_Directory
7067 (Project : Project_Id;
7068 In_Tree : Project_Tree_Ref;
7069 Name : File_Name_Type;
7070 Parent : Path_Name_Type;
7071 Dir : out Path_Name_Type;
7072 Display : out Path_Name_Type;
7073 Create : String := "";
7074 Current_Dir : String;
7075 Location : Source_Ptr := No_Location)
7077 The_Parent : constant String :=
7078 Get_Name_String (Parent) & Directory_Separator;
7080 The_Parent_Last : constant Natural :=
7081 Compute_Directory_Last (The_Parent);
7083 Full_Name : File_Name_Type;
7085 The_Name : File_Name_Type;
7088 Get_Name_String (Name);
7090 -- Add Subdirs.all if it is a directory that may be created and
7091 -- Subdirs is not null;
7093 if Create /= "" and then Subdirs /= null then
7094 if Name_Buffer (Name_Len) /= Directory_Separator then
7095 Add_Char_To_Name_Buffer (Directory_Separator);
7098 Add_Str_To_Name_Buffer (Subdirs.all);
7101 -- Convert '/' to directory separator (for Windows)
7103 for J in 1 .. Name_Len loop
7104 if Name_Buffer (J) = '/' then
7105 Name_Buffer (J) := Directory_Separator;
7109 The_Name := Name_Find;
7111 if Current_Verbosity = High then
7112 Write_Str ("Locate_Directory (""");
7113 Write_Str (Get_Name_String (The_Name));
7114 Write_Str (""", """);
7115 Write_Str (The_Parent);
7122 if Is_Absolute_Path (Get_Name_String (The_Name)) then
7123 Full_Name := The_Name;
7127 Add_Str_To_Name_Buffer
7128 (The_Parent (The_Parent'First .. The_Parent_Last));
7129 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7130 Full_Name := Name_Find;
7134 Full_Path_Name : constant String := Get_Name_String (Full_Name);
7137 if (Setup_Projects or else Subdirs /= null)
7138 and then Create'Length > 0
7139 and then not Is_Directory (Full_Path_Name)
7142 Create_Path (Full_Path_Name);
7144 if not Quiet_Output then
7146 Write_Str (" directory """);
7147 Write_Str (Full_Path_Name);
7148 Write_Line (""" created");
7155 "could not create " & Create &
7156 " directory " & Full_Path_Name,
7161 if Is_Directory (Full_Path_Name) then
7163 Normed : constant String :=
7166 Directory => Current_Dir,
7167 Resolve_Links => False,
7168 Case_Sensitive => True);
7170 Canonical_Path : constant String :=
7173 Directory => Current_Dir,
7175 Opt.Follow_Links_For_Dirs,
7176 Case_Sensitive => False);
7179 Name_Len := Normed'Length;
7180 Name_Buffer (1 .. Name_Len) := Normed;
7181 Display := Name_Find;
7183 Name_Len := Canonical_Path'Length;
7184 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7189 end Locate_Directory;
7191 ---------------------------
7192 -- Find_Excluded_Sources --
7193 ---------------------------
7195 procedure Find_Excluded_Sources
7196 (In_Tree : Project_Tree_Ref;
7197 Data : Project_Data)
7199 Excluded_Sources : Variable_Value;
7200 Current : String_List_Id;
7201 Element : String_Element;
7202 Location : Source_Ptr;
7203 Name : File_Name_Type;
7205 -- If Excluded_Source_Files is not declared, check
7206 -- Locally_Removed_Files.
7210 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7212 if Excluded_Sources.Default then
7215 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7218 Excluded_Sources_Htable.Reset;
7220 -- If there are excluded sources, put them in the table
7222 if not Excluded_Sources.Default then
7223 Current := Excluded_Sources.Values;
7224 while Current /= Nil_String loop
7225 Element := In_Tree.String_Elements.Table (Current);
7227 if Osint.File_Names_Case_Sensitive then
7228 Name := File_Name_Type (Element.Value);
7230 Get_Name_String (Element.Value);
7231 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7235 -- If the element has no location, then use the location
7236 -- of Excluded_Sources to report possible errors.
7238 if Element.Location = No_Location then
7239 Location := Excluded_Sources.Location;
7241 Location := Element.Location;
7244 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7245 Current := Element.Next;
7248 end Find_Excluded_Sources;
7250 ---------------------------
7251 -- Find_Explicit_Sources --
7252 ---------------------------
7254 procedure Find_Explicit_Sources
7255 (Lang : Language_Index;
7256 Current_Dir : String;
7257 Project : Project_Id;
7258 In_Tree : Project_Tree_Ref;
7259 Data : in out Project_Data)
7261 Sources : constant Variable_Value :=
7264 Data.Decl.Attributes,
7266 Source_List_File : constant Variable_Value :=
7268 (Name_Source_List_File,
7269 Data.Decl.Attributes,
7271 Name_Loc : Name_Location;
7274 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7276 (Source_List_File.Kind = Single,
7277 "Source_List_File is not a single string");
7279 -- If the user has specified a Sources attribute
7281 if not Sources.Default then
7282 if not Source_List_File.Default then
7285 "?both variables source_files and " &
7286 "source_list_file are present",
7287 Source_List_File.Location);
7290 -- Sources is a list of file names
7293 Current : String_List_Id := Sources.Values;
7294 Element : String_Element;
7295 Location : Source_Ptr;
7296 Name : File_Name_Type;
7299 if Get_Mode = Ada_Only then
7300 Data.Ada_Sources_Present := Current /= Nil_String;
7303 -- If we are processing other languages in the case of gprmake,
7304 -- we should not reset the list of sources, which was already
7305 -- initialized for the Ada files.
7307 if Get_Mode /= Ada_Only or else Lang /= Ada_Language_Index then
7308 if Current = Nil_String then
7311 Data.Source_Dirs := Nil_String;
7312 when Multi_Language =>
7313 Data.First_Language_Processing := No_Language_Index;
7316 -- This project contains no source. For projects that
7317 -- don't extend other projects, this also means that
7318 -- there is no need for an object directory, if not
7321 if Data.Extends = No_Project
7322 and then Data.Object_Directory = Data.Directory
7324 Data.Object_Directory := No_Path;
7329 while Current /= Nil_String loop
7330 Element := In_Tree.String_Elements.Table (Current);
7331 Get_Name_String (Element.Value);
7333 if Osint.File_Names_Case_Sensitive then
7334 Name := File_Name_Type (Element.Value);
7336 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7340 -- If the element has no location, then use the
7341 -- location of Sources to report possible errors.
7343 if Element.Location = No_Location then
7344 Location := Sources.Location;
7346 Location := Element.Location;
7349 -- Check that there is no directory information
7351 for J in 1 .. Name_Len loop
7352 if Name_Buffer (J) = '/'
7353 or else Name_Buffer (J) = Directory_Separator
7355 Error_Msg_File_1 := Name;
7359 "file name cannot include directory " &
7366 -- In Multi_Language mode, check whether the file is
7367 -- already there (??? Is this really needed, and why ?)
7371 Name_Loc := No_Name_Location;
7372 when Multi_Language =>
7373 Name_Loc := Source_Names.Get (Name);
7376 if Name_Loc = No_Name_Location then
7379 Location => Location,
7380 Source => No_Source,
7383 Source_Names.Set (Name, Name_Loc);
7386 Current := Element.Next;
7389 if Get_Mode = Ada_Only then
7390 if Lang = Ada_Language_Index then
7391 Get_Path_Names_And_Record_Ada_Sources
7392 (Project, In_Tree, Data, Current_Dir);
7394 Record_Other_Sources
7395 (Project => Project,
7399 Naming_Exceptions => False);
7404 -- If we have no Source_Files attribute, check the Source_List_File
7407 elsif not Source_List_File.Default then
7409 -- Source_List_File is the name of the file
7410 -- that contains the source file names
7413 Source_File_Path_Name : constant String :=
7415 (File_Name_Type (Source_List_File.Value), Data.Directory);
7418 if Source_File_Path_Name'Length = 0 then
7419 Err_Vars.Error_Msg_File_1 :=
7420 File_Name_Type (Source_List_File.Value);
7423 "file with sources { does not exist",
7424 Source_List_File.Location);
7427 Get_Sources_From_File
7428 (Source_File_Path_Name, Source_List_File.Location,
7431 if Get_Mode = Ada_Only then
7432 -- Look in the source directories to find those sources
7434 if Lang = Ada_Language_Index then
7435 Get_Path_Names_And_Record_Ada_Sources
7436 (Project, In_Tree, Data, Current_Dir);
7439 Record_Other_Sources
7440 (Project => Project,
7444 Naming_Exceptions => False);
7451 -- Neither Source_Files nor Source_List_File has been
7452 -- specified. Find all the files that satisfy the naming
7453 -- scheme in all the source directories.
7457 if Lang = Ada_Language_Index then
7458 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7460 -- Find all the files that satisfy the naming scheme in
7461 -- all the source directories. All the naming exceptions
7462 -- that effectively exist are also part of the source
7463 -- of this language.
7465 Find_Sources (Project, In_Tree, Data, Lang, Current_Dir);
7468 when Multi_Language =>
7473 if Get_Mode = Multi_Language then
7475 (Project, In_Tree, Data,
7477 Sources.Default and then Source_List_File.Default);
7480 if Get_Mode = Ada_Only
7481 and then Lang = Ada_Language_Index
7482 and then Data.Extends = No_Project
7484 -- We should have found at least one source, if not report an error
7486 if Data.Ada_Sources = Nil_String then
7488 (Project, "Ada", In_Tree, Source_List_File.Location);
7492 end Find_Explicit_Sources;
7494 -------------------------------------------
7495 -- Get_Path_Names_And_Record_Ada_Sources --
7496 -------------------------------------------
7498 procedure Get_Path_Names_And_Record_Ada_Sources
7499 (Project : Project_Id;
7500 In_Tree : Project_Tree_Ref;
7501 Data : in out Project_Data;
7502 Current_Dir : String)
7504 Source_Dir : String_List_Id := Data.Source_Dirs;
7505 Element : String_Element;
7506 Path : Path_Name_Type;
7508 Name : File_Name_Type;
7509 Canonical_Name : File_Name_Type;
7510 Name_Str : String (1 .. 1_024);
7511 Last : Natural := 0;
7513 Current_Source : String_List_Id := Nil_String;
7514 First_Error : Boolean := True;
7515 Source_Recorded : Boolean := False;
7518 -- We look in all source directories for the file names in the
7519 -- hash table Source_Names
7521 while Source_Dir /= Nil_String loop
7522 Source_Recorded := False;
7523 Element := In_Tree.String_Elements.Table (Source_Dir);
7526 Dir_Path : constant String :=
7527 Get_Name_String (Element.Display_Value);
7529 if Current_Verbosity = High then
7530 Write_Str ("checking directory """);
7531 Write_Str (Dir_Path);
7535 Open (Dir, Dir_Path);
7538 Read (Dir, Name_Str, Last);
7542 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7545 if Osint.File_Names_Case_Sensitive then
7546 Canonical_Name := Name;
7548 Canonical_Case_File_Name (Name_Str (1 .. Last));
7549 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7550 Canonical_Name := Name_Find;
7553 NL := Source_Names.Get (Canonical_Name);
7555 if NL /= No_Name_Location and then not NL.Found then
7557 Source_Names.Set (Canonical_Name, NL);
7558 Name_Len := Dir_Path'Length;
7559 Name_Buffer (1 .. Name_Len) := Dir_Path;
7561 if Name_Buffer (Name_Len) /= Directory_Separator then
7562 Add_Char_To_Name_Buffer (Directory_Separator);
7565 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7568 if Current_Verbosity = High then
7569 Write_Str (" found ");
7570 Write_Line (Get_Name_String (Name));
7573 -- Register the source if it is an Ada compilation unit
7581 Location => NL.Location,
7582 Current_Source => Current_Source,
7583 Source_Recorded => Source_Recorded,
7584 Current_Dir => Current_Dir);
7591 if Source_Recorded then
7592 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7596 Source_Dir := Element.Next;
7599 -- It is an error if a source file name in a source list or
7600 -- in a source list file is not found.
7602 NL := Source_Names.Get_First;
7603 while NL /= No_Name_Location loop
7604 if not NL.Found then
7605 Err_Vars.Error_Msg_File_1 := NL.Name;
7610 "source file { cannot be found",
7612 First_Error := False;
7617 "\source file { cannot be found",
7622 NL := Source_Names.Get_Next;
7624 end Get_Path_Names_And_Record_Ada_Sources;
7626 --------------------------
7627 -- Check_Naming_Schemes --
7628 --------------------------
7630 procedure Check_Naming_Schemes
7631 (In_Tree : Project_Tree_Ref;
7632 Data : in out Project_Data;
7634 File_Name : File_Name_Type;
7635 Alternate_Languages : out Alternate_Language_Id;
7636 Language : out Language_Index;
7637 Language_Name : out Name_Id;
7638 Display_Language_Name : out Name_Id;
7640 Lang_Kind : out Language_Kind;
7641 Kind : out Source_Kind)
7643 Last : Positive := Filename'Last;
7644 Config : Language_Config;
7645 Lang : Name_List_Index := Data.Languages;
7646 Header_File : Boolean := False;
7647 First_Language : Language_Index;
7652 Alternate_Languages := No_Alternate_Language;
7654 while Lang /= No_Name_List loop
7655 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7656 Language := Data.First_Language_Processing;
7658 if Current_Verbosity = High then
7660 (" Testing language "
7661 & Get_Name_String (Language_Name)
7662 & " Header_File=" & Header_File'Img);
7665 while Language /= No_Language_Index loop
7666 if In_Tree.Languages_Data.Table (Language).Name =
7669 Display_Language_Name :=
7670 In_Tree.Languages_Data.Table (Language).Display_Name;
7671 Config := In_Tree.Languages_Data.Table (Language).Config;
7672 Lang_Kind := Config.Kind;
7674 if Config.Kind = File_Based then
7676 -- For file based languages, there is no Unit. Just
7677 -- check if the file name has the implementation or,
7678 -- if it is specified, the template suffix of the
7684 and then Config.Naming_Data.Body_Suffix /= No_File
7687 Impl_Suffix : constant String :=
7688 Get_Name_String (Config.Naming_Data.Body_Suffix);
7691 if Filename'Length > Impl_Suffix'Length
7694 (Last - Impl_Suffix'Length + 1 .. Last) =
7699 if Current_Verbosity = High then
7700 Write_Str (" source of language ");
7702 (Get_Name_String (Display_Language_Name));
7710 if Config.Naming_Data.Spec_Suffix /= No_File then
7712 Spec_Suffix : constant String :=
7714 (Config.Naming_Data.Spec_Suffix);
7717 if Filename'Length > Spec_Suffix'Length
7720 (Last - Spec_Suffix'Length + 1 .. Last) =
7725 if Current_Verbosity = High then
7726 Write_Str (" header file of language ");
7728 (Get_Name_String (Display_Language_Name));
7732 Alternate_Language_Table.Increment_Last
7733 (In_Tree.Alt_Langs);
7734 In_Tree.Alt_Langs.Table
7735 (Alternate_Language_Table.Last
7736 (In_Tree.Alt_Langs)) :=
7737 (Language => Language,
7738 Next => Alternate_Languages);
7739 Alternate_Languages :=
7740 Alternate_Language_Table.Last
7741 (In_Tree.Alt_Langs);
7743 Header_File := True;
7744 First_Language := Language;
7750 elsif not Header_File then
7751 -- Unit based language
7753 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7758 -- ??? Are we doing this once per file in the project ?
7759 -- It should be done only once per project.
7761 case Config.Naming_Data.Casing is
7762 when All_Lower_Case =>
7763 for J in Filename'Range loop
7764 if Is_Letter (Filename (J)) then
7765 if not Is_Lower (Filename (J)) then
7772 when All_Upper_Case =>
7773 for J in Filename'Range loop
7774 if Is_Letter (Filename (J)) then
7775 if not Is_Upper (Filename (J)) then
7790 if Config.Naming_Data.Separate_Suffix /= No_File
7792 Config.Naming_Data.Separate_Suffix /=
7793 Config.Naming_Data.Body_Suffix
7796 Suffix : constant String :=
7798 (Config.Naming_Data.Separate_Suffix);
7800 if Filename'Length > Suffix'Length
7803 (Last - Suffix'Length + 1 .. Last) =
7807 Last := Last - Suffix'Length;
7814 and then Config.Naming_Data.Body_Suffix /= No_File
7817 Suffix : constant String :=
7819 (Config.Naming_Data.Body_Suffix);
7821 if Filename'Length > Suffix'Length
7824 (Last - Suffix'Length + 1 .. Last) =
7828 Last := Last - Suffix'Length;
7835 and then Config.Naming_Data.Spec_Suffix /= No_File
7838 Suffix : constant String :=
7840 (Config.Naming_Data.Spec_Suffix);
7842 if Filename'Length > Suffix'Length
7845 (Last - Suffix'Length + 1 .. Last) =
7849 Last := Last - Suffix'Length;
7858 -- Replace dot replacements with dots
7863 J : Positive := Filename'First;
7865 Dot_Replacement : constant String :=
7867 (Config.Naming_Data.
7870 Max : constant Positive :=
7871 Last - Dot_Replacement'Length + 1;
7875 Name_Len := Name_Len + 1;
7877 if J <= Max and then
7879 (J .. J + Dot_Replacement'Length - 1) =
7882 Name_Buffer (Name_Len) := '.';
7883 J := J + Dot_Replacement'Length;
7886 if Filename (J) = '.' then
7891 Name_Buffer (Name_Len) :=
7892 GNAT.Case_Util.To_Lower (Filename (J));
7903 -- The name buffer should contain the name of the
7904 -- the unit, if it is one.
7906 -- Check that this is a valid unit name
7908 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7910 if Unit /= No_Name then
7912 if Current_Verbosity = High then
7914 Write_Str (" spec of ");
7916 Write_Str (" body of ");
7919 Write_Str (Get_Name_String (Unit));
7920 Write_Str (" (language ");
7922 (Get_Name_String (Display_Language_Name));
7926 -- Comments required, declare block should
7930 Unit_Except : constant Unit_Exception :=
7931 Unit_Exceptions.Get (Unit);
7933 procedure Masked_Unit (Spec : Boolean);
7934 -- Indicate that there is an exception for
7935 -- the same unit, so the file is not a
7936 -- source for the unit.
7942 procedure Masked_Unit (Spec : Boolean) is
7944 if Current_Verbosity = High then
7946 Write_Str (Filename);
7947 Write_Str (""" contains the ");
7956 (" of a unit that is found in """);
7961 (Unit_Except.Spec));
7965 (Unit_Except.Impl));
7968 Write_Line (""" (ignored)");
7971 Language := No_Language_Index;
7976 if Unit_Except.Spec /= No_File
7977 and then Unit_Except.Spec /= File_Name
7979 Masked_Unit (Spec => True);
7983 if Unit_Except.Impl /= No_File
7984 and then Unit_Except.Impl /= File_Name
7986 Masked_Unit (Spec => False);
7997 Language := In_Tree.Languages_Data.Table (Language).Next;
8000 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8003 -- Comment needed here ???
8006 Language := First_Language;
8009 Language := No_Language_Index;
8011 if Current_Verbosity = High then
8012 Write_Line (" not a source of any language");
8015 end Check_Naming_Schemes;
8021 procedure Check_File
8022 (Project : Project_Id;
8023 In_Tree : Project_Tree_Ref;
8024 Data : in out Project_Data;
8026 File_Name : File_Name_Type;
8027 Display_File_Name : File_Name_Type;
8028 Source_Directory : String;
8029 For_All_Sources : Boolean)
8031 Display_Path : constant String :=
8034 Directory => Source_Directory,
8035 Resolve_Links => Opt.Follow_Links_For_Files,
8036 Case_Sensitive => True);
8038 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8039 Path_Id : Path_Name_Type;
8040 Display_Path_Id : Path_Name_Type;
8041 Check_Name : Boolean := False;
8042 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8043 Language : Language_Index;
8046 Src_Ind : Source_File_Index;
8047 Src_Data : Source_Data;
8049 Source_To_Replace : Source_Id := No_Source;
8050 Language_Name : Name_Id;
8051 Display_Language_Name : Name_Id;
8052 Lang_Kind : Language_Kind;
8053 Kind : Source_Kind := Spec;
8056 Name_Len := Display_Path'Length;
8057 Name_Buffer (1 .. Name_Len) := Display_Path;
8058 Display_Path_Id := Name_Find;
8060 if Osint.File_Names_Case_Sensitive then
8061 Path_Id := Display_Path_Id;
8063 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8064 Path_Id := Name_Find;
8067 if Name_Loc = No_Name_Location then
8068 Check_Name := For_All_Sources;
8071 if Name_Loc.Found then
8073 -- Check if it is OK to have the same file name in several
8074 -- source directories.
8076 if not Data.Known_Order_Of_Source_Dirs then
8077 Error_Msg_File_1 := File_Name;
8080 "{ is found in several source directories",
8085 Name_Loc.Found := True;
8087 if Name_Loc.Source = No_Source then
8091 In_Tree.Sources.Table (Name_Loc.Source).Path := Path_Id;
8092 In_Tree.Sources.Table
8093 (Name_Loc.Source).Display_Path := Display_Path_Id;
8095 Source_Paths_Htable.Set
8096 (In_Tree.Source_Paths_HT,
8100 -- Check if this is a subunit
8102 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8104 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8106 Src_Ind := Sinput.P.Load_Project_File
8107 (Get_Name_String (Path_Id));
8109 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8110 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8118 Check_Naming_Schemes
8119 (In_Tree => In_Tree,
8121 Filename => Get_Name_String (File_Name),
8122 File_Name => File_Name,
8123 Alternate_Languages => Alternate_Languages,
8124 Language => Language,
8125 Language_Name => Language_Name,
8126 Display_Language_Name => Display_Language_Name,
8128 Lang_Kind => Lang_Kind,
8131 if Language = No_Language_Index then
8133 -- A file name in a list must be a source of a language
8135 if Name_Loc.Found then
8136 Error_Msg_File_1 := File_Name;
8140 "language unknown for {",
8145 -- Check if the same file name or unit is used in the prj tree
8147 Source := In_Tree.First_Source;
8149 while Source /= No_Source loop
8150 Src_Data := In_Tree.Sources.Table (Source);
8153 and then Src_Data.Unit = Unit
8154 and then Src_Data.Kind = Kind)
8155 or else (Unit = No_Name
8156 and then Src_Data.File = File_Name)
8158 -- Duplication of file/unit in same project is only
8159 -- allowed if order of source directories is known.
8161 if Project = Src_Data.Project then
8162 if Data.Known_Order_Of_Source_Dirs then
8165 elsif Unit /= No_Name then
8166 Error_Msg_Name_1 := Unit;
8169 "duplicate unit %%",
8174 Error_Msg_File_1 := File_Name;
8177 "duplicate source file " &
8183 -- Do not allow the same unit name in different
8184 -- projects, except if one is extending the other.
8186 -- For a file based language, the same file name
8187 -- replaces a file in a project being extended, but
8188 -- it is allowed to have the same file name in
8189 -- unrelated projects.
8192 (Project, Src_Data.Project, In_Tree)
8194 Source_To_Replace := Source;
8196 elsif Unit /= No_Name then
8197 Error_Msg_Name_1 := Unit;
8200 "unit %% cannot belong to several projects",
8203 Error_Msg_Name_1 := In_Tree.Projects.Table (Project).Name;
8204 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8211 In_Tree.Projects.Table (Src_Data.Project).Name;
8212 Error_Msg_Name_2 := Name_Id (Src_Data.Display_Path);
8222 Source := Src_Data.Next_In_Sources;
8231 Lang => Language_Name,
8232 Lang_Id => Language,
8233 Lang_Kind => Lang_Kind,
8235 Alternate_Languages => Alternate_Languages,
8236 File_Name => File_Name,
8237 Display_File => Display_File_Name,
8240 Display_Path => Display_Path_Id,
8241 Source_To_Replace => Source_To_Replace);
8247 ------------------------
8248 -- Search_Directories --
8249 ------------------------
8251 procedure Search_Directories
8252 (Project : Project_Id;
8253 In_Tree : Project_Tree_Ref;
8254 Data : in out Project_Data;
8255 For_All_Sources : Boolean)
8257 Source_Dir : String_List_Id;
8258 Element : String_Element;
8260 Name : String (1 .. 1_000);
8262 File_Name : File_Name_Type;
8263 Display_File_Name : File_Name_Type;
8266 if Current_Verbosity = High then
8267 Write_Line ("Looking for sources:");
8270 -- Loop through subdirectories
8272 Source_Dir := Data.Source_Dirs;
8273 while Source_Dir /= Nil_String loop
8275 Element := In_Tree.String_Elements.Table (Source_Dir);
8276 if Element.Value /= No_Name then
8277 Get_Name_String (Element.Display_Value);
8280 Source_Directory : constant String :=
8281 Name_Buffer (1 .. Name_Len) &
8282 Directory_Separator;
8283 Dir_Last : constant Natural :=
8284 Compute_Directory_Last
8288 if Current_Verbosity = High then
8289 Write_Str ("Source_Dir = ");
8290 Write_Line (Source_Directory);
8293 -- We look to every entry in the source directory
8295 Open (Dir, Source_Directory);
8298 Read (Dir, Name, Last);
8302 -- ??? Duplicate system call here, we just did a
8303 -- a similar one. Maybe Ada.Directories would be more
8306 (Source_Directory & Name (1 .. Last))
8308 if Current_Verbosity = High then
8309 Write_Str (" Checking ");
8310 Write_Line (Name (1 .. Last));
8314 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8315 Display_File_Name := Name_Find;
8317 if Osint.File_Names_Case_Sensitive then
8318 File_Name := Display_File_Name;
8320 Canonical_Case_File_Name
8321 (Name_Buffer (1 .. Name_Len));
8322 File_Name := Name_Find;
8327 Excluded_Sources_Htable.Get (File_Name);
8330 if FF /= No_File_Found then
8331 if not FF.Found then
8333 Excluded_Sources_Htable.Set
8336 if Current_Verbosity = High then
8337 Write_Str (" excluded source """);
8338 Write_Str (Get_Name_String (File_Name));
8345 (Project => Project,
8348 Name => Name (1 .. Last),
8349 File_Name => File_Name,
8350 Display_File_Name => Display_File_Name,
8351 Source_Directory => Source_Directory
8352 (Source_Directory'First .. Dir_Last),
8353 For_All_Sources => For_All_Sources);
8364 when Directory_Error =>
8367 Source_Dir := Element.Next;
8370 if Current_Verbosity = High then
8371 Write_Line ("end Looking for sources.");
8373 end Search_Directories;
8375 ----------------------
8376 -- Look_For_Sources --
8377 ----------------------
8379 procedure Look_For_Sources
8380 (Project : Project_Id;
8381 In_Tree : Project_Tree_Ref;
8382 Data : in out Project_Data;
8383 Current_Dir : String)
8385 procedure Remove_Locally_Removed_Files_From_Units;
8386 -- Mark all locally removed sources as such in the Units table
8388 procedure Process_Other_Sources_In_Ada_Only_Mode;
8389 -- Find sources for language other than Ada when in Ada_Only mode
8391 procedure Process_Sources_In_Multi_Language_Mode;
8392 -- Find all source files when in multi language mode
8394 ---------------------------------------------
8395 -- Remove_Locally_Removed_Files_From_Units --
8396 ---------------------------------------------
8398 procedure Remove_Locally_Removed_Files_From_Units is
8399 Excluded : File_Found := Excluded_Sources_Htable.Get_First;
8402 Extended : Project_Id;
8404 while Excluded /= No_File_Found loop
8408 for Index in Unit_Table.First ..
8409 Unit_Table.Last (In_Tree.Units)
8411 Unit := In_Tree.Units.Table (Index);
8413 for Kind in Spec_Or_Body'Range loop
8414 if Unit.File_Names (Kind).Name = Excluded.File then
8417 -- Check that this is from the current project or
8418 -- that the current project extends.
8420 Extended := Unit.File_Names (Kind).Project;
8422 if Extended = Project
8423 or else Project_Extends (Project, Extended, In_Tree)
8425 Unit.File_Names (Kind).Path := Slash;
8426 Unit.File_Names (Kind).Needs_Pragma := False;
8427 In_Tree.Units.Table (Index) := Unit;
8428 Add_Forbidden_File_Name
8429 (Unit.File_Names (Kind).Name);
8433 "cannot remove a source from " &
8440 end loop For_Each_Unit;
8443 Err_Vars.Error_Msg_File_1 := Excluded.File;
8445 (Project, In_Tree, "unknown file {", Excluded.Location);
8448 Excluded := Excluded_Sources_Htable.Get_Next;
8450 end Remove_Locally_Removed_Files_From_Units;
8452 --------------------------------------------
8453 -- Process_Other_Sources_In_Ada_Only_Mode --
8454 --------------------------------------------
8456 procedure Process_Other_Sources_In_Ada_Only_Mode is
8458 -- Set Source_Present to False. It will be set back to True
8459 -- whenever a source is found.
8461 Data.Other_Sources_Present := False;
8462 for Lang in Ada_Language_Index + 1 .. Last_Language_Index loop
8464 -- For each language (other than Ada) in the project file
8466 if Is_Present (Lang, Data, In_Tree) then
8468 -- Reset the indication that there are sources of this
8469 -- language. It will be set back to True whenever we find
8470 -- a source of the language.
8472 Set (Lang, False, Data, In_Tree);
8474 -- First, get the source suffix for the language
8476 Set (Suffix => Suffix_For (Lang, Data.Naming, In_Tree),
8477 For_Language => Lang,
8479 In_Tree => In_Tree);
8481 -- Then, deal with the naming exceptions, if any
8486 Naming_Exceptions : constant Variable_Value :=
8488 (Index => Language_Names.Table (Lang),
8490 In_Array => Data.Naming.Implementation_Exceptions,
8491 In_Tree => In_Tree);
8492 Element_Id : String_List_Id;
8493 Element : String_Element;
8494 File_Id : File_Name_Type;
8495 Source_Found : Boolean := False;
8498 -- If there are naming exceptions, look through them one
8501 if Naming_Exceptions /= Nil_Variable_Value then
8502 Element_Id := Naming_Exceptions.Values;
8504 while Element_Id /= Nil_String loop
8505 Element := In_Tree.String_Elements.Table (Element_Id);
8507 if Osint.File_Names_Case_Sensitive then
8508 File_Id := File_Name_Type (Element.Value);
8510 Get_Name_String (Element.Value);
8511 Canonical_Case_File_Name
8512 (Name_Buffer (1 .. Name_Len));
8513 File_Id := Name_Find;
8516 -- Put each naming exception in the Source_Names
8517 -- hash table, but if there are repetition, don't
8518 -- bother after the first instance.
8520 if Source_Names.Get (File_Id) = No_Name_Location then
8521 Source_Found := True;
8525 Location => Element.Location,
8526 Source => No_Source,
8531 Element_Id := Element.Next;
8534 -- If there is at least one naming exception, record
8535 -- those that are found in the source directories.
8537 if Source_Found then
8538 Record_Other_Sources
8539 (Project => Project,
8543 Naming_Exceptions => True);
8549 -- Now, check if a list of sources is declared either through
8550 -- a string list (attribute Source_Files) or a text file
8551 -- (attribute Source_List_File). If a source list is declared,
8552 -- we will consider only those naming exceptions that are
8556 Find_Explicit_Sources
8557 (Lang, Current_Dir, Project, In_Tree, Data);
8560 end Process_Other_Sources_In_Ada_Only_Mode;
8562 --------------------------------------------
8563 -- Process_Sources_In_Multi_Language_Mode --
8564 --------------------------------------------
8566 procedure Process_Sources_In_Multi_Language_Mode is
8567 Source : Source_Id := Data.First_Source;
8568 Src_Data : Source_Data;
8569 Name_Loc : Name_Location;
8573 -- First, put all the naming exceptions, if any, in the Source_Names
8576 Unit_Exceptions.Reset;
8578 while Source /= No_Source loop
8579 Src_Data := In_Tree.Sources.Table (Source);
8581 -- A file that is excluded cannot also be an exception file name
8583 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8586 Error_Msg_File_1 := Src_Data.File;
8590 "{ cannot be both excluded and an exception file name",
8594 Name_Loc := (Name => Src_Data.File,
8595 Location => No_Location,
8597 Except => Src_Data.Unit /= No_Name,
8600 if Current_Verbosity = High then
8601 Write_Str ("Putting source #");
8602 Write_Str (Source'Img);
8603 Write_Str (", file ");
8604 Write_Str (Get_Name_String (Src_Data.File));
8605 Write_Line (" in Source_Names");
8608 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8610 -- If this is an Ada exception, record it in table Unit_Exceptions
8612 if Src_Data.Unit /= No_Name then
8614 Unit_Except : Unit_Exception :=
8615 Unit_Exceptions.Get (Src_Data.Unit);
8618 Unit_Except.Name := Src_Data.Unit;
8620 if Src_Data.Kind = Spec then
8621 Unit_Except.Spec := Src_Data.File;
8623 Unit_Except.Impl := Src_Data.File;
8626 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8630 Source := Src_Data.Next_In_Project;
8633 Find_Explicit_Sources
8634 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
8636 FF := Excluded_Sources_Htable.Get_First;
8638 while FF /= No_File_Found loop
8640 Source := In_Tree.First_Source;
8642 while Source /= No_Source loop
8643 Src_Data := In_Tree.Sources.Table (Source);
8645 if Src_Data.File = FF.File then
8647 -- Check that this is from this project or a
8648 -- project that the current project extends.
8650 if Src_Data.Project = Project or else
8651 Is_Extending (Project, Src_Data.Project, In_Tree)
8653 Src_Data.Locally_Removed := True;
8654 In_Tree.Sources.Table (Source) := Src_Data;
8655 Add_Forbidden_File_Name (FF.File);
8661 Source := Src_Data.Next_In_Sources;
8664 if not FF.Found and not OK then
8665 Err_Vars.Error_Msg_File_1 := FF.File;
8666 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8669 FF := Excluded_Sources_Htable.Get_Next;
8671 end Process_Sources_In_Multi_Language_Mode;
8673 -- Start of processing for Look_For_Sources
8677 Find_Excluded_Sources (In_Tree, Data);
8681 if Is_A_Language (In_Tree, Data, Name_Ada) then
8682 Find_Explicit_Sources
8683 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
8684 Remove_Locally_Removed_Files_From_Units;
8687 if Data.Other_Sources_Present then
8688 Process_Other_Sources_In_Ada_Only_Mode;
8691 when Multi_Language =>
8692 if Data.First_Language_Processing /= No_Language_Index then
8693 Process_Sources_In_Multi_Language_Mode;
8696 end Look_For_Sources;
8702 function Path_Name_Of
8703 (File_Name : File_Name_Type;
8704 Directory : Path_Name_Type) return String
8706 Result : String_Access;
8708 The_Directory : constant String := Get_Name_String (Directory);
8711 Get_Name_String (File_Name);
8712 Result := Locate_Regular_File
8713 (File_Name => Name_Buffer (1 .. Name_Len),
8714 Path => The_Directory);
8716 if Result = null then
8719 Canonical_Case_File_Name (Result.all);
8724 -------------------------------
8725 -- Prepare_Ada_Naming_Exceptions --
8726 -------------------------------
8728 procedure Prepare_Ada_Naming_Exceptions
8729 (List : Array_Element_Id;
8730 In_Tree : Project_Tree_Ref;
8731 Kind : Spec_Or_Body)
8733 Current : Array_Element_Id;
8734 Element : Array_Element;
8738 -- Traverse the list
8741 while Current /= No_Array_Element loop
8742 Element := In_Tree.Array_Elements.Table (Current);
8744 if Element.Index /= No_Name then
8747 Unit => Element.Index,
8748 Next => No_Ada_Naming_Exception);
8749 Reverse_Ada_Naming_Exceptions.Set
8750 (Unit, (Element.Value.Value, Element.Value.Index));
8752 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8753 Ada_Naming_Exception_Table.Increment_Last;
8754 Ada_Naming_Exception_Table.Table
8755 (Ada_Naming_Exception_Table.Last) := Unit;
8756 Ada_Naming_Exceptions.Set
8757 (File_Name_Type (Element.Value.Value),
8758 Ada_Naming_Exception_Table.Last);
8761 Current := Element.Next;
8763 end Prepare_Ada_Naming_Exceptions;
8765 ---------------------
8766 -- Project_Extends --
8767 ---------------------
8769 function Project_Extends
8770 (Extending : Project_Id;
8771 Extended : Project_Id;
8772 In_Tree : Project_Tree_Ref) return Boolean
8774 Current : Project_Id := Extending;
8777 if Current = No_Project then
8780 elsif Current = Extended then
8784 Current := In_Tree.Projects.Table (Current).Extends;
8786 end Project_Extends;
8788 -----------------------
8789 -- Record_Ada_Source --
8790 -----------------------
8792 procedure Record_Ada_Source
8793 (File_Name : File_Name_Type;
8794 Path_Name : Path_Name_Type;
8795 Project : Project_Id;
8796 In_Tree : Project_Tree_Ref;
8797 Data : in out Project_Data;
8798 Location : Source_Ptr;
8799 Current_Source : in out String_List_Id;
8800 Source_Recorded : in out Boolean;
8801 Current_Dir : String)
8803 Canonical_File_Name : File_Name_Type;
8804 Canonical_Path_Name : Path_Name_Type;
8806 Exception_Id : Ada_Naming_Exception_Id;
8807 Unit_Name : Name_Id;
8808 Unit_Kind : Spec_Or_Body;
8809 Unit_Ind : Int := 0;
8811 Name_Index : Name_And_Index;
8812 Needs_Pragma : Boolean;
8814 The_Location : Source_Ptr := Location;
8815 Previous_Source : constant String_List_Id := Current_Source;
8816 Except_Name : Name_And_Index := No_Name_And_Index;
8818 Unit_Prj : Unit_Project;
8820 File_Name_Recorded : Boolean := False;
8823 if Osint.File_Names_Case_Sensitive then
8824 Canonical_File_Name := File_Name;
8825 Canonical_Path_Name := Path_Name;
8827 Get_Name_String (File_Name);
8828 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8829 Canonical_File_Name := Name_Find;
8832 Canonical_Path : constant String :=
8834 (Get_Name_String (Path_Name),
8835 Directory => Current_Dir,
8836 Resolve_Links => Opt.Follow_Links_For_Files,
8837 Case_Sensitive => False);
8840 Add_Str_To_Name_Buffer (Canonical_Path);
8841 Canonical_Path_Name := Name_Find;
8845 -- Find out the unit name, the unit kind and if it needs
8846 -- a specific SFN pragma.
8849 (In_Tree => In_Tree,
8850 Canonical_File_Name => Canonical_File_Name,
8851 Naming => Data.Naming,
8852 Exception_Id => Exception_Id,
8853 Unit_Name => Unit_Name,
8854 Unit_Kind => Unit_Kind,
8855 Needs_Pragma => Needs_Pragma);
8857 if Exception_Id = No_Ada_Naming_Exception and then
8860 if Current_Verbosity = High then
8862 Write_Str (Get_Name_String (Canonical_File_Name));
8863 Write_Line (""" is not a valid source file name (ignored).");
8867 -- Check to see if the source has been hidden by an exception,
8868 -- but only if it is not an exception.
8870 if not Needs_Pragma then
8872 Reverse_Ada_Naming_Exceptions.Get
8873 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8875 if Except_Name /= No_Name_And_Index then
8876 if Current_Verbosity = High then
8878 Write_Str (Get_Name_String (Canonical_File_Name));
8879 Write_Str (""" contains a unit that is found in """);
8880 Write_Str (Get_Name_String (Except_Name.Name));
8881 Write_Line (""" (ignored).");
8884 -- The file is not included in the source of the project since
8885 -- it is hidden by the exception. So, nothing else to do.
8892 if Exception_Id /= No_Ada_Naming_Exception then
8893 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8894 Exception_Id := Info.Next;
8895 Info.Next := No_Ada_Naming_Exception;
8896 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8898 Unit_Name := Info.Unit;
8899 Unit_Ind := Name_Index.Index;
8900 Unit_Kind := Info.Kind;
8903 -- Put the file name in the list of sources of the project
8905 String_Element_Table.Increment_Last
8906 (In_Tree.String_Elements);
8907 In_Tree.String_Elements.Table
8908 (String_Element_Table.Last
8909 (In_Tree.String_Elements)) :=
8910 (Value => Name_Id (Canonical_File_Name),
8911 Display_Value => Name_Id (File_Name),
8912 Location => No_Location,
8917 if Current_Source = Nil_String then
8918 Data.Ada_Sources := String_Element_Table.Last
8919 (In_Tree.String_Elements);
8920 Data.Sources := Data.Ada_Sources;
8922 In_Tree.String_Elements.Table
8923 (Current_Source).Next :=
8924 String_Element_Table.Last
8925 (In_Tree.String_Elements);
8928 Current_Source := String_Element_Table.Last
8929 (In_Tree.String_Elements);
8931 -- Put the unit in unit list
8934 The_Unit : Unit_Index :=
8935 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8937 The_Unit_Data : Unit_Data;
8940 if Current_Verbosity = High then
8941 Write_Str ("Putting ");
8942 Write_Str (Get_Name_String (Unit_Name));
8943 Write_Line (" in the unit list.");
8946 -- The unit is already in the list, but may be it is
8947 -- only the other unit kind (spec or body), or what is
8948 -- in the unit list is a unit of a project we are extending.
8950 if The_Unit /= No_Unit_Index then
8951 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8953 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8956 The_Unit_Data.File_Names (Unit_Kind).Path = Slash)
8957 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8958 or else Project_Extends
8960 The_Unit_Data.File_Names (Unit_Kind).Project,
8963 if The_Unit_Data.File_Names (Unit_Kind).Path = Slash then
8964 Remove_Forbidden_File_Name
8965 (The_Unit_Data.File_Names (Unit_Kind).Name);
8968 -- Record the file name in the hash table Files_Htable
8970 Unit_Prj := (Unit => The_Unit, Project => Project);
8973 Canonical_File_Name,
8976 The_Unit_Data.File_Names (Unit_Kind) :=
8977 (Name => Canonical_File_Name,
8979 Display_Name => File_Name,
8980 Path => Canonical_Path_Name,
8981 Display_Path => Path_Name,
8983 Needs_Pragma => Needs_Pragma);
8984 In_Tree.Units.Table (The_Unit) :=
8986 Source_Recorded := True;
8988 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8989 and then (Data.Known_Order_Of_Source_Dirs or else
8990 The_Unit_Data.File_Names (Unit_Kind).Path =
8991 Canonical_Path_Name)
8993 if Previous_Source = Nil_String then
8994 Data.Ada_Sources := Nil_String;
8995 Data.Sources := Nil_String;
8997 In_Tree.String_Elements.Table
8998 (Previous_Source).Next := Nil_String;
8999 String_Element_Table.Decrement_Last
9000 (In_Tree.String_Elements);
9003 Current_Source := Previous_Source;
9006 -- It is an error to have two units with the same name
9007 -- and the same kind (spec or body).
9009 if The_Location = No_Location then
9011 In_Tree.Projects.Table
9015 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9017 (Project, In_Tree, "duplicate unit %%", The_Location);
9019 Err_Vars.Error_Msg_Name_1 :=
9020 In_Tree.Projects.Table
9021 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9022 Err_Vars.Error_Msg_File_1 :=
9024 (The_Unit_Data.File_Names (Unit_Kind).Path);
9027 "\ project file %%, {", The_Location);
9029 Err_Vars.Error_Msg_Name_1 :=
9030 In_Tree.Projects.Table (Project).Name;
9031 Err_Vars.Error_Msg_File_1 :=
9032 File_Name_Type (Canonical_Path_Name);
9035 "\ project file %%, {", The_Location);
9038 -- It is a new unit, create a new record
9041 -- First, check if there is no other unit with this file
9042 -- name in another project. If it is, report an error.
9043 -- Of course, we do that only for the first unit in the
9046 Unit_Prj := Files_Htable.Get
9047 (In_Tree.Files_HT, Canonical_File_Name);
9049 if not File_Name_Recorded and then
9050 Unit_Prj /= No_Unit_Project
9052 Error_Msg_File_1 := File_Name;
9054 In_Tree.Projects.Table
9055 (Unit_Prj.Project).Name;
9058 "{ is already a source of project %%",
9062 Unit_Table.Increment_Last (In_Tree.Units);
9063 The_Unit := Unit_Table.Last (In_Tree.Units);
9065 (In_Tree.Units_HT, Unit_Name, The_Unit);
9066 Unit_Prj := (Unit => The_Unit, Project => Project);
9069 Canonical_File_Name,
9071 The_Unit_Data.Name := Unit_Name;
9072 The_Unit_Data.File_Names (Unit_Kind) :=
9073 (Name => Canonical_File_Name,
9075 Display_Name => File_Name,
9076 Path => Canonical_Path_Name,
9077 Display_Path => Path_Name,
9079 Needs_Pragma => Needs_Pragma);
9080 In_Tree.Units.Table (The_Unit) :=
9082 Source_Recorded := True;
9087 exit when Exception_Id = No_Ada_Naming_Exception;
9088 File_Name_Recorded := True;
9091 end Record_Ada_Source;
9093 --------------------------
9094 -- Record_Other_Sources --
9095 --------------------------
9097 procedure Record_Other_Sources
9098 (Project : Project_Id;
9099 In_Tree : Project_Tree_Ref;
9100 Data : in out Project_Data;
9101 Language : Language_Index;
9102 Naming_Exceptions : Boolean)
9104 Source_Dir : String_List_Id;
9105 Element : String_Element;
9106 Path : Path_Name_Type;
9108 Canonical_Name : File_Name_Type;
9109 Name_Str : String (1 .. 1_024);
9110 Last : Natural := 0;
9112 First_Error : Boolean := True;
9113 Suffix : constant String :=
9114 Body_Suffix_Of (Language, Data, In_Tree);
9117 Source_Dir := Data.Source_Dirs;
9118 while Source_Dir /= Nil_String loop
9119 Element := In_Tree.String_Elements.Table (Source_Dir);
9122 Dir_Path : constant String :=
9123 Get_Name_String (Element.Display_Value);
9125 if Current_Verbosity = High then
9126 Write_Str ("checking directory """);
9127 Write_Str (Dir_Path);
9128 Write_Str (""" for ");
9130 if Naming_Exceptions then
9131 Write_Str ("naming exceptions");
9134 Write_Str ("sources");
9137 Write_Str (" of Language ");
9138 Display_Language_Name (Language);
9141 Open (Dir, Dir_Path);
9144 Read (Dir, Name_Str, Last);
9148 (Dir_Path & Directory_Separator & Name_Str (1 .. Last))
9151 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
9152 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9153 Canonical_Name := Name_Find;
9154 NL := Source_Names.Get (Canonical_Name);
9156 if NL /= No_Name_Location then
9158 if not Data.Known_Order_Of_Source_Dirs then
9159 Error_Msg_File_1 := Canonical_Name;
9162 "{ is found in several source directories",
9168 Source_Names.Set (Canonical_Name, NL);
9169 Name_Len := Dir_Path'Length;
9170 Name_Buffer (1 .. Name_Len) := Dir_Path;
9171 Add_Char_To_Name_Buffer (Directory_Separator);
9172 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
9176 (File_Name => Canonical_Name,
9181 Location => NL.Location,
9182 Language => Language,
9184 Naming_Exception => Naming_Exceptions);
9193 Source_Dir := Element.Next;
9196 if not Naming_Exceptions then
9197 NL := Source_Names.Get_First;
9199 -- It is an error if a source file name in a source list or
9200 -- in a source list file is not found.
9202 while NL /= No_Name_Location loop
9203 if not NL.Found then
9204 Err_Vars.Error_Msg_File_1 := NL.Name;
9209 "source file { cannot be found",
9211 First_Error := False;
9216 "\source file { cannot be found",
9221 NL := Source_Names.Get_Next;
9224 -- Any naming exception of this language that is not in a list
9225 -- of sources must be removed.
9228 Source_Id : Other_Source_Id := Data.First_Other_Source;
9229 Prev_Id : Other_Source_Id := No_Other_Source;
9230 Source : Other_Source;
9233 while Source_Id /= No_Other_Source loop
9234 Source := In_Tree.Other_Sources.Table (Source_Id);
9236 if Source.Language = Language
9237 and then Source.Naming_Exception
9239 if Current_Verbosity = High then
9240 Write_Str ("Naming exception """);
9241 Write_Str (Get_Name_String (Source.File_Name));
9242 Write_Str (""" is not in the list of sources,");
9243 Write_Line (" so it is removed.");
9246 if Prev_Id = No_Other_Source then
9247 Data.First_Other_Source := Source.Next;
9250 In_Tree.Other_Sources.Table
9251 (Prev_Id).Next := Source.Next;
9254 Source_Id := Source.Next;
9256 if Source_Id = No_Other_Source then
9257 Data.Last_Other_Source := Prev_Id;
9261 Prev_Id := Source_Id;
9262 Source_Id := Source.Next;
9267 end Record_Other_Sources;
9273 procedure Remove_Source
9275 Replaced_By : Source_Id;
9276 Project : Project_Id;
9277 Data : in out Project_Data;
9278 In_Tree : Project_Tree_Ref)
9280 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9285 if Current_Verbosity = High then
9286 Write_Str ("Removing source #");
9287 Write_Line (Id'Img);
9290 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9292 -- Remove the source from the global source list
9294 Source := In_Tree.First_Source;
9297 In_Tree.First_Source := Src_Data.Next_In_Sources;
9300 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9301 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9304 In_Tree.Sources.Table (Source).Next_In_Sources :=
9305 Src_Data.Next_In_Sources;
9308 -- Remove the source from the project list
9310 if Src_Data.Project = Project then
9311 Source := Data.First_Source;
9314 Data.First_Source := Src_Data.Next_In_Project;
9316 if Src_Data.Next_In_Project = No_Source then
9317 Data.Last_Source := No_Source;
9321 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9322 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9325 In_Tree.Sources.Table (Source).Next_In_Project :=
9326 Src_Data.Next_In_Project;
9328 if Src_Data.Next_In_Project = No_Source then
9329 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9334 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9337 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9338 Src_Data.Next_In_Project;
9340 if Src_Data.Next_In_Project = No_Source then
9341 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9346 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9347 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9350 In_Tree.Sources.Table (Source).Next_In_Project :=
9351 Src_Data.Next_In_Project;
9353 if Src_Data.Next_In_Project = No_Source then
9354 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9359 -- Remove source from the language list
9361 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9364 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9365 Src_Data.Next_In_Lang;
9368 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9369 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9372 In_Tree.Sources.Table (Source).Next_In_Lang :=
9373 Src_Data.Next_In_Lang;
9377 -----------------------
9378 -- Report_No_Sources --
9379 -----------------------
9381 procedure Report_No_Sources
9382 (Project : Project_Id;
9384 In_Tree : Project_Tree_Ref;
9385 Location : Source_Ptr)
9388 case When_No_Sources is
9392 when Warning | Error =>
9393 Error_Msg_Warn := When_No_Sources = Warning;
9396 "<there are no " & Lang_Name & " sources in this project",
9399 end Report_No_Sources;
9401 ----------------------
9402 -- Show_Source_Dirs --
9403 ----------------------
9405 procedure Show_Source_Dirs
9406 (Data : Project_Data;
9407 In_Tree : Project_Tree_Ref)
9409 Current : String_List_Id;
9410 Element : String_Element;
9413 Write_Line ("Source_Dirs:");
9415 Current := Data.Source_Dirs;
9416 while Current /= Nil_String loop
9417 Element := In_Tree.String_Elements.Table (Current);
9419 Write_Line (Get_Name_String (Element.Value));
9420 Current := Element.Next;
9423 Write_Line ("end Source_Dirs.");
9424 end Show_Source_Dirs;
9431 (Language : Language_Index;
9432 Naming : Naming_Data;
9433 In_Tree : Project_Tree_Ref) return File_Name_Type
9435 Suffix : constant Variable_Value :=
9437 (Index => Language_Names.Table (Language),
9439 In_Array => Naming.Body_Suffix,
9440 In_Tree => In_Tree);
9442 -- If no suffix for this language in package Naming, use the default
9444 if Suffix = Nil_Variable_Value then
9448 when Ada_Language_Index =>
9449 Add_Str_To_Name_Buffer (".adb");
9451 when C_Language_Index =>
9452 Add_Str_To_Name_Buffer (".c");
9454 when C_Plus_Plus_Language_Index =>
9455 Add_Str_To_Name_Buffer (".cpp");
9461 -- Otherwise use the one specified
9464 Get_Name_String (Suffix.Value);
9467 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9471 -------------------------
9472 -- Warn_If_Not_Sources --
9473 -------------------------
9475 -- comments needed in this body ???
9477 procedure Warn_If_Not_Sources
9478 (Project : Project_Id;
9479 In_Tree : Project_Tree_Ref;
9480 Conventions : Array_Element_Id;
9482 Extending : Boolean)
9484 Conv : Array_Element_Id := Conventions;
9486 The_Unit_Id : Unit_Index;
9487 The_Unit_Data : Unit_Data;
9488 Location : Source_Ptr;
9491 while Conv /= No_Array_Element loop
9492 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9493 Error_Msg_Name_1 := Unit;
9494 Get_Name_String (Unit);
9495 To_Lower (Name_Buffer (1 .. Name_Len));
9497 The_Unit_Id := Units_Htable.Get
9498 (In_Tree.Units_HT, Unit);
9499 Location := In_Tree.Array_Elements.Table
9500 (Conv).Value.Location;
9502 if The_Unit_Id = No_Unit_Index then
9509 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9511 In_Tree.Array_Elements.Table (Conv).Value.Value;
9514 if not Check_Project
9515 (The_Unit_Data.File_Names (Specification).Project,
9516 Project, In_Tree, Extending)
9520 "?source of spec of unit %% (%%)" &
9521 " cannot be found in this project",
9526 if not Check_Project
9527 (The_Unit_Data.File_Names (Body_Part).Project,
9528 Project, In_Tree, Extending)
9532 "?source of body of unit %% (%%)" &
9533 " cannot be found in this project",
9539 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9541 end Warn_If_Not_Sources;