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 type Name_Location is record
69 Name : File_Name_Type;
70 Location : Source_Ptr;
71 Source : Source_Id := No_Source;
72 Except : Boolean := False;
73 Found : Boolean := False;
75 -- Information about file names found in string list attribute
76 -- Source_Files or in a source list file, stored in hash table
77 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
79 No_Name_Location : constant Name_Location :=
81 Location => No_Location,
86 package Source_Names is new GNAT.HTable.Simple_HTable
87 (Header_Num => Header_Num,
88 Element => Name_Location,
89 No_Element => No_Name_Location,
90 Key => File_Name_Type,
93 -- Hash table to store file names found in string list attribute
94 -- Source_Files or in a source list file, stored in hash table
95 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97 -- More documentation needed on what unit exceptions are about ???
99 type Unit_Exception is record
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
105 No_Unit_Exception : constant Unit_Exception :=
110 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
111 (Header_Num => Header_Num,
112 Element => Unit_Exception,
113 No_Element => No_Unit_Exception,
117 -- Hash table to store the unit exceptions
119 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
120 (Header_Num => Header_Num,
126 -- Hash table to store recursive source directories, to avoid looking
127 -- several times, and to avoid cycles that may be introduced by symbolic
130 type Ada_Naming_Exception_Id is new Nat;
131 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
133 type Unit_Info is record
136 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
140 -- Why is the following commented out ???
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 package Object_File_Names is new GNAT.HTable.Simple_HTable
163 (Header_Num => Header_Num,
164 Element => File_Name_Type,
165 No_Element => No_File,
166 Key => File_Name_Type,
169 -- A hash table to store the object file names for a project, to check that
170 -- two different sources have different object file names.
172 type File_Found is record
173 File : File_Name_Type := No_File;
174 Found : Boolean := False;
175 Location : Source_Ptr := No_Location;
177 No_File_Found : constant File_Found := (No_File, False, No_Location);
178 -- Comments needed ???
180 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
181 (Header_Num => Header_Num,
182 Element => File_Found,
183 No_Element => No_File_Found,
184 Key => File_Name_Type,
187 -- A hash table to store the excluded files, if any. This is filled by
188 -- Find_Excluded_Sources below.
190 procedure Find_Excluded_Sources
191 (Project : Project_Id;
192 In_Tree : Project_Tree_Ref;
193 Data : Project_Data);
194 -- Find the list of files that should not be considered as source files
195 -- for this project. Sets the list in the Excluded_Sources_Htable.
197 function Hash (Unit : Unit_Info) return Header_Num;
199 type Name_And_Index is record
200 Name : Name_Id := No_Name;
203 No_Name_And_Index : constant Name_And_Index :=
204 (Name => No_Name, Index => 0);
206 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
207 (Header_Num => Header_Num,
208 Element => Name_And_Index,
209 No_Element => No_Name_And_Index,
213 -- A table to check if a unit with an exceptional name will hide a source
214 -- with a file name following the naming convention.
218 Data : in out Project_Data;
219 In_Tree : Project_Tree_Ref;
220 Project : Project_Id;
222 Lang_Id : Language_Index;
224 File_Name : File_Name_Type;
225 Display_File : File_Name_Type;
226 Lang_Kind : Language_Kind;
227 Naming_Exception : Boolean := False;
228 Path : Path_Name_Type := No_Path;
229 Display_Path : Path_Name_Type := No_Path;
230 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
231 Other_Part : Source_Id := No_Source;
232 Unit : Name_Id := No_Name;
234 Source_To_Replace : Source_Id := No_Source);
235 -- Add a new source to the different lists: list of all sources in the
236 -- project tree, list of source of a project and list of sources of a
239 -- If Path is specified, the file is also added to Source_Paths_HT.
240 -- If Source_To_Replace is specified, it points to the source in the
241 -- extended project that the new file is overriding.
243 function ALI_File_Name (Source : String) return String;
244 -- Return the ALI file name corresponding to a source
246 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
247 -- Check that a name is a valid Ada unit name
249 procedure Check_Naming_Schemes
250 (Data : in out Project_Data;
251 Project : Project_Id;
252 In_Tree : Project_Tree_Ref);
253 -- Check the naming scheme part of Data
255 procedure Check_Ada_Naming_Scheme_Validity
256 (Project : Project_Id;
257 In_Tree : Project_Tree_Ref;
258 Naming : Naming_Data);
259 -- Check that the package Naming is correct
261 procedure Check_Configuration
262 (Project : Project_Id;
263 In_Tree : Project_Tree_Ref;
264 Data : in out Project_Data);
265 -- Check the configuration attributes for the project
267 procedure Check_If_Externally_Built
268 (Project : Project_Id;
269 In_Tree : Project_Tree_Ref;
270 Data : in out Project_Data);
271 -- Check attribute Externally_Built of project Project in project tree
272 -- In_Tree and modify its data Data if it has the value "true".
274 procedure Check_Interfaces
275 (Project : Project_Id;
276 In_Tree : Project_Tree_Ref;
277 Data : in out Project_Data);
278 -- If a list of sources is specified in attribute Interfaces, set
279 -- In_Interfaces only for the sources specified in the list.
281 procedure Check_Library_Attributes
282 (Project : Project_Id;
283 In_Tree : Project_Tree_Ref;
284 Current_Dir : String;
285 Data : in out Project_Data);
286 -- Check the library attributes of project Project in project tree In_Tree
287 -- and modify its data Data accordingly.
288 -- Current_Dir should represent the current directory, and is passed for
289 -- efficiency to avoid system calls to recompute it.
291 procedure Check_Package_Naming
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Data : in out Project_Data);
295 -- Check package Naming of project Project in project tree In_Tree and
296 -- modify its data Data accordingly.
298 procedure Check_Programming_Languages
299 (In_Tree : Project_Tree_Ref;
300 Project : Project_Id;
301 Data : in out Project_Data);
302 -- Check attribute Languages for the project with data Data in project
303 -- tree In_Tree and set the components of Data for all the programming
304 -- languages indicated in attribute Languages, if any.
306 function Check_Project
308 Root_Project : Project_Id;
309 In_Tree : Project_Tree_Ref;
310 Extending : Boolean) return Boolean;
311 -- Returns True if P is Root_Project or, if Extending is True, a project
312 -- extended by Root_Project.
314 procedure Check_Stand_Alone_Library
315 (Project : Project_Id;
316 In_Tree : Project_Tree_Ref;
317 Data : in out Project_Data;
318 Current_Dir : String;
319 Extending : Boolean);
320 -- Check if project Project in project tree In_Tree is a Stand-Alone
321 -- Library project, and modify its data Data accordingly if it is one.
322 -- Current_Dir should represent the current directory, and is passed for
323 -- efficiency to avoid system calls to recompute it.
325 procedure Get_Path_Names_And_Record_Ada_Sources
326 (Project : Project_Id;
327 In_Tree : Project_Tree_Ref;
328 Data : in out Project_Data;
329 Current_Dir : String);
330 -- Find the path names of the source files in the Source_Names table
331 -- in the source directories and record those that are Ada sources.
333 function Compute_Directory_Last (Dir : String) return Natural;
334 -- Return the index of the last significant character in Dir. This is used
335 -- to avoid duplicate '/' (slash) characters at the end of directory names.
338 (Project : Project_Id;
339 In_Tree : Project_Tree_Ref;
341 Flag_Location : Source_Ptr);
342 -- Output an error message. If Error_Report is null, simply call
343 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
346 procedure Find_Ada_Sources
347 (Project : Project_Id;
348 In_Tree : Project_Tree_Ref;
349 Data : in out Project_Data;
350 Current_Dir : String);
351 -- Find all the Ada sources in all of the source directories of a project
352 -- Current_Dir should represent the current directory, and is passed for
353 -- efficiency to avoid system calls to recompute it.
355 procedure Search_Directories
356 (Project : Project_Id;
357 In_Tree : Project_Tree_Ref;
358 Data : in out Project_Data;
359 For_All_Sources : Boolean);
360 -- Search the source directories to find the sources.
361 -- If For_All_Sources is True, check each regular file name against the
362 -- naming schemes of the different languages. Otherwise consider only the
363 -- file names in the hash table Source_Names.
366 (Project : Project_Id;
367 In_Tree : Project_Tree_Ref;
368 Data : in out Project_Data;
370 File_Name : File_Name_Type;
371 Display_File_Name : File_Name_Type;
372 Source_Directory : String;
373 For_All_Sources : Boolean);
374 -- Check if file File_Name is a valid source of the project. This is used
375 -- in multi-language mode only.
376 -- When the file matches one of the naming schemes, it is added to
377 -- various htables through Add_Source and to Source_Paths_Htable.
379 -- Name is the name of the candidate file. It hasn't been normalized yet
380 -- and is the direct result of readdir().
382 -- File_Name is the same as Name, but has been normalized.
383 -- Display_File_Name, however, has not been normalized.
385 -- Source_Directory is the directory in which the file
386 -- was found. It hasn't been normalized (nor has had links resolved).
387 -- It should not end with a directory separator, to avoid duplicates
390 -- If For_All_Sources is True, then all possible file names are analyzed
391 -- otherwise only those currently set in the Source_Names htable.
393 procedure Check_Naming_Schemes
394 (In_Tree : Project_Tree_Ref;
395 Data : in out Project_Data;
397 File_Name : File_Name_Type;
398 Alternate_Languages : out Alternate_Language_Id;
399 Language : out Language_Index;
400 Language_Name : out Name_Id;
401 Display_Language_Name : out Name_Id;
403 Lang_Kind : out Language_Kind;
404 Kind : out Source_Kind);
405 -- Check if the file name File_Name conforms to one of the naming
406 -- schemes of the project.
408 -- If the file does not match one of the naming schemes, set Language
409 -- to No_Language_Index.
411 -- Filename is the name of the file being investigated. It has been
412 -- normalized (case-folded). File_Name is the same value.
414 procedure Free_Ada_Naming_Exceptions;
415 -- Free the internal hash tables used for checking naming exceptions
417 procedure Get_Directories
418 (Project : Project_Id;
419 In_Tree : Project_Tree_Ref;
420 Current_Dir : String;
421 Data : in out Project_Data);
422 -- 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 (Current_Dir : String;
445 Project : Project_Id;
446 In_Tree : Project_Tree_Ref;
447 Data : in out Project_Data);
448 -- Process the Source_Files and Source_List_File attributes, and store
449 -- 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 Externally_Built : Boolean := False);
485 -- Locate a directory. Name is the directory name. Parent is the root
486 -- directory, if Name a relative path name. Dir is set to the canonical
487 -- case path name of the directory, and Display is the directory path name
488 -- for display purposes. If the directory does not exist and Setup_Projects
489 -- is True and Create is a non null string, an attempt is made to create
490 -- the directory. If the directory does not exist and Setup_Projects is
491 -- false, then Dir and Display are set to No_Name.
493 -- Current_Dir should represent the current directory, and is passed for
494 -- efficiency to avoid system calls to recompute it.
496 procedure Look_For_Sources
497 (Project : Project_Id;
498 In_Tree : Project_Tree_Ref;
499 Data : in out Project_Data;
500 Current_Dir : String);
501 -- Find all the sources of project Project in project tree In_Tree and
502 -- update its Data accordingly.
504 -- Current_Dir should represent the current directory, and is passed for
505 -- efficiency to avoid system calls to recompute it.
507 function Path_Name_Of
508 (File_Name : File_Name_Type;
509 Directory : Path_Name_Type) return String;
510 -- Returns the path name of a (non project) file. Returns an empty string
511 -- if file cannot be found.
513 procedure Prepare_Ada_Naming_Exceptions
514 (List : Array_Element_Id;
515 In_Tree : Project_Tree_Ref;
516 Kind : Spec_Or_Body);
517 -- Prepare the internal hash tables used for checking naming exceptions
518 -- for Ada. Insert all elements of List in the tables.
520 function Project_Extends
521 (Extending : Project_Id;
522 Extended : Project_Id;
523 In_Tree : Project_Tree_Ref) return Boolean;
524 -- Returns True if Extending is extending Extended either directly or
527 procedure Record_Ada_Source
528 (File_Name : File_Name_Type;
529 Path_Name : Path_Name_Type;
530 Project : Project_Id;
531 In_Tree : Project_Tree_Ref;
532 Data : in out Project_Data;
533 Location : Source_Ptr;
534 Current_Source : in out String_List_Id;
535 Source_Recorded : in out Boolean;
536 Current_Dir : String);
537 -- Put a unit in the list of units of a project, if the file name
538 -- corresponds to a valid unit name.
540 -- Current_Dir should represent the current directory, and is passed for
541 -- efficiency to avoid system calls to recompute it.
543 procedure Remove_Source
545 Replaced_By : Source_Id;
546 Project : Project_Id;
547 Data : in out Project_Data;
548 In_Tree : Project_Tree_Ref);
551 procedure Report_No_Sources
552 (Project : Project_Id;
554 In_Tree : Project_Tree_Ref;
555 Location : Source_Ptr;
556 Continuation : Boolean := False);
557 -- Report an error or a warning depending on the value of When_No_Sources
558 -- when there are no sources for language Lang_Name.
560 procedure Show_Source_Dirs
561 (Data : Project_Data; In_Tree : Project_Tree_Ref);
562 -- List all the source directories of a project
564 procedure Warn_If_Not_Sources
565 (Project : Project_Id;
566 In_Tree : Project_Tree_Ref;
567 Conventions : Array_Element_Id;
569 Extending : Boolean);
570 -- Check that individual naming conventions apply to immediate sources of
571 -- the project. If not, issue a warning.
579 Data : in out Project_Data;
580 In_Tree : Project_Tree_Ref;
581 Project : Project_Id;
583 Lang_Id : Language_Index;
585 File_Name : File_Name_Type;
586 Display_File : File_Name_Type;
587 Lang_Kind : Language_Kind;
588 Naming_Exception : Boolean := False;
589 Path : Path_Name_Type := No_Path;
590 Display_Path : Path_Name_Type := No_Path;
591 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
592 Other_Part : Source_Id := No_Source;
593 Unit : Name_Id := No_Name;
595 Source_To_Replace : Source_Id := No_Source)
597 Source : constant Source_Id := Data.Last_Source;
598 Src_Data : Source_Data := No_Source_Data;
599 Config : constant Language_Config :=
600 In_Tree.Languages_Data.Table (Lang_Id).Config;
603 -- This is a new source so create an entry for it in the Sources table
605 Source_Data_Table.Increment_Last (In_Tree.Sources);
606 Id := Source_Data_Table.Last (In_Tree.Sources);
608 if Current_Verbosity = High then
609 Write_Str ("Adding source #");
611 Write_Str (", File : ");
612 Write_Str (Get_Name_String (File_Name));
614 if Lang_Kind = Unit_Based then
615 Write_Str (", Unit : ");
616 Write_Str (Get_Name_String (Unit));
622 Src_Data.Project := Project;
623 Src_Data.Language_Name := Lang;
624 Src_Data.Language := Lang_Id;
625 Src_Data.Lang_Kind := Lang_Kind;
626 Src_Data.Compiled := In_Tree.Languages_Data.Table
627 (Lang_Id).Config.Compiler_Driver /=
629 Src_Data.Kind := Kind;
630 Src_Data.Alternate_Languages := Alternate_Languages;
631 Src_Data.Other_Part := Other_Part;
633 Src_Data.Object_Exists := Config.Object_Generated;
634 Src_Data.Object_Linked := Config.Objects_Linked;
636 if Other_Part /= No_Source then
637 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
640 Src_Data.Unit := Unit;
641 Src_Data.Index := Index;
642 Src_Data.File := File_Name;
643 Src_Data.Display_File := Display_File;
644 Src_Data.Dependency := In_Tree.Languages_Data.Table
645 (Lang_Id).Config.Dependency_Kind;
646 Src_Data.Naming_Exception := Naming_Exception;
648 if Src_Data.Compiled and then Src_Data.Object_Exists then
650 Object_Name (File_Name, Config.Object_File_Suffix);
652 Dependency_Name (File_Name, Src_Data.Dependency);
653 Src_Data.Switches := Switches_Name (File_Name);
656 if Path /= No_Path then
657 Src_Data.Path := (Path, Display_Path);
658 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
661 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
664 if Unit /= No_Name then
665 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
668 -- Add the source to the global list
670 Src_Data.Next_In_Sources := In_Tree.First_Source;
671 In_Tree.First_Source := Id;
673 -- Add the source to the project list
675 if Source = No_Source then
676 Data.First_Source := Id;
678 In_Tree.Sources.Table (Source).Next_In_Project := Id;
681 Data.Last_Source := Id;
683 -- Add the source to the language list
685 Src_Data.Next_In_Lang :=
686 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
687 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
689 In_Tree.Sources.Table (Id) := Src_Data;
691 if Source_To_Replace /= No_Source then
692 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
700 function ALI_File_Name (Source : String) return String is
702 -- If the source name has an extension, then replace it with
705 for Index in reverse Source'First + 1 .. Source'Last loop
706 if Source (Index) = '.' then
707 return Source (Source'First .. Index - 1) & ALI_Suffix;
711 -- If there is no dot, or if it is the first character, just add the
714 return Source & ALI_Suffix;
722 (Project : Project_Id;
723 In_Tree : Project_Tree_Ref;
724 Report_Error : Put_Line_Access;
725 When_No_Sources : Error_Warning;
726 Current_Dir : String)
728 Data : Project_Data := In_Tree.Projects.Table (Project);
729 Extending : Boolean := False;
732 Nmsc.When_No_Sources := When_No_Sources;
733 Error_Report := Report_Error;
735 Recursive_Dirs.Reset;
737 Check_If_Externally_Built (Project, In_Tree, Data);
739 -- Object, exec and source directories
741 Get_Directories (Project, In_Tree, Current_Dir, Data);
743 -- Get the programming languages
745 Check_Programming_Languages (In_Tree, Project, Data);
747 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
750 "an abstract project needs to have no language, no sources " &
751 "or no source directories",
755 -- Check configuration in multi language mode
757 if Must_Check_Configuration then
758 Check_Configuration (Project, In_Tree, Data);
761 -- Library attributes
763 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
765 if Current_Verbosity = High then
766 Show_Source_Dirs (Data, In_Tree);
769 Check_Package_Naming (Project, In_Tree, Data);
771 Extending := Data.Extends /= No_Project;
773 Check_Naming_Schemes (Data, Project, In_Tree);
775 if Get_Mode = Ada_Only then
776 Prepare_Ada_Naming_Exceptions
777 (Data.Naming.Bodies, In_Tree, Body_Part);
778 Prepare_Ada_Naming_Exceptions
779 (Data.Naming.Specs, In_Tree, Specification);
784 if Data.Source_Dirs /= Nil_String then
785 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
787 if Get_Mode = Ada_Only then
789 -- Check that all individual naming conventions apply to sources
790 -- of this project file.
793 (Project, In_Tree, Data.Naming.Bodies,
795 Extending => Extending);
797 (Project, In_Tree, Data.Naming.Specs,
799 Extending => Extending);
801 elsif Get_Mode = Multi_Language and then
802 (not Data.Externally_Built) and then
806 Language : Language_Index;
808 Alt_Lang : Alternate_Language_Id;
809 Alt_Lang_Data : Alternate_Language_Data;
810 Continuation : Boolean := False;
813 Language := Data.First_Language_Processing;
814 while Language /= No_Language_Index loop
815 Source := Data.First_Source;
816 Source_Loop : while Source /= No_Source loop
818 Src_Data : Source_Data renames
819 In_Tree.Sources.Table (Source);
822 exit Source_Loop when Src_Data.Language = Language;
824 Alt_Lang := Src_Data.Alternate_Languages;
827 while Alt_Lang /= No_Alternate_Language loop
829 In_Tree.Alt_Langs.Table (Alt_Lang);
831 when Alt_Lang_Data.Language = Language;
832 Alt_Lang := Alt_Lang_Data.Next;
833 end loop Alternate_Loop;
835 Source := Src_Data.Next_In_Project;
837 end loop Source_Loop;
839 if Source = No_Source then
843 (In_Tree.Languages_Data.Table
844 (Language).Display_Name),
848 Continuation := True;
851 Language := In_Tree.Languages_Data.Table (Language).Next;
857 if Get_Mode = Multi_Language then
859 -- If a list of sources is specified in attribute Interfaces, set
860 -- In_Interfaces only for the sources specified in the list.
862 Check_Interfaces (Project, In_Tree, Data);
865 -- If it is a library project file, check if it is a standalone library
868 Check_Stand_Alone_Library
869 (Project, In_Tree, Data, Current_Dir, Extending);
872 -- Put the list of Mains, if any, in the project data
874 Get_Mains (Project, In_Tree, Data);
876 -- Update the project data in the Projects table
878 In_Tree.Projects.Table (Project) := Data;
880 Free_Ada_Naming_Exceptions;
887 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
888 The_Name : String := Name;
890 Need_Letter : Boolean := True;
891 Last_Underscore : Boolean := False;
892 OK : Boolean := The_Name'Length > 0;
895 function Is_Reserved (Name : Name_Id) return Boolean;
896 function Is_Reserved (S : String) return Boolean;
897 -- Check that the given name is not an Ada 95 reserved word. The reason
898 -- for the Ada 95 here is that we do not want to exclude the case of an
899 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
900 -- name would be rejected anyway by the compiler. That means there is no
901 -- requirement that the project file parser reject this.
907 function Is_Reserved (S : String) return Boolean is
910 Add_Str_To_Name_Buffer (S);
911 return Is_Reserved (Name_Find);
918 function Is_Reserved (Name : Name_Id) return Boolean is
920 if Get_Name_Table_Byte (Name) /= 0
921 and then Name /= Name_Project
922 and then Name /= Name_Extends
923 and then Name /= Name_External
924 and then Name not in Ada_2005_Reserved_Words
928 if Current_Verbosity = High then
929 Write_Str (The_Name);
930 Write_Line (" is an Ada reserved word.");
940 -- Start of processing for Check_Ada_Name
945 Name_Len := The_Name'Length;
946 Name_Buffer (1 .. Name_Len) := The_Name;
948 -- Special cases of children of packages A, G, I and S on VMS
951 and then Name_Len > 3
952 and then Name_Buffer (2 .. 3) = "__"
954 ((Name_Buffer (1) = 'a') or else
955 (Name_Buffer (1) = 'g') or else
956 (Name_Buffer (1) = 'i') or else
957 (Name_Buffer (1) = 's'))
959 Name_Buffer (2) := '.';
960 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
961 Name_Len := Name_Len - 1;
964 Real_Name := Name_Find;
966 if Is_Reserved (Real_Name) then
970 First := The_Name'First;
972 for Index in The_Name'Range loop
975 -- We need a letter (at the beginning, and following a dot),
976 -- but we don't have one.
978 if Is_Letter (The_Name (Index)) then
979 Need_Letter := False;
984 if Current_Verbosity = High then
985 Write_Int (Types.Int (Index));
987 Write_Char (The_Name (Index));
988 Write_Line ("' is not a letter.");
994 elsif Last_Underscore
995 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
997 -- Two underscores are illegal, and a dot cannot follow
1002 if Current_Verbosity = High then
1003 Write_Int (Types.Int (Index));
1005 Write_Char (The_Name (Index));
1006 Write_Line ("' is illegal here.");
1011 elsif The_Name (Index) = '.' then
1013 -- First, check if the name before the dot is not a reserved word
1014 if Is_Reserved (The_Name (First .. Index - 1)) then
1020 -- We need a letter after a dot
1022 Need_Letter := True;
1024 elsif The_Name (Index) = '_' then
1025 Last_Underscore := True;
1028 -- We need an letter or a digit
1030 Last_Underscore := False;
1032 if not Is_Alphanumeric (The_Name (Index)) then
1035 if Current_Verbosity = High then
1036 Write_Int (Types.Int (Index));
1038 Write_Char (The_Name (Index));
1039 Write_Line ("' is not alphanumeric.");
1047 -- Cannot end with an underscore or a dot
1049 OK := OK and then not Need_Letter and then not Last_Underscore;
1052 if First /= Name'First and then
1053 Is_Reserved (The_Name (First .. The_Name'Last))
1061 -- Signal a problem with No_Name
1067 --------------------------------------
1068 -- Check_Ada_Naming_Scheme_Validity --
1069 --------------------------------------
1071 procedure Check_Ada_Naming_Scheme_Validity
1072 (Project : Project_Id;
1073 In_Tree : Project_Tree_Ref;
1074 Naming : Naming_Data)
1077 -- Only check if we are not using the Default naming scheme
1079 if Naming /= In_Tree.Private_Part.Default_Naming then
1081 Dot_Replacement : constant String :=
1083 (Naming.Dot_Replacement);
1085 Spec_Suffix : constant String :=
1086 Spec_Suffix_Of (In_Tree, "ada", Naming);
1088 Body_Suffix : constant String :=
1089 Body_Suffix_Of (In_Tree, "ada", Naming);
1091 Separate_Suffix : constant String :=
1093 (Naming.Separate_Suffix);
1096 -- Dot_Replacement cannot
1099 -- - start or end with an alphanumeric
1100 -- - be a single '_'
1101 -- - start with an '_' followed by an alphanumeric
1102 -- - contain a '.' except if it is "."
1104 if Dot_Replacement'Length = 0
1105 or else Is_Alphanumeric
1106 (Dot_Replacement (Dot_Replacement'First))
1107 or else Is_Alphanumeric
1108 (Dot_Replacement (Dot_Replacement'Last))
1109 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1111 (Dot_Replacement'Length = 1
1114 (Dot_Replacement (Dot_Replacement'First + 1))))
1115 or else (Dot_Replacement'Length > 1
1117 Index (Source => Dot_Replacement,
1118 Pattern => ".") /= 0)
1122 '"' & Dot_Replacement &
1123 """ is illegal for Dot_Replacement.",
1124 Naming.Dot_Repl_Loc);
1130 if Is_Illegal_Suffix
1131 (Spec_Suffix, Dot_Replacement = ".")
1133 Err_Vars.Error_Msg_File_1 :=
1134 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1137 "{ is illegal for Spec_Suffix",
1138 Naming.Ada_Spec_Suffix_Loc);
1141 if Is_Illegal_Suffix
1142 (Body_Suffix, Dot_Replacement = ".")
1144 Err_Vars.Error_Msg_File_1 :=
1145 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1148 "{ is illegal for Body_Suffix",
1149 Naming.Ada_Body_Suffix_Loc);
1152 if Body_Suffix /= Separate_Suffix then
1153 if Is_Illegal_Suffix
1154 (Separate_Suffix, Dot_Replacement = ".")
1156 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1159 "{ is illegal for Separate_Suffix",
1160 Naming.Sep_Suffix_Loc);
1164 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1165 -- since that would cause a clear ambiguity. Note that we do
1166 -- allow a Spec_Suffix to have the same termination as one of
1167 -- these, which causes a potential ambiguity, but we resolve
1168 -- that my matching the longest possible suffix.
1170 if Spec_Suffix = Body_Suffix then
1175 """) cannot be the same as Spec_Suffix.",
1176 Naming.Ada_Body_Suffix_Loc);
1179 if Body_Suffix /= Separate_Suffix
1180 and then Spec_Suffix = Separate_Suffix
1184 "Separate_Suffix (""" &
1186 """) cannot be the same as Spec_Suffix.",
1187 Naming.Sep_Suffix_Loc);
1191 end Check_Ada_Naming_Scheme_Validity;
1193 -------------------------
1194 -- Check_Configuration --
1195 -------------------------
1197 procedure Check_Configuration
1198 (Project : Project_Id;
1199 In_Tree : Project_Tree_Ref;
1200 Data : in out Project_Data)
1202 Dot_Replacement : File_Name_Type := No_File;
1203 Casing : Casing_Type := All_Lower_Case;
1204 Separate_Suffix : File_Name_Type := No_File;
1206 Lang_Index : Language_Index := No_Language_Index;
1207 -- The index of the language data being checked
1209 Prev_Index : Language_Index := No_Language_Index;
1210 -- The index of the previous language
1212 Current_Language : Name_Id := No_Name;
1213 -- The name of the language
1215 Lang_Data : Language_Data;
1216 -- The data of the language being checked
1218 procedure Get_Language_Index_Of (Language : Name_Id);
1219 -- Get the language index of Language, if Language is one of the
1220 -- languages of the project.
1222 procedure Process_Project_Level_Simple_Attributes;
1223 -- Process the simple attributes at the project level
1225 procedure Process_Project_Level_Array_Attributes;
1226 -- Process the associate array attributes at the project level
1228 procedure Process_Packages;
1229 -- Read the packages of the project
1231 ---------------------------
1232 -- Get_Language_Index_Of --
1233 ---------------------------
1235 procedure Get_Language_Index_Of (Language : Name_Id) is
1236 Real_Language : Name_Id;
1239 Get_Name_String (Language);
1240 To_Lower (Name_Buffer (1 .. Name_Len));
1241 Real_Language := Name_Find;
1243 -- Nothing to do if the language is the same as the current language
1245 if Current_Language /= Real_Language then
1246 Lang_Index := Data.First_Language_Processing;
1247 while Lang_Index /= No_Language_Index loop
1248 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1251 In_Tree.Languages_Data.Table (Lang_Index).Next;
1254 if Lang_Index = No_Language_Index then
1255 Current_Language := No_Name;
1257 Current_Language := Real_Language;
1260 end Get_Language_Index_Of;
1262 ----------------------
1263 -- Process_Packages --
1264 ----------------------
1266 procedure Process_Packages is
1267 Packages : Package_Id;
1268 Element : Package_Element;
1270 procedure Process_Binder (Arrays : Array_Id);
1271 -- Process the associate array attributes of package Binder
1273 procedure Process_Builder (Attributes : Variable_Id);
1274 -- Process the simple attributes of package Builder
1276 procedure Process_Compiler (Arrays : Array_Id);
1277 -- Process the associate array attributes of package Compiler
1279 procedure Process_Naming (Attributes : Variable_Id);
1280 -- Process the simple attributes of package Naming
1282 procedure Process_Naming (Arrays : Array_Id);
1283 -- Process the associate array attributes of package Naming
1285 procedure Process_Linker (Attributes : Variable_Id);
1286 -- Process the simple attributes of package Linker of a
1287 -- configuration project.
1289 --------------------
1290 -- Process_Binder --
1291 --------------------
1293 procedure Process_Binder (Arrays : Array_Id) is
1294 Current_Array_Id : Array_Id;
1295 Current_Array : Array_Data;
1296 Element_Id : Array_Element_Id;
1297 Element : Array_Element;
1300 -- Process the associative array attribute of package Binder
1302 Current_Array_Id := Arrays;
1303 while Current_Array_Id /= No_Array loop
1304 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1306 Element_Id := Current_Array.Value;
1307 while Element_Id /= No_Array_Element loop
1308 Element := In_Tree.Array_Elements.Table (Element_Id);
1310 if Element.Index /= All_Other_Names then
1312 -- Get the name of the language
1314 Get_Language_Index_Of (Element.Index);
1316 if Lang_Index /= No_Language_Index then
1317 case Current_Array.Name is
1320 -- Attribute Driver (<language>)
1322 In_Tree.Languages_Data.Table
1323 (Lang_Index).Config.Binder_Driver :=
1324 File_Name_Type (Element.Value.Value);
1326 when Name_Required_Switches =>
1328 In_Tree.Languages_Data.Table
1329 (Lang_Index).Config.Binder_Required_Switches,
1330 From_List => Element.Value.Values,
1331 In_Tree => In_Tree);
1335 -- Attribute Prefix (<language>)
1337 In_Tree.Languages_Data.Table
1338 (Lang_Index).Config.Binder_Prefix :=
1339 Element.Value.Value;
1341 when Name_Objects_Path =>
1343 -- Attribute Objects_Path (<language>)
1345 In_Tree.Languages_Data.Table
1346 (Lang_Index).Config.Objects_Path :=
1347 Element.Value.Value;
1349 when Name_Objects_Path_File =>
1351 -- Attribute Objects_Path (<language>)
1353 In_Tree.Languages_Data.Table
1354 (Lang_Index).Config.Objects_Path_File :=
1355 Element.Value.Value;
1363 Element_Id := Element.Next;
1366 Current_Array_Id := Current_Array.Next;
1370 ---------------------
1371 -- Process_Builder --
1372 ---------------------
1374 procedure Process_Builder (Attributes : Variable_Id) is
1375 Attribute_Id : Variable_Id;
1376 Attribute : Variable;
1379 -- Process non associated array attribute from package Builder
1381 Attribute_Id := Attributes;
1382 while Attribute_Id /= No_Variable loop
1384 In_Tree.Variable_Elements.Table (Attribute_Id);
1386 if not Attribute.Value.Default then
1387 if Attribute.Name = Name_Executable_Suffix then
1389 -- Attribute Executable_Suffix: the suffix of the
1392 Data.Config.Executable_Suffix :=
1393 Attribute.Value.Value;
1397 Attribute_Id := Attribute.Next;
1399 end Process_Builder;
1401 ----------------------
1402 -- Process_Compiler --
1403 ----------------------
1405 procedure Process_Compiler (Arrays : Array_Id) is
1406 Current_Array_Id : Array_Id;
1407 Current_Array : Array_Data;
1408 Element_Id : Array_Element_Id;
1409 Element : Array_Element;
1410 List : String_List_Id;
1413 -- Process the associative array attribute of package Compiler
1415 Current_Array_Id := Arrays;
1416 while Current_Array_Id /= No_Array loop
1417 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1419 Element_Id := Current_Array.Value;
1420 while Element_Id /= No_Array_Element loop
1421 Element := In_Tree.Array_Elements.Table (Element_Id);
1423 if Element.Index /= All_Other_Names then
1425 -- Get the name of the language
1427 Get_Language_Index_Of (Element.Index);
1429 if Lang_Index /= No_Language_Index then
1430 case Current_Array.Name is
1431 when Name_Dependency_Switches =>
1433 -- Attribute Dependency_Switches (<language>)
1435 if In_Tree.Languages_Data.Table
1436 (Lang_Index).Config.Dependency_Kind = None
1438 In_Tree.Languages_Data.Table
1439 (Lang_Index).Config.Dependency_Kind :=
1443 List := Element.Value.Values;
1445 if List /= Nil_String then
1447 In_Tree.Languages_Data.Table
1448 (Lang_Index).Config.Dependency_Option,
1450 In_Tree => In_Tree);
1453 when Name_Dependency_Driver =>
1455 -- Attribute Dependency_Driver (<language>)
1457 if In_Tree.Languages_Data.Table
1458 (Lang_Index).Config.Dependency_Kind = None
1460 In_Tree.Languages_Data.Table
1461 (Lang_Index).Config.Dependency_Kind :=
1465 List := Element.Value.Values;
1467 if List /= Nil_String then
1469 In_Tree.Languages_Data.Table
1470 (Lang_Index).Config.Compute_Dependency,
1472 In_Tree => In_Tree);
1475 when Name_Include_Switches =>
1477 -- Attribute Include_Switches (<language>)
1479 List := Element.Value.Values;
1481 if List = Nil_String then
1485 "include option cannot be null",
1486 Element.Value.Location);
1490 In_Tree.Languages_Data.Table
1491 (Lang_Index).Config.Include_Option,
1493 In_Tree => In_Tree);
1495 when Name_Include_Path =>
1497 -- Attribute Include_Path (<language>)
1499 In_Tree.Languages_Data.Table
1500 (Lang_Index).Config.Include_Path :=
1501 Element.Value.Value;
1503 when Name_Include_Path_File =>
1505 -- Attribute Include_Path_File (<language>)
1507 In_Tree.Languages_Data.Table
1508 (Lang_Index).Config.Include_Path_File :=
1509 Element.Value.Value;
1513 -- Attribute Driver (<language>)
1515 Get_Name_String (Element.Value.Value);
1517 In_Tree.Languages_Data.Table
1518 (Lang_Index).Config.Compiler_Driver :=
1519 File_Name_Type (Element.Value.Value);
1521 when Name_Required_Switches =>
1523 In_Tree.Languages_Data.Table
1524 (Lang_Index).Config.
1525 Compiler_Required_Switches,
1526 From_List => Element.Value.Values,
1527 In_Tree => In_Tree);
1529 when Name_Path_Syntax =>
1531 In_Tree.Languages_Data.Table
1532 (Lang_Index).Config.Path_Syntax :=
1533 Path_Syntax_Kind'Value
1534 (Get_Name_String (Element.Value.Value));
1537 when Constraint_Error =>
1541 "invalid value for Path_Syntax",
1542 Element.Value.Location);
1545 when Name_Object_File_Suffix =>
1546 if Get_Name_String (Element.Value.Value) = "" then
1549 "object file suffix cannot be empty",
1550 Element.Value.Location);
1553 In_Tree.Languages_Data.Table
1554 (Lang_Index).Config.Object_File_Suffix :=
1555 Element.Value.Value;
1558 when Name_Pic_Option =>
1560 -- Attribute Compiler_Pic_Option (<language>)
1562 List := Element.Value.Values;
1564 if List = Nil_String then
1568 "compiler PIC option cannot be null",
1569 Element.Value.Location);
1573 In_Tree.Languages_Data.Table
1574 (Lang_Index).Config.Compilation_PIC_Option,
1576 In_Tree => In_Tree);
1578 when Name_Mapping_File_Switches =>
1580 -- Attribute Mapping_File_Switches (<language>)
1582 List := Element.Value.Values;
1584 if List = Nil_String then
1588 "mapping file switches cannot be null",
1589 Element.Value.Location);
1593 In_Tree.Languages_Data.Table
1594 (Lang_Index).Config.Mapping_File_Switches,
1596 In_Tree => In_Tree);
1598 when Name_Mapping_Spec_Suffix =>
1600 -- Attribute Mapping_Spec_Suffix (<language>)
1602 In_Tree.Languages_Data.Table
1603 (Lang_Index).Config.Mapping_Spec_Suffix :=
1604 File_Name_Type (Element.Value.Value);
1606 when Name_Mapping_Body_Suffix =>
1608 -- Attribute Mapping_Body_Suffix (<language>)
1610 In_Tree.Languages_Data.Table
1611 (Lang_Index).Config.Mapping_Body_Suffix :=
1612 File_Name_Type (Element.Value.Value);
1614 when Name_Config_File_Switches =>
1616 -- Attribute Config_File_Switches (<language>)
1618 List := Element.Value.Values;
1620 if List = Nil_String then
1624 "config file switches cannot be null",
1625 Element.Value.Location);
1629 In_Tree.Languages_Data.Table
1630 (Lang_Index).Config.Config_File_Switches,
1632 In_Tree => In_Tree);
1634 when Name_Objects_Path =>
1636 -- Attribute Objects_Path (<language>)
1638 In_Tree.Languages_Data.Table
1639 (Lang_Index).Config.Objects_Path :=
1640 Element.Value.Value;
1642 when Name_Objects_Path_File =>
1644 -- Attribute Objects_Path_File (<language>)
1646 In_Tree.Languages_Data.Table
1647 (Lang_Index).Config.Objects_Path_File :=
1648 Element.Value.Value;
1650 when Name_Config_Body_File_Name =>
1652 -- Attribute Config_Body_File_Name (<language>)
1654 In_Tree.Languages_Data.Table
1655 (Lang_Index).Config.Config_Body :=
1656 Element.Value.Value;
1658 when Name_Config_Body_File_Name_Pattern =>
1660 -- Attribute Config_Body_File_Name_Pattern
1663 In_Tree.Languages_Data.Table
1664 (Lang_Index).Config.Config_Body_Pattern :=
1665 Element.Value.Value;
1667 when Name_Config_Spec_File_Name =>
1669 -- Attribute Config_Spec_File_Name (<language>)
1671 In_Tree.Languages_Data.Table
1672 (Lang_Index).Config.Config_Spec :=
1673 Element.Value.Value;
1675 when Name_Config_Spec_File_Name_Pattern =>
1677 -- Attribute Config_Spec_File_Name_Pattern
1680 In_Tree.Languages_Data.Table
1681 (Lang_Index).Config.Config_Spec_Pattern :=
1682 Element.Value.Value;
1684 when Name_Config_File_Unique =>
1686 -- Attribute Config_File_Unique (<language>)
1689 In_Tree.Languages_Data.Table
1690 (Lang_Index).Config.Config_File_Unique :=
1692 (Get_Name_String (Element.Value.Value));
1694 when Constraint_Error =>
1698 "illegal value for Config_File_Unique",
1699 Element.Value.Location);
1708 Element_Id := Element.Next;
1711 Current_Array_Id := Current_Array.Next;
1713 end Process_Compiler;
1715 --------------------
1716 -- Process_Naming --
1717 --------------------
1719 procedure Process_Naming (Attributes : Variable_Id) is
1720 Attribute_Id : Variable_Id;
1721 Attribute : Variable;
1724 -- Process non associated array attribute from package Naming
1726 Attribute_Id := Attributes;
1727 while Attribute_Id /= No_Variable loop
1728 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1730 if not Attribute.Value.Default then
1731 if Attribute.Name = Name_Separate_Suffix then
1733 -- Attribute Separate_Suffix
1735 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1737 elsif Attribute.Name = Name_Casing then
1743 Value (Get_Name_String (Attribute.Value.Value));
1746 when Constraint_Error =>
1750 "invalid value for Casing",
1751 Attribute.Value.Location);
1754 elsif Attribute.Name = Name_Dot_Replacement then
1756 -- Attribute Dot_Replacement
1758 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1763 Attribute_Id := Attribute.Next;
1767 procedure Process_Naming (Arrays : Array_Id) is
1768 Current_Array_Id : Array_Id;
1769 Current_Array : Array_Data;
1770 Element_Id : Array_Element_Id;
1771 Element : Array_Element;
1773 -- Process the associative array attribute of package Naming
1775 Current_Array_Id := Arrays;
1776 while Current_Array_Id /= No_Array loop
1777 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1779 Element_Id := Current_Array.Value;
1780 while Element_Id /= No_Array_Element loop
1781 Element := In_Tree.Array_Elements.Table (Element_Id);
1783 -- Get the name of the language
1785 Get_Language_Index_Of (Element.Index);
1787 if Lang_Index /= No_Language_Index then
1788 case Current_Array.Name is
1789 when Name_Specification_Suffix | Name_Spec_Suffix =>
1791 -- Attribute Spec_Suffix (<language>)
1793 In_Tree.Languages_Data.Table
1794 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1795 File_Name_Type (Element.Value.Value);
1797 when Name_Implementation_Suffix | Name_Body_Suffix =>
1799 -- Attribute Body_Suffix (<language>)
1801 In_Tree.Languages_Data.Table
1802 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1803 File_Name_Type (Element.Value.Value);
1805 In_Tree.Languages_Data.Table
1806 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1807 File_Name_Type (Element.Value.Value);
1814 Element_Id := Element.Next;
1817 Current_Array_Id := Current_Array.Next;
1821 --------------------
1822 -- Process_Linker --
1823 --------------------
1825 procedure Process_Linker (Attributes : Variable_Id) is
1826 Attribute_Id : Variable_Id;
1827 Attribute : Variable;
1830 -- Process non associated array attribute from package Linker
1832 Attribute_Id := Attributes;
1833 while Attribute_Id /= No_Variable loop
1835 In_Tree.Variable_Elements.Table (Attribute_Id);
1837 if not Attribute.Value.Default then
1838 if Attribute.Name = Name_Driver then
1840 -- Attribute Linker'Driver: the default linker to use
1842 Data.Config.Linker :=
1843 Path_Name_Type (Attribute.Value.Value);
1845 elsif Attribute.Name = Name_Required_Switches then
1847 -- Attribute Required_Switches: the minimum
1848 -- options to use when invoking the linker
1851 Data.Config.Minimum_Linker_Options,
1852 From_List => Attribute.Value.Values,
1853 In_Tree => In_Tree);
1855 elsif Attribute.Name = Name_Map_File_Option then
1856 Data.Config.Map_File_Option := Attribute.Value.Value;
1858 elsif Attribute.Name = Name_Max_Command_Line_Length then
1860 Data.Config.Max_Command_Line_Length :=
1861 Natural'Value (Get_Name_String
1862 (Attribute.Value.Value));
1865 when Constraint_Error =>
1869 "value must be positive or equal to 0",
1870 Attribute.Value.Location);
1873 elsif Attribute.Name = Name_Response_File_Format then
1878 Get_Name_String (Attribute.Value.Value);
1879 To_Lower (Name_Buffer (1 .. Name_Len));
1882 if Name = Name_None then
1883 Data.Config.Resp_File_Format := None;
1885 elsif Name = Name_Gnu then
1886 Data.Config.Resp_File_Format := GNU;
1888 elsif Name = Name_Object_List then
1889 Data.Config.Resp_File_Format := Object_List;
1891 elsif Name = Name_Option_List then
1892 Data.Config.Resp_File_Format := Option_List;
1898 "illegal response file format",
1899 Attribute.Value.Location);
1903 elsif Attribute.Name = Name_Response_File_Switches then
1905 Data.Config.Resp_File_Options,
1906 From_List => Attribute.Value.Values,
1907 In_Tree => In_Tree);
1911 Attribute_Id := Attribute.Next;
1915 -- Start of processing for Process_Packages
1918 Packages := Data.Decl.Packages;
1919 while Packages /= No_Package loop
1920 Element := In_Tree.Packages.Table (Packages);
1922 case Element.Name is
1925 -- Process attributes of package Binder
1927 Process_Binder (Element.Decl.Arrays);
1929 when Name_Builder =>
1931 -- Process attributes of package Builder
1933 Process_Builder (Element.Decl.Attributes);
1935 when Name_Compiler =>
1937 -- Process attributes of package Compiler
1939 Process_Compiler (Element.Decl.Arrays);
1943 -- Process attributes of package Linker
1945 Process_Linker (Element.Decl.Attributes);
1949 -- Process attributes of package Naming
1951 Process_Naming (Element.Decl.Attributes);
1952 Process_Naming (Element.Decl.Arrays);
1958 Packages := Element.Next;
1960 end Process_Packages;
1962 ---------------------------------------------
1963 -- Process_Project_Level_Simple_Attributes --
1964 ---------------------------------------------
1966 procedure Process_Project_Level_Simple_Attributes is
1967 Attribute_Id : Variable_Id;
1968 Attribute : Variable;
1969 List : String_List_Id;
1972 -- Process non associated array attribute at project level
1974 Attribute_Id := Data.Decl.Attributes;
1975 while Attribute_Id /= No_Variable loop
1977 In_Tree.Variable_Elements.Table (Attribute_Id);
1979 if not Attribute.Value.Default then
1980 if Attribute.Name = Name_Library_Builder then
1982 -- Attribute Library_Builder: the application to invoke
1983 -- to build libraries.
1985 Data.Config.Library_Builder :=
1986 Path_Name_Type (Attribute.Value.Value);
1988 elsif Attribute.Name = Name_Archive_Builder then
1990 -- Attribute Archive_Builder: the archive builder
1991 -- (usually "ar") and its minimum options (usually "cr").
1993 List := Attribute.Value.Values;
1995 if List = Nil_String then
1999 "archive builder cannot be null",
2000 Attribute.Value.Location);
2003 Put (Into_List => Data.Config.Archive_Builder,
2005 In_Tree => In_Tree);
2007 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
2009 -- Attribute Archive_Builder: the archive builder
2010 -- (usually "ar") and its minimum options (usually "cr").
2012 List := Attribute.Value.Values;
2014 if List /= Nil_String then
2016 (Into_List => Data.Config.Archive_Builder_Append_Option,
2018 In_Tree => In_Tree);
2021 elsif Attribute.Name = Name_Archive_Indexer then
2023 -- Attribute Archive_Indexer: the optional archive
2024 -- indexer (usually "ranlib") with its minimum options
2027 List := Attribute.Value.Values;
2029 if List = Nil_String then
2033 "archive indexer cannot be null",
2034 Attribute.Value.Location);
2037 Put (Into_List => Data.Config.Archive_Indexer,
2039 In_Tree => In_Tree);
2041 elsif Attribute.Name = Name_Library_Partial_Linker then
2043 -- Attribute Library_Partial_Linker: the optional linker
2044 -- driver with its minimum options, to partially link
2047 List := Attribute.Value.Values;
2049 if List = Nil_String then
2053 "partial linker cannot be null",
2054 Attribute.Value.Location);
2057 Put (Into_List => Data.Config.Lib_Partial_Linker,
2059 In_Tree => In_Tree);
2061 elsif Attribute.Name = Name_Library_GCC then
2062 Data.Config.Shared_Lib_Driver :=
2063 File_Name_Type (Attribute.Value.Value);
2065 elsif Attribute.Name = Name_Archive_Suffix then
2066 Data.Config.Archive_Suffix :=
2067 File_Name_Type (Attribute.Value.Value);
2069 elsif Attribute.Name = Name_Linker_Executable_Option then
2071 -- Attribute Linker_Executable_Option: optional options
2072 -- to specify an executable name. Defaults to "-o".
2074 List := Attribute.Value.Values;
2076 if List = Nil_String then
2080 "linker executable option cannot be null",
2081 Attribute.Value.Location);
2084 Put (Into_List => Data.Config.Linker_Executable_Option,
2086 In_Tree => In_Tree);
2088 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2090 -- Attribute Linker_Lib_Dir_Option: optional options
2091 -- to specify a library search directory. Defaults to
2094 Get_Name_String (Attribute.Value.Value);
2096 if Name_Len = 0 then
2100 "linker library directory option cannot be empty",
2101 Attribute.Value.Location);
2104 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2106 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2108 -- Attribute Linker_Lib_Name_Option: optional options
2109 -- to specify the name of a library to be linked in.
2110 -- Defaults to "-l".
2112 Get_Name_String (Attribute.Value.Value);
2114 if Name_Len = 0 then
2118 "linker library name option cannot be empty",
2119 Attribute.Value.Location);
2122 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2124 elsif Attribute.Name = Name_Run_Path_Option then
2126 -- Attribute Run_Path_Option: optional options to
2127 -- specify a path for libraries.
2129 List := Attribute.Value.Values;
2131 if List /= Nil_String then
2132 Put (Into_List => Data.Config.Run_Path_Option,
2134 In_Tree => In_Tree);
2137 elsif Attribute.Name = Name_Library_Support then
2139 pragma Unsuppress (All_Checks);
2141 Data.Config.Lib_Support :=
2142 Library_Support'Value (Get_Name_String
2143 (Attribute.Value.Value));
2145 when Constraint_Error =>
2149 "invalid value """ &
2150 Get_Name_String (Attribute.Value.Value) &
2151 """ for Library_Support",
2152 Attribute.Value.Location);
2155 elsif Attribute.Name = Name_Shared_Library_Prefix then
2156 Data.Config.Shared_Lib_Prefix :=
2157 File_Name_Type (Attribute.Value.Value);
2159 elsif Attribute.Name = Name_Shared_Library_Suffix then
2160 Data.Config.Shared_Lib_Suffix :=
2161 File_Name_Type (Attribute.Value.Value);
2163 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2165 pragma Unsuppress (All_Checks);
2167 Data.Config.Symbolic_Link_Supported :=
2168 Boolean'Value (Get_Name_String
2169 (Attribute.Value.Value));
2171 when Constraint_Error =>
2176 & Get_Name_String (Attribute.Value.Value)
2177 & """ for Symbolic_Link_Supported",
2178 Attribute.Value.Location);
2182 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2185 pragma Unsuppress (All_Checks);
2187 Data.Config.Lib_Maj_Min_Id_Supported :=
2188 Boolean'Value (Get_Name_String
2189 (Attribute.Value.Value));
2191 when Constraint_Error =>
2195 "invalid value """ &
2196 Get_Name_String (Attribute.Value.Value) &
2197 """ for Library_Major_Minor_Id_Supported",
2198 Attribute.Value.Location);
2201 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2203 pragma Unsuppress (All_Checks);
2205 Data.Config.Auto_Init_Supported :=
2206 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2208 when Constraint_Error =>
2213 & Get_Name_String (Attribute.Value.Value)
2214 & """ for Library_Auto_Init_Supported",
2215 Attribute.Value.Location);
2218 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2219 List := Attribute.Value.Values;
2221 if List /= Nil_String then
2222 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2224 In_Tree => In_Tree);
2227 elsif Attribute.Name = Name_Library_Version_Switches then
2228 List := Attribute.Value.Values;
2230 if List /= Nil_String then
2231 Put (Into_List => Data.Config.Lib_Version_Options,
2233 In_Tree => In_Tree);
2238 Attribute_Id := Attribute.Next;
2240 end Process_Project_Level_Simple_Attributes;
2242 --------------------------------------------
2243 -- Process_Project_Level_Array_Attributes --
2244 --------------------------------------------
2246 procedure Process_Project_Level_Array_Attributes is
2247 Current_Array_Id : Array_Id;
2248 Current_Array : Array_Data;
2249 Element_Id : Array_Element_Id;
2250 Element : Array_Element;
2251 List : String_List_Id;
2254 -- Process the associative array attributes at project level
2256 Current_Array_Id := Data.Decl.Arrays;
2257 while Current_Array_Id /= No_Array loop
2258 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2260 Element_Id := Current_Array.Value;
2261 while Element_Id /= No_Array_Element loop
2262 Element := In_Tree.Array_Elements.Table (Element_Id);
2264 -- Get the name of the language
2266 Get_Language_Index_Of (Element.Index);
2268 if Lang_Index /= No_Language_Index then
2269 case Current_Array.Name is
2270 when Name_Inherit_Source_Path =>
2271 List := Element.Value.Values;
2273 if List /= Nil_String then
2276 In_Tree.Languages_Data.Table (Lang_Index).
2277 Config.Include_Compatible_Languages,
2280 Lower_Case => True);
2283 when Name_Toolchain_Description =>
2285 -- Attribute Toolchain_Description (<language>)
2287 In_Tree.Languages_Data.Table
2288 (Lang_Index).Config.Toolchain_Description :=
2289 Element.Value.Value;
2291 when Name_Toolchain_Version =>
2293 -- Attribute Toolchain_Version (<language>)
2295 In_Tree.Languages_Data.Table
2296 (Lang_Index).Config.Toolchain_Version :=
2297 Element.Value.Value;
2299 when Name_Runtime_Library_Dir =>
2301 -- Attribute Runtime_Library_Dir (<language>)
2303 In_Tree.Languages_Data.Table
2304 (Lang_Index).Config.Runtime_Library_Dir :=
2305 Element.Value.Value;
2307 when Name_Runtime_Source_Dir =>
2309 -- Attribute Runtime_Library_Dir (<language>)
2311 In_Tree.Languages_Data.Table
2312 (Lang_Index).Config.Runtime_Source_Dir :=
2313 Element.Value.Value;
2315 when Name_Object_Generated =>
2317 pragma Unsuppress (All_Checks);
2323 (Get_Name_String (Element.Value.Value));
2325 In_Tree.Languages_Data.Table
2326 (Lang_Index).Config.Object_Generated := Value;
2328 -- If no object is generated, no object may be
2332 In_Tree.Languages_Data.Table
2333 (Lang_Index).Config.Objects_Linked := False;
2337 when Constraint_Error =>
2342 & Get_Name_String (Element.Value.Value)
2343 & """ for Object_Generated",
2344 Element.Value.Location);
2347 when Name_Objects_Linked =>
2349 pragma Unsuppress (All_Checks);
2355 (Get_Name_String (Element.Value.Value));
2357 -- No change if Object_Generated is False, as this
2358 -- forces Objects_Linked to be False too.
2360 if In_Tree.Languages_Data.Table
2361 (Lang_Index).Config.Object_Generated
2363 In_Tree.Languages_Data.Table
2364 (Lang_Index).Config.Objects_Linked :=
2369 when Constraint_Error =>
2374 & Get_Name_String (Element.Value.Value)
2375 & """ for Objects_Linked",
2376 Element.Value.Location);
2383 Element_Id := Element.Next;
2386 Current_Array_Id := Current_Array.Next;
2388 end Process_Project_Level_Array_Attributes;
2391 Process_Project_Level_Simple_Attributes;
2392 Process_Project_Level_Array_Attributes;
2395 -- For unit based languages, set Casing, Dot_Replacement and
2396 -- Separate_Suffix in Naming_Data.
2398 Lang_Index := Data.First_Language_Processing;
2399 while Lang_Index /= No_Language_Index loop
2400 if In_Tree.Languages_Data.Table
2401 (Lang_Index).Name = Name_Ada
2403 In_Tree.Languages_Data.Table
2404 (Lang_Index).Config.Naming_Data.Casing := Casing;
2405 In_Tree.Languages_Data.Table
2406 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2409 if Separate_Suffix /= No_File then
2410 In_Tree.Languages_Data.Table
2411 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2418 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2421 -- Give empty names to various prefixes/suffixes, if they have not
2422 -- been specified in the configuration.
2424 if Data.Config.Archive_Suffix = No_File then
2425 Data.Config.Archive_Suffix := Empty_File;
2428 if Data.Config.Shared_Lib_Prefix = No_File then
2429 Data.Config.Shared_Lib_Prefix := Empty_File;
2432 if Data.Config.Shared_Lib_Suffix = No_File then
2433 Data.Config.Shared_Lib_Suffix := Empty_File;
2436 Lang_Index := Data.First_Language_Processing;
2437 while Lang_Index /= No_Language_Index loop
2438 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2440 Current_Language := Lang_Data.Display_Name;
2442 -- For all languages, Compiler_Driver needs to be specified
2444 if Lang_Data.Config.Compiler_Driver = No_File then
2445 Error_Msg_Name_1 := Current_Language;
2449 "?no compiler specified for language %%" &
2450 ", ignoring all its sources",
2453 if Lang_Index = Data.First_Language_Processing then
2454 Data.First_Language_Processing :=
2457 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2461 elsif Lang_Data.Name = Name_Ada then
2462 Prev_Index := Lang_Index;
2464 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2465 -- Body_Suffix need to be specified.
2467 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2471 "Dot_Replacement not specified for Ada",
2475 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2479 "Spec_Suffix not specified for Ada",
2483 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2487 "Body_Suffix not specified for Ada",
2492 Prev_Index := Lang_Index;
2494 -- For file based languages, either Spec_Suffix or Body_Suffix
2495 -- need to be specified.
2497 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2498 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2500 Error_Msg_Name_1 := Current_Language;
2504 "no suffixes specified for %%",
2509 Lang_Index := Lang_Data.Next;
2511 end Check_Configuration;
2513 -------------------------------
2514 -- Check_If_Externally_Built --
2515 -------------------------------
2517 procedure Check_If_Externally_Built
2518 (Project : Project_Id;
2519 In_Tree : Project_Tree_Ref;
2520 Data : in out Project_Data)
2522 Externally_Built : constant Variable_Value :=
2524 (Name_Externally_Built,
2525 Data.Decl.Attributes, In_Tree);
2528 if not Externally_Built.Default then
2529 Get_Name_String (Externally_Built.Value);
2530 To_Lower (Name_Buffer (1 .. Name_Len));
2532 if Name_Buffer (1 .. Name_Len) = "true" then
2533 Data.Externally_Built := True;
2535 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2536 Error_Msg (Project, In_Tree,
2537 "Externally_Built may only be true or false",
2538 Externally_Built.Location);
2542 -- A virtual project extending an externally built project is itself
2543 -- externally built.
2545 if Data.Virtual and then Data.Extends /= No_Project then
2546 Data.Externally_Built :=
2547 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2550 if Current_Verbosity = High then
2551 Write_Str ("Project is ");
2553 if not Data.Externally_Built then
2557 Write_Line ("externally built.");
2559 end Check_If_Externally_Built;
2561 ----------------------
2562 -- Check_Interfaces --
2563 ----------------------
2565 procedure Check_Interfaces
2566 (Project : Project_Id;
2567 In_Tree : Project_Tree_Ref;
2568 Data : in out Project_Data)
2570 Interfaces : constant Prj.Variable_Value :=
2572 (Snames.Name_Interfaces,
2573 Data.Decl.Attributes,
2576 List : String_List_Id;
2577 Element : String_Element;
2578 Name : File_Name_Type;
2582 Project_2 : Project_Id;
2583 Data_2 : Project_Data;
2586 if not Interfaces.Default then
2588 -- Set In_Interfaces to False for all sources. It will be set to True
2589 -- later for the sources in the Interfaces list.
2591 Project_2 := Project;
2594 Source := Data_2.First_Source;
2595 while Source /= No_Source loop
2597 Src_Data : Source_Data renames
2598 In_Tree.Sources.Table (Source);
2600 Src_Data.In_Interfaces := False;
2601 Source := Src_Data.Next_In_Project;
2605 Project_2 := Data_2.Extends;
2607 exit when Project_2 = No_Project;
2609 Data_2 := In_Tree.Projects.Table (Project_2);
2612 List := Interfaces.Values;
2613 while List /= Nil_String loop
2614 Element := In_Tree.String_Elements.Table (List);
2615 Get_Name_String (Element.Value);
2616 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2619 Project_2 := Project;
2623 Source := Data_2.First_Source;
2624 while Source /= No_Source loop
2626 Src_Data : Source_Data renames
2627 In_Tree.Sources.Table (Source);
2630 if Src_Data.File = Name then
2631 if not Src_Data.Locally_Removed then
2632 Src_Data.In_Interfaces := True;
2633 Src_Data.Declared_In_Interfaces := True;
2635 if Src_Data.Other_Part /= No_Source then
2636 In_Tree.Sources.Table
2637 (Src_Data.Other_Part).In_Interfaces := True;
2638 In_Tree.Sources.Table
2639 (Src_Data.Other_Part).Declared_In_Interfaces :=
2643 if Current_Verbosity = High then
2644 Write_Str (" interface: ");
2646 (Get_Name_String (Src_Data.Path.Name));
2653 Source := Src_Data.Next_In_Project;
2657 Project_2 := Data_2.Extends;
2659 exit Big_Loop when Project_2 = No_Project;
2661 Data_2 := In_Tree.Projects.Table (Project_2);
2664 if Source = No_Source then
2665 Error_Msg_File_1 := File_Name_Type (Element.Value);
2666 Error_Msg_Name_1 := Data.Name;
2671 "{ cannot be an interface of project %% "
2672 & "as it is not one of its sources",
2676 List := Element.Next;
2679 Data.Interfaces_Defined := True;
2681 elsif Data.Extends /= No_Project then
2682 Data.Interfaces_Defined :=
2683 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2685 if Data.Interfaces_Defined then
2686 Source := Data.First_Source;
2687 while Source /= No_Source loop
2689 Src_Data : Source_Data renames
2690 In_Tree.Sources.Table (Source);
2693 if not Src_Data.Declared_In_Interfaces then
2694 Src_Data.In_Interfaces := False;
2697 Source := Src_Data.Next_In_Project;
2702 end Check_Interfaces;
2704 --------------------------
2705 -- Check_Naming_Schemes --
2706 --------------------------
2708 procedure Check_Naming_Schemes
2709 (Data : in out Project_Data;
2710 Project : Project_Id;
2711 In_Tree : Project_Tree_Ref)
2713 Naming_Id : constant Package_Id :=
2714 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2715 Naming : Package_Element;
2717 procedure Check_Unit_Names (List : Array_Element_Id);
2718 -- Check that a list of unit names contains only valid names
2720 procedure Get_Exceptions (Kind : Source_Kind);
2721 -- Comment required ???
2723 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2724 -- Comment required ???
2726 ----------------------
2727 -- Check_Unit_Names --
2728 ----------------------
2730 procedure Check_Unit_Names (List : Array_Element_Id) is
2731 Current : Array_Element_Id;
2732 Element : Array_Element;
2733 Unit_Name : Name_Id;
2736 -- Loop through elements of the string list
2739 while Current /= No_Array_Element loop
2740 Element := In_Tree.Array_Elements.Table (Current);
2742 -- Put file name in canonical case
2744 if not Osint.File_Names_Case_Sensitive then
2745 Get_Name_String (Element.Value.Value);
2746 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2747 Element.Value.Value := Name_Find;
2750 -- Check that it contains a valid unit name
2752 Get_Name_String (Element.Index);
2753 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2755 if Unit_Name = No_Name then
2756 Err_Vars.Error_Msg_Name_1 := Element.Index;
2759 "%% is not a valid unit name.",
2760 Element.Value.Location);
2763 if Current_Verbosity = High then
2764 Write_Str (" Unit (""");
2765 Write_Str (Get_Name_String (Unit_Name));
2769 Element.Index := Unit_Name;
2770 In_Tree.Array_Elements.Table (Current) := Element;
2773 Current := Element.Next;
2775 end Check_Unit_Names;
2777 --------------------
2778 -- Get_Exceptions --
2779 --------------------
2781 procedure Get_Exceptions (Kind : Source_Kind) is
2782 Exceptions : Array_Element_Id;
2783 Exception_List : Variable_Value;
2784 Element_Id : String_List_Id;
2785 Element : String_Element;
2786 File_Name : File_Name_Type;
2787 Lang_Id : Language_Index;
2789 Lang_Kind : Language_Kind;
2796 (Name_Implementation_Exceptions,
2797 In_Arrays => Naming.Decl.Arrays,
2798 In_Tree => In_Tree);
2803 (Name_Specification_Exceptions,
2804 In_Arrays => Naming.Decl.Arrays,
2805 In_Tree => In_Tree);
2808 Lang_Id := Data.First_Language_Processing;
2809 while Lang_Id /= No_Language_Index loop
2810 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2813 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2815 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2817 Exception_List := Value_Of
2819 In_Array => Exceptions,
2820 In_Tree => In_Tree);
2822 if Exception_List /= Nil_Variable_Value then
2823 Element_Id := Exception_List.Values;
2824 while Element_Id /= Nil_String loop
2825 Element := In_Tree.String_Elements.Table (Element_Id);
2827 if Osint.File_Names_Case_Sensitive then
2828 File_Name := File_Name_Type (Element.Value);
2830 Get_Name_String (Element.Value);
2831 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2832 File_Name := Name_Find;
2835 Source := Data.First_Source;
2836 while Source /= No_Source
2838 In_Tree.Sources.Table (Source).File /= File_Name
2841 In_Tree.Sources.Table (Source).Next_In_Project;
2844 if Source = No_Source then
2853 File_Name => File_Name,
2854 Display_File => File_Name_Type (Element.Value),
2855 Naming_Exception => True,
2856 Lang_Kind => Lang_Kind);
2859 -- Check if the file name is already recorded for
2860 -- another language or another kind.
2863 In_Tree.Sources.Table (Source).Language /= Lang_Id
2868 "the same file cannot be a source " &
2872 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2876 "the same file cannot be a source " &
2881 -- If the file is already recorded for the same
2882 -- language and the same kind, it means that the file
2883 -- name appears several times in the *_Exceptions
2884 -- attribute; so there is nothing to do.
2888 Element_Id := Element.Next;
2893 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2897 -------------------------
2898 -- Get_Unit_Exceptions --
2899 -------------------------
2901 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2902 Exceptions : Array_Element_Id;
2903 Element : Array_Element;
2906 File_Name : File_Name_Type;
2907 Lang_Id : constant Language_Index :=
2908 Data.Unit_Based_Language_Index;
2909 Lang : constant Name_Id :=
2910 Data.Unit_Based_Language_Name;
2913 Source_To_Replace : Source_Id := No_Source;
2915 Other_Project : Project_Id;
2916 Other_Part : Source_Id := No_Source;
2919 if Lang_Id = No_Language_Index or else Lang = No_Name then
2924 Exceptions := Value_Of
2926 In_Arrays => Naming.Decl.Arrays,
2927 In_Tree => In_Tree);
2929 if Exceptions = No_Array_Element then
2932 (Name_Implementation,
2933 In_Arrays => Naming.Decl.Arrays,
2934 In_Tree => In_Tree);
2941 In_Arrays => Naming.Decl.Arrays,
2942 In_Tree => In_Tree);
2944 if Exceptions = No_Array_Element then
2945 Exceptions := Value_Of
2946 (Name_Specification,
2947 In_Arrays => Naming.Decl.Arrays,
2948 In_Tree => In_Tree);
2953 while Exceptions /= No_Array_Element loop
2954 Element := In_Tree.Array_Elements.Table (Exceptions);
2956 if Osint.File_Names_Case_Sensitive then
2957 File_Name := File_Name_Type (Element.Value.Value);
2959 Get_Name_String (Element.Value.Value);
2960 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2961 File_Name := Name_Find;
2964 Get_Name_String (Element.Index);
2965 To_Lower (Name_Buffer (1 .. Name_Len));
2968 Index := Element.Value.Index;
2970 -- For Ada, check if it is a valid unit name
2972 if Lang = Name_Ada then
2973 Get_Name_String (Element.Index);
2974 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2976 if Unit = No_Name then
2977 Err_Vars.Error_Msg_Name_1 := Element.Index;
2980 "%% is not a valid unit name.",
2981 Element.Value.Location);
2985 if Unit /= No_Name then
2987 -- Check if the source already exists
2989 Source := In_Tree.First_Source;
2990 Source_To_Replace := No_Source;
2992 while Source /= No_Source and then
2993 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2994 In_Tree.Sources.Table (Source).Index /= Index)
2996 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2999 if Source /= No_Source then
3000 if In_Tree.Sources.Table (Source).Kind /= Kind then
3001 Other_Part := Source;
3005 In_Tree.Sources.Table (Source).Next_In_Sources;
3007 exit when Source = No_Source or else
3008 (In_Tree.Sources.Table (Source).Unit = Unit
3010 In_Tree.Sources.Table (Source).Index = Index);
3014 if Source /= No_Source then
3015 Other_Project := In_Tree.Sources.Table (Source).Project;
3017 if Is_Extending (Project, Other_Project, In_Tree) then
3019 In_Tree.Sources.Table (Source).Other_Part;
3021 -- Record the source to be removed
3023 Source_To_Replace := Source;
3024 Source := No_Source;
3027 Error_Msg_Name_1 := Unit;
3029 In_Tree.Projects.Table (Other_Project).Name;
3033 "%% is already a source of project %%",
3034 Element.Value.Location);
3039 if Source = No_Source then
3048 File_Name => File_Name,
3049 Display_File => File_Name_Type (Element.Value.Value),
3050 Lang_Kind => Unit_Based,
3051 Other_Part => Other_Part,
3054 Naming_Exception => True,
3055 Source_To_Replace => Source_To_Replace);
3059 Exceptions := Element.Next;
3062 end Get_Unit_Exceptions;
3064 -- Start of processing for Check_Naming_Schemes
3067 if Get_Mode = Ada_Only then
3069 -- If there is a package Naming, we will put in Data.Naming what is
3070 -- in this package Naming.
3072 if Naming_Id /= No_Package then
3073 Naming := In_Tree.Packages.Table (Naming_Id);
3075 if Current_Verbosity = High then
3076 Write_Line ("Checking ""Naming"" for Ada.");
3080 Bodies : constant Array_Element_Id :=
3082 (Name_Body, Naming.Decl.Arrays, In_Tree);
3084 Specs : constant Array_Element_Id :=
3086 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3089 if Bodies /= No_Array_Element then
3091 -- We have elements in the array Body_Part
3093 if Current_Verbosity = High then
3094 Write_Line ("Found Bodies.");
3097 Data.Naming.Bodies := Bodies;
3098 Check_Unit_Names (Bodies);
3101 if Current_Verbosity = High then
3102 Write_Line ("No Bodies.");
3106 if Specs /= No_Array_Element then
3108 -- We have elements in the array Specs
3110 if Current_Verbosity = High then
3111 Write_Line ("Found Specs.");
3114 Data.Naming.Specs := Specs;
3115 Check_Unit_Names (Specs);
3118 if Current_Verbosity = High then
3119 Write_Line ("No Specs.");
3124 -- We are now checking if variables Dot_Replacement, Casing,
3125 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3127 -- For each variable, if it does not exist, we do nothing,
3128 -- because we already have the default.
3130 -- Check Dot_Replacement
3133 Dot_Replacement : constant Variable_Value :=
3135 (Name_Dot_Replacement,
3136 Naming.Decl.Attributes, In_Tree);
3139 pragma Assert (Dot_Replacement.Kind = Single,
3140 "Dot_Replacement is not a single string");
3142 if not Dot_Replacement.Default then
3143 Get_Name_String (Dot_Replacement.Value);
3145 if Name_Len = 0 then
3148 "Dot_Replacement cannot be empty",
3149 Dot_Replacement.Location);
3152 if Osint.File_Names_Case_Sensitive then
3153 Data.Naming.Dot_Replacement :=
3154 File_Name_Type (Dot_Replacement.Value);
3156 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3157 Data.Naming.Dot_Replacement := Name_Find;
3159 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3164 if Current_Verbosity = High then
3165 Write_Str (" Dot_Replacement = """);
3166 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3174 Casing_String : constant Variable_Value :=
3177 Naming.Decl.Attributes,
3181 pragma Assert (Casing_String.Kind = Single,
3182 "Casing is not a single string");
3184 if not Casing_String.Default then
3186 Casing_Image : constant String :=
3187 Get_Name_String (Casing_String.Value);
3190 Casing_Value : constant Casing_Type :=
3191 Value (Casing_Image);
3193 Data.Naming.Casing := Casing_Value;
3197 when Constraint_Error =>
3198 if Casing_Image'Length = 0 then
3201 "Casing cannot be an empty string",
3202 Casing_String.Location);
3205 Name_Len := Casing_Image'Length;
3206 Name_Buffer (1 .. Name_Len) := Casing_Image;
3207 Err_Vars.Error_Msg_Name_1 := Name_Find;
3210 "%% is not a correct Casing",
3211 Casing_String.Location);
3217 if Current_Verbosity = High then
3218 Write_Str (" Casing = ");
3219 Write_Str (Image (Data.Naming.Casing));
3224 -- Check Spec_Suffix
3227 Ada_Spec_Suffix : constant Variable_Value :=
3231 In_Array => Data.Naming.Spec_Suffix,
3232 In_Tree => In_Tree);
3235 if Ada_Spec_Suffix.Kind = Single
3236 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3238 Get_Name_String (Ada_Spec_Suffix.Value);
3239 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3240 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3241 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3248 Default_Ada_Spec_Suffix);
3252 if Current_Verbosity = High then
3253 Write_Str (" Spec_Suffix = """);
3254 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3259 -- Check Body_Suffix
3262 Ada_Body_Suffix : constant Variable_Value :=
3266 In_Array => Data.Naming.Body_Suffix,
3267 In_Tree => In_Tree);
3270 if Ada_Body_Suffix.Kind = Single
3271 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3273 Get_Name_String (Ada_Body_Suffix.Value);
3274 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3275 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3276 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3283 Default_Ada_Body_Suffix);
3287 if Current_Verbosity = High then
3288 Write_Str (" Body_Suffix = """);
3289 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3294 -- Check Separate_Suffix
3297 Ada_Sep_Suffix : constant Variable_Value :=
3299 (Variable_Name => Name_Separate_Suffix,
3300 In_Variables => Naming.Decl.Attributes,
3301 In_Tree => In_Tree);
3304 if Ada_Sep_Suffix.Default then
3305 Data.Naming.Separate_Suffix :=
3306 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3309 Get_Name_String (Ada_Sep_Suffix.Value);
3311 if Name_Len = 0 then
3314 "Separate_Suffix cannot be empty",
3315 Ada_Sep_Suffix.Location);
3318 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3319 Data.Naming.Separate_Suffix := Name_Find;
3320 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3325 if Current_Verbosity = High then
3326 Write_Str (" Separate_Suffix = """);
3327 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3332 -- Check if Data.Naming is valid
3334 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3337 elsif not In_Configuration then
3339 -- Look into package Naming, if there is one
3341 if Naming_Id /= No_Package then
3342 Naming := In_Tree.Packages.Table (Naming_Id);
3344 if Current_Verbosity = High then
3345 Write_Line ("Checking package Naming.");
3348 -- We are now checking if attribute Dot_Replacement, Casing,
3349 -- and/or Separate_Suffix exist.
3351 -- For each attribute, if it does not exist, we do nothing,
3352 -- because we already have the default.
3353 -- Otherwise, for all unit-based languages, we put the declared
3354 -- value in the language config.
3357 Dot_Repl : constant Variable_Value :=
3359 (Name_Dot_Replacement,
3360 Naming.Decl.Attributes, In_Tree);
3361 Dot_Replacement : File_Name_Type := No_File;
3363 Casing_String : constant Variable_Value :=
3366 Naming.Decl.Attributes,
3369 Casing : Casing_Type := All_Lower_Case;
3370 -- Casing type (junk initialization to stop bad gcc warning)
3372 Casing_Defined : Boolean := False;
3374 Sep_Suffix : constant Variable_Value :=
3376 (Variable_Name => Name_Separate_Suffix,
3377 In_Variables => Naming.Decl.Attributes,
3378 In_Tree => In_Tree);
3380 Separate_Suffix : File_Name_Type := No_File;
3381 Lang_Id : Language_Index;
3384 -- Check attribute Dot_Replacement
3386 if not Dot_Repl.Default then
3387 Get_Name_String (Dot_Repl.Value);
3389 if Name_Len = 0 then
3392 "Dot_Replacement cannot be empty",
3396 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3397 Dot_Replacement := Name_Find;
3399 if Current_Verbosity = High then
3400 Write_Str (" Dot_Replacement = """);
3401 Write_Str (Get_Name_String (Dot_Replacement));
3408 -- Check attribute Casing
3410 if not Casing_String.Default then
3412 Casing_Image : constant String :=
3413 Get_Name_String (Casing_String.Value);
3416 Casing_Value : constant Casing_Type :=
3417 Value (Casing_Image);
3419 Casing := Casing_Value;
3420 Casing_Defined := True;
3422 if Current_Verbosity = High then
3423 Write_Str (" Casing = ");
3424 Write_Str (Image (Casing));
3431 when Constraint_Error =>
3432 if Casing_Image'Length = 0 then
3435 "Casing cannot be an empty string",
3436 Casing_String.Location);
3439 Name_Len := Casing_Image'Length;
3440 Name_Buffer (1 .. Name_Len) := Casing_Image;
3441 Err_Vars.Error_Msg_Name_1 := Name_Find;
3444 "%% is not a correct Casing",
3445 Casing_String.Location);
3450 if not Sep_Suffix.Default then
3451 Get_Name_String (Sep_Suffix.Value);
3453 if Name_Len = 0 then
3456 "Separate_Suffix cannot be empty",
3457 Sep_Suffix.Location);
3460 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3461 Separate_Suffix := Name_Find;
3463 if Current_Verbosity = High then
3464 Write_Str (" Separate_Suffix = """);
3465 Write_Str (Get_Name_String (Separate_Suffix));
3472 -- For all unit based languages, if any, set the specified
3473 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3475 if Dot_Replacement /= No_File
3476 or else Casing_Defined
3477 or else Separate_Suffix /= No_File
3479 Lang_Id := Data.First_Language_Processing;
3480 while Lang_Id /= No_Language_Index loop
3481 if In_Tree.Languages_Data.Table
3482 (Lang_Id).Config.Kind = Unit_Based
3484 if Dot_Replacement /= No_File then
3485 In_Tree.Languages_Data.Table
3486 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3490 if Casing_Defined then
3491 In_Tree.Languages_Data.Table
3492 (Lang_Id).Config.Naming_Data.Casing := Casing;
3495 if Separate_Suffix /= No_File then
3496 In_Tree.Languages_Data.Table
3497 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3503 In_Tree.Languages_Data.Table (Lang_Id).Next;
3508 -- Next, get the spec and body suffixes
3511 Suffix : Variable_Value;
3512 Lang_Id : Language_Index;
3516 Lang_Id := Data.First_Language_Processing;
3517 while Lang_Id /= No_Language_Index loop
3518 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3524 Attribute_Or_Array_Name => Name_Spec_Suffix,
3525 In_Package => Naming_Id,
3526 In_Tree => In_Tree);
3528 if Suffix = Nil_Variable_Value then
3531 Attribute_Or_Array_Name => Name_Specification_Suffix,
3532 In_Package => Naming_Id,
3533 In_Tree => In_Tree);
3536 if Suffix /= Nil_Variable_Value then
3537 In_Tree.Languages_Data.Table (Lang_Id).
3538 Config.Naming_Data.Spec_Suffix :=
3539 File_Name_Type (Suffix.Value);
3546 Attribute_Or_Array_Name => Name_Body_Suffix,
3547 In_Package => Naming_Id,
3548 In_Tree => In_Tree);
3550 if Suffix = Nil_Variable_Value then
3553 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3554 In_Package => Naming_Id,
3555 In_Tree => In_Tree);
3558 if Suffix /= Nil_Variable_Value then
3559 In_Tree.Languages_Data.Table (Lang_Id).
3560 Config.Naming_Data.Body_Suffix :=
3561 File_Name_Type (Suffix.Value);
3564 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3568 -- Get the exceptions for file based languages
3570 Get_Exceptions (Spec);
3571 Get_Exceptions (Impl);
3573 -- Get the exceptions for unit based languages
3575 Get_Unit_Exceptions (Spec);
3576 Get_Unit_Exceptions (Impl);
3580 end Check_Naming_Schemes;
3582 ------------------------------
3583 -- Check_Library_Attributes --
3584 ------------------------------
3586 procedure Check_Library_Attributes
3587 (Project : Project_Id;
3588 In_Tree : Project_Tree_Ref;
3589 Current_Dir : String;
3590 Data : in out Project_Data)
3592 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3594 Lib_Dir : constant Prj.Variable_Value :=
3596 (Snames.Name_Library_Dir, Attributes, In_Tree);
3598 Lib_Name : constant Prj.Variable_Value :=
3600 (Snames.Name_Library_Name, Attributes, In_Tree);
3602 Lib_Version : constant Prj.Variable_Value :=
3604 (Snames.Name_Library_Version, Attributes, In_Tree);
3606 Lib_ALI_Dir : constant Prj.Variable_Value :=
3608 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3610 The_Lib_Kind : constant Prj.Variable_Value :=
3612 (Snames.Name_Library_Kind, Attributes, In_Tree);
3614 Imported_Project_List : Project_List := Empty_Project_List;
3616 Continuation : String_Access := No_Continuation_String'Access;
3618 Support_For_Libraries : Library_Support;
3620 Library_Directory_Present : Boolean;
3622 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3623 -- Check if an imported or extended project if also a library project
3629 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3630 Proj_Data : Project_Data;
3634 if Proj /= No_Project then
3635 Proj_Data := In_Tree.Projects.Table (Proj);
3637 if not Proj_Data.Library then
3639 -- The only not library projects that are OK are those that
3640 -- have no sources. However, header files from non-Ada
3641 -- languages are OK, as there is nothing to compile.
3643 Src_Id := Proj_Data.First_Source;
3644 while Src_Id /= No_Source loop
3646 Src : Source_Data renames In_Tree.Sources.Table (Src_Id);
3648 exit when Src.Lang_Kind /= File_Based
3649 or else Src.Kind /= Spec;
3650 Src_Id := Src.Next_In_Project;
3654 if Src_Id /= No_Source then
3655 Error_Msg_Name_1 := Data.Name;
3656 Error_Msg_Name_2 := Proj_Data.Name;
3659 if Data.Library_Kind /= Static then
3663 "shared library project %% cannot extend " &
3664 "project %% that is not a library project",
3666 Continuation := Continuation_String'Access;
3669 elsif Data.Library_Kind /= Static then
3673 "shared library project %% cannot import project %% " &
3674 "that is not a shared library project",
3676 Continuation := Continuation_String'Access;
3680 elsif Data.Library_Kind /= Static and then
3681 Proj_Data.Library_Kind = Static
3683 Error_Msg_Name_1 := Data.Name;
3684 Error_Msg_Name_2 := Proj_Data.Name;
3690 "shared library project %% cannot extend static " &
3691 "library project %%",
3698 "shared library project %% cannot import static " &
3699 "library project %%",
3703 Continuation := Continuation_String'Access;
3708 -- Start of processing for Check_Library_Attributes
3711 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3713 -- Special case of extending project
3715 if Data.Extends /= No_Project then
3717 Extended_Data : constant Project_Data :=
3718 In_Tree.Projects.Table (Data.Extends);
3721 -- If the project extended is a library project, we inherit the
3722 -- library name, if it is not redefined; we check that the library
3723 -- directory is specified.
3725 if Extended_Data.Library then
3726 if Data.Qualifier = Standard then
3729 "a standard project cannot extend a library project",
3733 if Lib_Name.Default then
3734 Data.Library_Name := Extended_Data.Library_Name;
3737 if Lib_Dir.Default then
3738 if not Data.Virtual then
3741 "a project extending a library project must " &
3742 "specify an attribute Library_Dir",
3746 -- For a virtual project extending a library project,
3747 -- inherit library directory.
3749 Data.Library_Dir := Extended_Data.Library_Dir;
3750 Library_Directory_Present := True;
3758 pragma Assert (Lib_Name.Kind = Single);
3760 if Lib_Name.Value = Empty_String then
3761 if Current_Verbosity = High
3762 and then Data.Library_Name = No_Name
3764 Write_Line ("No library name");
3768 -- There is no restriction on the syntax of library names
3770 Data.Library_Name := Lib_Name.Value;
3773 if Data.Library_Name /= No_Name then
3774 if Current_Verbosity = High then
3775 Write_Str ("Library name = """);
3776 Write_Str (Get_Name_String (Data.Library_Name));
3780 pragma Assert (Lib_Dir.Kind = Single);
3782 if not Library_Directory_Present then
3783 if Current_Verbosity = High then
3784 Write_Line ("No library directory");
3788 -- Find path name (unless inherited), check that it is a directory
3790 if Data.Library_Dir = No_Path_Information then
3794 File_Name_Type (Lib_Dir.Value),
3795 Data.Directory.Display_Name,
3796 Data.Library_Dir.Name,
3797 Data.Library_Dir.Display_Name,
3798 Create => "library",
3799 Current_Dir => Current_Dir,
3800 Location => Lib_Dir.Location,
3801 Externally_Built => Data.Externally_Built);
3804 if Data.Library_Dir = No_Path_Information then
3806 -- Get the absolute name of the library directory that
3807 -- does not exist, to report an error.
3810 Dir_Name : constant String :=
3811 Get_Name_String (Lib_Dir.Value);
3814 if Is_Absolute_Path (Dir_Name) then
3815 Err_Vars.Error_Msg_File_1 :=
3816 File_Name_Type (Lib_Dir.Value);
3819 Get_Name_String (Data.Directory.Display_Name);
3821 if Name_Buffer (Name_Len) /= Directory_Separator then
3822 Name_Len := Name_Len + 1;
3823 Name_Buffer (Name_Len) := Directory_Separator;
3827 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3829 Name_Len := Name_Len + Dir_Name'Length;
3830 Err_Vars.Error_Msg_File_1 := Name_Find;
3837 "library directory { does not exist",
3841 -- The library directory cannot be the same as the Object
3844 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3847 "library directory cannot be the same " &
3848 "as object directory",
3850 Data.Library_Dir := No_Path_Information;
3854 OK : Boolean := True;
3855 Dirs_Id : String_List_Id;
3856 Dir_Elem : String_Element;
3859 -- The library directory cannot be the same as a source
3860 -- directory of the current project.
3862 Dirs_Id := Data.Source_Dirs;
3863 while Dirs_Id /= Nil_String loop
3864 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3865 Dirs_Id := Dir_Elem.Next;
3868 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3870 Err_Vars.Error_Msg_File_1 :=
3871 File_Name_Type (Dir_Elem.Value);
3874 "library directory cannot be the same " &
3875 "as source directory {",
3884 -- The library directory cannot be the same as a source
3885 -- directory of another project either.
3888 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3889 if Pid /= Project then
3890 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3892 Dir_Loop : while Dirs_Id /= Nil_String loop
3894 In_Tree.String_Elements.Table (Dirs_Id);
3895 Dirs_Id := Dir_Elem.Next;
3897 if Data.Library_Dir.Name =
3898 Path_Name_Type (Dir_Elem.Value)
3900 Err_Vars.Error_Msg_File_1 :=
3901 File_Name_Type (Dir_Elem.Value);
3902 Err_Vars.Error_Msg_Name_1 :=
3903 In_Tree.Projects.Table (Pid).Name;
3907 "library directory cannot be the same " &
3908 "as source directory { of project %%",
3915 end loop Project_Loop;
3919 Data.Library_Dir := No_Path_Information;
3921 elsif Current_Verbosity = High then
3923 -- Display the Library directory in high verbosity
3925 Write_Str ("Library directory =""");
3927 (Get_Name_String (Data.Library_Dir.Display_Name));
3937 Data.Library_Dir /= No_Path_Information
3939 Data.Library_Name /= No_Name;
3941 if Data.Extends = No_Project then
3942 case Data.Qualifier is
3944 if Data.Library then
3947 "a standard project cannot be a library project",
3952 if not Data.Library then
3953 if Data.Library_Dir = No_Path_Information then
3956 "\attribute Library_Dir not declared",
3960 if Data.Library_Name = No_Name then
3963 "\attribute Library_Name not declared",
3974 if Data.Library then
3975 if Get_Mode = Multi_Language then
3976 Support_For_Libraries := Data.Config.Lib_Support;
3979 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3982 if Support_For_Libraries = Prj.None then
3985 "?libraries are not supported on this platform",
3987 Data.Library := False;
3990 if Lib_ALI_Dir.Value = Empty_String then
3991 if Current_Verbosity = High then
3992 Write_Line ("No library ALI directory specified");
3994 Data.Library_ALI_Dir := Data.Library_Dir;
3997 -- Find path name, check that it is a directory
4002 File_Name_Type (Lib_ALI_Dir.Value),
4003 Data.Directory.Display_Name,
4004 Data.Library_ALI_Dir.Name,
4005 Data.Library_ALI_Dir.Display_Name,
4006 Create => "library ALI",
4007 Current_Dir => Current_Dir,
4008 Location => Lib_ALI_Dir.Location,
4009 Externally_Built => Data.Externally_Built);
4011 if Data.Library_ALI_Dir = No_Path_Information then
4013 -- Get the absolute name of the library ALI directory that
4014 -- does not exist, to report an error.
4017 Dir_Name : constant String :=
4018 Get_Name_String (Lib_ALI_Dir.Value);
4021 if Is_Absolute_Path (Dir_Name) then
4022 Err_Vars.Error_Msg_File_1 :=
4023 File_Name_Type (Lib_Dir.Value);
4026 Get_Name_String (Data.Directory.Display_Name);
4028 if Name_Buffer (Name_Len) /= Directory_Separator then
4029 Name_Len := Name_Len + 1;
4030 Name_Buffer (Name_Len) := Directory_Separator;
4034 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
4036 Name_Len := Name_Len + Dir_Name'Length;
4037 Err_Vars.Error_Msg_File_1 := Name_Find;
4044 "library 'A'L'I directory { does not exist",
4045 Lib_ALI_Dir.Location);
4049 if Data.Library_ALI_Dir /= Data.Library_Dir then
4051 -- The library ALI directory cannot be the same as the
4052 -- Object directory.
4054 if Data.Library_ALI_Dir = Data.Object_Directory then
4057 "library 'A'L'I directory cannot be the same " &
4058 "as object directory",
4059 Lib_ALI_Dir.Location);
4060 Data.Library_ALI_Dir := No_Path_Information;
4064 OK : Boolean := True;
4065 Dirs_Id : String_List_Id;
4066 Dir_Elem : String_Element;
4069 -- The library ALI directory cannot be the same as
4070 -- a source directory of the current project.
4072 Dirs_Id := Data.Source_Dirs;
4073 while Dirs_Id /= Nil_String loop
4074 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4075 Dirs_Id := Dir_Elem.Next;
4077 if Data.Library_ALI_Dir.Name =
4078 Path_Name_Type (Dir_Elem.Value)
4080 Err_Vars.Error_Msg_File_1 :=
4081 File_Name_Type (Dir_Elem.Value);
4084 "library 'A'L'I directory cannot be " &
4085 "the same as source directory {",
4086 Lib_ALI_Dir.Location);
4094 -- The library ALI directory cannot be the same as
4095 -- a source directory of another project either.
4099 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4101 if Pid /= Project then
4103 In_Tree.Projects.Table (Pid).Source_Dirs;
4106 while Dirs_Id /= Nil_String loop
4108 In_Tree.String_Elements.Table (Dirs_Id);
4109 Dirs_Id := Dir_Elem.Next;
4111 if Data.Library_ALI_Dir.Name =
4112 Path_Name_Type (Dir_Elem.Value)
4114 Err_Vars.Error_Msg_File_1 :=
4115 File_Name_Type (Dir_Elem.Value);
4116 Err_Vars.Error_Msg_Name_1 :=
4117 In_Tree.Projects.Table (Pid).Name;
4121 "library 'A'L'I directory cannot " &
4122 "be the same as source directory " &
4124 Lib_ALI_Dir.Location);
4126 exit ALI_Project_Loop;
4128 end loop ALI_Dir_Loop;
4130 end loop ALI_Project_Loop;
4134 Data.Library_ALI_Dir := No_Path_Information;
4136 elsif Current_Verbosity = High then
4138 -- Display the Library ALI directory in high
4141 Write_Str ("Library ALI directory =""");
4144 (Data.Library_ALI_Dir.Display_Name));
4152 pragma Assert (Lib_Version.Kind = Single);
4154 if Lib_Version.Value = Empty_String then
4155 if Current_Verbosity = High then
4156 Write_Line ("No library version specified");
4160 Data.Lib_Internal_Name := Lib_Version.Value;
4163 pragma Assert (The_Lib_Kind.Kind = Single);
4165 if The_Lib_Kind.Value = Empty_String then
4166 if Current_Verbosity = High then
4167 Write_Line ("No library kind specified");
4171 Get_Name_String (The_Lib_Kind.Value);
4174 Kind_Name : constant String :=
4175 To_Lower (Name_Buffer (1 .. Name_Len));
4177 OK : Boolean := True;
4180 if Kind_Name = "static" then
4181 Data.Library_Kind := Static;
4183 elsif Kind_Name = "dynamic" then
4184 Data.Library_Kind := Dynamic;
4186 elsif Kind_Name = "relocatable" then
4187 Data.Library_Kind := Relocatable;
4192 "illegal value for Library_Kind",
4193 The_Lib_Kind.Location);
4197 if Current_Verbosity = High and then OK then
4198 Write_Str ("Library kind = ");
4199 Write_Line (Kind_Name);
4202 if Data.Library_Kind /= Static and then
4203 Support_For_Libraries = Prj.Static_Only
4207 "only static libraries are supported " &
4209 The_Lib_Kind.Location);
4210 Data.Library := False;
4215 if Data.Library then
4216 if Current_Verbosity = High then
4217 Write_Line ("This is a library project file");
4220 if Get_Mode = Multi_Language then
4221 Check_Library (Data.Extends, Extends => True);
4223 Imported_Project_List := Data.Imported_Projects;
4224 while Imported_Project_List /= Empty_Project_List loop
4226 (In_Tree.Project_Lists.Table
4227 (Imported_Project_List).Project,
4229 Imported_Project_List :=
4230 In_Tree.Project_Lists.Table
4231 (Imported_Project_List).Next;
4239 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4240 -- Warn if they are declared, as it is a common error to think that
4241 -- library are "linked" with Linker switches.
4243 if Data.Library then
4245 Linker_Package_Id : constant Package_Id :=
4247 (Name_Linker, Data.Decl.Packages, In_Tree);
4248 Linker_Package : Package_Element;
4249 Switches : Array_Element_Id := No_Array_Element;
4252 if Linker_Package_Id /= No_Package then
4253 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4257 (Name => Name_Switches,
4258 In_Arrays => Linker_Package.Decl.Arrays,
4259 In_Tree => In_Tree);
4261 if Switches = No_Array_Element then
4264 (Name => Name_Default_Switches,
4265 In_Arrays => Linker_Package.Decl.Arrays,
4266 In_Tree => In_Tree);
4269 if Switches /= No_Array_Element then
4272 "?Linker switches not taken into account in library " &
4280 if Data.Extends /= No_Project then
4281 In_Tree.Projects.Table (Data.Extends).Library := False;
4283 end Check_Library_Attributes;
4285 --------------------------
4286 -- Check_Package_Naming --
4287 --------------------------
4289 procedure Check_Package_Naming
4290 (Project : Project_Id;
4291 In_Tree : Project_Tree_Ref;
4292 Data : in out Project_Data)
4294 Naming_Id : constant Package_Id :=
4295 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4297 Naming : Package_Element;
4300 -- If there is a package Naming, we will put in Data.Naming
4301 -- what is in this package Naming.
4303 if Naming_Id /= No_Package then
4304 Naming := In_Tree.Packages.Table (Naming_Id);
4306 if Current_Verbosity = High then
4307 Write_Line ("Checking ""Naming"".");
4310 -- Check Spec_Suffix
4313 Spec_Suffixs : Array_Element_Id :=
4319 Suffix : Array_Element_Id;
4320 Element : Array_Element;
4321 Suffix2 : Array_Element_Id;
4324 -- If some suffixes have been specified, we make sure that
4325 -- for each language for which a default suffix has been
4326 -- specified, there is a suffix specified, either the one
4327 -- in the project file or if there were none, the default.
4329 if Spec_Suffixs /= No_Array_Element then
4330 Suffix := Data.Naming.Spec_Suffix;
4332 while Suffix /= No_Array_Element loop
4334 In_Tree.Array_Elements.Table (Suffix);
4335 Suffix2 := Spec_Suffixs;
4337 while Suffix2 /= No_Array_Element loop
4338 exit when In_Tree.Array_Elements.Table
4339 (Suffix2).Index = Element.Index;
4340 Suffix2 := In_Tree.Array_Elements.Table
4344 -- There is a registered default suffix, but no
4345 -- suffix specified in the project file.
4346 -- Add the default to the array.
4348 if Suffix2 = No_Array_Element then
4349 Array_Element_Table.Increment_Last
4350 (In_Tree.Array_Elements);
4351 In_Tree.Array_Elements.Table
4352 (Array_Element_Table.Last
4353 (In_Tree.Array_Elements)) :=
4354 (Index => Element.Index,
4355 Src_Index => Element.Src_Index,
4356 Index_Case_Sensitive => False,
4357 Value => Element.Value,
4358 Next => Spec_Suffixs);
4359 Spec_Suffixs := Array_Element_Table.Last
4360 (In_Tree.Array_Elements);
4363 Suffix := Element.Next;
4366 -- Put the resulting array as the specification suffixes
4368 Data.Naming.Spec_Suffix := Spec_Suffixs;
4373 Current : Array_Element_Id;
4374 Element : Array_Element;
4377 Current := Data.Naming.Spec_Suffix;
4378 while Current /= No_Array_Element loop
4379 Element := In_Tree.Array_Elements.Table (Current);
4380 Get_Name_String (Element.Value.Value);
4382 if Name_Len = 0 then
4385 "Spec_Suffix cannot be empty",
4386 Element.Value.Location);
4389 In_Tree.Array_Elements.Table (Current) := Element;
4390 Current := Element.Next;
4394 -- Check Body_Suffix
4397 Impl_Suffixs : Array_Element_Id :=
4403 Suffix : Array_Element_Id;
4404 Element : Array_Element;
4405 Suffix2 : Array_Element_Id;
4408 -- If some suffixes have been specified, we make sure that
4409 -- for each language for which a default suffix has been
4410 -- specified, there is a suffix specified, either the one
4411 -- in the project file or if there were none, the default.
4413 if Impl_Suffixs /= No_Array_Element then
4414 Suffix := Data.Naming.Body_Suffix;
4415 while Suffix /= No_Array_Element loop
4417 In_Tree.Array_Elements.Table (Suffix);
4419 Suffix2 := Impl_Suffixs;
4420 while Suffix2 /= No_Array_Element loop
4421 exit when In_Tree.Array_Elements.Table
4422 (Suffix2).Index = Element.Index;
4423 Suffix2 := In_Tree.Array_Elements.Table
4427 -- There is a registered default suffix, but no suffix was
4428 -- specified in the project file. Add default to the array.
4430 if Suffix2 = No_Array_Element then
4431 Array_Element_Table.Increment_Last
4432 (In_Tree.Array_Elements);
4433 In_Tree.Array_Elements.Table
4434 (Array_Element_Table.Last
4435 (In_Tree.Array_Elements)) :=
4436 (Index => Element.Index,
4437 Src_Index => Element.Src_Index,
4438 Index_Case_Sensitive => False,
4439 Value => Element.Value,
4440 Next => Impl_Suffixs);
4441 Impl_Suffixs := Array_Element_Table.Last
4442 (In_Tree.Array_Elements);
4445 Suffix := Element.Next;
4448 -- Put the resulting array as the implementation suffixes
4450 Data.Naming.Body_Suffix := Impl_Suffixs;
4455 Current : Array_Element_Id;
4456 Element : Array_Element;
4459 Current := Data.Naming.Body_Suffix;
4460 while Current /= No_Array_Element loop
4461 Element := In_Tree.Array_Elements.Table (Current);
4462 Get_Name_String (Element.Value.Value);
4464 if Name_Len = 0 then
4467 "Body_Suffix cannot be empty",
4468 Element.Value.Location);
4471 In_Tree.Array_Elements.Table (Current) := Element;
4472 Current := Element.Next;
4476 -- Get the exceptions, if any
4478 Data.Naming.Specification_Exceptions :=
4480 (Name_Specification_Exceptions,
4481 In_Arrays => Naming.Decl.Arrays,
4482 In_Tree => In_Tree);
4484 Data.Naming.Implementation_Exceptions :=
4486 (Name_Implementation_Exceptions,
4487 In_Arrays => Naming.Decl.Arrays,
4488 In_Tree => In_Tree);
4490 end Check_Package_Naming;
4492 ---------------------------------
4493 -- Check_Programming_Languages --
4494 ---------------------------------
4496 procedure Check_Programming_Languages
4497 (In_Tree : Project_Tree_Ref;
4498 Project : Project_Id;
4499 Data : in out Project_Data)
4501 Languages : Variable_Value := Nil_Variable_Value;
4502 Def_Lang : Variable_Value := Nil_Variable_Value;
4503 Def_Lang_Id : Name_Id;
4506 Data.First_Language_Processing := No_Language_Index;
4508 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4511 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4512 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4513 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4515 if Data.Source_Dirs /= Nil_String then
4517 -- Check if languages are specified in this project
4519 if Languages.Default then
4521 -- Attribute Languages is not specified. So, it defaults to
4522 -- a project of the default language only.
4524 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4525 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4527 -- In Ada_Only mode, the default language is Ada
4529 if Get_Mode = Ada_Only then
4530 In_Tree.Name_Lists.Table (Data.Languages) :=
4531 (Name => Name_Ada, Next => No_Name_List);
4533 -- Attribute Languages is not specified. So, it defaults to
4534 -- a project of language Ada only. No sources of languages
4537 Data.Other_Sources_Present := False;
4540 -- Fail if there is no default language defined
4542 if Def_Lang.Default then
4543 if not Default_Language_Is_Ada then
4547 "no languages defined for this project",
4549 Def_Lang_Id := No_Name;
4551 Def_Lang_Id := Name_Ada;
4555 Get_Name_String (Def_Lang.Value);
4556 To_Lower (Name_Buffer (1 .. Name_Len));
4557 Def_Lang_Id := Name_Find;
4560 if Def_Lang_Id /= No_Name then
4561 In_Tree.Name_Lists.Table (Data.Languages) :=
4562 (Name => Def_Lang_Id, Next => No_Name_List);
4564 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4566 Data.First_Language_Processing :=
4567 Language_Data_Table.Last (In_Tree.Languages_Data);
4568 In_Tree.Languages_Data.Table
4569 (Data.First_Language_Processing) := No_Language_Data;
4570 In_Tree.Languages_Data.Table
4571 (Data.First_Language_Processing).Name := Def_Lang_Id;
4572 Get_Name_String (Def_Lang_Id);
4573 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4574 In_Tree.Languages_Data.Table
4575 (Data.First_Language_Processing).Display_Name := Name_Find;
4577 if Def_Lang_Id = Name_Ada then
4578 In_Tree.Languages_Data.Table
4579 (Data.First_Language_Processing).Config.Kind
4581 In_Tree.Languages_Data.Table
4582 (Data.First_Language_Processing).Config.Dependency_Kind
4584 Data.Unit_Based_Language_Name := Name_Ada;
4585 Data.Unit_Based_Language_Index :=
4586 Data.First_Language_Processing;
4588 In_Tree.Languages_Data.Table
4589 (Data.First_Language_Processing).Config.Kind
4597 Current : String_List_Id := Languages.Values;
4598 Element : String_Element;
4599 Lang_Name : Name_Id;
4600 Index : Language_Index;
4601 Lang_Data : Language_Data;
4602 NL_Id : Name_List_Index := No_Name_List;
4605 -- Assume there are no language declared
4607 Data.Ada_Sources_Present := False;
4608 Data.Other_Sources_Present := False;
4610 -- If there are no languages declared, there are no sources
4612 if Current = Nil_String then
4613 Data.Source_Dirs := Nil_String;
4615 if Data.Qualifier = Standard then
4619 "a standard project cannot have no language declared",
4620 Languages.Location);
4624 -- Look through all the languages specified in attribute
4627 while Current /= Nil_String loop
4629 In_Tree.String_Elements.Table (Current);
4630 Get_Name_String (Element.Value);
4631 To_Lower (Name_Buffer (1 .. Name_Len));
4632 Lang_Name := Name_Find;
4634 NL_Id := Data.Languages;
4635 while NL_Id /= No_Name_List loop
4637 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4638 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4641 if NL_Id = No_Name_List then
4642 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4644 if Data.Languages = No_Name_List then
4646 Name_List_Table.Last (In_Tree.Name_Lists);
4649 NL_Id := Data.Languages;
4650 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4653 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4656 In_Tree.Name_Lists.Table (NL_Id).Next :=
4657 Name_List_Table.Last (In_Tree.Name_Lists);
4660 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4661 In_Tree.Name_Lists.Table (NL_Id) :=
4662 (Lang_Name, No_Name_List);
4664 if Get_Mode = Ada_Only then
4665 -- Check for language Ada
4667 if Lang_Name = Name_Ada then
4668 Data.Ada_Sources_Present := True;
4671 Data.Other_Sources_Present := True;
4675 Language_Data_Table.Increment_Last
4676 (In_Tree.Languages_Data);
4678 Language_Data_Table.Last (In_Tree.Languages_Data);
4679 Lang_Data.Name := Lang_Name;
4680 Lang_Data.Display_Name := Element.Value;
4681 Lang_Data.Next := Data.First_Language_Processing;
4683 if Lang_Name = Name_Ada then
4684 Lang_Data.Config.Kind := Unit_Based;
4685 Lang_Data.Config.Dependency_Kind := ALI_File;
4686 Data.Unit_Based_Language_Name := Name_Ada;
4687 Data.Unit_Based_Language_Index := Index;
4690 Lang_Data.Config.Kind := File_Based;
4691 Lang_Data.Config.Dependency_Kind := None;
4694 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4695 Data.First_Language_Processing := Index;
4699 Current := Element.Next;
4705 end Check_Programming_Languages;
4711 function Check_Project
4713 Root_Project : Project_Id;
4714 In_Tree : Project_Tree_Ref;
4715 Extending : Boolean) return Boolean
4718 if P = Root_Project then
4721 elsif Extending then
4723 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4726 while Data.Extends /= No_Project loop
4727 if P = Data.Extends then
4731 Data := In_Tree.Projects.Table (Data.Extends);
4739 -------------------------------
4740 -- Check_Stand_Alone_Library --
4741 -------------------------------
4743 procedure Check_Stand_Alone_Library
4744 (Project : Project_Id;
4745 In_Tree : Project_Tree_Ref;
4746 Data : in out Project_Data;
4747 Current_Dir : String;
4748 Extending : Boolean)
4750 Lib_Interfaces : constant Prj.Variable_Value :=
4752 (Snames.Name_Library_Interface,
4753 Data.Decl.Attributes,
4756 Lib_Auto_Init : constant Prj.Variable_Value :=
4758 (Snames.Name_Library_Auto_Init,
4759 Data.Decl.Attributes,
4762 Lib_Src_Dir : constant Prj.Variable_Value :=
4764 (Snames.Name_Library_Src_Dir,
4765 Data.Decl.Attributes,
4768 Lib_Symbol_File : constant Prj.Variable_Value :=
4770 (Snames.Name_Library_Symbol_File,
4771 Data.Decl.Attributes,
4774 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4776 (Snames.Name_Library_Symbol_Policy,
4777 Data.Decl.Attributes,
4780 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4782 (Snames.Name_Library_Reference_Symbol_File,
4783 Data.Decl.Attributes,
4786 Auto_Init_Supported : Boolean;
4787 OK : Boolean := True;
4789 Next_Proj : Project_Id;
4792 if Get_Mode = Multi_Language then
4793 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4795 Auto_Init_Supported :=
4796 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4799 pragma Assert (Lib_Interfaces.Kind = List);
4801 -- It is a stand-alone library project file if attribute
4802 -- Library_Interface is defined.
4804 if not Lib_Interfaces.Default then
4805 SAL_Library : declare
4806 Interfaces : String_List_Id := Lib_Interfaces.Values;
4807 Interface_ALIs : String_List_Id := Nil_String;
4809 The_Unit_Id : Unit_Index;
4810 The_Unit_Data : Unit_Data;
4812 procedure Add_ALI_For (Source : File_Name_Type);
4813 -- Add an ALI file name to the list of Interface ALIs
4819 procedure Add_ALI_For (Source : File_Name_Type) is
4821 Get_Name_String (Source);
4824 ALI : constant String :=
4825 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4826 ALI_Name_Id : Name_Id;
4829 Name_Len := ALI'Length;
4830 Name_Buffer (1 .. Name_Len) := ALI;
4831 ALI_Name_Id := Name_Find;
4833 String_Element_Table.Increment_Last
4834 (In_Tree.String_Elements);
4835 In_Tree.String_Elements.Table
4836 (String_Element_Table.Last
4837 (In_Tree.String_Elements)) :=
4838 (Value => ALI_Name_Id,
4840 Display_Value => ALI_Name_Id,
4842 In_Tree.String_Elements.Table
4843 (Interfaces).Location,
4845 Next => Interface_ALIs);
4846 Interface_ALIs := String_Element_Table.Last
4847 (In_Tree.String_Elements);
4851 -- Start of processing for SAL_Library
4854 Data.Standalone_Library := True;
4856 -- Library_Interface cannot be an empty list
4858 if Interfaces = Nil_String then
4861 "Library_Interface cannot be an empty list",
4862 Lib_Interfaces.Location);
4865 -- Process each unit name specified in the attribute
4866 -- Library_Interface.
4868 while Interfaces /= Nil_String loop
4870 (In_Tree.String_Elements.Table (Interfaces).Value);
4871 To_Lower (Name_Buffer (1 .. Name_Len));
4873 if Name_Len = 0 then
4876 "an interface cannot be an empty string",
4877 In_Tree.String_Elements.Table (Interfaces).Location);
4881 Error_Msg_Name_1 := Unit;
4883 if Get_Mode = Ada_Only then
4885 Units_Htable.Get (In_Tree.Units_HT, Unit);
4887 if The_Unit_Id = No_Unit_Index then
4891 In_Tree.String_Elements.Table
4892 (Interfaces).Location);
4895 -- Check that the unit is part of the project
4898 In_Tree.Units.Table (The_Unit_Id);
4900 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4901 and then The_Unit_Data.File_Names
4902 (Body_Part).Path.Name /= Slash
4905 (The_Unit_Data.File_Names (Body_Part).Project,
4906 Project, In_Tree, Extending)
4908 -- There is a body for this unit.
4909 -- If there is no spec, we need to check
4910 -- that it is not a subunit.
4912 if The_Unit_Data.File_Names
4913 (Specification).Name = No_File
4916 Src_Ind : Source_File_Index;
4919 Src_Ind := Sinput.P.Load_Project_File
4921 (The_Unit_Data.File_Names
4922 (Body_Part).Path.Name));
4924 if Sinput.P.Source_File_Is_Subunit
4929 "%% is a subunit; " &
4930 "it cannot be an interface",
4932 String_Elements.Table
4933 (Interfaces).Location);
4938 -- The unit is not a subunit, so we add
4939 -- to the Interface ALIs the ALI file
4940 -- corresponding to the body.
4943 (The_Unit_Data.File_Names (Body_Part).Name);
4948 "%% is not an unit of this project",
4949 In_Tree.String_Elements.Table
4950 (Interfaces).Location);
4953 elsif The_Unit_Data.File_Names
4954 (Specification).Name /= No_File
4955 and then The_Unit_Data.File_Names
4956 (Specification).Path.Name /= Slash
4957 and then Check_Project
4958 (The_Unit_Data.File_Names
4959 (Specification).Project,
4960 Project, In_Tree, Extending)
4963 -- The unit is part of the project, it has
4964 -- a spec, but no body. We add to the Interface
4965 -- ALIs the ALI file corresponding to the spec.
4968 (The_Unit_Data.File_Names (Specification).Name);
4973 "%% is not an unit of this project",
4974 In_Tree.String_Elements.Table
4975 (Interfaces).Location);
4980 -- Multi_Language mode
4982 Next_Proj := Data.Extends;
4983 Source := Data.First_Source;
4986 while Source /= No_Source and then
4987 In_Tree.Sources.Table (Source).Unit /= Unit
4990 In_Tree.Sources.Table (Source).Next_In_Project;
4993 exit when Source /= No_Source or else
4994 Next_Proj = No_Project;
4997 In_Tree.Projects.Table (Next_Proj).First_Source;
4999 In_Tree.Projects.Table (Next_Proj).Extends;
5002 if Source /= No_Source then
5003 if In_Tree.Sources.Table (Source).Kind = Sep then
5004 Source := No_Source;
5006 elsif In_Tree.Sources.Table (Source).Kind = Spec
5008 In_Tree.Sources.Table (Source).Other_Part /=
5011 Source := In_Tree.Sources.Table (Source).Other_Part;
5015 if Source /= No_Source then
5016 if In_Tree.Sources.Table (Source).Project /= Project
5020 In_Tree.Sources.Table (Source).Project,
5023 Source := No_Source;
5027 if Source = No_Source then
5030 "%% is not an unit of this project",
5031 In_Tree.String_Elements.Table
5032 (Interfaces).Location);
5035 if In_Tree.Sources.Table (Source).Kind = Spec and then
5036 In_Tree.Sources.Table (Source).Other_Part /=
5039 Source := In_Tree.Sources.Table (Source).Other_Part;
5042 String_Element_Table.Increment_Last
5043 (In_Tree.String_Elements);
5044 In_Tree.String_Elements.Table
5045 (String_Element_Table.Last
5046 (In_Tree.String_Elements)) :=
5048 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5051 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5053 In_Tree.String_Elements.Table
5054 (Interfaces).Location,
5056 Next => Interface_ALIs);
5057 Interface_ALIs := String_Element_Table.Last
5058 (In_Tree.String_Elements);
5066 In_Tree.String_Elements.Table (Interfaces).Next;
5069 -- Put the list of Interface ALIs in the project data
5071 Data.Lib_Interface_ALIs := Interface_ALIs;
5073 -- Check value of attribute Library_Auto_Init and set
5074 -- Lib_Auto_Init accordingly.
5076 if Lib_Auto_Init.Default then
5078 -- If no attribute Library_Auto_Init is declared, then set auto
5079 -- init only if it is supported.
5081 Data.Lib_Auto_Init := Auto_Init_Supported;
5084 Get_Name_String (Lib_Auto_Init.Value);
5085 To_Lower (Name_Buffer (1 .. Name_Len));
5087 if Name_Buffer (1 .. Name_Len) = "false" then
5088 Data.Lib_Auto_Init := False;
5090 elsif Name_Buffer (1 .. Name_Len) = "true" then
5091 if Auto_Init_Supported then
5092 Data.Lib_Auto_Init := True;
5095 -- Library_Auto_Init cannot be "true" if auto init is not
5100 "library auto init not supported " &
5102 Lib_Auto_Init.Location);
5108 "invalid value for attribute Library_Auto_Init",
5109 Lib_Auto_Init.Location);
5114 -- If attribute Library_Src_Dir is defined and not the empty string,
5115 -- check if the directory exist and is not the object directory or
5116 -- one of the source directories. This is the directory where copies
5117 -- of the interface sources will be copied. Note that this directory
5118 -- may be the library directory.
5120 if Lib_Src_Dir.Value /= Empty_String then
5122 Dir_Id : constant File_Name_Type :=
5123 File_Name_Type (Lib_Src_Dir.Value);
5130 Data.Directory.Display_Name,
5131 Data.Library_Src_Dir.Name,
5132 Data.Library_Src_Dir.Display_Name,
5133 Create => "library source copy",
5134 Current_Dir => Current_Dir,
5135 Location => Lib_Src_Dir.Location,
5136 Externally_Built => Data.Externally_Built);
5138 -- If directory does not exist, report an error
5140 if Data.Library_Src_Dir = No_Path_Information then
5142 -- Get the absolute name of the library directory that does
5143 -- not exist, to report an error.
5146 Dir_Name : constant String :=
5147 Get_Name_String (Dir_Id);
5150 if Is_Absolute_Path (Dir_Name) then
5151 Err_Vars.Error_Msg_File_1 := Dir_Id;
5154 Get_Name_String (Data.Directory.Name);
5156 if Name_Buffer (Name_Len) /=
5159 Name_Len := Name_Len + 1;
5160 Name_Buffer (Name_Len) :=
5161 Directory_Separator;
5166 Name_Len + Dir_Name'Length) :=
5168 Name_Len := Name_Len + Dir_Name'Length;
5169 Err_Vars.Error_Msg_Name_1 := Name_Find;
5174 Error_Msg_File_1 := Dir_Id;
5177 "Directory { does not exist",
5178 Lib_Src_Dir.Location);
5181 -- Report error if it is the same as the object directory
5183 elsif Data.Library_Src_Dir = Data.Object_Directory then
5186 "directory to copy interfaces cannot be " &
5187 "the object directory",
5188 Lib_Src_Dir.Location);
5189 Data.Library_Src_Dir := No_Path_Information;
5193 Src_Dirs : String_List_Id;
5194 Src_Dir : String_Element;
5197 -- Interface copy directory cannot be one of the source
5198 -- directory of the current project.
5200 Src_Dirs := Data.Source_Dirs;
5201 while Src_Dirs /= Nil_String loop
5202 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5204 -- Report error if it is one of the source directories
5206 if Data.Library_Src_Dir.Name =
5207 Path_Name_Type (Src_Dir.Value)
5211 "directory to copy interfaces cannot " &
5212 "be one of the source directories",
5213 Lib_Src_Dir.Location);
5214 Data.Library_Src_Dir := No_Path_Information;
5218 Src_Dirs := Src_Dir.Next;
5221 if Data.Library_Src_Dir /= No_Path_Information then
5223 -- It cannot be a source directory of any other
5226 Project_Loop : for Pid in 1 ..
5227 Project_Table.Last (In_Tree.Projects)
5230 In_Tree.Projects.Table (Pid).Source_Dirs;
5231 Dir_Loop : while Src_Dirs /= Nil_String loop
5233 In_Tree.String_Elements.Table (Src_Dirs);
5235 -- Report error if it is one of the source
5238 if Data.Library_Src_Dir.Name =
5239 Path_Name_Type (Src_Dir.Value)
5242 File_Name_Type (Src_Dir.Value);
5244 In_Tree.Projects.Table (Pid).Name;
5247 "directory to copy interfaces cannot " &
5248 "be the same as source directory { of " &
5250 Lib_Src_Dir.Location);
5251 Data.Library_Src_Dir := No_Path_Information;
5255 Src_Dirs := Src_Dir.Next;
5257 end loop Project_Loop;
5261 -- In high verbosity, if there is a valid Library_Src_Dir,
5262 -- display its path name.
5264 if Data.Library_Src_Dir /= No_Path_Information
5265 and then Current_Verbosity = High
5267 Write_Str ("Directory to copy interfaces =""");
5268 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5275 -- Check the symbol related attributes
5277 -- First, the symbol policy
5279 if not Lib_Symbol_Policy.Default then
5281 Value : constant String :=
5283 (Get_Name_String (Lib_Symbol_Policy.Value));
5286 -- Symbol policy must hove one of a limited number of values
5288 if Value = "autonomous" or else Value = "default" then
5289 Data.Symbol_Data.Symbol_Policy := Autonomous;
5291 elsif Value = "compliant" then
5292 Data.Symbol_Data.Symbol_Policy := Compliant;
5294 elsif Value = "controlled" then
5295 Data.Symbol_Data.Symbol_Policy := Controlled;
5297 elsif Value = "restricted" then
5298 Data.Symbol_Data.Symbol_Policy := Restricted;
5300 elsif Value = "direct" then
5301 Data.Symbol_Data.Symbol_Policy := Direct;
5306 "illegal value for Library_Symbol_Policy",
5307 Lib_Symbol_Policy.Location);
5312 -- If attribute Library_Symbol_File is not specified, symbol policy
5313 -- cannot be Restricted.
5315 if Lib_Symbol_File.Default then
5316 if Data.Symbol_Data.Symbol_Policy = Restricted then
5319 "Library_Symbol_File needs to be defined when " &
5320 "symbol policy is Restricted",
5321 Lib_Symbol_Policy.Location);
5325 -- Library_Symbol_File is defined
5327 Data.Symbol_Data.Symbol_File :=
5328 Path_Name_Type (Lib_Symbol_File.Value);
5330 Get_Name_String (Lib_Symbol_File.Value);
5332 if Name_Len = 0 then
5335 "symbol file name cannot be an empty string",
5336 Lib_Symbol_File.Location);
5339 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5342 for J in 1 .. Name_Len loop
5343 if Name_Buffer (J) = '/'
5344 or else Name_Buffer (J) = Directory_Separator
5353 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5356 "symbol file name { is illegal. " &
5357 "Name cannot include directory info.",
5358 Lib_Symbol_File.Location);
5363 -- If attribute Library_Reference_Symbol_File is not defined,
5364 -- symbol policy cannot be Compliant or Controlled.
5366 if Lib_Ref_Symbol_File.Default then
5367 if Data.Symbol_Data.Symbol_Policy = Compliant
5368 or else Data.Symbol_Data.Symbol_Policy = Controlled
5372 "a reference symbol file needs to be defined",
5373 Lib_Symbol_Policy.Location);
5377 -- Library_Reference_Symbol_File is defined, check file exists
5379 Data.Symbol_Data.Reference :=
5380 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5382 Get_Name_String (Lib_Ref_Symbol_File.Value);
5384 if Name_Len = 0 then
5387 "reference symbol file name cannot be an empty string",
5388 Lib_Symbol_File.Location);
5391 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5393 Add_Str_To_Name_Buffer
5394 (Get_Name_String (Data.Directory.Name));
5395 Add_Char_To_Name_Buffer (Directory_Separator);
5396 Add_Str_To_Name_Buffer
5397 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5398 Data.Symbol_Data.Reference := Name_Find;
5401 if not Is_Regular_File
5402 (Get_Name_String (Data.Symbol_Data.Reference))
5405 File_Name_Type (Lib_Ref_Symbol_File.Value);
5407 -- For controlled and direct symbol policies, it is an error
5408 -- if the reference symbol file does not exist. For other
5409 -- symbol policies, this is just a warning
5412 Data.Symbol_Data.Symbol_Policy /= Controlled
5413 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5417 "<library reference symbol file { does not exist",
5418 Lib_Ref_Symbol_File.Location);
5420 -- In addition in the non-controlled case, if symbol policy
5421 -- is Compliant, it is changed to Autonomous, because there
5422 -- is no reference to check against, and we don't want to
5423 -- fail in this case.
5425 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5426 if Data.Symbol_Data.Symbol_Policy = Compliant then
5427 Data.Symbol_Data.Symbol_Policy := Autonomous;
5432 -- If both the reference symbol file and the symbol file are
5433 -- defined, then check that they are not the same file.
5435 if Data.Symbol_Data.Symbol_File /= No_Path then
5436 Get_Name_String (Data.Symbol_Data.Symbol_File);
5438 if Name_Len > 0 then
5440 Symb_Path : constant String :=
5443 (Data.Object_Directory.Name) &
5444 Directory_Separator &
5445 Name_Buffer (1 .. Name_Len),
5446 Directory => Current_Dir,
5448 Opt.Follow_Links_For_Files);
5449 Ref_Path : constant String :=
5452 (Data.Symbol_Data.Reference),
5453 Directory => Current_Dir,
5455 Opt.Follow_Links_For_Files);
5457 if Symb_Path = Ref_Path then
5460 "library reference symbol file and library" &
5461 " symbol file cannot be the same file",
5462 Lib_Ref_Symbol_File.Location);
5470 end Check_Stand_Alone_Library;
5472 ----------------------------
5473 -- Compute_Directory_Last --
5474 ----------------------------
5476 function Compute_Directory_Last (Dir : String) return Natural is
5479 and then (Dir (Dir'Last - 1) = Directory_Separator
5480 or else Dir (Dir'Last - 1) = '/')
5482 return Dir'Last - 1;
5486 end Compute_Directory_Last;
5493 (Project : Project_Id;
5494 In_Tree : Project_Tree_Ref;
5496 Flag_Location : Source_Ptr)
5498 Real_Location : Source_Ptr := Flag_Location;
5499 Error_Buffer : String (1 .. 5_000);
5500 Error_Last : Natural := 0;
5501 Name_Number : Natural := 0;
5502 File_Number : Natural := 0;
5503 First : Positive := Msg'First;
5506 procedure Add (C : Character);
5507 -- Add a character to the buffer
5509 procedure Add (S : String);
5510 -- Add a string to the buffer
5513 -- Add a name to the buffer
5516 -- Add a file name to the buffer
5522 procedure Add (C : Character) is
5524 Error_Last := Error_Last + 1;
5525 Error_Buffer (Error_Last) := C;
5528 procedure Add (S : String) is
5530 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5531 Error_Last := Error_Last + S'Length;
5538 procedure Add_File is
5539 File : File_Name_Type;
5543 File_Number := File_Number + 1;
5547 File := Err_Vars.Error_Msg_File_1;
5549 File := Err_Vars.Error_Msg_File_2;
5551 File := Err_Vars.Error_Msg_File_3;
5556 Get_Name_String (File);
5557 Add (Name_Buffer (1 .. Name_Len));
5565 procedure Add_Name is
5570 Name_Number := Name_Number + 1;
5574 Name := Err_Vars.Error_Msg_Name_1;
5576 Name := Err_Vars.Error_Msg_Name_2;
5578 Name := Err_Vars.Error_Msg_Name_3;
5583 Get_Name_String (Name);
5584 Add (Name_Buffer (1 .. Name_Len));
5588 -- Start of processing for Error_Msg
5591 -- If location of error is unknown, use the location of the project
5593 if Real_Location = No_Location then
5594 Real_Location := In_Tree.Projects.Table (Project).Location;
5597 if Error_Report = null then
5598 Prj.Err.Error_Msg (Msg, Real_Location);
5602 -- Ignore continuation character
5604 if Msg (First) = '\' then
5608 -- Warning character is always the first one in this package
5609 -- this is an undocumented kludge???
5611 if Msg (First) = '?' then
5615 elsif Msg (First) = '<' then
5618 if Err_Vars.Error_Msg_Warn then
5624 while Index <= Msg'Last loop
5625 if Msg (Index) = '{' then
5628 elsif Msg (Index) = '%' then
5629 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5641 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5644 ----------------------
5645 -- Find_Ada_Sources --
5646 ----------------------
5648 procedure Find_Ada_Sources
5649 (Project : Project_Id;
5650 In_Tree : Project_Tree_Ref;
5651 Data : in out Project_Data;
5652 Current_Dir : String)
5654 Source_Dir : String_List_Id := Data.Source_Dirs;
5655 Element : String_Element;
5657 Current_Source : String_List_Id := Nil_String;
5658 Source_Recorded : Boolean := False;
5661 if Current_Verbosity = High then
5662 Write_Line ("Looking for sources:");
5665 -- For each subdirectory
5667 while Source_Dir /= Nil_String loop
5669 Source_Recorded := False;
5670 Element := In_Tree.String_Elements.Table (Source_Dir);
5671 if Element.Value /= No_Name then
5672 Get_Name_String (Element.Display_Value);
5675 Source_Directory : constant String :=
5676 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5677 Dir_Last : constant Natural :=
5678 Compute_Directory_Last (Source_Directory);
5681 if Current_Verbosity = High then
5682 Write_Str ("Source_Dir = ");
5683 Write_Line (Source_Directory);
5686 -- We look at every entry in the source directory
5689 Source_Directory (Source_Directory'First .. Dir_Last));
5692 Read (Dir, Name_Buffer, Name_Len);
5694 if Current_Verbosity = High then
5695 Write_Str (" Checking ");
5696 Write_Line (Name_Buffer (1 .. Name_Len));
5699 exit when Name_Len = 0;
5702 File_Name : constant File_Name_Type := Name_Find;
5704 -- ??? We could probably optimize the following call:
5705 -- we need to resolve links only once for the
5706 -- directory itself, and then do a single call to
5707 -- readlink() for each file. Unfortunately that would
5708 -- require a change in Normalize_Pathname so that it
5709 -- has the option of not resolving links for its
5710 -- Directory parameter, only for Name.
5712 Path : constant String :=
5714 (Name => Name_Buffer (1 .. Name_Len),
5717 (Source_Directory'First .. Dir_Last),
5719 Opt.Follow_Links_For_Files,
5720 Case_Sensitive => True);
5722 Path_Name : Path_Name_Type;
5725 Name_Len := Path'Length;
5726 Name_Buffer (1 .. Name_Len) := Path;
5727 Path_Name := Name_Find;
5729 -- We attempt to register it as a source. However,
5730 -- there is no error if the file does not contain a
5731 -- valid source. But there is an error if we have a
5732 -- duplicate unit name.
5735 (File_Name => File_Name,
5736 Path_Name => Path_Name,
5740 Location => No_Location,
5741 Current_Source => Current_Source,
5742 Source_Recorded => Source_Recorded,
5743 Current_Dir => Current_Dir);
5752 when Directory_Error =>
5756 if Source_Recorded then
5757 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5761 Source_Dir := Element.Next;
5764 if Current_Verbosity = High then
5765 Write_Line ("end Looking for sources.");
5768 end Find_Ada_Sources;
5770 --------------------------------
5771 -- Free_Ada_Naming_Exceptions --
5772 --------------------------------
5774 procedure Free_Ada_Naming_Exceptions is
5776 Ada_Naming_Exception_Table.Set_Last (0);
5777 Ada_Naming_Exceptions.Reset;
5778 Reverse_Ada_Naming_Exceptions.Reset;
5779 end Free_Ada_Naming_Exceptions;
5781 ---------------------
5782 -- Get_Directories --
5783 ---------------------
5785 procedure Get_Directories
5786 (Project : Project_Id;
5787 In_Tree : Project_Tree_Ref;
5788 Current_Dir : String;
5789 Data : in out Project_Data)
5791 Object_Dir : constant Variable_Value :=
5793 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5795 Exec_Dir : constant Variable_Value :=
5797 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5799 Source_Dirs : constant Variable_Value :=
5801 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5803 Excluded_Source_Dirs : constant Variable_Value :=
5805 (Name_Excluded_Source_Dirs,
5806 Data.Decl.Attributes,
5809 Source_Files : constant Variable_Value :=
5811 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5813 Last_Source_Dir : String_List_Id := Nil_String;
5815 Languages : constant Variable_Value :=
5817 (Name_Languages, Data.Decl.Attributes, In_Tree);
5819 procedure Find_Source_Dirs
5820 (From : File_Name_Type;
5821 Location : Source_Ptr;
5822 Removed : Boolean := False);
5823 -- Find one or several source directories, and add (or remove, if
5824 -- Removed is True) them to list of source directories of the project.
5826 ----------------------
5827 -- Find_Source_Dirs --
5828 ----------------------
5830 procedure Find_Source_Dirs
5831 (From : File_Name_Type;
5832 Location : Source_Ptr;
5833 Removed : Boolean := False)
5835 Directory : constant String := Get_Name_String (From);
5836 Element : String_Element;
5838 procedure Recursive_Find_Dirs (Path : Name_Id);
5839 -- Find all the subdirectories (recursively) of Path and add them
5840 -- to the list of source directories of the project.
5842 -------------------------
5843 -- Recursive_Find_Dirs --
5844 -------------------------
5846 procedure Recursive_Find_Dirs (Path : Name_Id) is
5848 Name : String (1 .. 250);
5850 List : String_List_Id;
5851 Prev : String_List_Id;
5852 Element : String_Element;
5853 Found : Boolean := False;
5855 Non_Canonical_Path : Name_Id := No_Name;
5856 Canonical_Path : Name_Id := No_Name;
5858 The_Path : constant String :=
5860 (Get_Name_String (Path),
5861 Directory => Current_Dir,
5862 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5863 Directory_Separator;
5865 The_Path_Last : constant Natural :=
5866 Compute_Directory_Last (The_Path);
5869 Name_Len := The_Path_Last - The_Path'First + 1;
5870 Name_Buffer (1 .. Name_Len) :=
5871 The_Path (The_Path'First .. The_Path_Last);
5872 Non_Canonical_Path := Name_Find;
5874 if Osint.File_Names_Case_Sensitive then
5875 Canonical_Path := Non_Canonical_Path;
5877 Get_Name_String (Non_Canonical_Path);
5878 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5879 Canonical_Path := Name_Find;
5882 -- To avoid processing the same directory several times, check
5883 -- if the directory is already in Recursive_Dirs. If it is, then
5884 -- there is nothing to do, just return. If it is not, put it there
5885 -- and continue recursive processing.
5888 if Recursive_Dirs.Get (Canonical_Path) then
5891 Recursive_Dirs.Set (Canonical_Path, True);
5895 -- Check if directory is already in list
5897 List := Data.Source_Dirs;
5899 while List /= Nil_String loop
5900 Element := In_Tree.String_Elements.Table (List);
5902 if Element.Value /= No_Name then
5903 Found := Element.Value = Canonical_Path;
5908 List := Element.Next;
5911 -- If directory is not already in list, put it there
5913 if (not Removed) and (not Found) then
5914 if Current_Verbosity = High then
5916 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5919 String_Element_Table.Increment_Last
5920 (In_Tree.String_Elements);
5922 (Value => Canonical_Path,
5923 Display_Value => Non_Canonical_Path,
5924 Location => No_Location,
5929 -- Case of first source directory
5931 if Last_Source_Dir = Nil_String then
5932 Data.Source_Dirs := String_Element_Table.Last
5933 (In_Tree.String_Elements);
5935 -- Here we already have source directories
5938 -- Link the previous last to the new one
5940 In_Tree.String_Elements.Table
5941 (Last_Source_Dir).Next :=
5942 String_Element_Table.Last
5943 (In_Tree.String_Elements);
5946 -- And register this source directory as the new last
5948 Last_Source_Dir := String_Element_Table.Last
5949 (In_Tree.String_Elements);
5950 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5953 elsif Removed and Found then
5954 if Prev = Nil_String then
5956 In_Tree.String_Elements.Table (List).Next;
5958 In_Tree.String_Elements.Table (Prev).Next :=
5959 In_Tree.String_Elements.Table (List).Next;
5963 -- Now look for subdirectories. We do that even when this
5964 -- directory is already in the list, because some of its
5965 -- subdirectories may not be in the list yet.
5967 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5970 Read (Dir, Name, Last);
5973 if Name (1 .. Last) /= "."
5974 and then Name (1 .. Last) /= ".."
5976 -- Avoid . and .. directories
5978 if Current_Verbosity = High then
5979 Write_Str (" Checking ");
5980 Write_Line (Name (1 .. Last));
5984 Path_Name : constant String :=
5986 (Name => Name (1 .. Last),
5988 The_Path (The_Path'First .. The_Path_Last),
5989 Resolve_Links => Opt.Follow_Links_For_Dirs,
5990 Case_Sensitive => True);
5993 if Is_Directory (Path_Name) then
5994 -- We have found a new subdirectory, call self
5996 Name_Len := Path_Name'Length;
5997 Name_Buffer (1 .. Name_Len) := Path_Name;
5998 Recursive_Find_Dirs (Name_Find);
6007 when Directory_Error =>
6009 end Recursive_Find_Dirs;
6011 -- Start of processing for Find_Source_Dirs
6014 if Current_Verbosity = High and then not Removed then
6015 Write_Str ("Find_Source_Dirs (""");
6016 Write_Str (Directory);
6020 -- First, check if we are looking for a directory tree, indicated
6021 -- by "/**" at the end.
6023 if Directory'Length >= 3
6024 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
6025 and then (Directory (Directory'Last - 2) = '/'
6027 Directory (Directory'Last - 2) = Directory_Separator)
6030 Data.Known_Order_Of_Source_Dirs := False;
6033 Name_Len := Directory'Length - 3;
6035 if Name_Len = 0 then
6037 -- Case of "/**": all directories in file system
6040 Name_Buffer (1) := Directory (Directory'First);
6043 Name_Buffer (1 .. Name_Len) :=
6044 Directory (Directory'First .. Directory'Last - 3);
6047 if Current_Verbosity = High then
6048 Write_Str ("Looking for all subdirectories of """);
6049 Write_Str (Name_Buffer (1 .. Name_Len));
6054 Base_Dir : constant File_Name_Type := Name_Find;
6055 Root_Dir : constant String :=
6057 (Name => Get_Name_String (Base_Dir),
6059 Get_Name_String (Data.Directory.Display_Name),
6060 Resolve_Links => False,
6061 Case_Sensitive => True);
6064 if Root_Dir'Length = 0 then
6065 Err_Vars.Error_Msg_File_1 := Base_Dir;
6067 if Location = No_Location then
6070 "{ is not a valid directory.",
6075 "{ is not a valid directory.",
6080 -- We have an existing directory, we register it and all of
6081 -- its subdirectories.
6083 if Current_Verbosity = High then
6084 Write_Line ("Looking for source directories:");
6087 Name_Len := Root_Dir'Length;
6088 Name_Buffer (1 .. Name_Len) := Root_Dir;
6089 Recursive_Find_Dirs (Name_Find);
6091 if Current_Verbosity = High then
6092 Write_Line ("End of looking for source directories.");
6097 -- We have a single directory
6101 Path_Name : Path_Name_Type;
6102 Display_Path_Name : Path_Name_Type;
6103 List : String_List_Id;
6104 Prev : String_List_Id;
6108 (Project => Project,
6111 Parent => Data.Directory.Display_Name,
6113 Display => Display_Path_Name,
6114 Current_Dir => Current_Dir);
6116 if Path_Name = No_Path then
6117 Err_Vars.Error_Msg_File_1 := From;
6119 if Location = No_Location then
6122 "{ is not a valid directory",
6127 "{ is not a valid directory",
6133 Path : constant String :=
6134 Get_Name_String (Path_Name) &
6135 Directory_Separator;
6136 Last_Path : constant Natural :=
6137 Compute_Directory_Last (Path);
6139 Display_Path : constant String :=
6141 (Display_Path_Name) &
6142 Directory_Separator;
6143 Last_Display_Path : constant Natural :=
6144 Compute_Directory_Last
6146 Display_Path_Id : Name_Id;
6150 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6151 Path_Id := Name_Find;
6153 Add_Str_To_Name_Buffer
6155 (Display_Path'First .. Last_Display_Path));
6156 Display_Path_Id := Name_Find;
6160 -- As it is an existing directory, we add it to the
6161 -- list of directories.
6163 String_Element_Table.Increment_Last
6164 (In_Tree.String_Elements);
6168 Display_Value => Display_Path_Id,
6169 Location => No_Location,
6171 Next => Nil_String);
6173 if Last_Source_Dir = Nil_String then
6175 -- This is the first source directory
6177 Data.Source_Dirs := String_Element_Table.Last
6178 (In_Tree.String_Elements);
6181 -- We already have source directories, link the
6182 -- previous last to the new one.
6184 In_Tree.String_Elements.Table
6185 (Last_Source_Dir).Next :=
6186 String_Element_Table.Last
6187 (In_Tree.String_Elements);
6190 -- And register this source directory as the new last
6192 Last_Source_Dir := String_Element_Table.Last
6193 (In_Tree.String_Elements);
6194 In_Tree.String_Elements.Table
6195 (Last_Source_Dir) := Element;
6198 -- Remove source dir, if present
6200 List := Data.Source_Dirs;
6203 -- Look for source dir in current list
6205 while List /= Nil_String loop
6206 Element := In_Tree.String_Elements.Table (List);
6207 exit when Element.Value = Path_Id;
6209 List := Element.Next;
6212 if List /= Nil_String then
6213 -- Source dir was found, remove it from the list
6215 if Prev = Nil_String then
6217 In_Tree.String_Elements.Table (List).Next;
6220 In_Tree.String_Elements.Table (Prev).Next :=
6221 In_Tree.String_Elements.Table (List).Next;
6229 end Find_Source_Dirs;
6231 -- Start of processing for Get_Directories
6234 if Current_Verbosity = High then
6235 Write_Line ("Starting to look for directories");
6238 -- Set the object directory to its default which may be nil, if there
6239 -- is no sources in the project.
6241 if (((not Source_Files.Default)
6242 and then Source_Files.Values = Nil_String)
6244 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
6246 ((not Languages.Default) and then Languages.Values = Nil_String))
6247 and then Data.Extends = No_Project
6249 Data.Object_Directory := No_Path_Information;
6252 Data.Object_Directory := Data.Directory;
6255 -- Check the object directory
6257 if Object_Dir.Value /= Empty_String then
6258 Get_Name_String (Object_Dir.Value);
6260 if Name_Len = 0 then
6263 "Object_Dir cannot be empty",
6264 Object_Dir.Location);
6267 -- We check that the specified object directory does exist
6272 File_Name_Type (Object_Dir.Value),
6273 Data.Directory.Display_Name,
6274 Data.Object_Directory.Name,
6275 Data.Object_Directory.Display_Name,
6277 Location => Object_Dir.Location,
6278 Current_Dir => Current_Dir,
6279 Externally_Built => Data.Externally_Built);
6281 if Data.Object_Directory = No_Path_Information then
6283 -- The object directory does not exist, report an error if the
6284 -- project is not externally built.
6286 if not Data.Externally_Built then
6287 Err_Vars.Error_Msg_File_1 :=
6288 File_Name_Type (Object_Dir.Value);
6291 "the object directory { cannot be found",
6295 -- Do not keep a nil Object_Directory. Set it to the specified
6296 -- (relative or absolute) path. This is for the benefit of
6297 -- tools that recover from errors; for example, these tools
6298 -- could create the non existent directory.
6300 Data.Object_Directory.Display_Name :=
6301 Path_Name_Type (Object_Dir.Value);
6303 if Osint.File_Names_Case_Sensitive then
6304 Data.Object_Directory.Name :=
6305 Path_Name_Type (Object_Dir.Value);
6307 Get_Name_String (Object_Dir.Value);
6308 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6309 Data.Object_Directory.Name := Name_Find;
6314 elsif Data.Object_Directory /= No_Path_Information and then
6318 Name_Buffer (1) := '.';
6323 Data.Directory.Display_Name,
6324 Data.Object_Directory.Name,
6325 Data.Object_Directory.Display_Name,
6327 Location => Object_Dir.Location,
6328 Current_Dir => Current_Dir,
6329 Externally_Built => Data.Externally_Built);
6332 if Current_Verbosity = High then
6333 if Data.Object_Directory = No_Path_Information then
6334 Write_Line ("No object directory");
6336 Write_Str ("Object directory: """);
6337 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6342 -- Check the exec directory
6344 -- We set the object directory to its default
6346 Data.Exec_Directory := Data.Object_Directory;
6348 if Exec_Dir.Value /= Empty_String then
6349 Get_Name_String (Exec_Dir.Value);
6351 if Name_Len = 0 then
6354 "Exec_Dir cannot be empty",
6358 -- We check that the specified exec directory does exist
6363 File_Name_Type (Exec_Dir.Value),
6364 Data.Directory.Display_Name,
6365 Data.Exec_Directory.Name,
6366 Data.Exec_Directory.Display_Name,
6368 Location => Exec_Dir.Location,
6369 Current_Dir => Current_Dir,
6370 Externally_Built => Data.Externally_Built);
6372 if Data.Exec_Directory = No_Path_Information then
6373 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6376 "the exec directory { cannot be found",
6382 if Current_Verbosity = High then
6383 if Data.Exec_Directory = No_Path_Information then
6384 Write_Line ("No exec directory");
6386 Write_Str ("Exec directory: """);
6387 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6392 -- Look for the source directories
6394 if Current_Verbosity = High then
6395 Write_Line ("Starting to look for source directories");
6398 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6400 if (not Source_Files.Default) and then
6401 Source_Files.Values = Nil_String
6403 Data.Source_Dirs := Nil_String;
6405 if Data.Qualifier = Standard then
6409 "a standard project cannot have no sources",
6410 Source_Files.Location);
6413 elsif Source_Dirs.Default then
6415 -- No Source_Dirs specified: the single source directory is the one
6416 -- containing the project file
6418 String_Element_Table.Increment_Last
6419 (In_Tree.String_Elements);
6420 Data.Source_Dirs := String_Element_Table.Last
6421 (In_Tree.String_Elements);
6422 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6423 (Value => Name_Id (Data.Directory.Name),
6424 Display_Value => Name_Id (Data.Directory.Display_Name),
6425 Location => No_Location,
6430 if Current_Verbosity = High then
6431 Write_Line ("Single source directory:");
6433 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6437 elsif Source_Dirs.Values = Nil_String then
6438 if Data.Qualifier = Standard then
6442 "a standard project cannot have no source directories",
6443 Source_Dirs.Location);
6446 Data.Source_Dirs := Nil_String;
6450 Source_Dir : String_List_Id;
6451 Element : String_Element;
6454 -- Process the source directories for each element of the list
6456 Source_Dir := Source_Dirs.Values;
6457 while Source_Dir /= Nil_String loop
6458 Element := In_Tree.String_Elements.Table (Source_Dir);
6460 (File_Name_Type (Element.Value), Element.Location);
6461 Source_Dir := Element.Next;
6466 if not Excluded_Source_Dirs.Default
6467 and then Excluded_Source_Dirs.Values /= Nil_String
6470 Source_Dir : String_List_Id;
6471 Element : String_Element;
6474 -- Process the source directories for each element of the list
6476 Source_Dir := Excluded_Source_Dirs.Values;
6477 while Source_Dir /= Nil_String loop
6478 Element := In_Tree.String_Elements.Table (Source_Dir);
6480 (File_Name_Type (Element.Value),
6483 Source_Dir := Element.Next;
6488 if Current_Verbosity = High then
6489 Write_Line ("Putting source directories in canonical cases");
6493 Current : String_List_Id := Data.Source_Dirs;
6494 Element : String_Element;
6497 while Current /= Nil_String loop
6498 Element := In_Tree.String_Elements.Table (Current);
6499 if Element.Value /= No_Name then
6500 if not Osint.File_Names_Case_Sensitive then
6501 Get_Name_String (Element.Value);
6502 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6503 Element.Value := Name_Find;
6506 In_Tree.String_Elements.Table (Current) := Element;
6509 Current := Element.Next;
6512 end Get_Directories;
6519 (Project : Project_Id;
6520 In_Tree : Project_Tree_Ref;
6521 Data : in out Project_Data)
6523 Mains : constant Variable_Value :=
6524 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6525 List : String_List_Id;
6526 Elem : String_Element;
6529 Data.Mains := Mains.Values;
6531 -- If no Mains were specified, and if we are an extending project,
6532 -- inherit the Mains from the project we are extending.
6534 if Mains.Default then
6535 if not Data.Library and then Data.Extends /= No_Project then
6537 In_Tree.Projects.Table (Data.Extends).Mains;
6540 -- In a library project file, Main cannot be specified
6542 elsif Data.Library then
6545 "a library project file cannot have Main specified",
6549 List := Mains.Values;
6550 while List /= Nil_String loop
6551 Elem := In_Tree.String_Elements.Table (List);
6553 if Length_Of_Name (Elem.Value) = 0 then
6556 "?a main cannot have an empty name",
6566 ---------------------------
6567 -- Get_Sources_From_File --
6568 ---------------------------
6570 procedure Get_Sources_From_File
6572 Location : Source_Ptr;
6573 Project : Project_Id;
6574 In_Tree : Project_Tree_Ref)
6576 File : Prj.Util.Text_File;
6577 Line : String (1 .. 250);
6579 Source_Name : File_Name_Type;
6580 Name_Loc : Name_Location;
6583 if Get_Mode = Ada_Only then
6587 if Current_Verbosity = High then
6588 Write_Str ("Opening """);
6595 Prj.Util.Open (File, Path);
6597 if not Prj.Util.Is_Valid (File) then
6598 Error_Msg (Project, In_Tree, "file does not exist", Location);
6601 -- Read the lines one by one
6603 while not Prj.Util.End_Of_File (File) loop
6604 Prj.Util.Get_Line (File, Line, Last);
6606 -- A non empty, non comment line should contain a file name
6609 and then (Last = 1 or else Line (1 .. 2) /= "--")
6612 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6613 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6614 Source_Name := Name_Find;
6616 -- Check that there is no directory information
6618 for J in 1 .. Last loop
6619 if Line (J) = '/' or else Line (J) = Directory_Separator then
6620 Error_Msg_File_1 := Source_Name;
6624 "file name cannot include directory information ({)",
6630 Name_Loc := Source_Names.Get (Source_Name);
6632 if Name_Loc = No_Name_Location then
6634 (Name => Source_Name,
6635 Location => Location,
6636 Source => No_Source,
6641 Source_Names.Set (Source_Name, Name_Loc);
6645 Prj.Util.Close (File);
6648 end Get_Sources_From_File;
6655 (In_Tree : Project_Tree_Ref;
6656 Canonical_File_Name : File_Name_Type;
6657 Naming : Naming_Data;
6658 Exception_Id : out Ada_Naming_Exception_Id;
6659 Unit_Name : out Name_Id;
6660 Unit_Kind : out Spec_Or_Body;
6661 Needs_Pragma : out Boolean)
6663 Info_Id : Ada_Naming_Exception_Id :=
6664 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6665 VMS_Name : File_Name_Type;
6668 if Info_Id = No_Ada_Naming_Exception then
6669 if Hostparm.OpenVMS then
6670 VMS_Name := Canonical_File_Name;
6671 Get_Name_String (VMS_Name);
6673 if Name_Buffer (Name_Len) = '.' then
6674 Name_Len := Name_Len - 1;
6675 VMS_Name := Name_Find;
6678 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6683 if Info_Id /= No_Ada_Naming_Exception then
6684 Exception_Id := Info_Id;
6685 Unit_Name := No_Name;
6686 Unit_Kind := Specification;
6687 Needs_Pragma := True;
6691 Needs_Pragma := False;
6692 Exception_Id := No_Ada_Naming_Exception;
6694 Get_Name_String (Canonical_File_Name);
6696 -- How about some comments and a name for this declare block ???
6697 -- In fact the whole code below needs more comments ???
6700 File : String := Name_Buffer (1 .. Name_Len);
6701 First : constant Positive := File'First;
6702 Last : Natural := File'Last;
6703 Standard_GNAT : Boolean;
6704 Spec : constant File_Name_Type :=
6705 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6706 Body_Suff : constant File_Name_Type :=
6707 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6710 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6711 and then Body_Suff = Default_Ada_Body_Suffix;
6714 Spec_Suffix : constant String := Get_Name_String (Spec);
6715 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6716 Sep_Suffix : constant String :=
6717 Get_Name_String (Naming.Separate_Suffix);
6719 May_Be_Spec : Boolean;
6720 May_Be_Body : Boolean;
6721 May_Be_Sep : Boolean;
6725 File'Length > Spec_Suffix'Length
6727 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6730 File'Length > Body_Suffix'Length
6732 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6735 File'Length > Sep_Suffix'Length
6737 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6739 -- If two May_Be_ booleans are True, always choose the longer one
6742 if May_Be_Body and then
6743 Spec_Suffix'Length < Body_Suffix'Length
6745 Unit_Kind := Body_Part;
6747 if May_Be_Sep and then
6748 Body_Suffix'Length < Sep_Suffix'Length
6750 Last := Last - Sep_Suffix'Length;
6751 May_Be_Body := False;
6754 Last := Last - Body_Suffix'Length;
6755 May_Be_Sep := False;
6758 elsif May_Be_Sep and then
6759 Spec_Suffix'Length < Sep_Suffix'Length
6761 Unit_Kind := Body_Part;
6762 Last := Last - Sep_Suffix'Length;
6765 Unit_Kind := Specification;
6766 Last := Last - Spec_Suffix'Length;
6769 elsif May_Be_Body then
6770 Unit_Kind := Body_Part;
6772 if May_Be_Sep and then
6773 Body_Suffix'Length < Sep_Suffix'Length
6775 Last := Last - Sep_Suffix'Length;
6776 May_Be_Body := False;
6778 Last := Last - Body_Suffix'Length;
6779 May_Be_Sep := False;
6782 elsif May_Be_Sep then
6783 Unit_Kind := Body_Part;
6784 Last := Last - Sep_Suffix'Length;
6792 -- This is not a source file
6794 Unit_Name := No_Name;
6795 Unit_Kind := Specification;
6797 if Current_Verbosity = High then
6798 Write_Line (" Not a valid file name.");
6803 elsif Current_Verbosity = High then
6805 when Specification =>
6806 Write_Str (" Specification: ");
6807 Write_Line (File (First .. Last + Spec_Suffix'Length));
6811 Write_Str (" Body: ");
6812 Write_Line (File (First .. Last + Body_Suffix'Length));
6815 Write_Str (" Separate: ");
6816 Write_Line (File (First .. Last + Sep_Suffix'Length));
6822 Get_Name_String (Naming.Dot_Replacement);
6824 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6826 if Name_Buffer (1 .. Name_Len) /= "." then
6828 -- If Dot_Replacement is not a single dot, then there should not
6829 -- be any dot in the name.
6831 for Index in First .. Last loop
6832 if File (Index) = '.' then
6833 if Current_Verbosity = High then
6835 (" Not a valid file name (some dot not replaced).");
6838 Unit_Name := No_Name;
6844 -- Replace the substring Dot_Replacement with dots
6847 Index : Positive := First;
6850 while Index <= Last - Name_Len + 1 loop
6852 if File (Index .. Index + Name_Len - 1) =
6853 Name_Buffer (1 .. Name_Len)
6855 File (Index) := '.';
6857 if Name_Len > 1 and then Index < Last then
6858 File (Index + 1 .. Last - Name_Len + 1) :=
6859 File (Index + Name_Len .. Last);
6862 Last := Last - Name_Len + 1;
6870 -- Check if the file casing is right
6873 Src : String := File (First .. Last);
6874 Src_Last : Positive := Last;
6877 -- If casing is significant, deal with upper/lower case translate
6879 if File_Names_Case_Sensitive then
6880 case Naming.Casing is
6881 when All_Lower_Case =>
6884 Mapping => Lower_Case_Map);
6886 when All_Upper_Case =>
6889 Mapping => Upper_Case_Map);
6891 when Mixed_Case | Unknown =>
6895 if Src /= File (First .. Last) then
6896 if Current_Verbosity = High then
6897 Write_Line (" Not a valid file name (casing).");
6900 Unit_Name := No_Name;
6905 -- Put the name in lower case
6909 Mapping => Lower_Case_Map);
6911 -- In the standard GNAT naming scheme, check for special cases:
6912 -- children or separates of A, G, I or S, and run time sources.
6914 if Standard_GNAT and then Src'Length >= 3 then
6916 S1 : constant Character := Src (Src'First);
6917 S2 : constant Character := Src (Src'First + 1);
6918 S3 : constant Character := Src (Src'First + 2);
6926 -- Children or separates of packages A, G, I or S. These
6927 -- names are x__ ... or x~... (where x is a, g, i, or s).
6928 -- Both versions (x__... and x~...) are allowed in all
6929 -- platforms, because it is not possible to know the
6930 -- platform before processing of the project files.
6932 if S2 = '_' and then S3 = '_' then
6933 Src (Src'First + 1) := '.';
6934 Src_Last := Src_Last - 1;
6935 Src (Src'First + 2 .. Src_Last) :=
6936 Src (Src'First + 3 .. Src_Last + 1);
6939 Src (Src'First + 1) := '.';
6941 -- If it is potentially a run time source, disable
6942 -- filling of the mapping file to avoid warnings.
6945 Set_Mapping_File_Initial_State_To_Empty;
6951 if Current_Verbosity = High then
6953 Write_Line (Src (Src'First .. Src_Last));
6956 -- Now, we check if this name is a valid unit name
6959 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6969 function Hash (Unit : Unit_Info) return Header_Num is
6971 return Header_Num (Unit.Unit mod 2048);
6974 -----------------------
6975 -- Is_Illegal_Suffix --
6976 -----------------------
6978 function Is_Illegal_Suffix
6980 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6983 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6987 -- If dot replacement is a single dot, and first character of suffix is
6990 if Dot_Replacement_Is_A_Single_Dot
6991 and then Suffix (Suffix'First) = '.'
6993 for Index in Suffix'First + 1 .. Suffix'Last loop
6995 -- If there is another dot
6997 if Suffix (Index) = '.' then
6999 -- It is illegal to have a letter following the initial dot
7001 return Is_Letter (Suffix (Suffix'First + 1));
7009 end Is_Illegal_Suffix;
7011 ----------------------
7012 -- Locate_Directory --
7013 ----------------------
7015 procedure Locate_Directory
7016 (Project : Project_Id;
7017 In_Tree : Project_Tree_Ref;
7018 Name : File_Name_Type;
7019 Parent : Path_Name_Type;
7020 Dir : out Path_Name_Type;
7021 Display : out Path_Name_Type;
7022 Create : String := "";
7023 Current_Dir : String;
7024 Location : Source_Ptr := No_Location;
7025 Externally_Built : Boolean := False)
7027 The_Parent : constant String :=
7028 Get_Name_String (Parent) & Directory_Separator;
7030 The_Parent_Last : constant Natural :=
7031 Compute_Directory_Last (The_Parent);
7033 Full_Name : File_Name_Type;
7035 The_Name : File_Name_Type;
7038 Get_Name_String (Name);
7040 -- Add Subdirs.all if it is a directory that may be created and
7041 -- Subdirs is not null;
7043 if Create /= "" and then Subdirs /= null then
7044 if Name_Buffer (Name_Len) /= Directory_Separator then
7045 Add_Char_To_Name_Buffer (Directory_Separator);
7048 Add_Str_To_Name_Buffer (Subdirs.all);
7051 -- Convert '/' to directory separator (for Windows)
7053 for J in 1 .. Name_Len loop
7054 if Name_Buffer (J) = '/' then
7055 Name_Buffer (J) := Directory_Separator;
7059 The_Name := Name_Find;
7061 if Current_Verbosity = High then
7062 Write_Str ("Locate_Directory (""");
7063 Write_Str (Get_Name_String (The_Name));
7064 Write_Str (""", """);
7065 Write_Str (The_Parent);
7072 if Is_Absolute_Path (Get_Name_String (The_Name)) then
7073 Full_Name := The_Name;
7077 Add_Str_To_Name_Buffer
7078 (The_Parent (The_Parent'First .. The_Parent_Last));
7079 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7080 Full_Name := Name_Find;
7084 Full_Path_Name : String_Access :=
7085 new String'(Get_Name_String (Full_Name));
7088 if (Setup_Projects or else Subdirs /= null)
7089 and then Create'Length > 0
7091 if not Is_Directory (Full_Path_Name.all) then
7092 -- If project is externally built, do not create a subdir,
7093 -- use the specified directory, without the subdir.
7095 if Externally_Built then
7096 if Is_Absolute_Path (Get_Name_String (Name)) then
7097 Get_Name_String (Name);
7101 Add_Str_To_Name_Buffer
7102 (The_Parent (The_Parent'First .. The_Parent_Last));
7103 Add_Str_To_Name_Buffer (Get_Name_String (Name));
7106 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
7110 Create_Path (Full_Path_Name.all);
7112 if not Quiet_Output then
7114 Write_Str (" directory """);
7115 Write_Str (Full_Path_Name.all);
7116 Write_Line (""" created");
7123 "could not create " & Create &
7124 " directory " & Full_Path_Name.all,
7131 if Is_Directory (Full_Path_Name.all) then
7133 Normed : constant String :=
7135 (Full_Path_Name.all,
7136 Directory => Current_Dir,
7137 Resolve_Links => False,
7138 Case_Sensitive => True);
7140 Canonical_Path : constant String :=
7143 Directory => Current_Dir,
7145 Opt.Follow_Links_For_Dirs,
7146 Case_Sensitive => False);
7149 Name_Len := Normed'Length;
7150 Name_Buffer (1 .. Name_Len) := Normed;
7151 Display := Name_Find;
7153 Name_Len := Canonical_Path'Length;
7154 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7159 Free (Full_Path_Name);
7161 end Locate_Directory;
7163 ---------------------------
7164 -- Find_Excluded_Sources --
7165 ---------------------------
7167 procedure Find_Excluded_Sources
7168 (Project : Project_Id;
7169 In_Tree : Project_Tree_Ref;
7170 Data : Project_Data)
7172 Excluded_Sources : Variable_Value;
7174 Excluded_Source_List_File : Variable_Value;
7176 Current : String_List_Id;
7178 Element : String_Element;
7180 Location : Source_Ptr;
7182 Name : File_Name_Type;
7184 File : Prj.Util.Text_File;
7185 Line : String (1 .. 300);
7188 Locally_Removed : Boolean := False;
7190 Excluded_Source_List_File :=
7192 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7196 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7198 -- If Excluded_Source_Files is not declared, check
7199 -- Locally_Removed_Files.
7201 if Excluded_Sources.Default then
7202 Locally_Removed := True;
7205 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7208 Excluded_Sources_Htable.Reset;
7210 -- If there are excluded sources, put them in the table
7212 if not Excluded_Sources.Default then
7213 if not Excluded_Source_List_File.Default then
7214 if Locally_Removed then
7217 "?both attributes Locally_Removed_Files and " &
7218 "Excluded_Source_List_File are present",
7219 Excluded_Source_List_File.Location);
7223 "?both attributes Excluded_Source_Files and " &
7224 "Excluded_Source_List_File are present",
7225 Excluded_Source_List_File.Location);
7229 Current := Excluded_Sources.Values;
7230 while Current /= Nil_String loop
7231 Element := In_Tree.String_Elements.Table (Current);
7233 if Osint.File_Names_Case_Sensitive then
7234 Name := File_Name_Type (Element.Value);
7236 Get_Name_String (Element.Value);
7237 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7241 -- If the element has no location, then use the location
7242 -- of Excluded_Sources to report possible errors.
7244 if Element.Location = No_Location then
7245 Location := Excluded_Sources.Location;
7247 Location := Element.Location;
7250 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7251 Current := Element.Next;
7254 elsif not Excluded_Source_List_File.Default then
7255 Location := Excluded_Source_List_File.Location;
7258 Source_File_Path_Name : constant String :=
7261 (Excluded_Source_List_File.Value),
7262 Data.Directory.Name);
7265 if Source_File_Path_Name'Length = 0 then
7266 Err_Vars.Error_Msg_File_1 :=
7267 File_Name_Type (Excluded_Source_List_File.Value);
7270 "file with excluded sources { does not exist",
7271 Excluded_Source_List_File.Location);
7276 Prj.Util.Open (File, Source_File_Path_Name);
7278 if not Prj.Util.Is_Valid (File) then
7280 (Project, In_Tree, "file does not exist", Location);
7282 -- Read the lines one by one
7284 while not Prj.Util.End_Of_File (File) loop
7285 Prj.Util.Get_Line (File, Line, Last);
7287 -- A non empty, non comment line should contain a file
7291 and then (Last = 1 or else Line (1 .. 2) /= "--")
7294 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7295 Canonical_Case_File_Name
7296 (Name_Buffer (1 .. Name_Len));
7299 -- Check that there is no directory information
7301 for J in 1 .. Last loop
7303 or else Line (J) = Directory_Separator
7305 Error_Msg_File_1 := Name;
7309 "file name cannot include " &
7310 "directory information ({)",
7316 Excluded_Sources_Htable.Set
7317 (Name, (Name, False, Location));
7321 Prj.Util.Close (File);
7326 end Find_Excluded_Sources;
7328 ---------------------------
7329 -- Find_Explicit_Sources --
7330 ---------------------------
7332 procedure Find_Explicit_Sources
7333 (Current_Dir : String;
7334 Project : Project_Id;
7335 In_Tree : Project_Tree_Ref;
7336 Data : in out Project_Data)
7338 Sources : constant Variable_Value :=
7341 Data.Decl.Attributes,
7343 Source_List_File : constant Variable_Value :=
7345 (Name_Source_List_File,
7346 Data.Decl.Attributes,
7348 Name_Loc : Name_Location;
7351 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7353 (Source_List_File.Kind = Single,
7354 "Source_List_File is not a single string");
7356 -- If the user has specified a Sources attribute
7358 if not Sources.Default then
7359 if not Source_List_File.Default then
7362 "?both attributes source_files and " &
7363 "source_list_file are present",
7364 Source_List_File.Location);
7367 -- Sources is a list of file names
7370 Current : String_List_Id := Sources.Values;
7371 Element : String_Element;
7372 Location : Source_Ptr;
7373 Name : File_Name_Type;
7376 if Get_Mode = Ada_Only then
7377 Data.Ada_Sources_Present := Current /= Nil_String;
7380 if Get_Mode = Multi_Language then
7381 if Current = Nil_String then
7382 Data.First_Language_Processing := No_Language_Index;
7384 -- This project contains no source. For projects that
7385 -- don't extend other projects, this also means that
7386 -- there is no need for an object directory, if not
7389 if Data.Extends = No_Project
7390 and then Data.Object_Directory = Data.Directory
7392 Data.Object_Directory := No_Path_Information;
7397 while Current /= Nil_String loop
7398 Element := In_Tree.String_Elements.Table (Current);
7399 Get_Name_String (Element.Value);
7401 if Osint.File_Names_Case_Sensitive then
7402 Name := File_Name_Type (Element.Value);
7404 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7408 -- If the element has no location, then use the
7409 -- location of Sources to report possible errors.
7411 if Element.Location = No_Location then
7412 Location := Sources.Location;
7414 Location := Element.Location;
7417 -- Check that there is no directory information
7419 for J in 1 .. Name_Len loop
7420 if Name_Buffer (J) = '/'
7421 or else Name_Buffer (J) = Directory_Separator
7423 Error_Msg_File_1 := Name;
7427 "file name cannot include directory " &
7434 -- In Multi_Language mode, check whether the file is
7435 -- already there: the same file name may be in the list; if
7436 -- the source is missing, the error will be on the first
7437 -- mention of the source file name.
7441 Name_Loc := No_Name_Location;
7442 when Multi_Language =>
7443 Name_Loc := Source_Names.Get (Name);
7446 if Name_Loc = No_Name_Location then
7449 Location => Location,
7450 Source => No_Source,
7453 Source_Names.Set (Name, Name_Loc);
7456 Current := Element.Next;
7459 if Get_Mode = Ada_Only then
7460 Get_Path_Names_And_Record_Ada_Sources
7461 (Project, In_Tree, Data, Current_Dir);
7465 -- If we have no Source_Files attribute, check the Source_List_File
7468 elsif not Source_List_File.Default then
7470 -- Source_List_File is the name of the file
7471 -- that contains the source file names
7474 Source_File_Path_Name : constant String :=
7476 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7479 if Source_File_Path_Name'Length = 0 then
7480 Err_Vars.Error_Msg_File_1 :=
7481 File_Name_Type (Source_List_File.Value);
7484 "file with sources { does not exist",
7485 Source_List_File.Location);
7488 Get_Sources_From_File
7489 (Source_File_Path_Name, Source_List_File.Location,
7492 if Get_Mode = Ada_Only then
7493 -- Look in the source directories to find those sources
7495 Get_Path_Names_And_Record_Ada_Sources
7496 (Project, In_Tree, Data, Current_Dir);
7502 -- Neither Source_Files nor Source_List_File has been
7503 -- specified. Find all the files that satisfy the naming
7504 -- scheme in all the source directories.
7506 if Get_Mode = Ada_Only then
7507 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7511 if Get_Mode = Multi_Language then
7513 (Project, In_Tree, Data,
7515 Sources.Default and then Source_List_File.Default);
7517 -- Check if all exceptions have been found.
7518 -- For Ada, it is an error if an exception is not found.
7519 -- For other language, the source is simply removed.
7525 Source := Data.First_Source;
7526 while Source /= No_Source loop
7528 Src_Data : Source_Data renames
7529 In_Tree.Sources.Table (Source);
7532 if Src_Data.Naming_Exception
7533 and then Src_Data.Path = No_Path_Information
7535 if Src_Data.Unit /= No_Name then
7536 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7537 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7540 "source file %% for unit %% not found",
7544 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7547 Source := Src_Data.Next_In_Project;
7552 -- Check that all sources in Source_Files or the file
7553 -- Source_List_File has been found.
7556 Name_Loc : Name_Location;
7559 Name_Loc := Source_Names.Get_First;
7560 while Name_Loc /= No_Name_Location loop
7561 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7562 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7566 "file %% not found",
7570 Name_Loc := Source_Names.Get_Next;
7575 if Get_Mode = Ada_Only
7576 and then Data.Extends = No_Project
7578 -- We should have found at least one source, if not report an error
7580 if Data.Ada_Sources = Nil_String then
7582 (Project, "Ada", In_Tree, Source_List_File.Location);
7586 end Find_Explicit_Sources;
7588 -------------------------------------------
7589 -- Get_Path_Names_And_Record_Ada_Sources --
7590 -------------------------------------------
7592 procedure Get_Path_Names_And_Record_Ada_Sources
7593 (Project : Project_Id;
7594 In_Tree : Project_Tree_Ref;
7595 Data : in out Project_Data;
7596 Current_Dir : String)
7598 Source_Dir : String_List_Id;
7599 Element : String_Element;
7600 Path : Path_Name_Type;
7602 Name : File_Name_Type;
7603 Canonical_Name : File_Name_Type;
7604 Name_Str : String (1 .. 1_024);
7605 Last : Natural := 0;
7607 Current_Source : String_List_Id := Nil_String;
7608 First_Error : Boolean := True;
7609 Source_Recorded : Boolean := False;
7612 -- We look in all source directories for the file names in the hash
7613 -- table Source_Names.
7615 Source_Dir := Data.Source_Dirs;
7616 while Source_Dir /= Nil_String loop
7617 Source_Recorded := False;
7618 Element := In_Tree.String_Elements.Table (Source_Dir);
7621 Dir_Path : constant String :=
7622 Get_Name_String (Element.Display_Value);
7624 if Current_Verbosity = High then
7625 Write_Str ("checking directory """);
7626 Write_Str (Dir_Path);
7630 Open (Dir, Dir_Path);
7633 Read (Dir, Name_Str, Last);
7637 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7640 if Osint.File_Names_Case_Sensitive then
7641 Canonical_Name := Name;
7643 Canonical_Case_File_Name (Name_Str (1 .. Last));
7644 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7645 Canonical_Name := Name_Find;
7648 NL := Source_Names.Get (Canonical_Name);
7650 if NL /= No_Name_Location and then not NL.Found then
7652 Source_Names.Set (Canonical_Name, NL);
7653 Name_Len := Dir_Path'Length;
7654 Name_Buffer (1 .. Name_Len) := Dir_Path;
7656 if Name_Buffer (Name_Len) /= Directory_Separator then
7657 Add_Char_To_Name_Buffer (Directory_Separator);
7660 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7663 if Current_Verbosity = High then
7664 Write_Str (" found ");
7665 Write_Line (Get_Name_String (Name));
7668 -- Register the source if it is an Ada compilation unit
7676 Location => NL.Location,
7677 Current_Source => Current_Source,
7678 Source_Recorded => Source_Recorded,
7679 Current_Dir => Current_Dir);
7686 if Source_Recorded then
7687 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7691 Source_Dir := Element.Next;
7694 -- It is an error if a source file name in a source list or
7695 -- in a source list file is not found.
7697 NL := Source_Names.Get_First;
7698 while NL /= No_Name_Location loop
7699 if not NL.Found then
7700 Err_Vars.Error_Msg_File_1 := NL.Name;
7705 "source file { cannot be found",
7707 First_Error := False;
7712 "\source file { cannot be found",
7717 NL := Source_Names.Get_Next;
7719 end Get_Path_Names_And_Record_Ada_Sources;
7721 --------------------------
7722 -- Check_Naming_Schemes --
7723 --------------------------
7725 procedure Check_Naming_Schemes
7726 (In_Tree : Project_Tree_Ref;
7727 Data : in out Project_Data;
7729 File_Name : File_Name_Type;
7730 Alternate_Languages : out Alternate_Language_Id;
7731 Language : out Language_Index;
7732 Language_Name : out Name_Id;
7733 Display_Language_Name : out Name_Id;
7735 Lang_Kind : out Language_Kind;
7736 Kind : out Source_Kind)
7738 Last : Positive := Filename'Last;
7739 Config : Language_Config;
7740 Lang : Name_List_Index := Data.Languages;
7741 Header_File : Boolean := False;
7742 First_Language : Language_Index := No_Language_Index;
7745 Last_Spec : Natural;
7746 Last_Body : Natural;
7752 Alternate_Languages := No_Alternate_Language;
7753 Language := No_Language_Index;
7754 Language_Name := No_Name;
7755 Display_Language_Name := No_Name;
7757 Lang_Kind := File_Based;
7760 while Lang /= No_Name_List loop
7761 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7762 Language := Data.First_Language_Processing;
7764 if Current_Verbosity = High then
7766 (" Testing language "
7767 & Get_Name_String (Language_Name)
7768 & " Header_File=" & Header_File'Img);
7771 while Language /= No_Language_Index loop
7772 if In_Tree.Languages_Data.Table (Language).Name =
7775 Display_Language_Name :=
7776 In_Tree.Languages_Data.Table (Language).Display_Name;
7777 Config := In_Tree.Languages_Data.Table (Language).Config;
7778 Lang_Kind := Config.Kind;
7780 if Config.Kind = File_Based then
7782 -- For file based languages, there is no Unit. Just
7783 -- check if the file name has the implementation or,
7784 -- if it is specified, the template suffix of the
7790 and then Config.Naming_Data.Body_Suffix /= No_File
7793 Impl_Suffix : constant String :=
7794 Get_Name_String (Config.Naming_Data.Body_Suffix);
7797 if Filename'Length > Impl_Suffix'Length
7800 (Last - Impl_Suffix'Length + 1 .. Last) =
7805 if Current_Verbosity = High then
7806 Write_Str (" source of language ");
7808 (Get_Name_String (Display_Language_Name));
7816 if Config.Naming_Data.Spec_Suffix /= No_File then
7818 Spec_Suffix : constant String :=
7820 (Config.Naming_Data.Spec_Suffix);
7823 if Filename'Length > Spec_Suffix'Length
7826 (Last - Spec_Suffix'Length + 1 .. Last) =
7831 if Current_Verbosity = High then
7832 Write_Str (" header file of language ");
7834 (Get_Name_String (Display_Language_Name));
7838 Alternate_Language_Table.Increment_Last
7839 (In_Tree.Alt_Langs);
7840 In_Tree.Alt_Langs.Table
7841 (Alternate_Language_Table.Last
7842 (In_Tree.Alt_Langs)) :=
7843 (Language => Language,
7844 Next => Alternate_Languages);
7845 Alternate_Languages :=
7846 Alternate_Language_Table.Last
7847 (In_Tree.Alt_Langs);
7849 Header_File := True;
7850 First_Language := Language;
7856 elsif not Header_File then
7857 -- Unit based language
7859 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7864 -- ??? Are we doing this once per file in the project ?
7865 -- It should be done only once per project.
7867 case Config.Naming_Data.Casing is
7868 when All_Lower_Case =>
7869 for J in Filename'Range loop
7870 if Is_Letter (Filename (J)) then
7871 if not Is_Lower (Filename (J)) then
7878 when All_Upper_Case =>
7879 for J in Filename'Range loop
7880 if Is_Letter (Filename (J)) then
7881 if not Is_Upper (Filename (J)) then
7897 Last_Spec := Natural'Last;
7898 Last_Body := Natural'Last;
7899 Last_Sep := Natural'Last;
7901 if Config.Naming_Data.Separate_Suffix /= No_File
7903 Config.Naming_Data.Separate_Suffix /=
7904 Config.Naming_Data.Body_Suffix
7907 Suffix : constant String :=
7909 (Config.Naming_Data.Separate_Suffix);
7911 if Filename'Length > Suffix'Length
7914 (Last - Suffix'Length + 1 .. Last) =
7917 Last_Sep := Last - Suffix'Length;
7922 if Config.Naming_Data.Body_Suffix /= No_File then
7924 Suffix : constant String :=
7926 (Config.Naming_Data.Body_Suffix);
7928 if Filename'Length > Suffix'Length
7931 (Last - Suffix'Length + 1 .. Last) =
7934 Last_Body := Last - Suffix'Length;
7939 if Config.Naming_Data.Spec_Suffix /= No_File then
7941 Suffix : constant String :=
7943 (Config.Naming_Data.Spec_Suffix);
7945 if Filename'Length > Suffix'Length
7948 (Last - Suffix'Length + 1 .. Last) =
7951 Last_Spec := Last - Suffix'Length;
7957 Last_Min : constant Natural :=
7958 Natural'Min (Natural'Min (Last_Spec,
7963 OK := Last_Min < Last;
7968 if Last_Min = Last_Spec then
7971 elsif Last_Min = Last_Body then
7983 -- Replace dot replacements with dots
7988 J : Positive := Filename'First;
7990 Dot_Replacement : constant String :=
7992 (Config.Naming_Data.
7995 Max : constant Positive :=
7996 Last - Dot_Replacement'Length + 1;
8000 Name_Len := Name_Len + 1;
8002 if J <= Max and then
8004 (J .. J + Dot_Replacement'Length - 1) =
8007 Name_Buffer (Name_Len) := '.';
8008 J := J + Dot_Replacement'Length;
8011 if Filename (J) = '.' then
8016 Name_Buffer (Name_Len) :=
8017 GNAT.Case_Util.To_Lower (Filename (J));
8028 -- The name buffer should contain the name of the
8029 -- the unit, if it is one.
8031 -- Check that this is a valid unit name
8033 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
8035 if Unit /= No_Name then
8037 if Current_Verbosity = High then
8039 Write_Str (" spec of ");
8041 Write_Str (" body of ");
8044 Write_Str (Get_Name_String (Unit));
8045 Write_Str (" (language ");
8047 (Get_Name_String (Display_Language_Name));
8051 -- Comments required, declare block should
8055 Unit_Except : constant Unit_Exception :=
8056 Unit_Exceptions.Get (Unit);
8058 procedure Masked_Unit (Spec : Boolean);
8059 -- Indicate that there is an exception for
8060 -- the same unit, so the file is not a
8061 -- source for the unit.
8067 procedure Masked_Unit (Spec : Boolean) is
8069 if Current_Verbosity = High then
8071 Write_Str (Filename);
8072 Write_Str (""" contains the ");
8081 (" of a unit that is found in """);
8086 (Unit_Except.Spec));
8090 (Unit_Except.Impl));
8093 Write_Line (""" (ignored)");
8096 Language := No_Language_Index;
8101 if Unit_Except.Spec /= No_File
8102 and then Unit_Except.Spec /= File_Name
8104 Masked_Unit (Spec => True);
8108 if Unit_Except.Impl /= No_File
8109 and then Unit_Except.Impl /= File_Name
8111 Masked_Unit (Spec => False);
8122 Language := In_Tree.Languages_Data.Table (Language).Next;
8125 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8128 -- Comment needed here ???
8131 Language := First_Language;
8134 Language := No_Language_Index;
8136 if Current_Verbosity = High then
8137 Write_Line (" not a source of any language");
8140 end Check_Naming_Schemes;
8146 procedure Check_File
8147 (Project : Project_Id;
8148 In_Tree : Project_Tree_Ref;
8149 Data : in out Project_Data;
8151 File_Name : File_Name_Type;
8152 Display_File_Name : File_Name_Type;
8153 Source_Directory : String;
8154 For_All_Sources : Boolean)
8156 Display_Path : constant String :=
8159 Directory => Source_Directory,
8160 Resolve_Links => Opt.Follow_Links_For_Files,
8161 Case_Sensitive => True);
8163 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8164 Path_Id : Path_Name_Type;
8165 Display_Path_Id : Path_Name_Type;
8166 Check_Name : Boolean := False;
8167 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8168 Language : Language_Index;
8170 Other_Part : Source_Id;
8172 Src_Ind : Source_File_Index;
8174 Source_To_Replace : Source_Id := No_Source;
8175 Language_Name : Name_Id;
8176 Display_Language_Name : Name_Id;
8177 Lang_Kind : Language_Kind;
8178 Kind : Source_Kind := Spec;
8181 Name_Len := Display_Path'Length;
8182 Name_Buffer (1 .. Name_Len) := Display_Path;
8183 Display_Path_Id := Name_Find;
8185 if Osint.File_Names_Case_Sensitive then
8186 Path_Id := Display_Path_Id;
8188 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8189 Path_Id := Name_Find;
8192 if Name_Loc = No_Name_Location then
8193 Check_Name := For_All_Sources;
8196 if Name_Loc.Found then
8198 -- Check if it is OK to have the same file name in several
8199 -- source directories.
8201 if not Data.Known_Order_Of_Source_Dirs then
8202 Error_Msg_File_1 := File_Name;
8205 "{ is found in several source directories",
8210 Name_Loc.Found := True;
8212 Source_Names.Set (File_Name, Name_Loc);
8214 if Name_Loc.Source = No_Source then
8218 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8219 (Path_Id, Display_Path_Id);
8221 Source_Paths_Htable.Set
8222 (In_Tree.Source_Paths_HT,
8226 -- Check if this is a subunit
8228 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8230 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8232 Src_Ind := Sinput.P.Load_Project_File
8233 (Get_Name_String (Path_Id));
8235 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8236 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8244 Other_Part := No_Source;
8246 Check_Naming_Schemes
8247 (In_Tree => In_Tree,
8249 Filename => Get_Name_String (File_Name),
8250 File_Name => File_Name,
8251 Alternate_Languages => Alternate_Languages,
8252 Language => Language,
8253 Language_Name => Language_Name,
8254 Display_Language_Name => Display_Language_Name,
8256 Lang_Kind => Lang_Kind,
8259 if Language = No_Language_Index then
8261 -- A file name in a list must be a source of a language
8263 if Name_Loc.Found then
8264 Error_Msg_File_1 := File_Name;
8268 "language unknown for {",
8273 -- Check if the same file name or unit is used in the prj tree
8275 Source := In_Tree.First_Source;
8277 while Source /= No_Source loop
8279 Src_Data : Source_Data renames
8280 In_Tree.Sources.Table (Source);
8284 and then Src_Data.Unit = Unit
8286 ((Src_Data.Kind = Spec and then Kind = Impl)
8288 (Src_Data.Kind = Impl and then Kind = Spec))
8290 Other_Part := Source;
8292 elsif (Unit /= No_Name
8293 and then Src_Data.Unit = Unit
8295 (Src_Data.Kind = Kind
8297 (Src_Data.Kind = Sep and then Kind = Impl)
8299 (Src_Data.Kind = Impl and then Kind = Sep)))
8301 (Unit = No_Name and then Src_Data.File = File_Name)
8303 -- Duplication of file/unit in same project is only
8304 -- allowed if order of source directories is known.
8306 if Project = Src_Data.Project then
8307 if Data.Known_Order_Of_Source_Dirs then
8310 elsif Unit /= No_Name then
8311 Error_Msg_Name_1 := Unit;
8313 (Project, In_Tree, "duplicate unit %%",
8318 Error_Msg_File_1 := File_Name;
8320 (Project, In_Tree, "duplicate source file name {",
8325 -- Do not allow the same unit name in different
8326 -- projects, except if one is extending the other.
8328 -- For a file based language, the same file name
8329 -- replaces a file in a project being extended, but
8330 -- it is allowed to have the same file name in
8331 -- unrelated projects.
8334 (Project, Src_Data.Project, In_Tree)
8336 Source_To_Replace := Source;
8338 elsif Unit /= No_Name
8339 and then not Src_Data.Locally_Removed
8341 Error_Msg_Name_1 := Unit;
8344 "unit %% cannot belong to several projects",
8348 In_Tree.Projects.Table (Project).Name;
8349 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8351 (Project, In_Tree, "\ project %%, %%", No_Location);
8354 In_Tree.Projects.Table (Src_Data.Project).Name;
8356 Name_Id (Src_Data.Path.Display_Name);
8358 (Project, In_Tree, "\ project %%, %%", No_Location);
8364 Source := Src_Data.Next_In_Sources;
8374 Lang => Language_Name,
8375 Lang_Id => Language,
8376 Lang_Kind => Lang_Kind,
8378 Alternate_Languages => Alternate_Languages,
8379 File_Name => File_Name,
8380 Display_File => Display_File_Name,
8381 Other_Part => Other_Part,
8384 Display_Path => Display_Path_Id,
8385 Source_To_Replace => Source_To_Replace);
8391 ------------------------
8392 -- Search_Directories --
8393 ------------------------
8395 procedure Search_Directories
8396 (Project : Project_Id;
8397 In_Tree : Project_Tree_Ref;
8398 Data : in out Project_Data;
8399 For_All_Sources : Boolean)
8401 Source_Dir : String_List_Id;
8402 Element : String_Element;
8404 Name : String (1 .. 1_000);
8406 File_Name : File_Name_Type;
8407 Display_File_Name : File_Name_Type;
8410 if Current_Verbosity = High then
8411 Write_Line ("Looking for sources:");
8414 -- Loop through subdirectories
8416 Source_Dir := Data.Source_Dirs;
8417 while Source_Dir /= Nil_String loop
8419 Element := In_Tree.String_Elements.Table (Source_Dir);
8420 if Element.Value /= No_Name then
8421 Get_Name_String (Element.Display_Value);
8424 Source_Directory : constant String :=
8425 Name_Buffer (1 .. Name_Len) &
8426 Directory_Separator;
8428 Dir_Last : constant Natural :=
8429 Compute_Directory_Last
8433 if Current_Verbosity = High then
8434 Write_Str ("Source_Dir = ");
8435 Write_Line (Source_Directory);
8438 -- We look to every entry in the source directory
8440 Open (Dir, Source_Directory);
8443 Read (Dir, Name, Last);
8447 -- ??? Duplicate system call here, we just did a
8448 -- a similar one. Maybe Ada.Directories would be more
8452 (Source_Directory & Name (1 .. Last))
8454 if Current_Verbosity = High then
8455 Write_Str (" Checking ");
8456 Write_Line (Name (1 .. Last));
8460 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8461 Display_File_Name := Name_Find;
8463 if Osint.File_Names_Case_Sensitive then
8464 File_Name := Display_File_Name;
8466 Canonical_Case_File_Name
8467 (Name_Buffer (1 .. Name_Len));
8468 File_Name := Name_Find;
8473 Excluded_Sources_Htable.Get (File_Name);
8476 if FF /= No_File_Found then
8477 if not FF.Found then
8479 Excluded_Sources_Htable.Set
8482 if Current_Verbosity = High then
8483 Write_Str (" excluded source """);
8484 Write_Str (Get_Name_String (File_Name));
8491 (Project => Project,
8494 Name => Name (1 .. Last),
8495 File_Name => File_Name,
8496 Display_File_Name => Display_File_Name,
8497 Source_Directory => Source_Directory
8498 (Source_Directory'First .. Dir_Last),
8499 For_All_Sources => For_All_Sources);
8510 when Directory_Error =>
8514 Source_Dir := Element.Next;
8517 if Current_Verbosity = High then
8518 Write_Line ("end Looking for sources.");
8520 end Search_Directories;
8522 ----------------------
8523 -- Look_For_Sources --
8524 ----------------------
8526 procedure Look_For_Sources
8527 (Project : Project_Id;
8528 In_Tree : Project_Tree_Ref;
8529 Data : in out Project_Data;
8530 Current_Dir : String)
8532 procedure Remove_Locally_Removed_Files_From_Units;
8533 -- Mark all locally removed sources as such in the Units table
8535 procedure Process_Sources_In_Multi_Language_Mode;
8536 -- Find all source files when in multi language mode
8538 ---------------------------------------------
8539 -- Remove_Locally_Removed_Files_From_Units --
8540 ---------------------------------------------
8542 procedure Remove_Locally_Removed_Files_From_Units is
8543 Excluded : File_Found;
8546 Extended : Project_Id;
8549 Excluded := Excluded_Sources_Htable.Get_First;
8550 while Excluded /= No_File_Found loop
8554 for Index in Unit_Table.First ..
8555 Unit_Table.Last (In_Tree.Units)
8557 Unit := In_Tree.Units.Table (Index);
8559 for Kind in Spec_Or_Body'Range loop
8560 if Unit.File_Names (Kind).Name = Excluded.File then
8563 -- Check that this is from the current project or
8564 -- that the current project extends.
8566 Extended := Unit.File_Names (Kind).Project;
8568 if Extended = Project
8569 or else Project_Extends (Project, Extended, In_Tree)
8571 Unit.File_Names (Kind).Path.Name := Slash;
8572 Unit.File_Names (Kind).Needs_Pragma := False;
8573 In_Tree.Units.Table (Index) := Unit;
8574 Add_Forbidden_File_Name
8575 (Unit.File_Names (Kind).Name);
8579 "cannot remove a source from " &
8586 end loop For_Each_Unit;
8589 Err_Vars.Error_Msg_File_1 := Excluded.File;
8591 (Project, In_Tree, "unknown file {", Excluded.Location);
8594 Excluded := Excluded_Sources_Htable.Get_Next;
8596 end Remove_Locally_Removed_Files_From_Units;
8598 --------------------------------------------
8599 -- Process_Sources_In_Multi_Language_Mode --
8600 --------------------------------------------
8602 procedure Process_Sources_In_Multi_Language_Mode is
8604 Name_Loc : Name_Location;
8609 -- First, put all naming exceptions if any, in the Source_Names table
8611 Unit_Exceptions.Reset;
8613 Source := Data.First_Source;
8614 while Source /= No_Source loop
8616 Src_Data : Source_Data renames In_Tree.Sources.Table (Source);
8619 -- An excluded file cannot also be an exception file name
8621 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8624 Error_Msg_File_1 := Src_Data.File;
8627 "{ cannot be both excluded and an exception file name",
8631 Name_Loc := (Name => Src_Data.File,
8632 Location => No_Location,
8634 Except => Src_Data.Unit /= No_Name,
8637 if Current_Verbosity = High then
8638 Write_Str ("Putting source #");
8639 Write_Str (Source'Img);
8640 Write_Str (", file ");
8641 Write_Str (Get_Name_String (Src_Data.File));
8642 Write_Line (" in Source_Names");
8645 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8647 -- If this is an Ada exception, record in table Unit_Exceptions
8649 if Src_Data.Unit /= No_Name then
8651 Unit_Except : Unit_Exception :=
8652 Unit_Exceptions.Get (Src_Data.Unit);
8655 Unit_Except.Name := Src_Data.Unit;
8657 if Src_Data.Kind = Spec then
8658 Unit_Except.Spec := Src_Data.File;
8660 Unit_Except.Impl := Src_Data.File;
8663 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8667 Source := Src_Data.Next_In_Project;
8671 Find_Explicit_Sources
8672 (Current_Dir, Project, In_Tree, Data);
8674 -- Mark as such the sources that are declared as excluded
8676 FF := Excluded_Sources_Htable.Get_First;
8677 while FF /= No_File_Found loop
8679 Source := In_Tree.First_Source;
8680 while Source /= No_Source loop
8682 Src_Data : Source_Data renames
8683 In_Tree.Sources.Table (Source);
8686 if Src_Data.File = FF.File then
8688 -- Check that this is from this project or a project that
8689 -- the current project extends.
8691 if Src_Data.Project = Project or else
8692 Is_Extending (Project, Src_Data.Project, In_Tree)
8694 Src_Data.Locally_Removed := True;
8695 Src_Data.In_Interfaces := False;
8696 Add_Forbidden_File_Name (FF.File);
8702 Source := Src_Data.Next_In_Sources;
8706 if not FF.Found and not OK then
8707 Err_Vars.Error_Msg_File_1 := FF.File;
8708 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8711 FF := Excluded_Sources_Htable.Get_Next;
8714 -- Check that two sources of this project do not have the same object
8717 Check_Object_File_Names : declare
8719 Source_Name : File_Name_Type;
8721 procedure Check_Object (Src_Data : Source_Data);
8722 -- Check if object file name of the current source is already in
8723 -- hash table Object_File_Names. If it is, report an error. If it
8724 -- is not, put it there with the file name of the current source.
8730 procedure Check_Object (Src_Data : Source_Data) is
8732 Source_Name := Object_File_Names.Get (Src_Data.Object);
8734 if Source_Name /= No_File then
8735 Error_Msg_File_1 := Src_Data.File;
8736 Error_Msg_File_2 := Source_Name;
8740 "{ and { have the same object file name",
8744 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8748 -- Start of processing for Check_Object_File_Names
8751 Object_File_Names.Reset;
8752 Src_Id := In_Tree.First_Source;
8753 while Src_Id /= No_Source loop
8755 Src_Data : Source_Data renames
8756 In_Tree.Sources.Table (Src_Id);
8759 if Src_Data.Compiled and then Src_Data.Object_Exists
8760 and then Project_Extends
8761 (Project, Src_Data.Project, In_Tree)
8763 if Src_Data.Unit = No_Name then
8764 if Src_Data.Kind = Impl then
8765 Check_Object (Src_Data);
8769 case Src_Data.Kind is
8771 if Src_Data.Other_Part = No_Source then
8772 Check_Object (Src_Data);
8779 if Src_Data.Other_Part /= No_Source then
8780 Check_Object (Src_Data);
8783 -- Check if it is a subunit
8786 Src_Ind : constant Source_File_Index :=
8787 Sinput.P.Load_Project_File
8789 (Src_Data.Path.Name));
8791 if Sinput.P.Source_File_Is_Subunit
8794 In_Tree.Sources.Table (Src_Id).Kind :=
8797 Check_Object (Src_Data);
8805 Src_Id := Src_Data.Next_In_Sources;
8808 end Check_Object_File_Names;
8809 end Process_Sources_In_Multi_Language_Mode;
8811 -- Start of processing for Look_For_Sources
8815 Find_Excluded_Sources (Project, In_Tree, Data);
8819 if Is_A_Language (In_Tree, Data, Name_Ada) then
8820 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8821 Remove_Locally_Removed_Files_From_Units;
8824 when Multi_Language =>
8825 if Data.First_Language_Processing /= No_Language_Index then
8826 Process_Sources_In_Multi_Language_Mode;
8829 end Look_For_Sources;
8835 function Path_Name_Of
8836 (File_Name : File_Name_Type;
8837 Directory : Path_Name_Type) return String
8839 Result : String_Access;
8840 The_Directory : constant String := Get_Name_String (Directory);
8843 Get_Name_String (File_Name);
8846 (File_Name => Name_Buffer (1 .. Name_Len),
8847 Path => The_Directory);
8849 if Result = null then
8853 R : String := Result.all;
8856 Canonical_Case_File_Name (R);
8862 -------------------------------
8863 -- Prepare_Ada_Naming_Exceptions --
8864 -------------------------------
8866 procedure Prepare_Ada_Naming_Exceptions
8867 (List : Array_Element_Id;
8868 In_Tree : Project_Tree_Ref;
8869 Kind : Spec_Or_Body)
8871 Current : Array_Element_Id;
8872 Element : Array_Element;
8876 -- Traverse the list
8879 while Current /= No_Array_Element loop
8880 Element := In_Tree.Array_Elements.Table (Current);
8882 if Element.Index /= No_Name then
8885 Unit => Element.Index,
8886 Next => No_Ada_Naming_Exception);
8887 Reverse_Ada_Naming_Exceptions.Set
8888 (Unit, (Element.Value.Value, Element.Value.Index));
8890 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8891 Ada_Naming_Exception_Table.Increment_Last;
8892 Ada_Naming_Exception_Table.Table
8893 (Ada_Naming_Exception_Table.Last) := Unit;
8894 Ada_Naming_Exceptions.Set
8895 (File_Name_Type (Element.Value.Value),
8896 Ada_Naming_Exception_Table.Last);
8899 Current := Element.Next;
8901 end Prepare_Ada_Naming_Exceptions;
8903 ---------------------
8904 -- Project_Extends --
8905 ---------------------
8907 function Project_Extends
8908 (Extending : Project_Id;
8909 Extended : Project_Id;
8910 In_Tree : Project_Tree_Ref) return Boolean
8912 Current : Project_Id := Extending;
8916 if Current = No_Project then
8919 elsif Current = Extended then
8923 Current := In_Tree.Projects.Table (Current).Extends;
8925 end Project_Extends;
8927 -----------------------
8928 -- Record_Ada_Source --
8929 -----------------------
8931 procedure Record_Ada_Source
8932 (File_Name : File_Name_Type;
8933 Path_Name : Path_Name_Type;
8934 Project : Project_Id;
8935 In_Tree : Project_Tree_Ref;
8936 Data : in out Project_Data;
8937 Location : Source_Ptr;
8938 Current_Source : in out String_List_Id;
8939 Source_Recorded : in out Boolean;
8940 Current_Dir : String)
8942 Canonical_File_Name : File_Name_Type;
8943 Canonical_Path_Name : Path_Name_Type;
8945 Exception_Id : Ada_Naming_Exception_Id;
8946 Unit_Name : Name_Id;
8947 Unit_Kind : Spec_Or_Body;
8948 Unit_Ind : Int := 0;
8950 Name_Index : Name_And_Index;
8951 Needs_Pragma : Boolean;
8953 The_Location : Source_Ptr := Location;
8954 Previous_Source : constant String_List_Id := Current_Source;
8955 Except_Name : Name_And_Index := No_Name_And_Index;
8957 Unit_Prj : Unit_Project;
8959 File_Name_Recorded : Boolean := False;
8962 if Osint.File_Names_Case_Sensitive then
8963 Canonical_File_Name := File_Name;
8964 Canonical_Path_Name := Path_Name;
8966 Get_Name_String (File_Name);
8967 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8968 Canonical_File_Name := Name_Find;
8971 Canonical_Path : constant String :=
8973 (Get_Name_String (Path_Name),
8974 Directory => Current_Dir,
8975 Resolve_Links => Opt.Follow_Links_For_Files,
8976 Case_Sensitive => False);
8979 Add_Str_To_Name_Buffer (Canonical_Path);
8980 Canonical_Path_Name := Name_Find;
8984 -- Find out the unit name, the unit kind and if it needs
8985 -- a specific SFN pragma.
8988 (In_Tree => In_Tree,
8989 Canonical_File_Name => Canonical_File_Name,
8990 Naming => Data.Naming,
8991 Exception_Id => Exception_Id,
8992 Unit_Name => Unit_Name,
8993 Unit_Kind => Unit_Kind,
8994 Needs_Pragma => Needs_Pragma);
8996 if Exception_Id = No_Ada_Naming_Exception
8997 and then Unit_Name = No_Name
8999 if Current_Verbosity = High then
9001 Write_Str (Get_Name_String (Canonical_File_Name));
9002 Write_Line (""" is not a valid source file name (ignored).");
9006 -- Check to see if the source has been hidden by an exception,
9007 -- but only if it is not an exception.
9009 if not Needs_Pragma then
9011 Reverse_Ada_Naming_Exceptions.Get
9012 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
9014 if Except_Name /= No_Name_And_Index then
9015 if Current_Verbosity = High then
9017 Write_Str (Get_Name_String (Canonical_File_Name));
9018 Write_Str (""" contains a unit that is found in """);
9019 Write_Str (Get_Name_String (Except_Name.Name));
9020 Write_Line (""" (ignored).");
9023 -- The file is not included in the source of the project since
9024 -- it is hidden by the exception. So, nothing else to do.
9031 if Exception_Id /= No_Ada_Naming_Exception then
9032 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
9033 Exception_Id := Info.Next;
9034 Info.Next := No_Ada_Naming_Exception;
9035 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
9037 Unit_Name := Info.Unit;
9038 Unit_Ind := Name_Index.Index;
9039 Unit_Kind := Info.Kind;
9042 -- Put the file name in the list of sources of the project
9044 String_Element_Table.Increment_Last (In_Tree.String_Elements);
9045 In_Tree.String_Elements.Table
9046 (String_Element_Table.Last (In_Tree.String_Elements)) :=
9047 (Value => Name_Id (Canonical_File_Name),
9048 Display_Value => Name_Id (File_Name),
9049 Location => No_Location,
9054 if Current_Source = Nil_String then
9056 String_Element_Table.Last (In_Tree.String_Elements);
9058 In_Tree.String_Elements.Table (Current_Source).Next :=
9059 String_Element_Table.Last (In_Tree.String_Elements);
9063 String_Element_Table.Last (In_Tree.String_Elements);
9065 -- Put the unit in unit list
9068 The_Unit : Unit_Index :=
9069 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
9071 The_Unit_Data : Unit_Data;
9074 if Current_Verbosity = High then
9075 Write_Str ("Putting ");
9076 Write_Str (Get_Name_String (Unit_Name));
9077 Write_Line (" in the unit list.");
9080 -- The unit is already in the list, but may be it is
9081 -- only the other unit kind (spec or body), or what is
9082 -- in the unit list is a unit of a project we are extending.
9084 if The_Unit /= No_Unit_Index then
9085 The_Unit_Data := In_Tree.Units.Table (The_Unit);
9087 if (The_Unit_Data.File_Names (Unit_Kind).Name =
9090 The_Unit_Data.File_Names
9091 (Unit_Kind).Path.Name = Slash)
9092 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
9093 or else Project_Extends
9095 The_Unit_Data.File_Names (Unit_Kind).Project,
9099 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
9101 Remove_Forbidden_File_Name
9102 (The_Unit_Data.File_Names (Unit_Kind).Name);
9105 -- Record the file name in the hash table Files_Htable
9107 Unit_Prj := (Unit => The_Unit, Project => Project);
9110 Canonical_File_Name,
9113 The_Unit_Data.File_Names (Unit_Kind) :=
9114 (Name => Canonical_File_Name,
9116 Display_Name => File_Name,
9117 Path => (Canonical_Path_Name, Path_Name),
9119 Needs_Pragma => Needs_Pragma);
9120 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9121 Source_Recorded := True;
9123 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
9124 and then (Data.Known_Order_Of_Source_Dirs
9126 The_Unit_Data.File_Names
9127 (Unit_Kind).Path.Name = Canonical_Path_Name)
9129 if Previous_Source = Nil_String then
9130 Data.Ada_Sources := Nil_String;
9132 In_Tree.String_Elements.Table (Previous_Source).Next :=
9134 String_Element_Table.Decrement_Last
9135 (In_Tree.String_Elements);
9138 Current_Source := Previous_Source;
9141 -- It is an error to have two units with the same name
9142 -- and the same kind (spec or body).
9144 if The_Location = No_Location then
9146 In_Tree.Projects.Table (Project).Location;
9149 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9151 (Project, In_Tree, "duplicate unit %%", The_Location);
9153 Err_Vars.Error_Msg_Name_1 :=
9154 In_Tree.Projects.Table
9155 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9156 Err_Vars.Error_Msg_File_1 :=
9158 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
9161 "\ project file %%, {", The_Location);
9163 Err_Vars.Error_Msg_Name_1 :=
9164 In_Tree.Projects.Table (Project).Name;
9165 Err_Vars.Error_Msg_File_1 :=
9166 File_Name_Type (Canonical_Path_Name);
9169 "\ project file %%, {", The_Location);
9172 -- It is a new unit, create a new record
9175 -- First, check if there is no other unit with this file
9176 -- name in another project. If it is, report error but note
9177 -- we do that only for the first unit in the source file.
9180 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
9182 if not File_Name_Recorded and then
9183 Unit_Prj /= No_Unit_Project
9185 Error_Msg_File_1 := File_Name;
9187 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9190 "{ is already a source of project %%",
9194 Unit_Table.Increment_Last (In_Tree.Units);
9195 The_Unit := Unit_Table.Last (In_Tree.Units);
9197 (In_Tree.Units_HT, Unit_Name, The_Unit);
9198 Unit_Prj := (Unit => The_Unit, Project => Project);
9201 Canonical_File_Name,
9203 The_Unit_Data.Name := Unit_Name;
9204 The_Unit_Data.File_Names (Unit_Kind) :=
9205 (Name => Canonical_File_Name,
9207 Display_Name => File_Name,
9208 Path => (Canonical_Path_Name, Path_Name),
9210 Needs_Pragma => Needs_Pragma);
9211 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9212 Source_Recorded := True;
9217 exit when Exception_Id = No_Ada_Naming_Exception;
9218 File_Name_Recorded := True;
9221 end Record_Ada_Source;
9227 procedure Remove_Source
9229 Replaced_By : Source_Id;
9230 Project : Project_Id;
9231 Data : in out Project_Data;
9232 In_Tree : Project_Tree_Ref)
9234 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9238 if Current_Verbosity = High then
9239 Write_Str ("Removing source #");
9240 Write_Line (Id'Img);
9243 if Replaced_By /= No_Source then
9244 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9245 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9246 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9249 -- Remove the source from the global source list
9251 Source := In_Tree.First_Source;
9254 In_Tree.First_Source := Src_Data.Next_In_Sources;
9257 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9258 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9261 In_Tree.Sources.Table (Source).Next_In_Sources :=
9262 Src_Data.Next_In_Sources;
9265 -- Remove the source from the project list
9267 if Src_Data.Project = Project then
9268 Source := Data.First_Source;
9271 Data.First_Source := Src_Data.Next_In_Project;
9273 if Src_Data.Next_In_Project = No_Source then
9274 Data.Last_Source := No_Source;
9278 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9279 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9282 In_Tree.Sources.Table (Source).Next_In_Project :=
9283 Src_Data.Next_In_Project;
9285 if Src_Data.Next_In_Project = No_Source then
9286 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9291 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9294 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9295 Src_Data.Next_In_Project;
9297 if Src_Data.Next_In_Project = No_Source then
9298 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9303 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9304 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9307 In_Tree.Sources.Table (Source).Next_In_Project :=
9308 Src_Data.Next_In_Project;
9310 if Src_Data.Next_In_Project = No_Source then
9311 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9316 -- Remove source from the language list
9318 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9321 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9322 Src_Data.Next_In_Lang;
9325 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9326 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9329 In_Tree.Sources.Table (Source).Next_In_Lang :=
9330 Src_Data.Next_In_Lang;
9334 -----------------------
9335 -- Report_No_Sources --
9336 -----------------------
9338 procedure Report_No_Sources
9339 (Project : Project_Id;
9341 In_Tree : Project_Tree_Ref;
9342 Location : Source_Ptr;
9343 Continuation : Boolean := False)
9346 case When_No_Sources is
9350 when Warning | Error =>
9352 Msg : constant String :=
9355 " sources in this project";
9358 Error_Msg_Warn := When_No_Sources = Warning;
9360 if Continuation then
9362 (Project, In_Tree, "\" & Msg, Location);
9366 (Project, In_Tree, Msg, Location);
9370 end Report_No_Sources;
9372 ----------------------
9373 -- Show_Source_Dirs --
9374 ----------------------
9376 procedure Show_Source_Dirs
9377 (Data : Project_Data;
9378 In_Tree : Project_Tree_Ref)
9380 Current : String_List_Id;
9381 Element : String_Element;
9384 Write_Line ("Source_Dirs:");
9386 Current := Data.Source_Dirs;
9387 while Current /= Nil_String loop
9388 Element := In_Tree.String_Elements.Table (Current);
9390 Write_Line (Get_Name_String (Element.Value));
9391 Current := Element.Next;
9394 Write_Line ("end Source_Dirs.");
9395 end Show_Source_Dirs;
9397 -------------------------
9398 -- Warn_If_Not_Sources --
9399 -------------------------
9401 -- comments needed in this body ???
9403 procedure Warn_If_Not_Sources
9404 (Project : Project_Id;
9405 In_Tree : Project_Tree_Ref;
9406 Conventions : Array_Element_Id;
9408 Extending : Boolean)
9410 Conv : Array_Element_Id;
9412 The_Unit_Id : Unit_Index;
9413 The_Unit_Data : Unit_Data;
9414 Location : Source_Ptr;
9417 Conv := Conventions;
9418 while Conv /= No_Array_Element loop
9419 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9420 Error_Msg_Name_1 := Unit;
9421 Get_Name_String (Unit);
9422 To_Lower (Name_Buffer (1 .. Name_Len));
9424 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9425 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9427 if The_Unit_Id = No_Unit_Index then
9428 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9431 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9433 In_Tree.Array_Elements.Table (Conv).Value.Value;
9436 if not Check_Project
9437 (The_Unit_Data.File_Names (Specification).Project,
9438 Project, In_Tree, Extending)
9442 "?source of spec of unit %% (%%)" &
9443 " cannot be found in this project",
9448 if not Check_Project
9449 (The_Unit_Data.File_Names (Body_Part).Project,
9450 Project, In_Tree, Extending)
9454 "?source of body of unit %% (%%)" &
9455 " cannot be found in this project",
9461 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9463 end Warn_If_Not_Sources;