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 -- Locate a directory. Name is the directory name. Parent is the root
485 -- directory, if Name a relative path name. Dir is set to the canonical
486 -- case path name of the directory, and Display is the directory path name
487 -- for display purposes. If the directory does not exist and Project_Setup
488 -- is True and Create is a non null string, an attempt is made to create
489 -- the directory. If the directory does not exist and Project_Setup is
490 -- false, then Dir and Display are set to No_Name.
492 -- Current_Dir should represent the current directory, and is passed for
493 -- efficiency to avoid system calls to recompute it.
495 procedure Look_For_Sources
496 (Project : Project_Id;
497 In_Tree : Project_Tree_Ref;
498 Data : in out Project_Data;
499 Current_Dir : String);
500 -- Find all the sources of project Project in project tree In_Tree and
501 -- update its Data accordingly.
503 -- Current_Dir should represent the current directory, and is passed for
504 -- efficiency to avoid system calls to recompute it.
506 function Path_Name_Of
507 (File_Name : File_Name_Type;
508 Directory : Path_Name_Type) return String;
509 -- Returns the path name of a (non project) file. Returns an empty string
510 -- if file cannot be found.
512 procedure Prepare_Ada_Naming_Exceptions
513 (List : Array_Element_Id;
514 In_Tree : Project_Tree_Ref;
515 Kind : Spec_Or_Body);
516 -- Prepare the internal hash tables used for checking naming exceptions
517 -- for Ada. Insert all elements of List in the tables.
519 function Project_Extends
520 (Extending : Project_Id;
521 Extended : Project_Id;
522 In_Tree : Project_Tree_Ref) return Boolean;
523 -- Returns True if Extending is extending Extended either directly or
526 procedure Record_Ada_Source
527 (File_Name : File_Name_Type;
528 Path_Name : Path_Name_Type;
529 Project : Project_Id;
530 In_Tree : Project_Tree_Ref;
531 Data : in out Project_Data;
532 Location : Source_Ptr;
533 Current_Source : in out String_List_Id;
534 Source_Recorded : in out Boolean;
535 Current_Dir : String);
536 -- Put a unit in the list of units of a project, if the file name
537 -- corresponds to a valid unit name.
539 -- Current_Dir should represent the current directory, and is passed for
540 -- efficiency to avoid system calls to recompute it.
542 procedure Remove_Source
544 Replaced_By : Source_Id;
545 Project : Project_Id;
546 Data : in out Project_Data;
547 In_Tree : Project_Tree_Ref);
550 procedure Report_No_Sources
551 (Project : Project_Id;
553 In_Tree : Project_Tree_Ref;
554 Location : Source_Ptr;
555 Continuation : Boolean := False);
556 -- Report an error or a warning depending on the value of When_No_Sources
557 -- when there are no sources for language Lang_Name.
559 procedure Show_Source_Dirs
560 (Data : Project_Data; In_Tree : Project_Tree_Ref);
561 -- List all the source directories of a project
563 procedure Warn_If_Not_Sources
564 (Project : Project_Id;
565 In_Tree : Project_Tree_Ref;
566 Conventions : Array_Element_Id;
568 Extending : Boolean);
569 -- Check that individual naming conventions apply to immediate sources of
570 -- the project. If not, issue a warning.
578 Data : in out Project_Data;
579 In_Tree : Project_Tree_Ref;
580 Project : Project_Id;
582 Lang_Id : Language_Index;
584 File_Name : File_Name_Type;
585 Display_File : File_Name_Type;
586 Lang_Kind : Language_Kind;
587 Naming_Exception : Boolean := False;
588 Path : Path_Name_Type := No_Path;
589 Display_Path : Path_Name_Type := No_Path;
590 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
591 Other_Part : Source_Id := No_Source;
592 Unit : Name_Id := No_Name;
594 Source_To_Replace : Source_Id := No_Source)
596 Source : constant Source_Id := Data.Last_Source;
597 Src_Data : Source_Data := No_Source_Data;
598 Config : constant Language_Config :=
599 In_Tree.Languages_Data.Table (Lang_Id).Config;
602 -- This is a new source so create an entry for it in the Sources table
604 Source_Data_Table.Increment_Last (In_Tree.Sources);
605 Id := Source_Data_Table.Last (In_Tree.Sources);
607 if Current_Verbosity = High then
608 Write_Str ("Adding source #");
610 Write_Str (", File : ");
611 Write_Str (Get_Name_String (File_Name));
613 if Lang_Kind = Unit_Based then
614 Write_Str (", Unit : ");
615 Write_Str (Get_Name_String (Unit));
621 Src_Data.Project := Project;
622 Src_Data.Language_Name := Lang;
623 Src_Data.Language := Lang_Id;
624 Src_Data.Lang_Kind := Lang_Kind;
625 Src_Data.Compiled := In_Tree.Languages_Data.Table
626 (Lang_Id).Config.Compiler_Driver /=
628 Src_Data.Kind := Kind;
629 Src_Data.Alternate_Languages := Alternate_Languages;
630 Src_Data.Other_Part := Other_Part;
632 Src_Data.Object_Exists := Config.Object_Generated;
633 Src_Data.Object_Linked := Config.Objects_Linked;
635 if Other_Part /= No_Source then
636 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
639 Src_Data.Unit := Unit;
640 Src_Data.Index := Index;
641 Src_Data.File := File_Name;
642 Src_Data.Display_File := Display_File;
643 Src_Data.Dependency := In_Tree.Languages_Data.Table
644 (Lang_Id).Config.Dependency_Kind;
645 Src_Data.Naming_Exception := Naming_Exception;
647 if Src_Data.Compiled and then Src_Data.Object_Exists then
648 Src_Data.Object := Object_Name (File_Name);
650 Dependency_Name (File_Name, Src_Data.Dependency);
651 Src_Data.Switches := Switches_Name (File_Name);
654 if Path /= No_Path then
655 Src_Data.Path := (Path, Display_Path);
656 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
659 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
662 if Unit /= No_Name then
663 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
666 -- Add the source to the global list
668 Src_Data.Next_In_Sources := In_Tree.First_Source;
669 In_Tree.First_Source := Id;
671 -- Add the source to the project list
673 if Source = No_Source then
674 Data.First_Source := Id;
676 In_Tree.Sources.Table (Source).Next_In_Project := Id;
679 Data.Last_Source := Id;
681 -- Add the source to the language list
683 Src_Data.Next_In_Lang :=
684 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
685 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
687 In_Tree.Sources.Table (Id) := Src_Data;
689 if Source_To_Replace /= No_Source then
690 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
698 function ALI_File_Name (Source : String) return String is
700 -- If the source name has an extension, then replace it with
703 for Index in reverse Source'First + 1 .. Source'Last loop
704 if Source (Index) = '.' then
705 return Source (Source'First .. Index - 1) & ALI_Suffix;
709 -- If there is no dot, or if it is the first character, just add the
712 return Source & ALI_Suffix;
720 (Project : Project_Id;
721 In_Tree : Project_Tree_Ref;
722 Report_Error : Put_Line_Access;
723 When_No_Sources : Error_Warning;
724 Current_Dir : String)
726 Data : Project_Data := In_Tree.Projects.Table (Project);
727 Extending : Boolean := False;
730 Nmsc.When_No_Sources := When_No_Sources;
731 Error_Report := Report_Error;
733 Recursive_Dirs.Reset;
735 Check_If_Externally_Built (Project, In_Tree, Data);
737 -- Object, exec and source directories
739 Get_Directories (Project, In_Tree, Current_Dir, Data);
741 -- Get the programming languages
743 Check_Programming_Languages (In_Tree, Project, Data);
745 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
748 "an abstract project need to have no language, no sources or no " &
749 "source directories",
753 -- Check configuration in multi language mode
755 if Must_Check_Configuration then
756 Check_Configuration (Project, In_Tree, Data);
759 -- Library attributes
761 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
763 if Current_Verbosity = High then
764 Show_Source_Dirs (Data, In_Tree);
767 Check_Package_Naming (Project, In_Tree, Data);
769 Extending := Data.Extends /= No_Project;
771 Check_Naming_Schemes (Data, Project, In_Tree);
773 if Get_Mode = Ada_Only then
774 Prepare_Ada_Naming_Exceptions
775 (Data.Naming.Bodies, In_Tree, Body_Part);
776 Prepare_Ada_Naming_Exceptions
777 (Data.Naming.Specs, In_Tree, Specification);
782 if Data.Source_Dirs /= Nil_String then
783 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
785 if Get_Mode = Ada_Only then
787 -- Check that all individual naming conventions apply to sources
788 -- of this project file.
791 (Project, In_Tree, Data.Naming.Bodies,
793 Extending => Extending);
795 (Project, In_Tree, Data.Naming.Specs,
797 Extending => Extending);
799 elsif Get_Mode = Multi_Language and then
800 (not Data.Externally_Built) and then
804 Language : Language_Index;
806 Alt_Lang : Alternate_Language_Id;
807 Alt_Lang_Data : Alternate_Language_Data;
808 Continuation : Boolean := False;
811 Language := Data.First_Language_Processing;
812 while Language /= No_Language_Index loop
813 Source := Data.First_Source;
814 Source_Loop : while Source /= No_Source loop
816 Src_Data : Source_Data renames
817 In_Tree.Sources.Table (Source);
820 exit Source_Loop when Src_Data.Language = Language;
822 Alt_Lang := Src_Data.Alternate_Languages;
825 while Alt_Lang /= No_Alternate_Language loop
827 In_Tree.Alt_Langs.Table (Alt_Lang);
829 when Alt_Lang_Data.Language = Language;
830 Alt_Lang := Alt_Lang_Data.Next;
831 end loop Alternate_Loop;
833 Source := Src_Data.Next_In_Project;
835 end loop Source_Loop;
837 if Source = No_Source then
841 (In_Tree.Languages_Data.Table
842 (Language).Display_Name),
846 Continuation := True;
849 Language := In_Tree.Languages_Data.Table (Language).Next;
855 if Get_Mode = Multi_Language then
857 -- If a list of sources is specified in attribute Interfaces, set
858 -- In_Interfaces only for the sources specified in the list.
860 Check_Interfaces (Project, In_Tree, Data);
863 -- If it is a library project file, check if it is a standalone library
866 Check_Stand_Alone_Library
867 (Project, In_Tree, Data, Current_Dir, Extending);
870 -- Put the list of Mains, if any, in the project data
872 Get_Mains (Project, In_Tree, Data);
874 -- Update the project data in the Projects table
876 In_Tree.Projects.Table (Project) := Data;
878 Free_Ada_Naming_Exceptions;
885 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
886 The_Name : String := Name;
888 Need_Letter : Boolean := True;
889 Last_Underscore : Boolean := False;
890 OK : Boolean := The_Name'Length > 0;
893 function Is_Reserved (Name : Name_Id) return Boolean;
894 function Is_Reserved (S : String) return Boolean;
895 -- Check that the given name is not an Ada 95 reserved word. The reason
896 -- for the Ada 95 here is that we do not want to exclude the case of an
897 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
898 -- name would be rejected anyway by the compiler. That means there is no
899 -- requirement that the project file parser reject this.
905 function Is_Reserved (S : String) return Boolean is
908 Add_Str_To_Name_Buffer (S);
909 return Is_Reserved (Name_Find);
916 function Is_Reserved (Name : Name_Id) return Boolean is
918 if Get_Name_Table_Byte (Name) /= 0
919 and then Name /= Name_Project
920 and then Name /= Name_Extends
921 and then Name /= Name_External
922 and then Name not in Ada_2005_Reserved_Words
926 if Current_Verbosity = High then
927 Write_Str (The_Name);
928 Write_Line (" is an Ada reserved word.");
938 -- Start of processing for Check_Ada_Name
943 Name_Len := The_Name'Length;
944 Name_Buffer (1 .. Name_Len) := The_Name;
946 -- Special cases of children of packages A, G, I and S on VMS
949 and then Name_Len > 3
950 and then Name_Buffer (2 .. 3) = "__"
952 ((Name_Buffer (1) = 'a') or else
953 (Name_Buffer (1) = 'g') or else
954 (Name_Buffer (1) = 'i') or else
955 (Name_Buffer (1) = 's'))
957 Name_Buffer (2) := '.';
958 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
959 Name_Len := Name_Len - 1;
962 Real_Name := Name_Find;
964 if Is_Reserved (Real_Name) then
968 First := The_Name'First;
970 for Index in The_Name'Range loop
973 -- We need a letter (at the beginning, and following a dot),
974 -- but we don't have one.
976 if Is_Letter (The_Name (Index)) then
977 Need_Letter := False;
982 if Current_Verbosity = High then
983 Write_Int (Types.Int (Index));
985 Write_Char (The_Name (Index));
986 Write_Line ("' is not a letter.");
992 elsif Last_Underscore
993 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
995 -- Two underscores are illegal, and a dot cannot follow
1000 if Current_Verbosity = High then
1001 Write_Int (Types.Int (Index));
1003 Write_Char (The_Name (Index));
1004 Write_Line ("' is illegal here.");
1009 elsif The_Name (Index) = '.' then
1011 -- First, check if the name before the dot is not a reserved word
1012 if Is_Reserved (The_Name (First .. Index - 1)) then
1018 -- We need a letter after a dot
1020 Need_Letter := True;
1022 elsif The_Name (Index) = '_' then
1023 Last_Underscore := True;
1026 -- We need an letter or a digit
1028 Last_Underscore := False;
1030 if not Is_Alphanumeric (The_Name (Index)) then
1033 if Current_Verbosity = High then
1034 Write_Int (Types.Int (Index));
1036 Write_Char (The_Name (Index));
1037 Write_Line ("' is not alphanumeric.");
1045 -- Cannot end with an underscore or a dot
1047 OK := OK and then not Need_Letter and then not Last_Underscore;
1050 if First /= Name'First and then
1051 Is_Reserved (The_Name (First .. The_Name'Last))
1059 -- Signal a problem with No_Name
1065 --------------------------------------
1066 -- Check_Ada_Naming_Scheme_Validity --
1067 --------------------------------------
1069 procedure Check_Ada_Naming_Scheme_Validity
1070 (Project : Project_Id;
1071 In_Tree : Project_Tree_Ref;
1072 Naming : Naming_Data)
1075 -- Only check if we are not using the Default naming scheme
1077 if Naming /= In_Tree.Private_Part.Default_Naming then
1079 Dot_Replacement : constant String :=
1081 (Naming.Dot_Replacement);
1083 Spec_Suffix : constant String :=
1084 Spec_Suffix_Of (In_Tree, "ada", Naming);
1086 Body_Suffix : constant String :=
1087 Body_Suffix_Of (In_Tree, "ada", Naming);
1089 Separate_Suffix : constant String :=
1091 (Naming.Separate_Suffix);
1094 -- Dot_Replacement cannot
1097 -- - start or end with an alphanumeric
1098 -- - be a single '_'
1099 -- - start with an '_' followed by an alphanumeric
1100 -- - contain a '.' except if it is "."
1102 if Dot_Replacement'Length = 0
1103 or else Is_Alphanumeric
1104 (Dot_Replacement (Dot_Replacement'First))
1105 or else Is_Alphanumeric
1106 (Dot_Replacement (Dot_Replacement'Last))
1107 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1109 (Dot_Replacement'Length = 1
1112 (Dot_Replacement (Dot_Replacement'First + 1))))
1113 or else (Dot_Replacement'Length > 1
1115 Index (Source => Dot_Replacement,
1116 Pattern => ".") /= 0)
1120 '"' & Dot_Replacement &
1121 """ is illegal for Dot_Replacement.",
1122 Naming.Dot_Repl_Loc);
1128 if Is_Illegal_Suffix
1129 (Spec_Suffix, Dot_Replacement = ".")
1131 Err_Vars.Error_Msg_File_1 :=
1132 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1135 "{ is illegal for Spec_Suffix",
1136 Naming.Ada_Spec_Suffix_Loc);
1139 if Is_Illegal_Suffix
1140 (Body_Suffix, Dot_Replacement = ".")
1142 Err_Vars.Error_Msg_File_1 :=
1143 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1146 "{ is illegal for Body_Suffix",
1147 Naming.Ada_Body_Suffix_Loc);
1150 if Body_Suffix /= Separate_Suffix then
1151 if Is_Illegal_Suffix
1152 (Separate_Suffix, Dot_Replacement = ".")
1154 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1157 "{ is illegal for Separate_Suffix",
1158 Naming.Sep_Suffix_Loc);
1162 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1163 -- since that would cause a clear ambiguity. Note that we do
1164 -- allow a Spec_Suffix to have the same termination as one of
1165 -- these, which causes a potential ambiguity, but we resolve
1166 -- that my matching the longest possible suffix.
1168 if Spec_Suffix = Body_Suffix then
1173 """) cannot be the same as Spec_Suffix.",
1174 Naming.Ada_Body_Suffix_Loc);
1177 if Body_Suffix /= Separate_Suffix
1178 and then Spec_Suffix = Separate_Suffix
1182 "Separate_Suffix (""" &
1184 """) cannot be the same as Spec_Suffix.",
1185 Naming.Sep_Suffix_Loc);
1189 end Check_Ada_Naming_Scheme_Validity;
1191 -------------------------
1192 -- Check_Configuration --
1193 -------------------------
1195 procedure Check_Configuration
1196 (Project : Project_Id;
1197 In_Tree : Project_Tree_Ref;
1198 Data : in out Project_Data)
1200 Dot_Replacement : File_Name_Type := No_File;
1201 Casing : Casing_Type := All_Lower_Case;
1202 Separate_Suffix : File_Name_Type := No_File;
1204 Lang_Index : Language_Index := No_Language_Index;
1205 -- The index of the language data being checked
1207 Prev_Index : Language_Index := No_Language_Index;
1208 -- The index of the previous language
1210 Current_Language : Name_Id := No_Name;
1211 -- The name of the language
1213 Lang_Data : Language_Data;
1214 -- The data of the language being checked
1216 procedure Get_Language_Index_Of (Language : Name_Id);
1217 -- Get the language index of Language, if Language is one of the
1218 -- languages of the project.
1220 procedure Process_Project_Level_Simple_Attributes;
1221 -- Process the simple attributes at the project level
1223 procedure Process_Project_Level_Array_Attributes;
1224 -- Process the associate array attributes at the project level
1226 procedure Process_Packages;
1227 -- Read the packages of the project
1229 ---------------------------
1230 -- Get_Language_Index_Of --
1231 ---------------------------
1233 procedure Get_Language_Index_Of (Language : Name_Id) is
1234 Real_Language : Name_Id;
1237 Get_Name_String (Language);
1238 To_Lower (Name_Buffer (1 .. Name_Len));
1239 Real_Language := Name_Find;
1241 -- Nothing to do if the language is the same as the current language
1243 if Current_Language /= Real_Language then
1244 Lang_Index := Data.First_Language_Processing;
1245 while Lang_Index /= No_Language_Index loop
1246 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1249 In_Tree.Languages_Data.Table (Lang_Index).Next;
1252 if Lang_Index = No_Language_Index then
1253 Current_Language := No_Name;
1255 Current_Language := Real_Language;
1258 end Get_Language_Index_Of;
1260 ----------------------
1261 -- Process_Packages --
1262 ----------------------
1264 procedure Process_Packages is
1265 Packages : Package_Id;
1266 Element : Package_Element;
1268 procedure Process_Binder (Arrays : Array_Id);
1269 -- Process the associate array attributes of package Binder
1271 procedure Process_Builder (Attributes : Variable_Id);
1272 -- Process the simple attributes of package Builder
1274 procedure Process_Compiler (Arrays : Array_Id);
1275 -- Process the associate array attributes of package Compiler
1277 procedure Process_Naming (Attributes : Variable_Id);
1278 -- Process the simple attributes of package Naming
1280 procedure Process_Naming (Arrays : Array_Id);
1281 -- Process the associate array attributes of package Naming
1283 procedure Process_Linker (Attributes : Variable_Id);
1284 -- Process the simple attributes of package Linker of a
1285 -- configuration project.
1287 --------------------
1288 -- Process_Binder --
1289 --------------------
1291 procedure Process_Binder (Arrays : Array_Id) is
1292 Current_Array_Id : Array_Id;
1293 Current_Array : Array_Data;
1294 Element_Id : Array_Element_Id;
1295 Element : Array_Element;
1298 -- Process the associative array attribute of package Binder
1300 Current_Array_Id := Arrays;
1301 while Current_Array_Id /= No_Array loop
1302 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1304 Element_Id := Current_Array.Value;
1305 while Element_Id /= No_Array_Element loop
1306 Element := In_Tree.Array_Elements.Table (Element_Id);
1308 if Element.Index /= All_Other_Names then
1310 -- Get the name of the language
1312 Get_Language_Index_Of (Element.Index);
1314 if Lang_Index /= No_Language_Index then
1315 case Current_Array.Name is
1318 -- Attribute Driver (<language>)
1320 In_Tree.Languages_Data.Table
1321 (Lang_Index).Config.Binder_Driver :=
1322 File_Name_Type (Element.Value.Value);
1324 when Name_Required_Switches =>
1326 In_Tree.Languages_Data.Table
1327 (Lang_Index).Config.Binder_Required_Switches,
1328 From_List => Element.Value.Values,
1329 In_Tree => In_Tree);
1333 -- Attribute Prefix (<language>)
1335 In_Tree.Languages_Data.Table
1336 (Lang_Index).Config.Binder_Prefix :=
1337 Element.Value.Value;
1339 when Name_Objects_Path =>
1341 -- Attribute Objects_Path (<language>)
1343 In_Tree.Languages_Data.Table
1344 (Lang_Index).Config.Objects_Path :=
1345 Element.Value.Value;
1347 when Name_Objects_Path_File =>
1349 -- Attribute Objects_Path (<language>)
1351 In_Tree.Languages_Data.Table
1352 (Lang_Index).Config.Objects_Path_File :=
1353 Element.Value.Value;
1361 Element_Id := Element.Next;
1364 Current_Array_Id := Current_Array.Next;
1368 ---------------------
1369 -- Process_Builder --
1370 ---------------------
1372 procedure Process_Builder (Attributes : Variable_Id) is
1373 Attribute_Id : Variable_Id;
1374 Attribute : Variable;
1377 -- Process non associated array attribute from package Builder
1379 Attribute_Id := Attributes;
1380 while Attribute_Id /= No_Variable loop
1382 In_Tree.Variable_Elements.Table (Attribute_Id);
1384 if not Attribute.Value.Default then
1385 if Attribute.Name = Name_Executable_Suffix then
1387 -- Attribute Executable_Suffix: the suffix of the
1390 Data.Config.Executable_Suffix :=
1391 Attribute.Value.Value;
1395 Attribute_Id := Attribute.Next;
1397 end Process_Builder;
1399 ----------------------
1400 -- Process_Compiler --
1401 ----------------------
1403 procedure Process_Compiler (Arrays : Array_Id) is
1404 Current_Array_Id : Array_Id;
1405 Current_Array : Array_Data;
1406 Element_Id : Array_Element_Id;
1407 Element : Array_Element;
1408 List : String_List_Id;
1411 -- Process the associative array attribute of package Compiler
1413 Current_Array_Id := Arrays;
1414 while Current_Array_Id /= No_Array loop
1415 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1417 Element_Id := Current_Array.Value;
1418 while Element_Id /= No_Array_Element loop
1419 Element := In_Tree.Array_Elements.Table (Element_Id);
1421 if Element.Index /= All_Other_Names then
1423 -- Get the name of the language
1425 Get_Language_Index_Of (Element.Index);
1427 if Lang_Index /= No_Language_Index then
1428 case Current_Array.Name is
1429 when Name_Dependency_Switches =>
1431 -- Attribute Dependency_Switches (<language>)
1433 if In_Tree.Languages_Data.Table
1434 (Lang_Index).Config.Dependency_Kind = None
1436 In_Tree.Languages_Data.Table
1437 (Lang_Index).Config.Dependency_Kind :=
1441 List := Element.Value.Values;
1443 if List /= Nil_String then
1445 In_Tree.Languages_Data.Table
1446 (Lang_Index).Config.Dependency_Option,
1448 In_Tree => In_Tree);
1451 when Name_Dependency_Driver =>
1453 -- Attribute Dependency_Driver (<language>)
1455 if In_Tree.Languages_Data.Table
1456 (Lang_Index).Config.Dependency_Kind = None
1458 In_Tree.Languages_Data.Table
1459 (Lang_Index).Config.Dependency_Kind :=
1463 List := Element.Value.Values;
1465 if List /= Nil_String then
1467 In_Tree.Languages_Data.Table
1468 (Lang_Index).Config.Compute_Dependency,
1470 In_Tree => In_Tree);
1473 when Name_Include_Switches =>
1475 -- Attribute Include_Switches (<language>)
1477 List := Element.Value.Values;
1479 if List = Nil_String then
1483 "include option cannot be null",
1484 Element.Value.Location);
1488 In_Tree.Languages_Data.Table
1489 (Lang_Index).Config.Include_Option,
1491 In_Tree => In_Tree);
1493 when Name_Include_Path =>
1495 -- Attribute Include_Path (<language>)
1497 In_Tree.Languages_Data.Table
1498 (Lang_Index).Config.Include_Path :=
1499 Element.Value.Value;
1501 when Name_Include_Path_File =>
1503 -- Attribute Include_Path_File (<language>)
1505 In_Tree.Languages_Data.Table
1506 (Lang_Index).Config.Include_Path_File :=
1507 Element.Value.Value;
1511 -- Attribute Driver (<language>)
1513 Get_Name_String (Element.Value.Value);
1515 In_Tree.Languages_Data.Table
1516 (Lang_Index).Config.Compiler_Driver :=
1517 File_Name_Type (Element.Value.Value);
1519 when Name_Required_Switches =>
1521 In_Tree.Languages_Data.Table
1522 (Lang_Index).Config.
1523 Compiler_Required_Switches,
1524 From_List => Element.Value.Values,
1525 In_Tree => In_Tree);
1527 when Name_Path_Syntax =>
1529 In_Tree.Languages_Data.Table
1530 (Lang_Index).Config.Path_Syntax :=
1531 Path_Syntax_Kind'Value
1532 (Get_Name_String (Element.Value.Value));
1535 when Constraint_Error =>
1539 "invalid value for Path_Syntax",
1540 Element.Value.Location);
1543 when Name_Pic_Option =>
1545 -- Attribute Compiler_Pic_Option (<language>)
1547 List := Element.Value.Values;
1549 if List = Nil_String then
1553 "compiler PIC option cannot be null",
1554 Element.Value.Location);
1558 In_Tree.Languages_Data.Table
1559 (Lang_Index).Config.Compilation_PIC_Option,
1561 In_Tree => In_Tree);
1563 when Name_Mapping_File_Switches =>
1565 -- Attribute Mapping_File_Switches (<language>)
1567 List := Element.Value.Values;
1569 if List = Nil_String then
1573 "mapping file switches cannot be null",
1574 Element.Value.Location);
1578 In_Tree.Languages_Data.Table
1579 (Lang_Index).Config.Mapping_File_Switches,
1581 In_Tree => In_Tree);
1583 when Name_Mapping_Spec_Suffix =>
1585 -- Attribute Mapping_Spec_Suffix (<language>)
1587 In_Tree.Languages_Data.Table
1588 (Lang_Index).Config.Mapping_Spec_Suffix :=
1589 File_Name_Type (Element.Value.Value);
1591 when Name_Mapping_Body_Suffix =>
1593 -- Attribute Mapping_Body_Suffix (<language>)
1595 In_Tree.Languages_Data.Table
1596 (Lang_Index).Config.Mapping_Body_Suffix :=
1597 File_Name_Type (Element.Value.Value);
1599 when Name_Config_File_Switches =>
1601 -- Attribute Config_File_Switches (<language>)
1603 List := Element.Value.Values;
1605 if List = Nil_String then
1609 "config file switches cannot be null",
1610 Element.Value.Location);
1614 In_Tree.Languages_Data.Table
1615 (Lang_Index).Config.Config_File_Switches,
1617 In_Tree => In_Tree);
1619 when Name_Objects_Path =>
1621 -- Attribute Objects_Path (<language>)
1623 In_Tree.Languages_Data.Table
1624 (Lang_Index).Config.Objects_Path :=
1625 Element.Value.Value;
1627 when Name_Objects_Path_File =>
1629 -- Attribute Objects_Path_File (<language>)
1631 In_Tree.Languages_Data.Table
1632 (Lang_Index).Config.Objects_Path_File :=
1633 Element.Value.Value;
1635 when Name_Config_Body_File_Name =>
1637 -- Attribute Config_Body_File_Name (<language>)
1639 In_Tree.Languages_Data.Table
1640 (Lang_Index).Config.Config_Body :=
1641 Element.Value.Value;
1643 when Name_Config_Body_File_Name_Pattern =>
1645 -- Attribute Config_Body_File_Name_Pattern
1648 In_Tree.Languages_Data.Table
1649 (Lang_Index).Config.Config_Body_Pattern :=
1650 Element.Value.Value;
1652 when Name_Config_Spec_File_Name =>
1654 -- Attribute Config_Spec_File_Name (<language>)
1656 In_Tree.Languages_Data.Table
1657 (Lang_Index).Config.Config_Spec :=
1658 Element.Value.Value;
1660 when Name_Config_Spec_File_Name_Pattern =>
1662 -- Attribute Config_Spec_File_Name_Pattern
1665 In_Tree.Languages_Data.Table
1666 (Lang_Index).Config.Config_Spec_Pattern :=
1667 Element.Value.Value;
1669 when Name_Config_File_Unique =>
1671 -- Attribute Config_File_Unique (<language>)
1674 In_Tree.Languages_Data.Table
1675 (Lang_Index).Config.Config_File_Unique :=
1677 (Get_Name_String (Element.Value.Value));
1679 when Constraint_Error =>
1683 "illegal value for Config_File_Unique",
1684 Element.Value.Location);
1693 Element_Id := Element.Next;
1696 Current_Array_Id := Current_Array.Next;
1698 end Process_Compiler;
1700 --------------------
1701 -- Process_Naming --
1702 --------------------
1704 procedure Process_Naming (Attributes : Variable_Id) is
1705 Attribute_Id : Variable_Id;
1706 Attribute : Variable;
1709 -- Process non associated array attribute from package Naming
1711 Attribute_Id := Attributes;
1712 while Attribute_Id /= No_Variable loop
1713 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1715 if not Attribute.Value.Default then
1716 if Attribute.Name = Name_Separate_Suffix then
1718 -- Attribute Separate_Suffix
1720 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1722 elsif Attribute.Name = Name_Casing then
1728 Value (Get_Name_String (Attribute.Value.Value));
1731 when Constraint_Error =>
1735 "invalid value for Casing",
1736 Attribute.Value.Location);
1739 elsif Attribute.Name = Name_Dot_Replacement then
1741 -- Attribute Dot_Replacement
1743 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1748 Attribute_Id := Attribute.Next;
1752 procedure Process_Naming (Arrays : Array_Id) is
1753 Current_Array_Id : Array_Id;
1754 Current_Array : Array_Data;
1755 Element_Id : Array_Element_Id;
1756 Element : Array_Element;
1758 -- Process the associative array attribute of package Naming
1760 Current_Array_Id := Arrays;
1761 while Current_Array_Id /= No_Array loop
1762 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1764 Element_Id := Current_Array.Value;
1765 while Element_Id /= No_Array_Element loop
1766 Element := In_Tree.Array_Elements.Table (Element_Id);
1768 -- Get the name of the language
1770 Get_Language_Index_Of (Element.Index);
1772 if Lang_Index /= No_Language_Index then
1773 case Current_Array.Name is
1774 when Name_Specification_Suffix | Name_Spec_Suffix =>
1776 -- Attribute Spec_Suffix (<language>)
1778 In_Tree.Languages_Data.Table
1779 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1780 File_Name_Type (Element.Value.Value);
1782 when Name_Implementation_Suffix | Name_Body_Suffix =>
1784 -- Attribute Body_Suffix (<language>)
1786 In_Tree.Languages_Data.Table
1787 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1788 File_Name_Type (Element.Value.Value);
1790 In_Tree.Languages_Data.Table
1791 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1792 File_Name_Type (Element.Value.Value);
1799 Element_Id := Element.Next;
1802 Current_Array_Id := Current_Array.Next;
1806 --------------------
1807 -- Process_Linker --
1808 --------------------
1810 procedure Process_Linker (Attributes : Variable_Id) is
1811 Attribute_Id : Variable_Id;
1812 Attribute : Variable;
1815 -- Process non associated array attribute from package Linker
1817 Attribute_Id := Attributes;
1818 while Attribute_Id /= No_Variable loop
1820 In_Tree.Variable_Elements.Table (Attribute_Id);
1822 if not Attribute.Value.Default then
1823 if Attribute.Name = Name_Driver then
1825 -- Attribute Linker'Driver: the default linker to use
1827 Data.Config.Linker :=
1828 Path_Name_Type (Attribute.Value.Value);
1830 elsif Attribute.Name = Name_Required_Switches then
1832 -- Attribute Required_Switches: the minimum
1833 -- options to use when invoking the linker
1836 Data.Config.Minimum_Linker_Options,
1837 From_List => Attribute.Value.Values,
1838 In_Tree => In_Tree);
1840 elsif Attribute.Name = Name_Map_File_Option then
1841 Data.Config.Map_File_Option := Attribute.Value.Value;
1845 Attribute_Id := Attribute.Next;
1849 -- Start of processing for Process_Packages
1852 Packages := Data.Decl.Packages;
1853 while Packages /= No_Package loop
1854 Element := In_Tree.Packages.Table (Packages);
1856 case Element.Name is
1859 -- Process attributes of package Binder
1861 Process_Binder (Element.Decl.Arrays);
1863 when Name_Builder =>
1865 -- Process attributes of package Builder
1867 Process_Builder (Element.Decl.Attributes);
1869 when Name_Compiler =>
1871 -- Process attributes of package Compiler
1873 Process_Compiler (Element.Decl.Arrays);
1877 -- Process attributes of package Linker
1879 Process_Linker (Element.Decl.Attributes);
1883 -- Process attributes of package Naming
1885 Process_Naming (Element.Decl.Attributes);
1886 Process_Naming (Element.Decl.Arrays);
1892 Packages := Element.Next;
1894 end Process_Packages;
1896 ---------------------------------------------
1897 -- Process_Project_Level_Simple_Attributes --
1898 ---------------------------------------------
1900 procedure Process_Project_Level_Simple_Attributes is
1901 Attribute_Id : Variable_Id;
1902 Attribute : Variable;
1903 List : String_List_Id;
1906 -- Process non associated array attribute at project level
1908 Attribute_Id := Data.Decl.Attributes;
1909 while Attribute_Id /= No_Variable loop
1911 In_Tree.Variable_Elements.Table (Attribute_Id);
1913 if not Attribute.Value.Default then
1914 if Attribute.Name = Name_Library_Builder then
1916 -- Attribute Library_Builder: the application to invoke
1917 -- to build libraries.
1919 Data.Config.Library_Builder :=
1920 Path_Name_Type (Attribute.Value.Value);
1922 elsif Attribute.Name = Name_Archive_Builder then
1924 -- Attribute Archive_Builder: the archive builder
1925 -- (usually "ar") and its minimum options (usually "cr").
1927 List := Attribute.Value.Values;
1929 if List = Nil_String then
1933 "archive builder cannot be null",
1934 Attribute.Value.Location);
1937 Put (Into_List => Data.Config.Archive_Builder,
1939 In_Tree => In_Tree);
1941 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1943 -- Attribute Archive_Builder: the archive builder
1944 -- (usually "ar") and its minimum options (usually "cr").
1946 List := Attribute.Value.Values;
1948 if List /= Nil_String then
1950 (Into_List => Data.Config.Archive_Builder_Append_Option,
1952 In_Tree => In_Tree);
1955 elsif Attribute.Name = Name_Archive_Indexer then
1957 -- Attribute Archive_Indexer: the optional archive
1958 -- indexer (usually "ranlib") with its minimum options
1961 List := Attribute.Value.Values;
1963 if List = Nil_String then
1967 "archive indexer cannot be null",
1968 Attribute.Value.Location);
1971 Put (Into_List => Data.Config.Archive_Indexer,
1973 In_Tree => In_Tree);
1975 elsif Attribute.Name = Name_Library_Partial_Linker then
1977 -- Attribute Library_Partial_Linker: the optional linker
1978 -- driver with its minimum options, to partially link
1981 List := Attribute.Value.Values;
1983 if List = Nil_String then
1987 "partial linker cannot be null",
1988 Attribute.Value.Location);
1991 Put (Into_List => Data.Config.Lib_Partial_Linker,
1993 In_Tree => In_Tree);
1995 elsif Attribute.Name = Name_Library_GCC then
1996 Data.Config.Shared_Lib_Driver :=
1997 File_Name_Type (Attribute.Value.Value);
1999 elsif Attribute.Name = Name_Archive_Suffix then
2000 Data.Config.Archive_Suffix :=
2001 File_Name_Type (Attribute.Value.Value);
2003 elsif Attribute.Name = Name_Linker_Executable_Option then
2005 -- Attribute Linker_Executable_Option: optional options
2006 -- to specify an executable name. Defaults to "-o".
2008 List := Attribute.Value.Values;
2010 if List = Nil_String then
2014 "linker executable option cannot be null",
2015 Attribute.Value.Location);
2018 Put (Into_List => Data.Config.Linker_Executable_Option,
2020 In_Tree => In_Tree);
2022 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2024 -- Attribute Linker_Lib_Dir_Option: optional options
2025 -- to specify a library search directory. Defaults to
2028 Get_Name_String (Attribute.Value.Value);
2030 if Name_Len = 0 then
2034 "linker library directory option cannot be empty",
2035 Attribute.Value.Location);
2038 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2040 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2042 -- Attribute Linker_Lib_Name_Option: optional options
2043 -- to specify the name of a library to be linked in.
2044 -- Defaults to "-l".
2046 Get_Name_String (Attribute.Value.Value);
2048 if Name_Len = 0 then
2052 "linker library name option cannot be empty",
2053 Attribute.Value.Location);
2056 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2058 elsif Attribute.Name = Name_Run_Path_Option then
2060 -- Attribute Run_Path_Option: optional options to
2061 -- specify a path for libraries.
2063 List := Attribute.Value.Values;
2065 if List /= Nil_String then
2066 Put (Into_List => Data.Config.Run_Path_Option,
2068 In_Tree => In_Tree);
2071 elsif Attribute.Name = Name_Library_Support then
2073 pragma Unsuppress (All_Checks);
2075 Data.Config.Lib_Support :=
2076 Library_Support'Value (Get_Name_String
2077 (Attribute.Value.Value));
2079 when Constraint_Error =>
2083 "invalid value """ &
2084 Get_Name_String (Attribute.Value.Value) &
2085 """ for Library_Support",
2086 Attribute.Value.Location);
2089 elsif Attribute.Name = Name_Shared_Library_Prefix then
2090 Data.Config.Shared_Lib_Prefix :=
2091 File_Name_Type (Attribute.Value.Value);
2093 elsif Attribute.Name = Name_Shared_Library_Suffix then
2094 Data.Config.Shared_Lib_Suffix :=
2095 File_Name_Type (Attribute.Value.Value);
2097 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2099 pragma Unsuppress (All_Checks);
2101 Data.Config.Symbolic_Link_Supported :=
2102 Boolean'Value (Get_Name_String
2103 (Attribute.Value.Value));
2105 when Constraint_Error =>
2110 & Get_Name_String (Attribute.Value.Value)
2111 & """ for Symbolic_Link_Supported",
2112 Attribute.Value.Location);
2116 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2119 pragma Unsuppress (All_Checks);
2121 Data.Config.Lib_Maj_Min_Id_Supported :=
2122 Boolean'Value (Get_Name_String
2123 (Attribute.Value.Value));
2125 when Constraint_Error =>
2129 "invalid value """ &
2130 Get_Name_String (Attribute.Value.Value) &
2131 """ for Library_Major_Minor_Id_Supported",
2132 Attribute.Value.Location);
2135 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2137 pragma Unsuppress (All_Checks);
2139 Data.Config.Auto_Init_Supported :=
2140 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2142 when Constraint_Error =>
2147 & Get_Name_String (Attribute.Value.Value)
2148 & """ for Library_Auto_Init_Supported",
2149 Attribute.Value.Location);
2152 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2153 List := Attribute.Value.Values;
2155 if List /= Nil_String then
2156 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2158 In_Tree => In_Tree);
2161 elsif Attribute.Name = Name_Library_Version_Switches then
2162 List := Attribute.Value.Values;
2164 if List /= Nil_String then
2165 Put (Into_List => Data.Config.Lib_Version_Options,
2167 In_Tree => In_Tree);
2172 Attribute_Id := Attribute.Next;
2174 end Process_Project_Level_Simple_Attributes;
2176 --------------------------------------------
2177 -- Process_Project_Level_Array_Attributes --
2178 --------------------------------------------
2180 procedure Process_Project_Level_Array_Attributes is
2181 Current_Array_Id : Array_Id;
2182 Current_Array : Array_Data;
2183 Element_Id : Array_Element_Id;
2184 Element : Array_Element;
2185 List : String_List_Id;
2188 -- Process the associative array attributes at project level
2190 Current_Array_Id := Data.Decl.Arrays;
2191 while Current_Array_Id /= No_Array loop
2192 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2194 Element_Id := Current_Array.Value;
2195 while Element_Id /= No_Array_Element loop
2196 Element := In_Tree.Array_Elements.Table (Element_Id);
2198 -- Get the name of the language
2200 Get_Language_Index_Of (Element.Index);
2202 if Lang_Index /= No_Language_Index then
2203 case Current_Array.Name is
2204 when Name_Inherit_Source_Path =>
2205 List := Element.Value.Values;
2207 if List /= Nil_String then
2210 In_Tree.Languages_Data.Table (Lang_Index).
2211 Config.Include_Compatible_Languages,
2214 Lower_Case => True);
2217 when Name_Toolchain_Description =>
2219 -- Attribute Toolchain_Description (<language>)
2221 In_Tree.Languages_Data.Table
2222 (Lang_Index).Config.Toolchain_Description :=
2223 Element.Value.Value;
2225 when Name_Toolchain_Version =>
2227 -- Attribute Toolchain_Version (<language>)
2229 In_Tree.Languages_Data.Table
2230 (Lang_Index).Config.Toolchain_Version :=
2231 Element.Value.Value;
2233 when Name_Runtime_Library_Dir =>
2235 -- Attribute Runtime_Library_Dir (<language>)
2237 In_Tree.Languages_Data.Table
2238 (Lang_Index).Config.Runtime_Library_Dir :=
2239 Element.Value.Value;
2241 when Name_Object_Generated =>
2243 pragma Unsuppress (All_Checks);
2249 (Get_Name_String (Element.Value.Value));
2251 In_Tree.Languages_Data.Table
2252 (Lang_Index).Config.Object_Generated := Value;
2254 -- If no object is generated, no object may be
2258 In_Tree.Languages_Data.Table
2259 (Lang_Index).Config.Objects_Linked := False;
2263 when Constraint_Error =>
2268 & Get_Name_String (Element.Value.Value)
2269 & """ for Object_Generated",
2270 Element.Value.Location);
2273 when Name_Objects_Linked =>
2275 pragma Unsuppress (All_Checks);
2281 (Get_Name_String (Element.Value.Value));
2283 -- No change if Object_Generated is False, as this
2284 -- forces Objects_Linked to be False too.
2286 if In_Tree.Languages_Data.Table
2287 (Lang_Index).Config.Object_Generated
2289 In_Tree.Languages_Data.Table
2290 (Lang_Index).Config.Objects_Linked :=
2295 when Constraint_Error =>
2300 & Get_Name_String (Element.Value.Value)
2301 & """ for Objects_Linked",
2302 Element.Value.Location);
2309 Element_Id := Element.Next;
2312 Current_Array_Id := Current_Array.Next;
2314 end Process_Project_Level_Array_Attributes;
2317 Process_Project_Level_Simple_Attributes;
2318 Process_Project_Level_Array_Attributes;
2321 -- For unit based languages, set Casing, Dot_Replacement and
2322 -- Separate_Suffix in Naming_Data.
2324 Lang_Index := Data.First_Language_Processing;
2325 while Lang_Index /= No_Language_Index loop
2326 if In_Tree.Languages_Data.Table
2327 (Lang_Index).Name = Name_Ada
2329 In_Tree.Languages_Data.Table
2330 (Lang_Index).Config.Naming_Data.Casing := Casing;
2331 In_Tree.Languages_Data.Table
2332 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2335 if Separate_Suffix /= No_File then
2336 In_Tree.Languages_Data.Table
2337 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2344 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2347 -- Give empty names to various prefixes/suffixes, if they have not
2348 -- been specified in the configuration.
2350 if Data.Config.Archive_Suffix = No_File then
2351 Data.Config.Archive_Suffix := Empty_File;
2354 if Data.Config.Shared_Lib_Prefix = No_File then
2355 Data.Config.Shared_Lib_Prefix := Empty_File;
2358 if Data.Config.Shared_Lib_Suffix = No_File then
2359 Data.Config.Shared_Lib_Suffix := Empty_File;
2362 Lang_Index := Data.First_Language_Processing;
2363 while Lang_Index /= No_Language_Index loop
2364 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2366 Current_Language := Lang_Data.Display_Name;
2368 -- For all languages, Compiler_Driver needs to be specified
2370 if Lang_Data.Config.Compiler_Driver = No_File then
2371 Error_Msg_Name_1 := Current_Language;
2375 "?no compiler specified for language %%" &
2376 ", ignoring all its sources",
2379 if Lang_Index = Data.First_Language_Processing then
2380 Data.First_Language_Processing :=
2383 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2387 elsif Lang_Data.Name = Name_Ada then
2388 Prev_Index := Lang_Index;
2390 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2391 -- Body_Suffix need to be specified.
2393 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2397 "Dot_Replacement not specified for Ada",
2401 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2405 "Spec_Suffix not specified for Ada",
2409 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2413 "Body_Suffix not specified for Ada",
2418 Prev_Index := Lang_Index;
2420 -- For file based languages, either Spec_Suffix or Body_Suffix
2421 -- need to be specified.
2423 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2424 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2426 Error_Msg_Name_1 := Current_Language;
2430 "no suffixes specified for %%",
2435 Lang_Index := Lang_Data.Next;
2437 end Check_Configuration;
2439 -------------------------------
2440 -- Check_If_Externally_Built --
2441 -------------------------------
2443 procedure Check_If_Externally_Built
2444 (Project : Project_Id;
2445 In_Tree : Project_Tree_Ref;
2446 Data : in out Project_Data)
2448 Externally_Built : constant Variable_Value :=
2450 (Name_Externally_Built,
2451 Data.Decl.Attributes, In_Tree);
2454 if not Externally_Built.Default then
2455 Get_Name_String (Externally_Built.Value);
2456 To_Lower (Name_Buffer (1 .. Name_Len));
2458 if Name_Buffer (1 .. Name_Len) = "true" then
2459 Data.Externally_Built := True;
2461 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2462 Error_Msg (Project, In_Tree,
2463 "Externally_Built may only be true or false",
2464 Externally_Built.Location);
2468 -- A virtual project extending an externally built project is itself
2469 -- externally built.
2471 if Data.Virtual and then Data.Extends /= No_Project then
2472 Data.Externally_Built :=
2473 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2476 if Current_Verbosity = High then
2477 Write_Str ("Project is ");
2479 if not Data.Externally_Built then
2483 Write_Line ("externally built.");
2485 end Check_If_Externally_Built;
2487 ----------------------
2488 -- Check_Interfaces --
2489 ----------------------
2491 procedure Check_Interfaces
2492 (Project : Project_Id;
2493 In_Tree : Project_Tree_Ref;
2494 Data : in out Project_Data)
2496 Interfaces : constant Prj.Variable_Value :=
2498 (Snames.Name_Interfaces,
2499 Data.Decl.Attributes,
2502 List : String_List_Id;
2503 Element : String_Element;
2504 Name : File_Name_Type;
2508 Project_2 : Project_Id;
2509 Data_2 : Project_Data;
2512 if not Interfaces.Default then
2514 -- Set In_Interfaces to False for all sources. It will be set to True
2515 -- later for the sources in the Interfaces list.
2517 Project_2 := Project;
2520 Source := Data_2.First_Source;
2521 while Source /= No_Source loop
2523 Src_Data : Source_Data renames
2524 In_Tree.Sources.Table (Source);
2526 Src_Data.In_Interfaces := False;
2527 Source := Src_Data.Next_In_Project;
2531 Project_2 := Data_2.Extends;
2533 exit when Project_2 = No_Project;
2535 Data_2 := In_Tree.Projects.Table (Project_2);
2538 List := Interfaces.Values;
2539 while List /= Nil_String loop
2540 Element := In_Tree.String_Elements.Table (List);
2541 Get_Name_String (Element.Value);
2542 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2545 Project_2 := Project;
2549 Source := Data_2.First_Source;
2550 while Source /= No_Source loop
2552 Src_Data : Source_Data renames
2553 In_Tree.Sources.Table (Source);
2556 if Src_Data.File = Name then
2557 if not Src_Data.Locally_Removed then
2558 Src_Data.In_Interfaces := True;
2559 Src_Data.Declared_In_Interfaces := True;
2561 if Src_Data.Other_Part /= No_Source then
2562 In_Tree.Sources.Table
2563 (Src_Data.Other_Part).In_Interfaces := True;
2564 In_Tree.Sources.Table
2565 (Src_Data.Other_Part).Declared_In_Interfaces :=
2569 if Current_Verbosity = High then
2570 Write_Str (" interface: ");
2572 (Get_Name_String (Src_Data.Path.Name));
2579 Source := Src_Data.Next_In_Project;
2583 Project_2 := Data_2.Extends;
2585 exit Big_Loop when Project_2 = No_Project;
2587 Data_2 := In_Tree.Projects.Table (Project_2);
2590 if Source = No_Source then
2591 Error_Msg_File_1 := File_Name_Type (Element.Value);
2592 Error_Msg_Name_1 := Data.Name;
2597 "{ cannot be an interface of project %% " &
2598 "as it is not one of its sources",
2602 List := Element.Next;
2605 Data.Interfaces_Defined := True;
2607 elsif Data.Extends /= No_Project then
2608 Data.Interfaces_Defined :=
2609 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2611 if Data.Interfaces_Defined then
2612 Source := Data.First_Source;
2613 while Source /= No_Source loop
2615 Src_Data : Source_Data renames
2616 In_Tree.Sources.Table (Source);
2619 if not Src_Data.Declared_In_Interfaces then
2620 Src_Data.In_Interfaces := False;
2623 Source := Src_Data.Next_In_Project;
2628 end Check_Interfaces;
2630 --------------------------
2631 -- Check_Naming_Schemes --
2632 --------------------------
2634 procedure Check_Naming_Schemes
2635 (Data : in out Project_Data;
2636 Project : Project_Id;
2637 In_Tree : Project_Tree_Ref)
2639 Naming_Id : constant Package_Id :=
2640 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2641 Naming : Package_Element;
2643 procedure Check_Unit_Names (List : Array_Element_Id);
2644 -- Check that a list of unit names contains only valid names
2646 procedure Get_Exceptions (Kind : Source_Kind);
2647 -- Comment required ???
2649 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2650 -- Comment required ???
2652 ----------------------
2653 -- Check_Unit_Names --
2654 ----------------------
2656 procedure Check_Unit_Names (List : Array_Element_Id) is
2657 Current : Array_Element_Id;
2658 Element : Array_Element;
2659 Unit_Name : Name_Id;
2662 -- Loop through elements of the string list
2665 while Current /= No_Array_Element loop
2666 Element := In_Tree.Array_Elements.Table (Current);
2668 -- Put file name in canonical case
2670 if not Osint.File_Names_Case_Sensitive then
2671 Get_Name_String (Element.Value.Value);
2672 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2673 Element.Value.Value := Name_Find;
2676 -- Check that it contains a valid unit name
2678 Get_Name_String (Element.Index);
2679 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2681 if Unit_Name = No_Name then
2682 Err_Vars.Error_Msg_Name_1 := Element.Index;
2685 "%% is not a valid unit name.",
2686 Element.Value.Location);
2689 if Current_Verbosity = High then
2690 Write_Str (" Unit (""");
2691 Write_Str (Get_Name_String (Unit_Name));
2695 Element.Index := Unit_Name;
2696 In_Tree.Array_Elements.Table (Current) := Element;
2699 Current := Element.Next;
2701 end Check_Unit_Names;
2703 --------------------
2704 -- Get_Exceptions --
2705 --------------------
2707 procedure Get_Exceptions (Kind : Source_Kind) is
2708 Exceptions : Array_Element_Id;
2709 Exception_List : Variable_Value;
2710 Element_Id : String_List_Id;
2711 Element : String_Element;
2712 File_Name : File_Name_Type;
2713 Lang_Id : Language_Index;
2715 Lang_Kind : Language_Kind;
2722 (Name_Implementation_Exceptions,
2723 In_Arrays => Naming.Decl.Arrays,
2724 In_Tree => In_Tree);
2729 (Name_Specification_Exceptions,
2730 In_Arrays => Naming.Decl.Arrays,
2731 In_Tree => In_Tree);
2734 Lang_Id := Data.First_Language_Processing;
2735 while Lang_Id /= No_Language_Index loop
2736 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2739 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2741 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2743 Exception_List := Value_Of
2745 In_Array => Exceptions,
2746 In_Tree => In_Tree);
2748 if Exception_List /= Nil_Variable_Value then
2749 Element_Id := Exception_List.Values;
2750 while Element_Id /= Nil_String loop
2751 Element := In_Tree.String_Elements.Table (Element_Id);
2753 if Osint.File_Names_Case_Sensitive then
2754 File_Name := File_Name_Type (Element.Value);
2756 Get_Name_String (Element.Value);
2757 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2758 File_Name := Name_Find;
2761 Source := Data.First_Source;
2762 while Source /= No_Source
2764 In_Tree.Sources.Table (Source).File /= File_Name
2767 In_Tree.Sources.Table (Source).Next_In_Project;
2770 if Source = No_Source then
2779 File_Name => File_Name,
2780 Display_File => File_Name_Type (Element.Value),
2781 Naming_Exception => True,
2782 Lang_Kind => Lang_Kind);
2785 -- Check if the file name is already recorded for
2786 -- another language or another kind.
2789 In_Tree.Sources.Table (Source).Language /= Lang_Id
2794 "the same file cannot be a source " &
2798 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2802 "the same file cannot be a source " &
2807 -- If the file is already recorded for the same
2808 -- language and the same kind, it means that the file
2809 -- name appears several times in the *_Exceptions
2810 -- attribute; so there is nothing to do.
2814 Element_Id := Element.Next;
2819 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2823 -------------------------
2824 -- Get_Unit_Exceptions --
2825 -------------------------
2827 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2828 Exceptions : Array_Element_Id;
2829 Element : Array_Element;
2832 File_Name : File_Name_Type;
2833 Lang_Id : constant Language_Index :=
2834 Data.Unit_Based_Language_Index;
2835 Lang : constant Name_Id :=
2836 Data.Unit_Based_Language_Name;
2839 Source_To_Replace : Source_Id := No_Source;
2841 Other_Project : Project_Id;
2842 Other_Part : Source_Id := No_Source;
2845 if Lang_Id = No_Language_Index or else Lang = No_Name then
2850 Exceptions := Value_Of
2852 In_Arrays => Naming.Decl.Arrays,
2853 In_Tree => In_Tree);
2855 if Exceptions = No_Array_Element then
2858 (Name_Implementation,
2859 In_Arrays => Naming.Decl.Arrays,
2860 In_Tree => In_Tree);
2867 In_Arrays => Naming.Decl.Arrays,
2868 In_Tree => In_Tree);
2870 if Exceptions = No_Array_Element then
2871 Exceptions := Value_Of
2872 (Name_Specification,
2873 In_Arrays => Naming.Decl.Arrays,
2874 In_Tree => In_Tree);
2879 while Exceptions /= No_Array_Element loop
2880 Element := In_Tree.Array_Elements.Table (Exceptions);
2882 if Osint.File_Names_Case_Sensitive then
2883 File_Name := File_Name_Type (Element.Value.Value);
2885 Get_Name_String (Element.Value.Value);
2886 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2887 File_Name := Name_Find;
2890 Get_Name_String (Element.Index);
2891 To_Lower (Name_Buffer (1 .. Name_Len));
2894 Index := Element.Value.Index;
2896 -- For Ada, check if it is a valid unit name
2898 if Lang = Name_Ada then
2899 Get_Name_String (Element.Index);
2900 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2902 if Unit = No_Name then
2903 Err_Vars.Error_Msg_Name_1 := Element.Index;
2906 "%% is not a valid unit name.",
2907 Element.Value.Location);
2911 if Unit /= No_Name then
2913 -- Check if the source already exists
2915 Source := In_Tree.First_Source;
2916 Source_To_Replace := No_Source;
2918 while Source /= No_Source and then
2919 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2920 In_Tree.Sources.Table (Source).Index /= Index)
2922 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2925 if Source /= No_Source then
2926 if In_Tree.Sources.Table (Source).Kind /= Kind then
2927 Other_Part := Source;
2931 In_Tree.Sources.Table (Source).Next_In_Sources;
2933 exit when Source = No_Source or else
2934 (In_Tree.Sources.Table (Source).Unit = Unit
2936 In_Tree.Sources.Table (Source).Index = Index);
2940 if Source /= No_Source then
2941 Other_Project := In_Tree.Sources.Table (Source).Project;
2943 if Is_Extending (Project, Other_Project, In_Tree) then
2945 In_Tree.Sources.Table (Source).Other_Part;
2947 -- Record the source to be removed
2949 Source_To_Replace := Source;
2950 Source := No_Source;
2953 Error_Msg_Name_1 := Unit;
2955 In_Tree.Projects.Table (Other_Project).Name;
2959 "%% is already a source of project %%",
2960 Element.Value.Location);
2965 if Source = No_Source then
2974 File_Name => File_Name,
2975 Display_File => File_Name_Type (Element.Value.Value),
2976 Lang_Kind => Unit_Based,
2977 Other_Part => Other_Part,
2980 Naming_Exception => True,
2981 Source_To_Replace => Source_To_Replace);
2985 Exceptions := Element.Next;
2988 end Get_Unit_Exceptions;
2990 -- Start of processing for Check_Naming_Schemes
2993 if Get_Mode = Ada_Only then
2995 -- If there is a package Naming, we will put in Data.Naming what is
2996 -- in this package Naming.
2998 if Naming_Id /= No_Package then
2999 Naming := In_Tree.Packages.Table (Naming_Id);
3001 if Current_Verbosity = High then
3002 Write_Line ("Checking ""Naming"" for Ada.");
3006 Bodies : constant Array_Element_Id :=
3008 (Name_Body, Naming.Decl.Arrays, In_Tree);
3010 Specs : constant Array_Element_Id :=
3012 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3015 if Bodies /= No_Array_Element then
3017 -- We have elements in the array Body_Part
3019 if Current_Verbosity = High then
3020 Write_Line ("Found Bodies.");
3023 Data.Naming.Bodies := Bodies;
3024 Check_Unit_Names (Bodies);
3027 if Current_Verbosity = High then
3028 Write_Line ("No Bodies.");
3032 if Specs /= No_Array_Element then
3034 -- We have elements in the array Specs
3036 if Current_Verbosity = High then
3037 Write_Line ("Found Specs.");
3040 Data.Naming.Specs := Specs;
3041 Check_Unit_Names (Specs);
3044 if Current_Verbosity = High then
3045 Write_Line ("No Specs.");
3050 -- We are now checking if variables Dot_Replacement, Casing,
3051 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3053 -- For each variable, if it does not exist, we do nothing,
3054 -- because we already have the default.
3056 -- Check Dot_Replacement
3059 Dot_Replacement : constant Variable_Value :=
3061 (Name_Dot_Replacement,
3062 Naming.Decl.Attributes, In_Tree);
3065 pragma Assert (Dot_Replacement.Kind = Single,
3066 "Dot_Replacement is not a single string");
3068 if not Dot_Replacement.Default then
3069 Get_Name_String (Dot_Replacement.Value);
3071 if Name_Len = 0 then
3074 "Dot_Replacement cannot be empty",
3075 Dot_Replacement.Location);
3078 if Osint.File_Names_Case_Sensitive then
3079 Data.Naming.Dot_Replacement :=
3080 File_Name_Type (Dot_Replacement.Value);
3082 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3083 Data.Naming.Dot_Replacement := Name_Find;
3085 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3090 if Current_Verbosity = High then
3091 Write_Str (" Dot_Replacement = """);
3092 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3100 Casing_String : constant Variable_Value :=
3103 Naming.Decl.Attributes,
3107 pragma Assert (Casing_String.Kind = Single,
3108 "Casing is not a single string");
3110 if not Casing_String.Default then
3112 Casing_Image : constant String :=
3113 Get_Name_String (Casing_String.Value);
3116 Casing_Value : constant Casing_Type :=
3117 Value (Casing_Image);
3119 Data.Naming.Casing := Casing_Value;
3123 when Constraint_Error =>
3124 if Casing_Image'Length = 0 then
3127 "Casing cannot be an empty string",
3128 Casing_String.Location);
3131 Name_Len := Casing_Image'Length;
3132 Name_Buffer (1 .. Name_Len) := Casing_Image;
3133 Err_Vars.Error_Msg_Name_1 := Name_Find;
3136 "%% is not a correct Casing",
3137 Casing_String.Location);
3143 if Current_Verbosity = High then
3144 Write_Str (" Casing = ");
3145 Write_Str (Image (Data.Naming.Casing));
3150 -- Check Spec_Suffix
3153 Ada_Spec_Suffix : constant Variable_Value :=
3157 In_Array => Data.Naming.Spec_Suffix,
3158 In_Tree => In_Tree);
3161 if Ada_Spec_Suffix.Kind = Single
3162 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3164 Get_Name_String (Ada_Spec_Suffix.Value);
3165 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3166 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3167 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3174 Default_Ada_Spec_Suffix);
3178 if Current_Verbosity = High then
3179 Write_Str (" Spec_Suffix = """);
3180 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3185 -- Check Body_Suffix
3188 Ada_Body_Suffix : constant Variable_Value :=
3192 In_Array => Data.Naming.Body_Suffix,
3193 In_Tree => In_Tree);
3196 if Ada_Body_Suffix.Kind = Single
3197 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3199 Get_Name_String (Ada_Body_Suffix.Value);
3200 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3201 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3202 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3209 Default_Ada_Body_Suffix);
3213 if Current_Verbosity = High then
3214 Write_Str (" Body_Suffix = """);
3215 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3220 -- Check Separate_Suffix
3223 Ada_Sep_Suffix : constant Variable_Value :=
3225 (Variable_Name => Name_Separate_Suffix,
3226 In_Variables => Naming.Decl.Attributes,
3227 In_Tree => In_Tree);
3230 if Ada_Sep_Suffix.Default then
3231 Data.Naming.Separate_Suffix :=
3232 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3235 Get_Name_String (Ada_Sep_Suffix.Value);
3237 if Name_Len = 0 then
3240 "Separate_Suffix cannot be empty",
3241 Ada_Sep_Suffix.Location);
3244 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3245 Data.Naming.Separate_Suffix := Name_Find;
3246 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3251 if Current_Verbosity = High then
3252 Write_Str (" Separate_Suffix = """);
3253 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3258 -- Check if Data.Naming is valid
3260 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3263 elsif not In_Configuration then
3265 -- Look into package Naming, if there is one
3267 if Naming_Id /= No_Package then
3268 Naming := In_Tree.Packages.Table (Naming_Id);
3270 if Current_Verbosity = High then
3271 Write_Line ("Checking package Naming.");
3274 -- We are now checking if attribute Dot_Replacement, Casing,
3275 -- and/or Separate_Suffix exist.
3277 -- For each attribute, if it does not exist, we do nothing,
3278 -- because we already have the default.
3279 -- Otherwise, for all unit-based languages, we put the declared
3280 -- value in the language config.
3283 Dot_Repl : constant Variable_Value :=
3285 (Name_Dot_Replacement,
3286 Naming.Decl.Attributes, In_Tree);
3287 Dot_Replacement : File_Name_Type := No_File;
3289 Casing_String : constant Variable_Value :=
3292 Naming.Decl.Attributes,
3295 Casing : Casing_Type := All_Lower_Case;
3296 -- Casing type (junk initialization to stop bad gcc warning)
3298 Casing_Defined : Boolean := False;
3300 Sep_Suffix : constant Variable_Value :=
3302 (Variable_Name => Name_Separate_Suffix,
3303 In_Variables => Naming.Decl.Attributes,
3304 In_Tree => In_Tree);
3306 Separate_Suffix : File_Name_Type := No_File;
3307 Lang_Id : Language_Index;
3310 -- Check attribute Dot_Replacement
3312 if not Dot_Repl.Default then
3313 Get_Name_String (Dot_Repl.Value);
3315 if Name_Len = 0 then
3318 "Dot_Replacement cannot be empty",
3322 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3323 Dot_Replacement := Name_Find;
3325 if Current_Verbosity = High then
3326 Write_Str (" Dot_Replacement = """);
3327 Write_Str (Get_Name_String (Dot_Replacement));
3334 -- Check attribute Casing
3336 if not Casing_String.Default then
3338 Casing_Image : constant String :=
3339 Get_Name_String (Casing_String.Value);
3342 Casing_Value : constant Casing_Type :=
3343 Value (Casing_Image);
3345 Casing := Casing_Value;
3346 Casing_Defined := True;
3348 if Current_Verbosity = High then
3349 Write_Str (" Casing = ");
3350 Write_Str (Image (Casing));
3357 when Constraint_Error =>
3358 if Casing_Image'Length = 0 then
3361 "Casing cannot be an empty string",
3362 Casing_String.Location);
3365 Name_Len := Casing_Image'Length;
3366 Name_Buffer (1 .. Name_Len) := Casing_Image;
3367 Err_Vars.Error_Msg_Name_1 := Name_Find;
3370 "%% is not a correct Casing",
3371 Casing_String.Location);
3376 if not Sep_Suffix.Default then
3377 Get_Name_String (Sep_Suffix.Value);
3379 if Name_Len = 0 then
3382 "Separate_Suffix cannot be empty",
3383 Sep_Suffix.Location);
3386 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3387 Separate_Suffix := Name_Find;
3389 if Current_Verbosity = High then
3390 Write_Str (" Separate_Suffix = """);
3391 Write_Str (Get_Name_String (Separate_Suffix));
3398 -- For all unit based languages, if any, set the specified
3399 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3401 if Dot_Replacement /= No_File
3402 or else Casing_Defined
3403 or else Separate_Suffix /= No_File
3405 Lang_Id := Data.First_Language_Processing;
3406 while Lang_Id /= No_Language_Index loop
3407 if In_Tree.Languages_Data.Table
3408 (Lang_Id).Config.Kind = Unit_Based
3410 if Dot_Replacement /= No_File then
3411 In_Tree.Languages_Data.Table
3412 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3416 if Casing_Defined then
3417 In_Tree.Languages_Data.Table
3418 (Lang_Id).Config.Naming_Data.Casing := Casing;
3421 if Separate_Suffix /= No_File then
3422 In_Tree.Languages_Data.Table
3423 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3429 In_Tree.Languages_Data.Table (Lang_Id).Next;
3434 -- Next, get the spec and body suffixes
3437 Suffix : Variable_Value;
3438 Lang_Id : Language_Index;
3442 Lang_Id := Data.First_Language_Processing;
3443 while Lang_Id /= No_Language_Index loop
3444 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3450 Attribute_Or_Array_Name => Name_Spec_Suffix,
3451 In_Package => Naming_Id,
3452 In_Tree => In_Tree);
3454 if Suffix = Nil_Variable_Value then
3457 Attribute_Or_Array_Name => Name_Specification_Suffix,
3458 In_Package => Naming_Id,
3459 In_Tree => In_Tree);
3462 if Suffix /= Nil_Variable_Value then
3463 In_Tree.Languages_Data.Table (Lang_Id).
3464 Config.Naming_Data.Spec_Suffix :=
3465 File_Name_Type (Suffix.Value);
3472 Attribute_Or_Array_Name => Name_Body_Suffix,
3473 In_Package => Naming_Id,
3474 In_Tree => In_Tree);
3476 if Suffix = Nil_Variable_Value then
3479 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3480 In_Package => Naming_Id,
3481 In_Tree => In_Tree);
3484 if Suffix /= Nil_Variable_Value then
3485 In_Tree.Languages_Data.Table (Lang_Id).
3486 Config.Naming_Data.Body_Suffix :=
3487 File_Name_Type (Suffix.Value);
3490 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3494 -- Get the exceptions for file based languages
3496 Get_Exceptions (Spec);
3497 Get_Exceptions (Impl);
3499 -- Get the exceptions for unit based languages
3501 Get_Unit_Exceptions (Spec);
3502 Get_Unit_Exceptions (Impl);
3506 end Check_Naming_Schemes;
3508 ------------------------------
3509 -- Check_Library_Attributes --
3510 ------------------------------
3512 procedure Check_Library_Attributes
3513 (Project : Project_Id;
3514 In_Tree : Project_Tree_Ref;
3515 Current_Dir : String;
3516 Data : in out Project_Data)
3518 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3520 Lib_Dir : constant Prj.Variable_Value :=
3522 (Snames.Name_Library_Dir, Attributes, In_Tree);
3524 Lib_Name : constant Prj.Variable_Value :=
3526 (Snames.Name_Library_Name, Attributes, In_Tree);
3528 Lib_Version : constant Prj.Variable_Value :=
3530 (Snames.Name_Library_Version, Attributes, In_Tree);
3532 Lib_ALI_Dir : constant Prj.Variable_Value :=
3534 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3536 The_Lib_Kind : constant Prj.Variable_Value :=
3538 (Snames.Name_Library_Kind, Attributes, In_Tree);
3540 Imported_Project_List : Project_List := Empty_Project_List;
3542 Continuation : String_Access := No_Continuation_String'Access;
3544 Support_For_Libraries : Library_Support;
3546 Library_Directory_Present : Boolean;
3548 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3549 -- Check if an imported or extended project if also a library project
3555 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3556 Proj_Data : Project_Data;
3560 if Proj /= No_Project then
3561 Proj_Data := In_Tree.Projects.Table (Proj);
3563 if not Proj_Data.Library then
3565 -- The only not library projects that are OK are those that
3566 -- have no sources. However, header files from non-Ada
3567 -- languages are OK, as there is nothing to compile.
3569 Src_Id := Proj_Data.First_Source;
3570 while Src_Id /= No_Source loop
3572 Src : Source_Data renames In_Tree.Sources.Table (Src_Id);
3574 exit when Src.Lang_Kind /= File_Based
3575 or else Src.Kind /= Spec;
3576 Src_Id := Src.Next_In_Project;
3580 if Src_Id /= No_Source then
3581 Error_Msg_Name_1 := Data.Name;
3582 Error_Msg_Name_2 := Proj_Data.Name;
3585 if Data.Library_Kind /= Static then
3589 "shared library project %% cannot extend " &
3590 "project %% that is not a library project",
3592 Continuation := Continuation_String'Access;
3595 elsif Data.Library_Kind /= Static then
3599 "shared library project %% cannot import project %% " &
3600 "that is not a shared library project",
3602 Continuation := Continuation_String'Access;
3606 elsif Data.Library_Kind /= Static and then
3607 Proj_Data.Library_Kind = Static
3609 Error_Msg_Name_1 := Data.Name;
3610 Error_Msg_Name_2 := Proj_Data.Name;
3616 "shared library project %% cannot extend static " &
3617 "library project %%",
3624 "shared library project %% cannot import static " &
3625 "library project %%",
3629 Continuation := Continuation_String'Access;
3634 -- Start of processing for Check_Library_Attributes
3637 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3639 -- Special case of extending project
3641 if Data.Extends /= No_Project then
3643 Extended_Data : constant Project_Data :=
3644 In_Tree.Projects.Table (Data.Extends);
3647 -- If the project extended is a library project, we inherit the
3648 -- library name, if it is not redefined; we check that the library
3649 -- directory is specified.
3651 if Extended_Data.Library then
3652 if Data.Qualifier = Standard then
3655 "a standard project cannot extend a library project",
3659 if Lib_Name.Default then
3660 Data.Library_Name := Extended_Data.Library_Name;
3663 if Lib_Dir.Default then
3664 if not Data.Virtual then
3667 "a project extending a library project must " &
3668 "specify an attribute Library_Dir",
3672 -- For a virtual project extending a library project,
3673 -- inherit library directory.
3675 Data.Library_Dir := Extended_Data.Library_Dir;
3676 Library_Directory_Present := True;
3684 pragma Assert (Lib_Name.Kind = Single);
3686 if Lib_Name.Value = Empty_String then
3687 if Current_Verbosity = High
3688 and then Data.Library_Name = No_Name
3690 Write_Line ("No library name");
3694 -- There is no restriction on the syntax of library names
3696 Data.Library_Name := Lib_Name.Value;
3699 if Data.Library_Name /= No_Name then
3700 if Current_Verbosity = High then
3701 Write_Str ("Library name = """);
3702 Write_Str (Get_Name_String (Data.Library_Name));
3706 pragma Assert (Lib_Dir.Kind = Single);
3708 if not Library_Directory_Present then
3709 if Current_Verbosity = High then
3710 Write_Line ("No library directory");
3714 -- Find path name (unless inherited), check that it is a directory
3716 if Data.Library_Dir = No_Path_Information then
3720 File_Name_Type (Lib_Dir.Value),
3721 Data.Directory.Display_Name,
3722 Data.Library_Dir.Name,
3723 Data.Library_Dir.Display_Name,
3724 Create => "library",
3725 Current_Dir => Current_Dir,
3726 Location => Lib_Dir.Location);
3729 if Data.Library_Dir = No_Path_Information then
3731 -- Get the absolute name of the library directory that
3732 -- does not exist, to report an error.
3735 Dir_Name : constant String :=
3736 Get_Name_String (Lib_Dir.Value);
3739 if Is_Absolute_Path (Dir_Name) then
3740 Err_Vars.Error_Msg_File_1 :=
3741 File_Name_Type (Lib_Dir.Value);
3744 Get_Name_String (Data.Directory.Display_Name);
3746 if Name_Buffer (Name_Len) /= Directory_Separator then
3747 Name_Len := Name_Len + 1;
3748 Name_Buffer (Name_Len) := Directory_Separator;
3752 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3754 Name_Len := Name_Len + Dir_Name'Length;
3755 Err_Vars.Error_Msg_File_1 := Name_Find;
3762 "library directory { does not exist",
3766 -- The library directory cannot be the same as the Object
3769 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3772 "library directory cannot be the same " &
3773 "as object directory",
3775 Data.Library_Dir := No_Path_Information;
3779 OK : Boolean := True;
3780 Dirs_Id : String_List_Id;
3781 Dir_Elem : String_Element;
3784 -- The library directory cannot be the same as a source
3785 -- directory of the current project.
3787 Dirs_Id := Data.Source_Dirs;
3788 while Dirs_Id /= Nil_String loop
3789 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3790 Dirs_Id := Dir_Elem.Next;
3793 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3795 Err_Vars.Error_Msg_File_1 :=
3796 File_Name_Type (Dir_Elem.Value);
3799 "library directory cannot be the same " &
3800 "as source directory {",
3809 -- The library directory cannot be the same as a source
3810 -- directory of another project either.
3813 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3814 if Pid /= Project then
3815 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3817 Dir_Loop : while Dirs_Id /= Nil_String loop
3819 In_Tree.String_Elements.Table (Dirs_Id);
3820 Dirs_Id := Dir_Elem.Next;
3822 if Data.Library_Dir.Name =
3823 Path_Name_Type (Dir_Elem.Value)
3825 Err_Vars.Error_Msg_File_1 :=
3826 File_Name_Type (Dir_Elem.Value);
3827 Err_Vars.Error_Msg_Name_1 :=
3828 In_Tree.Projects.Table (Pid).Name;
3832 "library directory cannot be the same " &
3833 "as source directory { of project %%",
3840 end loop Project_Loop;
3844 Data.Library_Dir := No_Path_Information;
3846 elsif Current_Verbosity = High then
3848 -- Display the Library directory in high verbosity
3850 Write_Str ("Library directory =""");
3852 (Get_Name_String (Data.Library_Dir.Display_Name));
3862 Data.Library_Dir /= No_Path_Information
3864 Data.Library_Name /= No_Name;
3866 if Data.Extends = No_Project then
3867 case Data.Qualifier is
3869 if Data.Library then
3872 "a standard project cannot be a library project",
3877 if not Data.Library then
3878 if Data.Library_Dir = No_Path_Information then
3881 "\attribute Library_Dir not declared",
3885 if Data.Library_Name = No_Name then
3888 "\attribute Library_Name not declared",
3899 if Data.Library then
3900 if Get_Mode = Multi_Language then
3901 Support_For_Libraries := Data.Config.Lib_Support;
3904 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3907 if Support_For_Libraries = Prj.None then
3910 "?libraries are not supported on this platform",
3912 Data.Library := False;
3915 if Lib_ALI_Dir.Value = Empty_String then
3916 if Current_Verbosity = High then
3917 Write_Line ("No library ALI directory specified");
3919 Data.Library_ALI_Dir := Data.Library_Dir;
3922 -- Find path name, check that it is a directory
3927 File_Name_Type (Lib_ALI_Dir.Value),
3928 Data.Directory.Display_Name,
3929 Data.Library_ALI_Dir.Name,
3930 Data.Library_ALI_Dir.Display_Name,
3931 Create => "library ALI",
3932 Current_Dir => Current_Dir,
3933 Location => Lib_ALI_Dir.Location);
3935 if Data.Library_ALI_Dir = No_Path_Information then
3937 -- Get the absolute name of the library ALI directory that
3938 -- does not exist, to report an error.
3941 Dir_Name : constant String :=
3942 Get_Name_String (Lib_ALI_Dir.Value);
3945 if Is_Absolute_Path (Dir_Name) then
3946 Err_Vars.Error_Msg_File_1 :=
3947 File_Name_Type (Lib_Dir.Value);
3950 Get_Name_String (Data.Directory.Display_Name);
3952 if Name_Buffer (Name_Len) /= Directory_Separator then
3953 Name_Len := Name_Len + 1;
3954 Name_Buffer (Name_Len) := Directory_Separator;
3958 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3960 Name_Len := Name_Len + Dir_Name'Length;
3961 Err_Vars.Error_Msg_File_1 := Name_Find;
3968 "library 'A'L'I directory { does not exist",
3969 Lib_ALI_Dir.Location);
3973 if Data.Library_ALI_Dir /= Data.Library_Dir then
3975 -- The library ALI directory cannot be the same as the
3976 -- Object directory.
3978 if Data.Library_ALI_Dir = Data.Object_Directory then
3981 "library 'A'L'I directory cannot be the same " &
3982 "as object directory",
3983 Lib_ALI_Dir.Location);
3984 Data.Library_ALI_Dir := No_Path_Information;
3988 OK : Boolean := True;
3989 Dirs_Id : String_List_Id;
3990 Dir_Elem : String_Element;
3993 -- The library ALI directory cannot be the same as
3994 -- a source directory of the current project.
3996 Dirs_Id := Data.Source_Dirs;
3997 while Dirs_Id /= Nil_String loop
3998 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3999 Dirs_Id := Dir_Elem.Next;
4001 if Data.Library_ALI_Dir.Name =
4002 Path_Name_Type (Dir_Elem.Value)
4004 Err_Vars.Error_Msg_File_1 :=
4005 File_Name_Type (Dir_Elem.Value);
4008 "library 'A'L'I directory cannot be " &
4009 "the same as source directory {",
4010 Lib_ALI_Dir.Location);
4018 -- The library ALI directory cannot be the same as
4019 -- a source directory of another project either.
4023 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4025 if Pid /= Project then
4027 In_Tree.Projects.Table (Pid).Source_Dirs;
4030 while Dirs_Id /= Nil_String loop
4032 In_Tree.String_Elements.Table (Dirs_Id);
4033 Dirs_Id := Dir_Elem.Next;
4035 if Data.Library_ALI_Dir.Name =
4036 Path_Name_Type (Dir_Elem.Value)
4038 Err_Vars.Error_Msg_File_1 :=
4039 File_Name_Type (Dir_Elem.Value);
4040 Err_Vars.Error_Msg_Name_1 :=
4041 In_Tree.Projects.Table (Pid).Name;
4045 "library 'A'L'I directory cannot " &
4046 "be the same as source directory " &
4048 Lib_ALI_Dir.Location);
4050 exit ALI_Project_Loop;
4052 end loop ALI_Dir_Loop;
4054 end loop ALI_Project_Loop;
4058 Data.Library_ALI_Dir := No_Path_Information;
4060 elsif Current_Verbosity = High then
4062 -- Display the Library ALI directory in high
4065 Write_Str ("Library ALI directory =""");
4068 (Data.Library_ALI_Dir.Display_Name));
4076 pragma Assert (Lib_Version.Kind = Single);
4078 if Lib_Version.Value = Empty_String then
4079 if Current_Verbosity = High then
4080 Write_Line ("No library version specified");
4084 Data.Lib_Internal_Name := Lib_Version.Value;
4087 pragma Assert (The_Lib_Kind.Kind = Single);
4089 if The_Lib_Kind.Value = Empty_String then
4090 if Current_Verbosity = High then
4091 Write_Line ("No library kind specified");
4095 Get_Name_String (The_Lib_Kind.Value);
4098 Kind_Name : constant String :=
4099 To_Lower (Name_Buffer (1 .. Name_Len));
4101 OK : Boolean := True;
4104 if Kind_Name = "static" then
4105 Data.Library_Kind := Static;
4107 elsif Kind_Name = "dynamic" then
4108 Data.Library_Kind := Dynamic;
4110 elsif Kind_Name = "relocatable" then
4111 Data.Library_Kind := Relocatable;
4116 "illegal value for Library_Kind",
4117 The_Lib_Kind.Location);
4121 if Current_Verbosity = High and then OK then
4122 Write_Str ("Library kind = ");
4123 Write_Line (Kind_Name);
4126 if Data.Library_Kind /= Static and then
4127 Support_For_Libraries = Prj.Static_Only
4131 "only static libraries are supported " &
4133 The_Lib_Kind.Location);
4134 Data.Library := False;
4139 if Data.Library then
4140 if Current_Verbosity = High then
4141 Write_Line ("This is a library project file");
4144 if Get_Mode = Multi_Language then
4145 Check_Library (Data.Extends, Extends => True);
4147 Imported_Project_List := Data.Imported_Projects;
4148 while Imported_Project_List /= Empty_Project_List loop
4150 (In_Tree.Project_Lists.Table
4151 (Imported_Project_List).Project,
4153 Imported_Project_List :=
4154 In_Tree.Project_Lists.Table
4155 (Imported_Project_List).Next;
4163 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4164 -- Warn if they are declared, as it is a common error to think that
4165 -- library are "linked" with Linker switches.
4167 if Data.Library then
4169 Linker_Package_Id : constant Package_Id :=
4171 (Name_Linker, Data.Decl.Packages, In_Tree);
4172 Linker_Package : Package_Element;
4173 Switches : Array_Element_Id := No_Array_Element;
4176 if Linker_Package_Id /= No_Package then
4177 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4181 (Name => Name_Switches,
4182 In_Arrays => Linker_Package.Decl.Arrays,
4183 In_Tree => In_Tree);
4185 if Switches = No_Array_Element then
4188 (Name => Name_Default_Switches,
4189 In_Arrays => Linker_Package.Decl.Arrays,
4190 In_Tree => In_Tree);
4193 if Switches /= No_Array_Element then
4196 "?Linker switches not taken into account in library " &
4204 if Data.Extends /= No_Project then
4205 In_Tree.Projects.Table (Data.Extends).Library := False;
4207 end Check_Library_Attributes;
4209 --------------------------
4210 -- Check_Package_Naming --
4211 --------------------------
4213 procedure Check_Package_Naming
4214 (Project : Project_Id;
4215 In_Tree : Project_Tree_Ref;
4216 Data : in out Project_Data)
4218 Naming_Id : constant Package_Id :=
4219 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4221 Naming : Package_Element;
4224 -- If there is a package Naming, we will put in Data.Naming
4225 -- what is in this package Naming.
4227 if Naming_Id /= No_Package then
4228 Naming := In_Tree.Packages.Table (Naming_Id);
4230 if Current_Verbosity = High then
4231 Write_Line ("Checking ""Naming"".");
4234 -- Check Spec_Suffix
4237 Spec_Suffixs : Array_Element_Id :=
4243 Suffix : Array_Element_Id;
4244 Element : Array_Element;
4245 Suffix2 : Array_Element_Id;
4248 -- If some suffixes have been specified, we make sure that
4249 -- for each language for which a default suffix has been
4250 -- specified, there is a suffix specified, either the one
4251 -- in the project file or if there were none, the default.
4253 if Spec_Suffixs /= No_Array_Element then
4254 Suffix := Data.Naming.Spec_Suffix;
4256 while Suffix /= No_Array_Element loop
4258 In_Tree.Array_Elements.Table (Suffix);
4259 Suffix2 := Spec_Suffixs;
4261 while Suffix2 /= No_Array_Element loop
4262 exit when In_Tree.Array_Elements.Table
4263 (Suffix2).Index = Element.Index;
4264 Suffix2 := In_Tree.Array_Elements.Table
4268 -- There is a registered default suffix, but no
4269 -- suffix specified in the project file.
4270 -- Add the default to the array.
4272 if Suffix2 = No_Array_Element then
4273 Array_Element_Table.Increment_Last
4274 (In_Tree.Array_Elements);
4275 In_Tree.Array_Elements.Table
4276 (Array_Element_Table.Last
4277 (In_Tree.Array_Elements)) :=
4278 (Index => Element.Index,
4279 Src_Index => Element.Src_Index,
4280 Index_Case_Sensitive => False,
4281 Value => Element.Value,
4282 Next => Spec_Suffixs);
4283 Spec_Suffixs := Array_Element_Table.Last
4284 (In_Tree.Array_Elements);
4287 Suffix := Element.Next;
4290 -- Put the resulting array as the specification suffixes
4292 Data.Naming.Spec_Suffix := Spec_Suffixs;
4297 Current : Array_Element_Id;
4298 Element : Array_Element;
4301 Current := Data.Naming.Spec_Suffix;
4302 while Current /= No_Array_Element loop
4303 Element := In_Tree.Array_Elements.Table (Current);
4304 Get_Name_String (Element.Value.Value);
4306 if Name_Len = 0 then
4309 "Spec_Suffix cannot be empty",
4310 Element.Value.Location);
4313 In_Tree.Array_Elements.Table (Current) := Element;
4314 Current := Element.Next;
4318 -- Check Body_Suffix
4321 Impl_Suffixs : Array_Element_Id :=
4327 Suffix : Array_Element_Id;
4328 Element : Array_Element;
4329 Suffix2 : Array_Element_Id;
4332 -- If some suffixes have been specified, we make sure that
4333 -- for each language for which a default suffix has been
4334 -- specified, there is a suffix specified, either the one
4335 -- in the project file or if there were none, the default.
4337 if Impl_Suffixs /= No_Array_Element then
4338 Suffix := Data.Naming.Body_Suffix;
4339 while Suffix /= No_Array_Element loop
4341 In_Tree.Array_Elements.Table (Suffix);
4343 Suffix2 := Impl_Suffixs;
4344 while Suffix2 /= No_Array_Element loop
4345 exit when In_Tree.Array_Elements.Table
4346 (Suffix2).Index = Element.Index;
4347 Suffix2 := In_Tree.Array_Elements.Table
4351 -- There is a registered default suffix, but no suffix was
4352 -- specified in the project file. Add default to the array.
4354 if Suffix2 = No_Array_Element then
4355 Array_Element_Table.Increment_Last
4356 (In_Tree.Array_Elements);
4357 In_Tree.Array_Elements.Table
4358 (Array_Element_Table.Last
4359 (In_Tree.Array_Elements)) :=
4360 (Index => Element.Index,
4361 Src_Index => Element.Src_Index,
4362 Index_Case_Sensitive => False,
4363 Value => Element.Value,
4364 Next => Impl_Suffixs);
4365 Impl_Suffixs := Array_Element_Table.Last
4366 (In_Tree.Array_Elements);
4369 Suffix := Element.Next;
4372 -- Put the resulting array as the implementation suffixes
4374 Data.Naming.Body_Suffix := Impl_Suffixs;
4379 Current : Array_Element_Id;
4380 Element : Array_Element;
4383 Current := Data.Naming.Body_Suffix;
4384 while Current /= No_Array_Element loop
4385 Element := In_Tree.Array_Elements.Table (Current);
4386 Get_Name_String (Element.Value.Value);
4388 if Name_Len = 0 then
4391 "Body_Suffix cannot be empty",
4392 Element.Value.Location);
4395 In_Tree.Array_Elements.Table (Current) := Element;
4396 Current := Element.Next;
4400 -- Get the exceptions, if any
4402 Data.Naming.Specification_Exceptions :=
4404 (Name_Specification_Exceptions,
4405 In_Arrays => Naming.Decl.Arrays,
4406 In_Tree => In_Tree);
4408 Data.Naming.Implementation_Exceptions :=
4410 (Name_Implementation_Exceptions,
4411 In_Arrays => Naming.Decl.Arrays,
4412 In_Tree => In_Tree);
4414 end Check_Package_Naming;
4416 ---------------------------------
4417 -- Check_Programming_Languages --
4418 ---------------------------------
4420 procedure Check_Programming_Languages
4421 (In_Tree : Project_Tree_Ref;
4422 Project : Project_Id;
4423 Data : in out Project_Data)
4425 Languages : Variable_Value := Nil_Variable_Value;
4426 Def_Lang : Variable_Value := Nil_Variable_Value;
4427 Def_Lang_Id : Name_Id;
4430 Data.First_Language_Processing := No_Language_Index;
4432 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4435 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4436 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4437 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4439 if Data.Source_Dirs /= Nil_String then
4441 -- Check if languages are specified in this project
4443 if Languages.Default then
4445 -- Attribute Languages is not specified. So, it defaults to
4446 -- a project of the default language only.
4448 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4449 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4451 -- In Ada_Only mode, the default language is Ada
4453 if Get_Mode = Ada_Only then
4454 In_Tree.Name_Lists.Table (Data.Languages) :=
4455 (Name => Name_Ada, Next => No_Name_List);
4457 -- Attribute Languages is not specified. So, it defaults to
4458 -- a project of language Ada only. No sources of languages
4461 Data.Other_Sources_Present := False;
4464 -- Fail if there is no default language defined
4466 if Def_Lang.Default then
4467 if not Default_Language_Is_Ada then
4471 "no languages defined for this project",
4473 Def_Lang_Id := No_Name;
4475 Def_Lang_Id := Name_Ada;
4479 Get_Name_String (Def_Lang.Value);
4480 To_Lower (Name_Buffer (1 .. Name_Len));
4481 Def_Lang_Id := Name_Find;
4484 if Def_Lang_Id /= No_Name then
4485 In_Tree.Name_Lists.Table (Data.Languages) :=
4486 (Name => Def_Lang_Id, Next => No_Name_List);
4488 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4490 Data.First_Language_Processing :=
4491 Language_Data_Table.Last (In_Tree.Languages_Data);
4492 In_Tree.Languages_Data.Table
4493 (Data.First_Language_Processing) := No_Language_Data;
4494 In_Tree.Languages_Data.Table
4495 (Data.First_Language_Processing).Name := Def_Lang_Id;
4496 Get_Name_String (Def_Lang_Id);
4497 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4498 In_Tree.Languages_Data.Table
4499 (Data.First_Language_Processing).Display_Name := Name_Find;
4501 if Def_Lang_Id = Name_Ada then
4502 In_Tree.Languages_Data.Table
4503 (Data.First_Language_Processing).Config.Kind
4505 In_Tree.Languages_Data.Table
4506 (Data.First_Language_Processing).Config.Dependency_Kind
4508 Data.Unit_Based_Language_Name := Name_Ada;
4509 Data.Unit_Based_Language_Index :=
4510 Data.First_Language_Processing;
4512 In_Tree.Languages_Data.Table
4513 (Data.First_Language_Processing).Config.Kind
4521 Current : String_List_Id := Languages.Values;
4522 Element : String_Element;
4523 Lang_Name : Name_Id;
4524 Index : Language_Index;
4525 Lang_Data : Language_Data;
4526 NL_Id : Name_List_Index := No_Name_List;
4529 -- Assume there are no language declared
4531 Data.Ada_Sources_Present := False;
4532 Data.Other_Sources_Present := False;
4534 -- If there are no languages declared, there are no sources
4536 if Current = Nil_String then
4537 Data.Source_Dirs := Nil_String;
4539 if Data.Qualifier = Standard then
4543 "a standard project cannot have no language declared",
4544 Languages.Location);
4548 -- Look through all the languages specified in attribute
4551 while Current /= Nil_String loop
4553 In_Tree.String_Elements.Table (Current);
4554 Get_Name_String (Element.Value);
4555 To_Lower (Name_Buffer (1 .. Name_Len));
4556 Lang_Name := Name_Find;
4558 NL_Id := Data.Languages;
4559 while NL_Id /= No_Name_List loop
4561 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4562 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4565 if NL_Id = No_Name_List then
4566 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4568 if Data.Languages = No_Name_List then
4570 Name_List_Table.Last (In_Tree.Name_Lists);
4573 NL_Id := Data.Languages;
4574 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4577 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4580 In_Tree.Name_Lists.Table (NL_Id).Next :=
4581 Name_List_Table.Last (In_Tree.Name_Lists);
4584 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4585 In_Tree.Name_Lists.Table (NL_Id) :=
4586 (Lang_Name, No_Name_List);
4588 if Get_Mode = Ada_Only then
4589 -- Check for language Ada
4591 if Lang_Name = Name_Ada then
4592 Data.Ada_Sources_Present := True;
4595 Data.Other_Sources_Present := True;
4599 Language_Data_Table.Increment_Last
4600 (In_Tree.Languages_Data);
4602 Language_Data_Table.Last (In_Tree.Languages_Data);
4603 Lang_Data.Name := Lang_Name;
4604 Lang_Data.Display_Name := Element.Value;
4605 Lang_Data.Next := Data.First_Language_Processing;
4607 if Lang_Name = Name_Ada then
4608 Lang_Data.Config.Kind := Unit_Based;
4609 Lang_Data.Config.Dependency_Kind := ALI_File;
4610 Data.Unit_Based_Language_Name := Name_Ada;
4611 Data.Unit_Based_Language_Index := Index;
4614 Lang_Data.Config.Kind := File_Based;
4615 Lang_Data.Config.Dependency_Kind := None;
4618 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4619 Data.First_Language_Processing := Index;
4623 Current := Element.Next;
4629 end Check_Programming_Languages;
4635 function Check_Project
4637 Root_Project : Project_Id;
4638 In_Tree : Project_Tree_Ref;
4639 Extending : Boolean) return Boolean
4642 if P = Root_Project then
4645 elsif Extending then
4647 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4650 while Data.Extends /= No_Project loop
4651 if P = Data.Extends then
4655 Data := In_Tree.Projects.Table (Data.Extends);
4663 -------------------------------
4664 -- Check_Stand_Alone_Library --
4665 -------------------------------
4667 procedure Check_Stand_Alone_Library
4668 (Project : Project_Id;
4669 In_Tree : Project_Tree_Ref;
4670 Data : in out Project_Data;
4671 Current_Dir : String;
4672 Extending : Boolean)
4674 Lib_Interfaces : constant Prj.Variable_Value :=
4676 (Snames.Name_Library_Interface,
4677 Data.Decl.Attributes,
4680 Lib_Auto_Init : constant Prj.Variable_Value :=
4682 (Snames.Name_Library_Auto_Init,
4683 Data.Decl.Attributes,
4686 Lib_Src_Dir : constant Prj.Variable_Value :=
4688 (Snames.Name_Library_Src_Dir,
4689 Data.Decl.Attributes,
4692 Lib_Symbol_File : constant Prj.Variable_Value :=
4694 (Snames.Name_Library_Symbol_File,
4695 Data.Decl.Attributes,
4698 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4700 (Snames.Name_Library_Symbol_Policy,
4701 Data.Decl.Attributes,
4704 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4706 (Snames.Name_Library_Reference_Symbol_File,
4707 Data.Decl.Attributes,
4710 Auto_Init_Supported : Boolean;
4711 OK : Boolean := True;
4713 Next_Proj : Project_Id;
4716 if Get_Mode = Multi_Language then
4717 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4719 Auto_Init_Supported :=
4720 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4723 pragma Assert (Lib_Interfaces.Kind = List);
4725 -- It is a stand-alone library project file if attribute
4726 -- Library_Interface is defined.
4728 if not Lib_Interfaces.Default then
4729 SAL_Library : declare
4730 Interfaces : String_List_Id := Lib_Interfaces.Values;
4731 Interface_ALIs : String_List_Id := Nil_String;
4733 The_Unit_Id : Unit_Index;
4734 The_Unit_Data : Unit_Data;
4736 procedure Add_ALI_For (Source : File_Name_Type);
4737 -- Add an ALI file name to the list of Interface ALIs
4743 procedure Add_ALI_For (Source : File_Name_Type) is
4745 Get_Name_String (Source);
4748 ALI : constant String :=
4749 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4750 ALI_Name_Id : Name_Id;
4753 Name_Len := ALI'Length;
4754 Name_Buffer (1 .. Name_Len) := ALI;
4755 ALI_Name_Id := Name_Find;
4757 String_Element_Table.Increment_Last
4758 (In_Tree.String_Elements);
4759 In_Tree.String_Elements.Table
4760 (String_Element_Table.Last
4761 (In_Tree.String_Elements)) :=
4762 (Value => ALI_Name_Id,
4764 Display_Value => ALI_Name_Id,
4766 In_Tree.String_Elements.Table
4767 (Interfaces).Location,
4769 Next => Interface_ALIs);
4770 Interface_ALIs := String_Element_Table.Last
4771 (In_Tree.String_Elements);
4775 -- Start of processing for SAL_Library
4778 Data.Standalone_Library := True;
4780 -- Library_Interface cannot be an empty list
4782 if Interfaces = Nil_String then
4785 "Library_Interface cannot be an empty list",
4786 Lib_Interfaces.Location);
4789 -- Process each unit name specified in the attribute
4790 -- Library_Interface.
4792 while Interfaces /= Nil_String loop
4794 (In_Tree.String_Elements.Table (Interfaces).Value);
4795 To_Lower (Name_Buffer (1 .. Name_Len));
4797 if Name_Len = 0 then
4800 "an interface cannot be an empty string",
4801 In_Tree.String_Elements.Table (Interfaces).Location);
4805 Error_Msg_Name_1 := Unit;
4807 if Get_Mode = Ada_Only then
4809 Units_Htable.Get (In_Tree.Units_HT, Unit);
4811 if The_Unit_Id = No_Unit_Index then
4815 In_Tree.String_Elements.Table
4816 (Interfaces).Location);
4819 -- Check that the unit is part of the project
4822 In_Tree.Units.Table (The_Unit_Id);
4824 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4825 and then The_Unit_Data.File_Names
4826 (Body_Part).Path.Name /= Slash
4829 (The_Unit_Data.File_Names (Body_Part).Project,
4830 Project, In_Tree, Extending)
4832 -- There is a body for this unit.
4833 -- If there is no spec, we need to check
4834 -- that it is not a subunit.
4836 if The_Unit_Data.File_Names
4837 (Specification).Name = No_File
4840 Src_Ind : Source_File_Index;
4843 Src_Ind := Sinput.P.Load_Project_File
4845 (The_Unit_Data.File_Names
4846 (Body_Part).Path.Name));
4848 if Sinput.P.Source_File_Is_Subunit
4853 "%% is a subunit; " &
4854 "it cannot be an interface",
4856 String_Elements.Table
4857 (Interfaces).Location);
4862 -- The unit is not a subunit, so we add
4863 -- to the Interface ALIs the ALI file
4864 -- corresponding to the body.
4867 (The_Unit_Data.File_Names (Body_Part).Name);
4872 "%% is not an unit of this project",
4873 In_Tree.String_Elements.Table
4874 (Interfaces).Location);
4877 elsif The_Unit_Data.File_Names
4878 (Specification).Name /= No_File
4879 and then The_Unit_Data.File_Names
4880 (Specification).Path.Name /= Slash
4881 and then Check_Project
4882 (The_Unit_Data.File_Names
4883 (Specification).Project,
4884 Project, In_Tree, Extending)
4887 -- The unit is part of the project, it has
4888 -- a spec, but no body. We add to the Interface
4889 -- ALIs the ALI file corresponding to the spec.
4892 (The_Unit_Data.File_Names (Specification).Name);
4897 "%% is not an unit of this project",
4898 In_Tree.String_Elements.Table
4899 (Interfaces).Location);
4904 -- Multi_Language mode
4906 Next_Proj := Data.Extends;
4907 Source := Data.First_Source;
4910 while Source /= No_Source and then
4911 In_Tree.Sources.Table (Source).Unit /= Unit
4914 In_Tree.Sources.Table (Source).Next_In_Project;
4917 exit when Source /= No_Source or else
4918 Next_Proj = No_Project;
4921 In_Tree.Projects.Table (Next_Proj).First_Source;
4923 In_Tree.Projects.Table (Next_Proj).Extends;
4926 if Source /= No_Source then
4927 if In_Tree.Sources.Table (Source).Kind = Sep then
4928 Source := No_Source;
4930 elsif In_Tree.Sources.Table (Source).Kind = Spec
4932 In_Tree.Sources.Table (Source).Other_Part /=
4935 Source := In_Tree.Sources.Table (Source).Other_Part;
4939 if Source /= No_Source then
4940 if In_Tree.Sources.Table (Source).Project /= Project
4944 In_Tree.Sources.Table (Source).Project,
4947 Source := No_Source;
4951 if Source = No_Source then
4954 "%% is not an unit of this project",
4955 In_Tree.String_Elements.Table
4956 (Interfaces).Location);
4959 if In_Tree.Sources.Table (Source).Kind = Spec and then
4960 In_Tree.Sources.Table (Source).Other_Part /=
4963 Source := In_Tree.Sources.Table (Source).Other_Part;
4966 String_Element_Table.Increment_Last
4967 (In_Tree.String_Elements);
4968 In_Tree.String_Elements.Table
4969 (String_Element_Table.Last
4970 (In_Tree.String_Elements)) :=
4972 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4975 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4977 In_Tree.String_Elements.Table
4978 (Interfaces).Location,
4980 Next => Interface_ALIs);
4981 Interface_ALIs := String_Element_Table.Last
4982 (In_Tree.String_Elements);
4990 In_Tree.String_Elements.Table (Interfaces).Next;
4993 -- Put the list of Interface ALIs in the project data
4995 Data.Lib_Interface_ALIs := Interface_ALIs;
4997 -- Check value of attribute Library_Auto_Init and set
4998 -- Lib_Auto_Init accordingly.
5000 if Lib_Auto_Init.Default then
5002 -- If no attribute Library_Auto_Init is declared, then set auto
5003 -- init only if it is supported.
5005 Data.Lib_Auto_Init := Auto_Init_Supported;
5008 Get_Name_String (Lib_Auto_Init.Value);
5009 To_Lower (Name_Buffer (1 .. Name_Len));
5011 if Name_Buffer (1 .. Name_Len) = "false" then
5012 Data.Lib_Auto_Init := False;
5014 elsif Name_Buffer (1 .. Name_Len) = "true" then
5015 if Auto_Init_Supported then
5016 Data.Lib_Auto_Init := True;
5019 -- Library_Auto_Init cannot be "true" if auto init is not
5024 "library auto init not supported " &
5026 Lib_Auto_Init.Location);
5032 "invalid value for attribute Library_Auto_Init",
5033 Lib_Auto_Init.Location);
5038 -- If attribute Library_Src_Dir is defined and not the empty string,
5039 -- check if the directory exist and is not the object directory or
5040 -- one of the source directories. This is the directory where copies
5041 -- of the interface sources will be copied. Note that this directory
5042 -- may be the library directory.
5044 if Lib_Src_Dir.Value /= Empty_String then
5046 Dir_Id : constant File_Name_Type :=
5047 File_Name_Type (Lib_Src_Dir.Value);
5054 Data.Directory.Display_Name,
5055 Data.Library_Src_Dir.Name,
5056 Data.Library_Src_Dir.Display_Name,
5057 Create => "library source copy",
5058 Current_Dir => Current_Dir,
5059 Location => Lib_Src_Dir.Location);
5061 -- If directory does not exist, report an error
5063 if Data.Library_Src_Dir = No_Path_Information then
5065 -- Get the absolute name of the library directory that does
5066 -- not exist, to report an error.
5069 Dir_Name : constant String :=
5070 Get_Name_String (Dir_Id);
5073 if Is_Absolute_Path (Dir_Name) then
5074 Err_Vars.Error_Msg_File_1 := Dir_Id;
5077 Get_Name_String (Data.Directory.Name);
5079 if Name_Buffer (Name_Len) /=
5082 Name_Len := Name_Len + 1;
5083 Name_Buffer (Name_Len) :=
5084 Directory_Separator;
5089 Name_Len + Dir_Name'Length) :=
5091 Name_Len := Name_Len + Dir_Name'Length;
5092 Err_Vars.Error_Msg_Name_1 := Name_Find;
5097 Error_Msg_File_1 := Dir_Id;
5100 "Directory { does not exist",
5101 Lib_Src_Dir.Location);
5104 -- Report error if it is the same as the object directory
5106 elsif Data.Library_Src_Dir = Data.Object_Directory then
5109 "directory to copy interfaces cannot be " &
5110 "the object directory",
5111 Lib_Src_Dir.Location);
5112 Data.Library_Src_Dir := No_Path_Information;
5116 Src_Dirs : String_List_Id;
5117 Src_Dir : String_Element;
5120 -- Interface copy directory cannot be one of the source
5121 -- directory of the current project.
5123 Src_Dirs := Data.Source_Dirs;
5124 while Src_Dirs /= Nil_String loop
5125 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5127 -- Report error if it is one of the source directories
5129 if Data.Library_Src_Dir.Name =
5130 Path_Name_Type (Src_Dir.Value)
5134 "directory to copy interfaces cannot " &
5135 "be one of the source directories",
5136 Lib_Src_Dir.Location);
5137 Data.Library_Src_Dir := No_Path_Information;
5141 Src_Dirs := Src_Dir.Next;
5144 if Data.Library_Src_Dir /= No_Path_Information then
5146 -- It cannot be a source directory of any other
5149 Project_Loop : for Pid in 1 ..
5150 Project_Table.Last (In_Tree.Projects)
5153 In_Tree.Projects.Table (Pid).Source_Dirs;
5154 Dir_Loop : while Src_Dirs /= Nil_String loop
5156 In_Tree.String_Elements.Table (Src_Dirs);
5158 -- Report error if it is one of the source
5161 if Data.Library_Src_Dir.Name =
5162 Path_Name_Type (Src_Dir.Value)
5165 File_Name_Type (Src_Dir.Value);
5167 In_Tree.Projects.Table (Pid).Name;
5170 "directory to copy interfaces cannot " &
5171 "be the same as source directory { of " &
5173 Lib_Src_Dir.Location);
5174 Data.Library_Src_Dir := No_Path_Information;
5178 Src_Dirs := Src_Dir.Next;
5180 end loop Project_Loop;
5184 -- In high verbosity, if there is a valid Library_Src_Dir,
5185 -- display its path name.
5187 if Data.Library_Src_Dir /= No_Path_Information
5188 and then Current_Verbosity = High
5190 Write_Str ("Directory to copy interfaces =""");
5191 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5198 -- Check the symbol related attributes
5200 -- First, the symbol policy
5202 if not Lib_Symbol_Policy.Default then
5204 Value : constant String :=
5206 (Get_Name_String (Lib_Symbol_Policy.Value));
5209 -- Symbol policy must hove one of a limited number of values
5211 if Value = "autonomous" or else Value = "default" then
5212 Data.Symbol_Data.Symbol_Policy := Autonomous;
5214 elsif Value = "compliant" then
5215 Data.Symbol_Data.Symbol_Policy := Compliant;
5217 elsif Value = "controlled" then
5218 Data.Symbol_Data.Symbol_Policy := Controlled;
5220 elsif Value = "restricted" then
5221 Data.Symbol_Data.Symbol_Policy := Restricted;
5223 elsif Value = "direct" then
5224 Data.Symbol_Data.Symbol_Policy := Direct;
5229 "illegal value for Library_Symbol_Policy",
5230 Lib_Symbol_Policy.Location);
5235 -- If attribute Library_Symbol_File is not specified, symbol policy
5236 -- cannot be Restricted.
5238 if Lib_Symbol_File.Default then
5239 if Data.Symbol_Data.Symbol_Policy = Restricted then
5242 "Library_Symbol_File needs to be defined when " &
5243 "symbol policy is Restricted",
5244 Lib_Symbol_Policy.Location);
5248 -- Library_Symbol_File is defined
5250 Data.Symbol_Data.Symbol_File :=
5251 Path_Name_Type (Lib_Symbol_File.Value);
5253 Get_Name_String (Lib_Symbol_File.Value);
5255 if Name_Len = 0 then
5258 "symbol file name cannot be an empty string",
5259 Lib_Symbol_File.Location);
5262 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5265 for J in 1 .. Name_Len loop
5266 if Name_Buffer (J) = '/'
5267 or else Name_Buffer (J) = Directory_Separator
5276 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5279 "symbol file name { is illegal. " &
5280 "Name cannot include directory info.",
5281 Lib_Symbol_File.Location);
5286 -- If attribute Library_Reference_Symbol_File is not defined,
5287 -- symbol policy cannot be Compliant or Controlled.
5289 if Lib_Ref_Symbol_File.Default then
5290 if Data.Symbol_Data.Symbol_Policy = Compliant
5291 or else Data.Symbol_Data.Symbol_Policy = Controlled
5295 "a reference symbol file need to be defined",
5296 Lib_Symbol_Policy.Location);
5300 -- Library_Reference_Symbol_File is defined, check file exists
5302 Data.Symbol_Data.Reference :=
5303 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5305 Get_Name_String (Lib_Ref_Symbol_File.Value);
5307 if Name_Len = 0 then
5310 "reference symbol file name cannot be an empty string",
5311 Lib_Symbol_File.Location);
5314 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5316 Add_Str_To_Name_Buffer
5317 (Get_Name_String (Data.Directory.Name));
5318 Add_Char_To_Name_Buffer (Directory_Separator);
5319 Add_Str_To_Name_Buffer
5320 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5321 Data.Symbol_Data.Reference := Name_Find;
5324 if not Is_Regular_File
5325 (Get_Name_String (Data.Symbol_Data.Reference))
5328 File_Name_Type (Lib_Ref_Symbol_File.Value);
5330 -- For controlled and direct symbol policies, it is an error
5331 -- if the reference symbol file does not exist. For other
5332 -- symbol policies, this is just a warning
5335 Data.Symbol_Data.Symbol_Policy /= Controlled
5336 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5340 "<library reference symbol file { does not exist",
5341 Lib_Ref_Symbol_File.Location);
5343 -- In addition in the non-controlled case, if symbol policy
5344 -- is Compliant, it is changed to Autonomous, because there
5345 -- is no reference to check against, and we don't want to
5346 -- fail in this case.
5348 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5349 if Data.Symbol_Data.Symbol_Policy = Compliant then
5350 Data.Symbol_Data.Symbol_Policy := Autonomous;
5355 -- If both the reference symbol file and the symbol file are
5356 -- defined, then check that they are not the same file.
5358 if Data.Symbol_Data.Symbol_File /= No_Path then
5359 Get_Name_String (Data.Symbol_Data.Symbol_File);
5361 if Name_Len > 0 then
5363 Symb_Path : constant String :=
5366 (Data.Object_Directory.Name) &
5367 Directory_Separator &
5368 Name_Buffer (1 .. Name_Len),
5369 Directory => Current_Dir,
5371 Opt.Follow_Links_For_Files);
5372 Ref_Path : constant String :=
5375 (Data.Symbol_Data.Reference),
5376 Directory => Current_Dir,
5378 Opt.Follow_Links_For_Files);
5380 if Symb_Path = Ref_Path then
5383 "library reference symbol file and library" &
5384 " symbol file cannot be the same file",
5385 Lib_Ref_Symbol_File.Location);
5393 end Check_Stand_Alone_Library;
5395 ----------------------------
5396 -- Compute_Directory_Last --
5397 ----------------------------
5399 function Compute_Directory_Last (Dir : String) return Natural is
5402 and then (Dir (Dir'Last - 1) = Directory_Separator
5403 or else Dir (Dir'Last - 1) = '/')
5405 return Dir'Last - 1;
5409 end Compute_Directory_Last;
5416 (Project : Project_Id;
5417 In_Tree : Project_Tree_Ref;
5419 Flag_Location : Source_Ptr)
5421 Real_Location : Source_Ptr := Flag_Location;
5422 Error_Buffer : String (1 .. 5_000);
5423 Error_Last : Natural := 0;
5424 Name_Number : Natural := 0;
5425 File_Number : Natural := 0;
5426 First : Positive := Msg'First;
5429 procedure Add (C : Character);
5430 -- Add a character to the buffer
5432 procedure Add (S : String);
5433 -- Add a string to the buffer
5436 -- Add a name to the buffer
5439 -- Add a file name to the buffer
5445 procedure Add (C : Character) is
5447 Error_Last := Error_Last + 1;
5448 Error_Buffer (Error_Last) := C;
5451 procedure Add (S : String) is
5453 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5454 Error_Last := Error_Last + S'Length;
5461 procedure Add_File is
5462 File : File_Name_Type;
5466 File_Number := File_Number + 1;
5470 File := Err_Vars.Error_Msg_File_1;
5472 File := Err_Vars.Error_Msg_File_2;
5474 File := Err_Vars.Error_Msg_File_3;
5479 Get_Name_String (File);
5480 Add (Name_Buffer (1 .. Name_Len));
5488 procedure Add_Name is
5493 Name_Number := Name_Number + 1;
5497 Name := Err_Vars.Error_Msg_Name_1;
5499 Name := Err_Vars.Error_Msg_Name_2;
5501 Name := Err_Vars.Error_Msg_Name_3;
5506 Get_Name_String (Name);
5507 Add (Name_Buffer (1 .. Name_Len));
5511 -- Start of processing for Error_Msg
5514 -- If location of error is unknown, use the location of the project
5516 if Real_Location = No_Location then
5517 Real_Location := In_Tree.Projects.Table (Project).Location;
5520 if Error_Report = null then
5521 Prj.Err.Error_Msg (Msg, Real_Location);
5525 -- Ignore continuation character
5527 if Msg (First) = '\' then
5531 -- Warning character is always the first one in this package
5532 -- this is an undocumented kludge???
5534 if Msg (First) = '?' then
5538 elsif Msg (First) = '<' then
5541 if Err_Vars.Error_Msg_Warn then
5547 while Index <= Msg'Last loop
5548 if Msg (Index) = '{' then
5551 elsif Msg (Index) = '%' then
5552 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5564 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5567 ----------------------
5568 -- Find_Ada_Sources --
5569 ----------------------
5571 procedure Find_Ada_Sources
5572 (Project : Project_Id;
5573 In_Tree : Project_Tree_Ref;
5574 Data : in out Project_Data;
5575 Current_Dir : String)
5577 Source_Dir : String_List_Id := Data.Source_Dirs;
5578 Element : String_Element;
5580 Current_Source : String_List_Id := Nil_String;
5581 Source_Recorded : Boolean := False;
5584 if Current_Verbosity = High then
5585 Write_Line ("Looking for sources:");
5588 -- For each subdirectory
5590 while Source_Dir /= Nil_String loop
5592 Source_Recorded := False;
5593 Element := In_Tree.String_Elements.Table (Source_Dir);
5594 if Element.Value /= No_Name then
5595 Get_Name_String (Element.Display_Value);
5598 Source_Directory : constant String :=
5599 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5600 Dir_Last : constant Natural :=
5601 Compute_Directory_Last (Source_Directory);
5604 if Current_Verbosity = High then
5605 Write_Str ("Source_Dir = ");
5606 Write_Line (Source_Directory);
5609 -- We look at every entry in the source directory
5612 Source_Directory (Source_Directory'First .. Dir_Last));
5615 Read (Dir, Name_Buffer, Name_Len);
5617 if Current_Verbosity = High then
5618 Write_Str (" Checking ");
5619 Write_Line (Name_Buffer (1 .. Name_Len));
5622 exit when Name_Len = 0;
5625 File_Name : constant File_Name_Type := Name_Find;
5627 -- ??? We could probably optimize the following call:
5628 -- we need to resolve links only once for the
5629 -- directory itself, and then do a single call to
5630 -- readlink() for each file. Unfortunately that would
5631 -- require a change in Normalize_Pathname so that it
5632 -- has the option of not resolving links for its
5633 -- Directory parameter, only for Name.
5635 Path : constant String :=
5637 (Name => Name_Buffer (1 .. Name_Len),
5640 (Source_Directory'First .. Dir_Last),
5642 Opt.Follow_Links_For_Files,
5643 Case_Sensitive => True);
5645 Path_Name : Path_Name_Type;
5648 Name_Len := Path'Length;
5649 Name_Buffer (1 .. Name_Len) := Path;
5650 Path_Name := Name_Find;
5652 -- We attempt to register it as a source. However,
5653 -- there is no error if the file does not contain a
5654 -- valid source. But there is an error if we have a
5655 -- duplicate unit name.
5658 (File_Name => File_Name,
5659 Path_Name => Path_Name,
5663 Location => No_Location,
5664 Current_Source => Current_Source,
5665 Source_Recorded => Source_Recorded,
5666 Current_Dir => Current_Dir);
5675 when Directory_Error =>
5679 if Source_Recorded then
5680 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5684 Source_Dir := Element.Next;
5687 if Current_Verbosity = High then
5688 Write_Line ("end Looking for sources.");
5691 end Find_Ada_Sources;
5693 --------------------------------
5694 -- Free_Ada_Naming_Exceptions --
5695 --------------------------------
5697 procedure Free_Ada_Naming_Exceptions is
5699 Ada_Naming_Exception_Table.Set_Last (0);
5700 Ada_Naming_Exceptions.Reset;
5701 Reverse_Ada_Naming_Exceptions.Reset;
5702 end Free_Ada_Naming_Exceptions;
5704 ---------------------
5705 -- Get_Directories --
5706 ---------------------
5708 procedure Get_Directories
5709 (Project : Project_Id;
5710 In_Tree : Project_Tree_Ref;
5711 Current_Dir : String;
5712 Data : in out Project_Data)
5714 Object_Dir : constant Variable_Value :=
5716 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5718 Exec_Dir : constant Variable_Value :=
5720 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5722 Source_Dirs : constant Variable_Value :=
5724 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5726 Excluded_Source_Dirs : constant Variable_Value :=
5728 (Name_Excluded_Source_Dirs,
5729 Data.Decl.Attributes,
5732 Source_Files : constant Variable_Value :=
5734 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5736 Last_Source_Dir : String_List_Id := Nil_String;
5738 procedure Find_Source_Dirs
5739 (From : File_Name_Type;
5740 Location : Source_Ptr;
5741 Removed : Boolean := False);
5742 -- Find one or several source directories, and add (or remove, if
5743 -- Removed is True) them to list of source directories of the project.
5745 ----------------------
5746 -- Find_Source_Dirs --
5747 ----------------------
5749 procedure Find_Source_Dirs
5750 (From : File_Name_Type;
5751 Location : Source_Ptr;
5752 Removed : Boolean := False)
5754 Directory : constant String := Get_Name_String (From);
5755 Element : String_Element;
5757 procedure Recursive_Find_Dirs (Path : Name_Id);
5758 -- Find all the subdirectories (recursively) of Path and add them
5759 -- to the list of source directories of the project.
5761 -------------------------
5762 -- Recursive_Find_Dirs --
5763 -------------------------
5765 procedure Recursive_Find_Dirs (Path : Name_Id) is
5767 Name : String (1 .. 250);
5769 List : String_List_Id;
5770 Prev : String_List_Id;
5771 Element : String_Element;
5772 Found : Boolean := False;
5774 Non_Canonical_Path : Name_Id := No_Name;
5775 Canonical_Path : Name_Id := No_Name;
5777 The_Path : constant String :=
5779 (Get_Name_String (Path),
5780 Directory => Current_Dir,
5781 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5782 Directory_Separator;
5784 The_Path_Last : constant Natural :=
5785 Compute_Directory_Last (The_Path);
5788 Name_Len := The_Path_Last - The_Path'First + 1;
5789 Name_Buffer (1 .. Name_Len) :=
5790 The_Path (The_Path'First .. The_Path_Last);
5791 Non_Canonical_Path := Name_Find;
5793 if Osint.File_Names_Case_Sensitive then
5794 Canonical_Path := Non_Canonical_Path;
5796 Get_Name_String (Non_Canonical_Path);
5797 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5798 Canonical_Path := Name_Find;
5801 -- To avoid processing the same directory several times, check
5802 -- if the directory is already in Recursive_Dirs. If it is, then
5803 -- there is nothing to do, just return. If it is not, put it there
5804 -- and continue recursive processing.
5807 if Recursive_Dirs.Get (Canonical_Path) then
5810 Recursive_Dirs.Set (Canonical_Path, True);
5814 -- Check if directory is already in list
5816 List := Data.Source_Dirs;
5818 while List /= Nil_String loop
5819 Element := In_Tree.String_Elements.Table (List);
5821 if Element.Value /= No_Name then
5822 Found := Element.Value = Canonical_Path;
5827 List := Element.Next;
5830 -- If directory is not already in list, put it there
5832 if (not Removed) and (not Found) then
5833 if Current_Verbosity = High then
5835 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5838 String_Element_Table.Increment_Last
5839 (In_Tree.String_Elements);
5841 (Value => Canonical_Path,
5842 Display_Value => Non_Canonical_Path,
5843 Location => No_Location,
5848 -- Case of first source directory
5850 if Last_Source_Dir = Nil_String then
5851 Data.Source_Dirs := String_Element_Table.Last
5852 (In_Tree.String_Elements);
5854 -- Here we already have source directories
5857 -- Link the previous last to the new one
5859 In_Tree.String_Elements.Table
5860 (Last_Source_Dir).Next :=
5861 String_Element_Table.Last
5862 (In_Tree.String_Elements);
5865 -- And register this source directory as the new last
5867 Last_Source_Dir := String_Element_Table.Last
5868 (In_Tree.String_Elements);
5869 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5872 elsif Removed and Found then
5873 if Prev = Nil_String then
5875 In_Tree.String_Elements.Table (List).Next;
5877 In_Tree.String_Elements.Table (Prev).Next :=
5878 In_Tree.String_Elements.Table (List).Next;
5882 -- Now look for subdirectories. We do that even when this
5883 -- directory is already in the list, because some of its
5884 -- subdirectories may not be in the list yet.
5886 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5889 Read (Dir, Name, Last);
5892 if Name (1 .. Last) /= "."
5893 and then Name (1 .. Last) /= ".."
5895 -- Avoid . and .. directories
5897 if Current_Verbosity = High then
5898 Write_Str (" Checking ");
5899 Write_Line (Name (1 .. Last));
5903 Path_Name : constant String :=
5905 (Name => Name (1 .. Last),
5907 The_Path (The_Path'First .. The_Path_Last),
5908 Resolve_Links => Opt.Follow_Links_For_Dirs,
5909 Case_Sensitive => True);
5912 if Is_Directory (Path_Name) then
5913 -- We have found a new subdirectory, call self
5915 Name_Len := Path_Name'Length;
5916 Name_Buffer (1 .. Name_Len) := Path_Name;
5917 Recursive_Find_Dirs (Name_Find);
5926 when Directory_Error =>
5928 end Recursive_Find_Dirs;
5930 -- Start of processing for Find_Source_Dirs
5933 if Current_Verbosity = High and then not Removed then
5934 Write_Str ("Find_Source_Dirs (""");
5935 Write_Str (Directory);
5939 -- First, check if we are looking for a directory tree, indicated
5940 -- by "/**" at the end.
5942 if Directory'Length >= 3
5943 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5944 and then (Directory (Directory'Last - 2) = '/'
5946 Directory (Directory'Last - 2) = Directory_Separator)
5949 Data.Known_Order_Of_Source_Dirs := False;
5952 Name_Len := Directory'Length - 3;
5954 if Name_Len = 0 then
5956 -- Case of "/**": all directories in file system
5959 Name_Buffer (1) := Directory (Directory'First);
5962 Name_Buffer (1 .. Name_Len) :=
5963 Directory (Directory'First .. Directory'Last - 3);
5966 if Current_Verbosity = High then
5967 Write_Str ("Looking for all subdirectories of """);
5968 Write_Str (Name_Buffer (1 .. Name_Len));
5973 Base_Dir : constant File_Name_Type := Name_Find;
5974 Root_Dir : constant String :=
5976 (Name => Get_Name_String (Base_Dir),
5978 Get_Name_String (Data.Directory.Display_Name),
5979 Resolve_Links => False,
5980 Case_Sensitive => True);
5983 if Root_Dir'Length = 0 then
5984 Err_Vars.Error_Msg_File_1 := Base_Dir;
5986 if Location = No_Location then
5989 "{ is not a valid directory.",
5994 "{ is not a valid directory.",
5999 -- We have an existing directory, we register it and all of
6000 -- its subdirectories.
6002 if Current_Verbosity = High then
6003 Write_Line ("Looking for source directories:");
6006 Name_Len := Root_Dir'Length;
6007 Name_Buffer (1 .. Name_Len) := Root_Dir;
6008 Recursive_Find_Dirs (Name_Find);
6010 if Current_Verbosity = High then
6011 Write_Line ("End of looking for source directories.");
6016 -- We have a single directory
6020 Path_Name : Path_Name_Type;
6021 Display_Path_Name : Path_Name_Type;
6022 List : String_List_Id;
6023 Prev : String_List_Id;
6027 (Project => Project,
6030 Parent => Data.Directory.Display_Name,
6032 Display => Display_Path_Name,
6033 Current_Dir => Current_Dir);
6035 if Path_Name = No_Path then
6036 Err_Vars.Error_Msg_File_1 := From;
6038 if Location = No_Location then
6041 "{ is not a valid directory",
6046 "{ is not a valid directory",
6052 Path : constant String :=
6053 Get_Name_String (Path_Name) &
6054 Directory_Separator;
6055 Last_Path : constant Natural :=
6056 Compute_Directory_Last (Path);
6058 Display_Path : constant String :=
6060 (Display_Path_Name) &
6061 Directory_Separator;
6062 Last_Display_Path : constant Natural :=
6063 Compute_Directory_Last
6065 Display_Path_Id : Name_Id;
6069 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6070 Path_Id := Name_Find;
6072 Add_Str_To_Name_Buffer
6074 (Display_Path'First .. Last_Display_Path));
6075 Display_Path_Id := Name_Find;
6079 -- As it is an existing directory, we add it to the
6080 -- list of directories.
6082 String_Element_Table.Increment_Last
6083 (In_Tree.String_Elements);
6087 Display_Value => Display_Path_Id,
6088 Location => No_Location,
6090 Next => Nil_String);
6092 if Last_Source_Dir = Nil_String then
6094 -- This is the first source directory
6096 Data.Source_Dirs := String_Element_Table.Last
6097 (In_Tree.String_Elements);
6100 -- We already have source directories, link the
6101 -- previous last to the new one.
6103 In_Tree.String_Elements.Table
6104 (Last_Source_Dir).Next :=
6105 String_Element_Table.Last
6106 (In_Tree.String_Elements);
6109 -- And register this source directory as the new last
6111 Last_Source_Dir := String_Element_Table.Last
6112 (In_Tree.String_Elements);
6113 In_Tree.String_Elements.Table
6114 (Last_Source_Dir) := Element;
6117 -- Remove source dir, if present
6119 List := Data.Source_Dirs;
6122 -- Look for source dir in current list
6124 while List /= Nil_String loop
6125 Element := In_Tree.String_Elements.Table (List);
6126 exit when Element.Value = Path_Id;
6128 List := Element.Next;
6131 if List /= Nil_String then
6132 -- Source dir was found, remove it from the list
6134 if Prev = Nil_String then
6136 In_Tree.String_Elements.Table (List).Next;
6139 In_Tree.String_Elements.Table (Prev).Next :=
6140 In_Tree.String_Elements.Table (List).Next;
6148 end Find_Source_Dirs;
6150 -- Start of processing for Get_Directories
6153 if Current_Verbosity = High then
6154 Write_Line ("Starting to look for directories");
6157 -- Check the object directory
6159 pragma Assert (Object_Dir.Kind = Single,
6160 "Object_Dir is not a single string");
6162 -- We set the object directory to its default
6164 Data.Object_Directory := Data.Directory;
6166 if Object_Dir.Value /= Empty_String then
6167 Get_Name_String (Object_Dir.Value);
6169 if Name_Len = 0 then
6172 "Object_Dir cannot be empty",
6173 Object_Dir.Location);
6176 -- We check that the specified object directory does exist
6181 File_Name_Type (Object_Dir.Value),
6182 Data.Directory.Display_Name,
6183 Data.Object_Directory.Name,
6184 Data.Object_Directory.Display_Name,
6186 Location => Object_Dir.Location,
6187 Current_Dir => Current_Dir);
6189 if Data.Object_Directory = No_Path_Information then
6191 -- The object directory does not exist, report an error if the
6192 -- project is not externally built.
6194 if not Data.Externally_Built then
6195 Err_Vars.Error_Msg_File_1 :=
6196 File_Name_Type (Object_Dir.Value);
6199 "the object directory { cannot be found",
6203 -- Do not keep a nil Object_Directory. Set it to the specified
6204 -- (relative or absolute) path. This is for the benefit of
6205 -- tools that recover from errors; for example, these tools
6206 -- could create the non existent directory.
6208 Data.Object_Directory.Display_Name :=
6209 Path_Name_Type (Object_Dir.Value);
6211 if Osint.File_Names_Case_Sensitive then
6212 Data.Object_Directory.Name :=
6213 Path_Name_Type (Object_Dir.Value);
6215 Get_Name_String (Object_Dir.Value);
6216 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6217 Data.Object_Directory.Name := Name_Find;
6222 elsif Subdirs /= null then
6224 Name_Buffer (1) := '.';
6229 Data.Directory.Display_Name,
6230 Data.Object_Directory.Name,
6231 Data.Object_Directory.Display_Name,
6233 Location => Object_Dir.Location,
6234 Current_Dir => Current_Dir);
6237 if Current_Verbosity = High then
6238 if Data.Object_Directory = No_Path_Information then
6239 Write_Line ("No object directory");
6241 Write_Str ("Object directory: """);
6242 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6247 -- Check the exec directory
6249 pragma Assert (Exec_Dir.Kind = Single,
6250 "Exec_Dir is not a single string");
6252 -- We set the object directory to its default
6254 Data.Exec_Directory := Data.Object_Directory;
6256 if Exec_Dir.Value /= Empty_String then
6257 Get_Name_String (Exec_Dir.Value);
6259 if Name_Len = 0 then
6262 "Exec_Dir cannot be empty",
6266 -- We check that the specified exec directory does exist
6271 File_Name_Type (Exec_Dir.Value),
6272 Data.Directory.Display_Name,
6273 Data.Exec_Directory.Name,
6274 Data.Exec_Directory.Display_Name,
6276 Location => Exec_Dir.Location,
6277 Current_Dir => Current_Dir);
6279 if Data.Exec_Directory = No_Path_Information then
6280 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6283 "the exec directory { cannot be found",
6289 if Current_Verbosity = High then
6290 if Data.Exec_Directory = No_Path_Information then
6291 Write_Line ("No exec directory");
6293 Write_Str ("Exec directory: """);
6294 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6299 -- Look for the source directories
6301 if Current_Verbosity = High then
6302 Write_Line ("Starting to look for source directories");
6305 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6307 if (not Source_Files.Default) and then
6308 Source_Files.Values = Nil_String
6310 Data.Source_Dirs := Nil_String;
6312 if Data.Qualifier = Standard then
6316 "a standard project cannot have no sources",
6317 Source_Files.Location);
6320 if Data.Extends = No_Project
6321 and then Data.Object_Directory = Data.Directory
6323 Data.Object_Directory := No_Path_Information;
6326 elsif Source_Dirs.Default then
6328 -- No Source_Dirs specified: the single source directory is the one
6329 -- containing the project file
6331 String_Element_Table.Increment_Last
6332 (In_Tree.String_Elements);
6333 Data.Source_Dirs := String_Element_Table.Last
6334 (In_Tree.String_Elements);
6335 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6336 (Value => Name_Id (Data.Directory.Name),
6337 Display_Value => Name_Id (Data.Directory.Display_Name),
6338 Location => No_Location,
6343 if Current_Verbosity = High then
6344 Write_Line ("Single source directory:");
6346 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6350 elsif Source_Dirs.Values = Nil_String then
6351 if Data.Qualifier = Standard then
6355 "a standard project cannot have no source directories",
6356 Source_Dirs.Location);
6359 -- If Source_Dirs is an empty string list, this means that this
6360 -- project contains no source. For projects that don't extend other
6361 -- projects, this also means that there is no need for an object
6362 -- directory, if not specified.
6364 if Data.Extends = No_Project
6365 and then Data.Object_Directory = Data.Directory
6367 Data.Object_Directory := No_Path_Information;
6370 Data.Source_Dirs := Nil_String;
6374 Source_Dir : String_List_Id;
6375 Element : String_Element;
6378 -- Process the source directories for each element of the list
6380 Source_Dir := Source_Dirs.Values;
6381 while Source_Dir /= Nil_String loop
6382 Element := In_Tree.String_Elements.Table (Source_Dir);
6384 (File_Name_Type (Element.Value), Element.Location);
6385 Source_Dir := Element.Next;
6390 if not Excluded_Source_Dirs.Default
6391 and then Excluded_Source_Dirs.Values /= Nil_String
6394 Source_Dir : String_List_Id;
6395 Element : String_Element;
6398 -- Process the source directories for each element of the list
6400 Source_Dir := Excluded_Source_Dirs.Values;
6401 while Source_Dir /= Nil_String loop
6402 Element := In_Tree.String_Elements.Table (Source_Dir);
6404 (File_Name_Type (Element.Value),
6407 Source_Dir := Element.Next;
6412 if Current_Verbosity = High then
6413 Write_Line ("Putting source directories in canonical cases");
6417 Current : String_List_Id := Data.Source_Dirs;
6418 Element : String_Element;
6421 while Current /= Nil_String loop
6422 Element := In_Tree.String_Elements.Table (Current);
6423 if Element.Value /= No_Name then
6424 if not Osint.File_Names_Case_Sensitive then
6425 Get_Name_String (Element.Value);
6426 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6427 Element.Value := Name_Find;
6430 In_Tree.String_Elements.Table (Current) := Element;
6433 Current := Element.Next;
6437 end Get_Directories;
6444 (Project : Project_Id;
6445 In_Tree : Project_Tree_Ref;
6446 Data : in out Project_Data)
6448 Mains : constant Variable_Value :=
6449 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6450 List : String_List_Id;
6451 Elem : String_Element;
6454 Data.Mains := Mains.Values;
6456 -- If no Mains were specified, and if we are an extending project,
6457 -- inherit the Mains from the project we are extending.
6459 if Mains.Default then
6460 if not Data.Library and then Data.Extends /= No_Project then
6462 In_Tree.Projects.Table (Data.Extends).Mains;
6465 -- In a library project file, Main cannot be specified
6467 elsif Data.Library then
6470 "a library project file cannot have Main specified",
6474 List := Mains.Values;
6475 while List /= Nil_String loop
6476 Elem := In_Tree.String_Elements.Table (List);
6478 if Length_Of_Name (Elem.Value) = 0 then
6481 "?a main cannot have an empty name",
6491 ---------------------------
6492 -- Get_Sources_From_File --
6493 ---------------------------
6495 procedure Get_Sources_From_File
6497 Location : Source_Ptr;
6498 Project : Project_Id;
6499 In_Tree : Project_Tree_Ref)
6501 File : Prj.Util.Text_File;
6502 Line : String (1 .. 250);
6504 Source_Name : File_Name_Type;
6505 Name_Loc : Name_Location;
6508 if Get_Mode = Ada_Only then
6512 if Current_Verbosity = High then
6513 Write_Str ("Opening """);
6520 Prj.Util.Open (File, Path);
6522 if not Prj.Util.Is_Valid (File) then
6523 Error_Msg (Project, In_Tree, "file does not exist", Location);
6526 -- Read the lines one by one
6528 while not Prj.Util.End_Of_File (File) loop
6529 Prj.Util.Get_Line (File, Line, Last);
6531 -- A non empty, non comment line should contain a file name
6534 and then (Last = 1 or else Line (1 .. 2) /= "--")
6537 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6538 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6539 Source_Name := Name_Find;
6541 -- Check that there is no directory information
6543 for J in 1 .. Last loop
6544 if Line (J) = '/' or else Line (J) = Directory_Separator then
6545 Error_Msg_File_1 := Source_Name;
6549 "file name cannot include directory information ({)",
6555 Name_Loc := Source_Names.Get (Source_Name);
6557 if Name_Loc = No_Name_Location then
6559 (Name => Source_Name,
6560 Location => Location,
6561 Source => No_Source,
6566 Source_Names.Set (Source_Name, Name_Loc);
6570 Prj.Util.Close (File);
6573 end Get_Sources_From_File;
6580 (In_Tree : Project_Tree_Ref;
6581 Canonical_File_Name : File_Name_Type;
6582 Naming : Naming_Data;
6583 Exception_Id : out Ada_Naming_Exception_Id;
6584 Unit_Name : out Name_Id;
6585 Unit_Kind : out Spec_Or_Body;
6586 Needs_Pragma : out Boolean)
6588 Info_Id : Ada_Naming_Exception_Id :=
6589 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6590 VMS_Name : File_Name_Type;
6593 if Info_Id = No_Ada_Naming_Exception then
6594 if Hostparm.OpenVMS then
6595 VMS_Name := Canonical_File_Name;
6596 Get_Name_String (VMS_Name);
6598 if Name_Buffer (Name_Len) = '.' then
6599 Name_Len := Name_Len - 1;
6600 VMS_Name := Name_Find;
6603 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6608 if Info_Id /= No_Ada_Naming_Exception then
6609 Exception_Id := Info_Id;
6610 Unit_Name := No_Name;
6611 Unit_Kind := Specification;
6612 Needs_Pragma := True;
6616 Needs_Pragma := False;
6617 Exception_Id := No_Ada_Naming_Exception;
6619 Get_Name_String (Canonical_File_Name);
6621 -- How about some comments and a name for this declare block ???
6622 -- In fact the whole code below needs more comments ???
6625 File : String := Name_Buffer (1 .. Name_Len);
6626 First : constant Positive := File'First;
6627 Last : Natural := File'Last;
6628 Standard_GNAT : Boolean;
6629 Spec : constant File_Name_Type :=
6630 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6631 Body_Suff : constant File_Name_Type :=
6632 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6635 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6636 and then Body_Suff = Default_Ada_Body_Suffix;
6639 Spec_Suffix : constant String := Get_Name_String (Spec);
6640 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6641 Sep_Suffix : constant String :=
6642 Get_Name_String (Naming.Separate_Suffix);
6644 May_Be_Spec : Boolean;
6645 May_Be_Body : Boolean;
6646 May_Be_Sep : Boolean;
6650 File'Length > Spec_Suffix'Length
6652 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6655 File'Length > Body_Suffix'Length
6657 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6660 File'Length > Sep_Suffix'Length
6662 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6664 -- If two May_Be_ booleans are True, always choose the longer one
6667 if May_Be_Body and then
6668 Spec_Suffix'Length < Body_Suffix'Length
6670 Unit_Kind := Body_Part;
6672 if May_Be_Sep and then
6673 Body_Suffix'Length < Sep_Suffix'Length
6675 Last := Last - Sep_Suffix'Length;
6676 May_Be_Body := False;
6679 Last := Last - Body_Suffix'Length;
6680 May_Be_Sep := False;
6683 elsif May_Be_Sep and then
6684 Spec_Suffix'Length < Sep_Suffix'Length
6686 Unit_Kind := Body_Part;
6687 Last := Last - Sep_Suffix'Length;
6690 Unit_Kind := Specification;
6691 Last := Last - Spec_Suffix'Length;
6694 elsif May_Be_Body then
6695 Unit_Kind := Body_Part;
6697 if May_Be_Sep and then
6698 Body_Suffix'Length < Sep_Suffix'Length
6700 Last := Last - Sep_Suffix'Length;
6701 May_Be_Body := False;
6703 Last := Last - Body_Suffix'Length;
6704 May_Be_Sep := False;
6707 elsif May_Be_Sep then
6708 Unit_Kind := Body_Part;
6709 Last := Last - Sep_Suffix'Length;
6717 -- This is not a source file
6719 Unit_Name := No_Name;
6720 Unit_Kind := Specification;
6722 if Current_Verbosity = High then
6723 Write_Line (" Not a valid file name.");
6728 elsif Current_Verbosity = High then
6730 when Specification =>
6731 Write_Str (" Specification: ");
6732 Write_Line (File (First .. Last + Spec_Suffix'Length));
6736 Write_Str (" Body: ");
6737 Write_Line (File (First .. Last + Body_Suffix'Length));
6740 Write_Str (" Separate: ");
6741 Write_Line (File (First .. Last + Sep_Suffix'Length));
6747 Get_Name_String (Naming.Dot_Replacement);
6749 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6751 if Name_Buffer (1 .. Name_Len) /= "." then
6753 -- If Dot_Replacement is not a single dot, then there should not
6754 -- be any dot in the name.
6756 for Index in First .. Last loop
6757 if File (Index) = '.' then
6758 if Current_Verbosity = High then
6760 (" Not a valid file name (some dot not replaced).");
6763 Unit_Name := No_Name;
6769 -- Replace the substring Dot_Replacement with dots
6772 Index : Positive := First;
6775 while Index <= Last - Name_Len + 1 loop
6777 if File (Index .. Index + Name_Len - 1) =
6778 Name_Buffer (1 .. Name_Len)
6780 File (Index) := '.';
6782 if Name_Len > 1 and then Index < Last then
6783 File (Index + 1 .. Last - Name_Len + 1) :=
6784 File (Index + Name_Len .. Last);
6787 Last := Last - Name_Len + 1;
6795 -- Check if the file casing is right
6798 Src : String := File (First .. Last);
6799 Src_Last : Positive := Last;
6802 -- If casing is significant, deal with upper/lower case translate
6804 if File_Names_Case_Sensitive then
6805 case Naming.Casing is
6806 when All_Lower_Case =>
6809 Mapping => Lower_Case_Map);
6811 when All_Upper_Case =>
6814 Mapping => Upper_Case_Map);
6816 when Mixed_Case | Unknown =>
6820 if Src /= File (First .. Last) then
6821 if Current_Verbosity = High then
6822 Write_Line (" Not a valid file name (casing).");
6825 Unit_Name := No_Name;
6830 -- Put the name in lower case
6834 Mapping => Lower_Case_Map);
6836 -- In the standard GNAT naming scheme, check for special cases:
6837 -- children or separates of A, G, I or S, and run time sources.
6839 if Standard_GNAT and then Src'Length >= 3 then
6841 S1 : constant Character := Src (Src'First);
6842 S2 : constant Character := Src (Src'First + 1);
6843 S3 : constant Character := Src (Src'First + 2);
6851 -- Children or separates of packages A, G, I or S. These
6852 -- names are x__ ... or x~... (where x is a, g, i, or s).
6853 -- Both versions (x__... and x~...) are allowed in all
6854 -- platforms, because it is not possible to know the
6855 -- platform before processing of the project files.
6857 if S2 = '_' and then S3 = '_' then
6858 Src (Src'First + 1) := '.';
6859 Src_Last := Src_Last - 1;
6860 Src (Src'First + 2 .. Src_Last) :=
6861 Src (Src'First + 3 .. Src_Last + 1);
6864 Src (Src'First + 1) := '.';
6866 -- If it is potentially a run time source, disable
6867 -- filling of the mapping file to avoid warnings.
6870 Set_Mapping_File_Initial_State_To_Empty;
6876 if Current_Verbosity = High then
6878 Write_Line (Src (Src'First .. Src_Last));
6881 -- Now, we check if this name is a valid unit name
6884 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6894 function Hash (Unit : Unit_Info) return Header_Num is
6896 return Header_Num (Unit.Unit mod 2048);
6899 -----------------------
6900 -- Is_Illegal_Suffix --
6901 -----------------------
6903 function Is_Illegal_Suffix
6905 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6908 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6912 -- If dot replacement is a single dot, and first character of suffix is
6915 if Dot_Replacement_Is_A_Single_Dot
6916 and then Suffix (Suffix'First) = '.'
6918 for Index in Suffix'First + 1 .. Suffix'Last loop
6920 -- If there is another dot
6922 if Suffix (Index) = '.' then
6924 -- It is illegal to have a letter following the initial dot
6926 return Is_Letter (Suffix (Suffix'First + 1));
6934 end Is_Illegal_Suffix;
6936 ----------------------
6937 -- Locate_Directory --
6938 ----------------------
6940 procedure Locate_Directory
6941 (Project : Project_Id;
6942 In_Tree : Project_Tree_Ref;
6943 Name : File_Name_Type;
6944 Parent : Path_Name_Type;
6945 Dir : out Path_Name_Type;
6946 Display : out Path_Name_Type;
6947 Create : String := "";
6948 Current_Dir : String;
6949 Location : Source_Ptr := No_Location)
6951 The_Parent : constant String :=
6952 Get_Name_String (Parent) & Directory_Separator;
6954 The_Parent_Last : constant Natural :=
6955 Compute_Directory_Last (The_Parent);
6957 Full_Name : File_Name_Type;
6959 The_Name : File_Name_Type;
6962 Get_Name_String (Name);
6964 -- Add Subdirs.all if it is a directory that may be created and
6965 -- Subdirs is not null;
6967 if Create /= "" and then Subdirs /= null then
6968 if Name_Buffer (Name_Len) /= Directory_Separator then
6969 Add_Char_To_Name_Buffer (Directory_Separator);
6972 Add_Str_To_Name_Buffer (Subdirs.all);
6975 -- Convert '/' to directory separator (for Windows)
6977 for J in 1 .. Name_Len loop
6978 if Name_Buffer (J) = '/' then
6979 Name_Buffer (J) := Directory_Separator;
6983 The_Name := Name_Find;
6985 if Current_Verbosity = High then
6986 Write_Str ("Locate_Directory (""");
6987 Write_Str (Get_Name_String (The_Name));
6988 Write_Str (""", """);
6989 Write_Str (The_Parent);
6996 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6997 Full_Name := The_Name;
7001 Add_Str_To_Name_Buffer
7002 (The_Parent (The_Parent'First .. The_Parent_Last));
7003 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7004 Full_Name := Name_Find;
7008 Full_Path_Name : constant String := Get_Name_String (Full_Name);
7011 if (Setup_Projects or else Subdirs /= null)
7012 and then Create'Length > 0
7013 and then not Is_Directory (Full_Path_Name)
7016 Create_Path (Full_Path_Name);
7018 if not Quiet_Output then
7020 Write_Str (" directory """);
7021 Write_Str (Full_Path_Name);
7022 Write_Line (""" created");
7029 "could not create " & Create &
7030 " directory " & Full_Path_Name,
7035 if Is_Directory (Full_Path_Name) then
7037 Normed : constant String :=
7040 Directory => Current_Dir,
7041 Resolve_Links => False,
7042 Case_Sensitive => True);
7044 Canonical_Path : constant String :=
7047 Directory => Current_Dir,
7049 Opt.Follow_Links_For_Dirs,
7050 Case_Sensitive => False);
7053 Name_Len := Normed'Length;
7054 Name_Buffer (1 .. Name_Len) := Normed;
7055 Display := Name_Find;
7057 Name_Len := Canonical_Path'Length;
7058 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7063 end Locate_Directory;
7065 ---------------------------
7066 -- Find_Excluded_Sources --
7067 ---------------------------
7069 procedure Find_Excluded_Sources
7070 (Project : Project_Id;
7071 In_Tree : Project_Tree_Ref;
7072 Data : Project_Data)
7074 Excluded_Sources : Variable_Value;
7076 Excluded_Source_List_File : Variable_Value;
7078 Current : String_List_Id;
7080 Element : String_Element;
7082 Location : Source_Ptr;
7084 Name : File_Name_Type;
7086 File : Prj.Util.Text_File;
7087 Line : String (1 .. 300);
7090 Locally_Removed : Boolean := False;
7092 Excluded_Source_List_File :=
7094 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7098 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7100 -- If Excluded_Source_Files is not declared, check
7101 -- Locally_Removed_Files.
7103 if Excluded_Sources.Default then
7104 Locally_Removed := True;
7107 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7110 Excluded_Sources_Htable.Reset;
7112 -- If there are excluded sources, put them in the table
7114 if not Excluded_Sources.Default then
7115 if not Excluded_Source_List_File.Default then
7116 if Locally_Removed then
7119 "?both attributes Locally_Removed_Files and " &
7120 "Excluded_Source_List_File are present",
7121 Excluded_Source_List_File.Location);
7125 "?both attributes Excluded_Source_Files and " &
7126 "Excluded_Source_List_File are present",
7127 Excluded_Source_List_File.Location);
7131 Current := Excluded_Sources.Values;
7132 while Current /= Nil_String loop
7133 Element := In_Tree.String_Elements.Table (Current);
7135 if Osint.File_Names_Case_Sensitive then
7136 Name := File_Name_Type (Element.Value);
7138 Get_Name_String (Element.Value);
7139 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7143 -- If the element has no location, then use the location
7144 -- of Excluded_Sources to report possible errors.
7146 if Element.Location = No_Location then
7147 Location := Excluded_Sources.Location;
7149 Location := Element.Location;
7152 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7153 Current := Element.Next;
7156 elsif not Excluded_Source_List_File.Default then
7157 Location := Excluded_Source_List_File.Location;
7160 Source_File_Path_Name : constant String :=
7163 (Excluded_Source_List_File.Value),
7164 Data.Directory.Name);
7167 if Source_File_Path_Name'Length = 0 then
7168 Err_Vars.Error_Msg_File_1 :=
7169 File_Name_Type (Excluded_Source_List_File.Value);
7172 "file with excluded sources { does not exist",
7173 Excluded_Source_List_File.Location);
7178 Prj.Util.Open (File, Source_File_Path_Name);
7180 if not Prj.Util.Is_Valid (File) then
7182 (Project, In_Tree, "file does not exist", Location);
7184 -- Read the lines one by one
7186 while not Prj.Util.End_Of_File (File) loop
7187 Prj.Util.Get_Line (File, Line, Last);
7189 -- A non empty, non comment line should contain a file
7193 and then (Last = 1 or else Line (1 .. 2) /= "--")
7196 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7197 Canonical_Case_File_Name
7198 (Name_Buffer (1 .. Name_Len));
7201 -- Check that there is no directory information
7203 for J in 1 .. Last loop
7205 or else Line (J) = Directory_Separator
7207 Error_Msg_File_1 := Name;
7211 "file name cannot include " &
7212 "directory information ({)",
7218 Excluded_Sources_Htable.Set
7219 (Name, (Name, False, Location));
7223 Prj.Util.Close (File);
7228 end Find_Excluded_Sources;
7230 ---------------------------
7231 -- Find_Explicit_Sources --
7232 ---------------------------
7234 procedure Find_Explicit_Sources
7235 (Current_Dir : String;
7236 Project : Project_Id;
7237 In_Tree : Project_Tree_Ref;
7238 Data : in out Project_Data)
7240 Sources : constant Variable_Value :=
7243 Data.Decl.Attributes,
7245 Source_List_File : constant Variable_Value :=
7247 (Name_Source_List_File,
7248 Data.Decl.Attributes,
7250 Name_Loc : Name_Location;
7253 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7255 (Source_List_File.Kind = Single,
7256 "Source_List_File is not a single string");
7258 -- If the user has specified a Sources attribute
7260 if not Sources.Default then
7261 if not Source_List_File.Default then
7264 "?both attributes source_files and " &
7265 "source_list_file are present",
7266 Source_List_File.Location);
7269 -- Sources is a list of file names
7272 Current : String_List_Id := Sources.Values;
7273 Element : String_Element;
7274 Location : Source_Ptr;
7275 Name : File_Name_Type;
7278 if Get_Mode = Ada_Only then
7279 Data.Ada_Sources_Present := Current /= Nil_String;
7282 if Get_Mode = Multi_Language then
7283 if Current = Nil_String then
7284 Data.First_Language_Processing := No_Language_Index;
7286 -- This project contains no source. For projects that
7287 -- don't extend other projects, this also means that
7288 -- there is no need for an object directory, if not
7291 if Data.Extends = No_Project
7292 and then Data.Object_Directory = Data.Directory
7294 Data.Object_Directory := No_Path_Information;
7299 while Current /= Nil_String loop
7300 Element := In_Tree.String_Elements.Table (Current);
7301 Get_Name_String (Element.Value);
7303 if Osint.File_Names_Case_Sensitive then
7304 Name := File_Name_Type (Element.Value);
7306 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7310 -- If the element has no location, then use the
7311 -- location of Sources to report possible errors.
7313 if Element.Location = No_Location then
7314 Location := Sources.Location;
7316 Location := Element.Location;
7319 -- Check that there is no directory information
7321 for J in 1 .. Name_Len loop
7322 if Name_Buffer (J) = '/'
7323 or else Name_Buffer (J) = Directory_Separator
7325 Error_Msg_File_1 := Name;
7329 "file name cannot include directory " &
7336 -- In Multi_Language mode, check whether the file is
7337 -- already there: the same file name may be in the list; if
7338 -- the source is missing, the error will be on the first
7339 -- mention of the source file name.
7343 Name_Loc := No_Name_Location;
7344 when Multi_Language =>
7345 Name_Loc := Source_Names.Get (Name);
7348 if Name_Loc = No_Name_Location then
7351 Location => Location,
7352 Source => No_Source,
7355 Source_Names.Set (Name, Name_Loc);
7358 Current := Element.Next;
7361 if Get_Mode = Ada_Only then
7362 Get_Path_Names_And_Record_Ada_Sources
7363 (Project, In_Tree, Data, Current_Dir);
7367 -- If we have no Source_Files attribute, check the Source_List_File
7370 elsif not Source_List_File.Default then
7372 -- Source_List_File is the name of the file
7373 -- that contains the source file names
7376 Source_File_Path_Name : constant String :=
7378 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7381 if Source_File_Path_Name'Length = 0 then
7382 Err_Vars.Error_Msg_File_1 :=
7383 File_Name_Type (Source_List_File.Value);
7386 "file with sources { does not exist",
7387 Source_List_File.Location);
7390 Get_Sources_From_File
7391 (Source_File_Path_Name, Source_List_File.Location,
7394 if Get_Mode = Ada_Only then
7395 -- Look in the source directories to find those sources
7397 Get_Path_Names_And_Record_Ada_Sources
7398 (Project, In_Tree, Data, Current_Dir);
7404 -- Neither Source_Files nor Source_List_File has been
7405 -- specified. Find all the files that satisfy the naming
7406 -- scheme in all the source directories.
7408 if Get_Mode = Ada_Only then
7409 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7413 if Get_Mode = Multi_Language then
7415 (Project, In_Tree, Data,
7417 Sources.Default and then Source_List_File.Default);
7419 -- Check if all exceptions have been found.
7420 -- For Ada, it is an error if an exception is not found.
7421 -- For other language, the source is simply removed.
7427 Source := Data.First_Source;
7428 while Source /= No_Source loop
7430 Src_Data : Source_Data renames
7431 In_Tree.Sources.Table (Source);
7434 if Src_Data.Naming_Exception
7435 and then Src_Data.Path = No_Path_Information
7437 if Src_Data.Unit /= No_Name then
7438 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7439 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7442 "source file %% for unit %% not found",
7446 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7449 Source := Src_Data.Next_In_Project;
7454 -- Check that all sources in Source_Files or the file
7455 -- Source_List_File has been found.
7458 Name_Loc : Name_Location;
7461 Name_Loc := Source_Names.Get_First;
7462 while Name_Loc /= No_Name_Location loop
7463 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7464 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7468 "file %% not found",
7472 Name_Loc := Source_Names.Get_Next;
7477 if Get_Mode = Ada_Only
7478 and then Data.Extends = No_Project
7480 -- We should have found at least one source, if not report an error
7482 if Data.Ada_Sources = Nil_String then
7484 (Project, "Ada", In_Tree, Source_List_File.Location);
7488 end Find_Explicit_Sources;
7490 -------------------------------------------
7491 -- Get_Path_Names_And_Record_Ada_Sources --
7492 -------------------------------------------
7494 procedure Get_Path_Names_And_Record_Ada_Sources
7495 (Project : Project_Id;
7496 In_Tree : Project_Tree_Ref;
7497 Data : in out Project_Data;
7498 Current_Dir : String)
7500 Source_Dir : String_List_Id;
7501 Element : String_Element;
7502 Path : Path_Name_Type;
7504 Name : File_Name_Type;
7505 Canonical_Name : File_Name_Type;
7506 Name_Str : String (1 .. 1_024);
7507 Last : Natural := 0;
7509 Current_Source : String_List_Id := Nil_String;
7510 First_Error : Boolean := True;
7511 Source_Recorded : Boolean := False;
7514 -- We look in all source directories for the file names in the hash
7515 -- table Source_Names.
7517 Source_Dir := Data.Source_Dirs;
7518 while Source_Dir /= Nil_String loop
7519 Source_Recorded := False;
7520 Element := In_Tree.String_Elements.Table (Source_Dir);
7523 Dir_Path : constant String :=
7524 Get_Name_String (Element.Display_Value);
7526 if Current_Verbosity = High then
7527 Write_Str ("checking directory """);
7528 Write_Str (Dir_Path);
7532 Open (Dir, Dir_Path);
7535 Read (Dir, Name_Str, Last);
7539 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7542 if Osint.File_Names_Case_Sensitive then
7543 Canonical_Name := Name;
7545 Canonical_Case_File_Name (Name_Str (1 .. Last));
7546 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7547 Canonical_Name := Name_Find;
7550 NL := Source_Names.Get (Canonical_Name);
7552 if NL /= No_Name_Location and then not NL.Found then
7554 Source_Names.Set (Canonical_Name, NL);
7555 Name_Len := Dir_Path'Length;
7556 Name_Buffer (1 .. Name_Len) := Dir_Path;
7558 if Name_Buffer (Name_Len) /= Directory_Separator then
7559 Add_Char_To_Name_Buffer (Directory_Separator);
7562 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7565 if Current_Verbosity = High then
7566 Write_Str (" found ");
7567 Write_Line (Get_Name_String (Name));
7570 -- Register the source if it is an Ada compilation unit
7578 Location => NL.Location,
7579 Current_Source => Current_Source,
7580 Source_Recorded => Source_Recorded,
7581 Current_Dir => Current_Dir);
7588 if Source_Recorded then
7589 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7593 Source_Dir := Element.Next;
7596 -- It is an error if a source file name in a source list or
7597 -- in a source list file is not found.
7599 NL := Source_Names.Get_First;
7600 while NL /= No_Name_Location loop
7601 if not NL.Found then
7602 Err_Vars.Error_Msg_File_1 := NL.Name;
7607 "source file { cannot be found",
7609 First_Error := False;
7614 "\source file { cannot be found",
7619 NL := Source_Names.Get_Next;
7621 end Get_Path_Names_And_Record_Ada_Sources;
7623 --------------------------
7624 -- Check_Naming_Schemes --
7625 --------------------------
7627 procedure Check_Naming_Schemes
7628 (In_Tree : Project_Tree_Ref;
7629 Data : in out Project_Data;
7631 File_Name : File_Name_Type;
7632 Alternate_Languages : out Alternate_Language_Id;
7633 Language : out Language_Index;
7634 Language_Name : out Name_Id;
7635 Display_Language_Name : out Name_Id;
7637 Lang_Kind : out Language_Kind;
7638 Kind : out Source_Kind)
7640 Last : Positive := Filename'Last;
7641 Config : Language_Config;
7642 Lang : Name_List_Index := Data.Languages;
7643 Header_File : Boolean := False;
7644 First_Language : Language_Index;
7647 Last_Spec : Natural;
7648 Last_Body : Natural;
7653 Alternate_Languages := No_Alternate_Language;
7655 while Lang /= No_Name_List loop
7656 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7657 Language := Data.First_Language_Processing;
7659 if Current_Verbosity = High then
7661 (" Testing language "
7662 & Get_Name_String (Language_Name)
7663 & " Header_File=" & Header_File'Img);
7666 while Language /= No_Language_Index loop
7667 if In_Tree.Languages_Data.Table (Language).Name =
7670 Display_Language_Name :=
7671 In_Tree.Languages_Data.Table (Language).Display_Name;
7672 Config := In_Tree.Languages_Data.Table (Language).Config;
7673 Lang_Kind := Config.Kind;
7675 if Config.Kind = File_Based then
7677 -- For file based languages, there is no Unit. Just
7678 -- check if the file name has the implementation or,
7679 -- if it is specified, the template suffix of the
7685 and then Config.Naming_Data.Body_Suffix /= No_File
7688 Impl_Suffix : constant String :=
7689 Get_Name_String (Config.Naming_Data.Body_Suffix);
7692 if Filename'Length > Impl_Suffix'Length
7695 (Last - Impl_Suffix'Length + 1 .. Last) =
7700 if Current_Verbosity = High then
7701 Write_Str (" source of language ");
7703 (Get_Name_String (Display_Language_Name));
7711 if Config.Naming_Data.Spec_Suffix /= No_File then
7713 Spec_Suffix : constant String :=
7715 (Config.Naming_Data.Spec_Suffix);
7718 if Filename'Length > Spec_Suffix'Length
7721 (Last - Spec_Suffix'Length + 1 .. Last) =
7726 if Current_Verbosity = High then
7727 Write_Str (" header file of language ");
7729 (Get_Name_String (Display_Language_Name));
7733 Alternate_Language_Table.Increment_Last
7734 (In_Tree.Alt_Langs);
7735 In_Tree.Alt_Langs.Table
7736 (Alternate_Language_Table.Last
7737 (In_Tree.Alt_Langs)) :=
7738 (Language => Language,
7739 Next => Alternate_Languages);
7740 Alternate_Languages :=
7741 Alternate_Language_Table.Last
7742 (In_Tree.Alt_Langs);
7744 Header_File := True;
7745 First_Language := Language;
7751 elsif not Header_File then
7752 -- Unit based language
7754 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7759 -- ??? Are we doing this once per file in the project ?
7760 -- It should be done only once per project.
7762 case Config.Naming_Data.Casing is
7763 when All_Lower_Case =>
7764 for J in Filename'Range loop
7765 if Is_Letter (Filename (J)) then
7766 if not Is_Lower (Filename (J)) then
7773 when All_Upper_Case =>
7774 for J in Filename'Range loop
7775 if Is_Letter (Filename (J)) then
7776 if not Is_Upper (Filename (J)) then
7792 Last_Spec := Natural'Last;
7793 Last_Body := Natural'Last;
7794 Last_Sep := Natural'Last;
7796 if Config.Naming_Data.Separate_Suffix /= No_File
7798 Config.Naming_Data.Separate_Suffix /=
7799 Config.Naming_Data.Body_Suffix
7802 Suffix : constant String :=
7804 (Config.Naming_Data.Separate_Suffix);
7806 if Filename'Length > Suffix'Length
7809 (Last - Suffix'Length + 1 .. Last) =
7812 Last_Sep := Last - Suffix'Length;
7817 if Config.Naming_Data.Body_Suffix /= No_File then
7819 Suffix : constant String :=
7821 (Config.Naming_Data.Body_Suffix);
7823 if Filename'Length > Suffix'Length
7826 (Last - Suffix'Length + 1 .. Last) =
7829 Last_Body := Last - Suffix'Length;
7834 if Config.Naming_Data.Spec_Suffix /= No_File then
7836 Suffix : constant String :=
7838 (Config.Naming_Data.Spec_Suffix);
7840 if Filename'Length > Suffix'Length
7843 (Last - Suffix'Length + 1 .. Last) =
7846 Last_Spec := Last - Suffix'Length;
7852 Last_Min : constant Natural :=
7853 Natural'Min (Natural'Min (Last_Spec,
7858 OK := Last_Min < Last;
7863 if Last_Min = Last_Spec then
7866 elsif Last_Min = Last_Body then
7878 -- Replace dot replacements with dots
7883 J : Positive := Filename'First;
7885 Dot_Replacement : constant String :=
7887 (Config.Naming_Data.
7890 Max : constant Positive :=
7891 Last - Dot_Replacement'Length + 1;
7895 Name_Len := Name_Len + 1;
7897 if J <= Max and then
7899 (J .. J + Dot_Replacement'Length - 1) =
7902 Name_Buffer (Name_Len) := '.';
7903 J := J + Dot_Replacement'Length;
7906 if Filename (J) = '.' then
7911 Name_Buffer (Name_Len) :=
7912 GNAT.Case_Util.To_Lower (Filename (J));
7923 -- The name buffer should contain the name of the
7924 -- the unit, if it is one.
7926 -- Check that this is a valid unit name
7928 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7930 if Unit /= No_Name then
7932 if Current_Verbosity = High then
7934 Write_Str (" spec of ");
7936 Write_Str (" body of ");
7939 Write_Str (Get_Name_String (Unit));
7940 Write_Str (" (language ");
7942 (Get_Name_String (Display_Language_Name));
7946 -- Comments required, declare block should
7950 Unit_Except : constant Unit_Exception :=
7951 Unit_Exceptions.Get (Unit);
7953 procedure Masked_Unit (Spec : Boolean);
7954 -- Indicate that there is an exception for
7955 -- the same unit, so the file is not a
7956 -- source for the unit.
7962 procedure Masked_Unit (Spec : Boolean) is
7964 if Current_Verbosity = High then
7966 Write_Str (Filename);
7967 Write_Str (""" contains the ");
7976 (" of a unit that is found in """);
7981 (Unit_Except.Spec));
7985 (Unit_Except.Impl));
7988 Write_Line (""" (ignored)");
7991 Language := No_Language_Index;
7996 if Unit_Except.Spec /= No_File
7997 and then Unit_Except.Spec /= File_Name
7999 Masked_Unit (Spec => True);
8003 if Unit_Except.Impl /= No_File
8004 and then Unit_Except.Impl /= File_Name
8006 Masked_Unit (Spec => False);
8017 Language := In_Tree.Languages_Data.Table (Language).Next;
8020 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8023 -- Comment needed here ???
8026 Language := First_Language;
8029 Language := No_Language_Index;
8031 if Current_Verbosity = High then
8032 Write_Line (" not a source of any language");
8035 end Check_Naming_Schemes;
8041 procedure Check_File
8042 (Project : Project_Id;
8043 In_Tree : Project_Tree_Ref;
8044 Data : in out Project_Data;
8046 File_Name : File_Name_Type;
8047 Display_File_Name : File_Name_Type;
8048 Source_Directory : String;
8049 For_All_Sources : Boolean)
8051 Display_Path : constant String :=
8054 Directory => Source_Directory,
8055 Resolve_Links => Opt.Follow_Links_For_Files,
8056 Case_Sensitive => True);
8058 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8059 Path_Id : Path_Name_Type;
8060 Display_Path_Id : Path_Name_Type;
8061 Check_Name : Boolean := False;
8062 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8063 Language : Language_Index;
8065 Other_Part : Source_Id;
8067 Src_Ind : Source_File_Index;
8069 Source_To_Replace : Source_Id := No_Source;
8070 Language_Name : Name_Id;
8071 Display_Language_Name : Name_Id;
8072 Lang_Kind : Language_Kind;
8073 Kind : Source_Kind := Spec;
8076 Name_Len := Display_Path'Length;
8077 Name_Buffer (1 .. Name_Len) := Display_Path;
8078 Display_Path_Id := Name_Find;
8080 if Osint.File_Names_Case_Sensitive then
8081 Path_Id := Display_Path_Id;
8083 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8084 Path_Id := Name_Find;
8087 if Name_Loc = No_Name_Location then
8088 Check_Name := For_All_Sources;
8091 if Name_Loc.Found then
8093 -- Check if it is OK to have the same file name in several
8094 -- source directories.
8096 if not Data.Known_Order_Of_Source_Dirs then
8097 Error_Msg_File_1 := File_Name;
8100 "{ is found in several source directories",
8105 Name_Loc.Found := True;
8107 Source_Names.Set (File_Name, Name_Loc);
8109 if Name_Loc.Source = No_Source then
8113 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8114 (Path_Id, Display_Path_Id);
8116 Source_Paths_Htable.Set
8117 (In_Tree.Source_Paths_HT,
8121 -- Check if this is a subunit
8123 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8125 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8127 Src_Ind := Sinput.P.Load_Project_File
8128 (Get_Name_String (Path_Id));
8130 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8131 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8139 Other_Part := No_Source;
8141 Check_Naming_Schemes
8142 (In_Tree => In_Tree,
8144 Filename => Get_Name_String (File_Name),
8145 File_Name => File_Name,
8146 Alternate_Languages => Alternate_Languages,
8147 Language => Language,
8148 Language_Name => Language_Name,
8149 Display_Language_Name => Display_Language_Name,
8151 Lang_Kind => Lang_Kind,
8154 if Language = No_Language_Index then
8156 -- A file name in a list must be a source of a language
8158 if Name_Loc.Found then
8159 Error_Msg_File_1 := File_Name;
8163 "language unknown for {",
8168 -- Check if the same file name or unit is used in the prj tree
8170 Source := In_Tree.First_Source;
8172 while Source /= No_Source loop
8174 Src_Data : Source_Data renames
8175 In_Tree.Sources.Table (Source);
8179 and then Src_Data.Unit = Unit
8181 ((Src_Data.Kind = Spec and then Kind = Impl)
8183 (Src_Data.Kind = Impl and then Kind = Spec))
8185 Other_Part := Source;
8187 elsif (Unit /= No_Name
8188 and then Src_Data.Unit = Unit
8190 (Src_Data.Kind = Kind
8192 (Src_Data.Kind = Sep and then Kind = Impl)
8194 (Src_Data.Kind = Impl and then Kind = Sep)))
8196 (Unit = No_Name and then Src_Data.File = File_Name)
8198 -- Duplication of file/unit in same project is only
8199 -- allowed if order of source directories is known.
8201 if Project = Src_Data.Project then
8202 if Data.Known_Order_Of_Source_Dirs then
8205 elsif Unit /= No_Name then
8206 Error_Msg_Name_1 := Unit;
8208 (Project, In_Tree, "duplicate unit %%",
8213 Error_Msg_File_1 := File_Name;
8215 (Project, In_Tree, "duplicate source file name {",
8220 -- Do not allow the same unit name in different
8221 -- projects, except if one is extending the other.
8223 -- For a file based language, the same file name
8224 -- replaces a file in a project being extended, but
8225 -- it is allowed to have the same file name in
8226 -- unrelated projects.
8229 (Project, Src_Data.Project, In_Tree)
8231 Source_To_Replace := Source;
8233 elsif Unit /= No_Name
8234 and then not Src_Data.Locally_Removed
8236 Error_Msg_Name_1 := Unit;
8239 "unit %% cannot belong to several projects",
8243 In_Tree.Projects.Table (Project).Name;
8244 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8246 (Project, In_Tree, "\ project %%, %%", No_Location);
8249 In_Tree.Projects.Table (Src_Data.Project).Name;
8251 Name_Id (Src_Data.Path.Display_Name);
8253 (Project, In_Tree, "\ project %%, %%", No_Location);
8259 Source := Src_Data.Next_In_Sources;
8269 Lang => Language_Name,
8270 Lang_Id => Language,
8271 Lang_Kind => Lang_Kind,
8273 Alternate_Languages => Alternate_Languages,
8274 File_Name => File_Name,
8275 Display_File => Display_File_Name,
8276 Other_Part => Other_Part,
8279 Display_Path => Display_Path_Id,
8280 Source_To_Replace => Source_To_Replace);
8286 ------------------------
8287 -- Search_Directories --
8288 ------------------------
8290 procedure Search_Directories
8291 (Project : Project_Id;
8292 In_Tree : Project_Tree_Ref;
8293 Data : in out Project_Data;
8294 For_All_Sources : Boolean)
8296 Source_Dir : String_List_Id;
8297 Element : String_Element;
8299 Name : String (1 .. 1_000);
8301 File_Name : File_Name_Type;
8302 Display_File_Name : File_Name_Type;
8305 if Current_Verbosity = High then
8306 Write_Line ("Looking for sources:");
8309 -- Loop through subdirectories
8311 Source_Dir := Data.Source_Dirs;
8312 while Source_Dir /= Nil_String loop
8314 Element := In_Tree.String_Elements.Table (Source_Dir);
8315 if Element.Value /= No_Name then
8316 Get_Name_String (Element.Display_Value);
8319 Source_Directory : constant String :=
8320 Name_Buffer (1 .. Name_Len) &
8321 Directory_Separator;
8323 Dir_Last : constant Natural :=
8324 Compute_Directory_Last
8328 if Current_Verbosity = High then
8329 Write_Str ("Source_Dir = ");
8330 Write_Line (Source_Directory);
8333 -- We look to every entry in the source directory
8335 Open (Dir, Source_Directory);
8338 Read (Dir, Name, Last);
8342 -- ??? Duplicate system call here, we just did a
8343 -- a similar one. Maybe Ada.Directories would be more
8347 (Source_Directory & Name (1 .. Last))
8349 if Current_Verbosity = High then
8350 Write_Str (" Checking ");
8351 Write_Line (Name (1 .. Last));
8355 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8356 Display_File_Name := Name_Find;
8358 if Osint.File_Names_Case_Sensitive then
8359 File_Name := Display_File_Name;
8361 Canonical_Case_File_Name
8362 (Name_Buffer (1 .. Name_Len));
8363 File_Name := Name_Find;
8368 Excluded_Sources_Htable.Get (File_Name);
8371 if FF /= No_File_Found then
8372 if not FF.Found then
8374 Excluded_Sources_Htable.Set
8377 if Current_Verbosity = High then
8378 Write_Str (" excluded source """);
8379 Write_Str (Get_Name_String (File_Name));
8386 (Project => Project,
8389 Name => Name (1 .. Last),
8390 File_Name => File_Name,
8391 Display_File_Name => Display_File_Name,
8392 Source_Directory => Source_Directory
8393 (Source_Directory'First .. Dir_Last),
8394 For_All_Sources => For_All_Sources);
8405 when Directory_Error =>
8409 Source_Dir := Element.Next;
8412 if Current_Verbosity = High then
8413 Write_Line ("end Looking for sources.");
8415 end Search_Directories;
8417 ----------------------
8418 -- Look_For_Sources --
8419 ----------------------
8421 procedure Look_For_Sources
8422 (Project : Project_Id;
8423 In_Tree : Project_Tree_Ref;
8424 Data : in out Project_Data;
8425 Current_Dir : String)
8427 procedure Remove_Locally_Removed_Files_From_Units;
8428 -- Mark all locally removed sources as such in the Units table
8430 procedure Process_Sources_In_Multi_Language_Mode;
8431 -- Find all source files when in multi language mode
8433 ---------------------------------------------
8434 -- Remove_Locally_Removed_Files_From_Units --
8435 ---------------------------------------------
8437 procedure Remove_Locally_Removed_Files_From_Units is
8438 Excluded : File_Found;
8441 Extended : Project_Id;
8444 Excluded := Excluded_Sources_Htable.Get_First;
8445 while Excluded /= No_File_Found loop
8449 for Index in Unit_Table.First ..
8450 Unit_Table.Last (In_Tree.Units)
8452 Unit := In_Tree.Units.Table (Index);
8454 for Kind in Spec_Or_Body'Range loop
8455 if Unit.File_Names (Kind).Name = Excluded.File then
8458 -- Check that this is from the current project or
8459 -- that the current project extends.
8461 Extended := Unit.File_Names (Kind).Project;
8463 if Extended = Project
8464 or else Project_Extends (Project, Extended, In_Tree)
8466 Unit.File_Names (Kind).Path.Name := Slash;
8467 Unit.File_Names (Kind).Needs_Pragma := False;
8468 In_Tree.Units.Table (Index) := Unit;
8469 Add_Forbidden_File_Name
8470 (Unit.File_Names (Kind).Name);
8474 "cannot remove a source from " &
8481 end loop For_Each_Unit;
8484 Err_Vars.Error_Msg_File_1 := Excluded.File;
8486 (Project, In_Tree, "unknown file {", Excluded.Location);
8489 Excluded := Excluded_Sources_Htable.Get_Next;
8491 end Remove_Locally_Removed_Files_From_Units;
8493 --------------------------------------------
8494 -- Process_Sources_In_Multi_Language_Mode --
8495 --------------------------------------------
8497 procedure Process_Sources_In_Multi_Language_Mode is
8499 Name_Loc : Name_Location;
8504 -- First, put all naming exceptions if any, in the Source_Names table
8506 Unit_Exceptions.Reset;
8508 Source := Data.First_Source;
8509 while Source /= No_Source loop
8511 Src_Data : Source_Data renames In_Tree.Sources.Table (Source);
8514 -- An excluded file cannot also be an exception file name
8516 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8519 Error_Msg_File_1 := Src_Data.File;
8522 "{ cannot be both excluded and an exception file name",
8526 Name_Loc := (Name => Src_Data.File,
8527 Location => No_Location,
8529 Except => Src_Data.Unit /= No_Name,
8532 if Current_Verbosity = High then
8533 Write_Str ("Putting source #");
8534 Write_Str (Source'Img);
8535 Write_Str (", file ");
8536 Write_Str (Get_Name_String (Src_Data.File));
8537 Write_Line (" in Source_Names");
8540 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8542 -- If this is an Ada exception, record in table Unit_Exceptions
8544 if Src_Data.Unit /= No_Name then
8546 Unit_Except : Unit_Exception :=
8547 Unit_Exceptions.Get (Src_Data.Unit);
8550 Unit_Except.Name := Src_Data.Unit;
8552 if Src_Data.Kind = Spec then
8553 Unit_Except.Spec := Src_Data.File;
8555 Unit_Except.Impl := Src_Data.File;
8558 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8562 Source := Src_Data.Next_In_Project;
8566 Find_Explicit_Sources
8567 (Current_Dir, Project, In_Tree, Data);
8569 -- Mark as such the sources that are declared as excluded
8571 FF := Excluded_Sources_Htable.Get_First;
8572 while FF /= No_File_Found loop
8574 Source := In_Tree.First_Source;
8575 while Source /= No_Source loop
8577 Src_Data : Source_Data renames
8578 In_Tree.Sources.Table (Source);
8581 if Src_Data.File = FF.File then
8583 -- Check that this is from this project or a project that
8584 -- the current project extends.
8586 if Src_Data.Project = Project or else
8587 Is_Extending (Project, Src_Data.Project, In_Tree)
8589 Src_Data.Locally_Removed := True;
8590 Src_Data.In_Interfaces := False;
8591 Add_Forbidden_File_Name (FF.File);
8597 Source := Src_Data.Next_In_Sources;
8601 if not FF.Found and not OK then
8602 Err_Vars.Error_Msg_File_1 := FF.File;
8603 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8606 FF := Excluded_Sources_Htable.Get_Next;
8609 -- Check that two sources of this project do not have the same object
8612 Check_Object_File_Names : declare
8614 Source_Name : File_Name_Type;
8616 procedure Check_Object (Src_Data : Source_Data);
8617 -- Check if object file name of the current source is already in
8618 -- hash table Object_File_Names. If it is, report an error. If it
8619 -- is not, put it there with the file name of the current source.
8625 procedure Check_Object (Src_Data : Source_Data) is
8627 Source_Name := Object_File_Names.Get (Src_Data.Object);
8629 if Source_Name /= No_File then
8630 Error_Msg_File_1 := Src_Data.File;
8631 Error_Msg_File_2 := Source_Name;
8635 "{ and { have the same object file name",
8639 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8643 -- Start of processing for Check_Object_File_Names
8646 Object_File_Names.Reset;
8647 Src_Id := In_Tree.First_Source;
8648 while Src_Id /= No_Source loop
8650 Src_Data : Source_Data renames
8651 In_Tree.Sources.Table (Src_Id);
8654 if Src_Data.Compiled and then Src_Data.Object_Exists
8655 and then Project_Extends
8656 (Project, Src_Data.Project, In_Tree)
8658 if Src_Data.Unit = No_Name then
8659 if Src_Data.Kind = Impl then
8660 Check_Object (Src_Data);
8664 case Src_Data.Kind is
8666 if Src_Data.Other_Part = No_Source then
8667 Check_Object (Src_Data);
8674 if Src_Data.Other_Part /= No_Source then
8675 Check_Object (Src_Data);
8678 -- Check if it is a subunit
8681 Src_Ind : constant Source_File_Index :=
8682 Sinput.P.Load_Project_File
8684 (Src_Data.Path.Name));
8686 if Sinput.P.Source_File_Is_Subunit
8689 In_Tree.Sources.Table (Src_Id).Kind :=
8692 Check_Object (Src_Data);
8700 Src_Id := Src_Data.Next_In_Sources;
8703 end Check_Object_File_Names;
8704 end Process_Sources_In_Multi_Language_Mode;
8706 -- Start of processing for Look_For_Sources
8710 Find_Excluded_Sources (Project, In_Tree, Data);
8714 if Is_A_Language (In_Tree, Data, Name_Ada) then
8715 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8716 Remove_Locally_Removed_Files_From_Units;
8719 when Multi_Language =>
8720 if Data.First_Language_Processing /= No_Language_Index then
8721 Process_Sources_In_Multi_Language_Mode;
8724 end Look_For_Sources;
8730 function Path_Name_Of
8731 (File_Name : File_Name_Type;
8732 Directory : Path_Name_Type) return String
8734 Result : String_Access;
8735 The_Directory : constant String := Get_Name_String (Directory);
8738 Get_Name_String (File_Name);
8741 (File_Name => Name_Buffer (1 .. Name_Len),
8742 Path => The_Directory);
8744 if Result = null then
8747 Canonical_Case_File_Name (Result.all);
8752 -------------------------------
8753 -- Prepare_Ada_Naming_Exceptions --
8754 -------------------------------
8756 procedure Prepare_Ada_Naming_Exceptions
8757 (List : Array_Element_Id;
8758 In_Tree : Project_Tree_Ref;
8759 Kind : Spec_Or_Body)
8761 Current : Array_Element_Id;
8762 Element : Array_Element;
8766 -- Traverse the list
8769 while Current /= No_Array_Element loop
8770 Element := In_Tree.Array_Elements.Table (Current);
8772 if Element.Index /= No_Name then
8775 Unit => Element.Index,
8776 Next => No_Ada_Naming_Exception);
8777 Reverse_Ada_Naming_Exceptions.Set
8778 (Unit, (Element.Value.Value, Element.Value.Index));
8780 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8781 Ada_Naming_Exception_Table.Increment_Last;
8782 Ada_Naming_Exception_Table.Table
8783 (Ada_Naming_Exception_Table.Last) := Unit;
8784 Ada_Naming_Exceptions.Set
8785 (File_Name_Type (Element.Value.Value),
8786 Ada_Naming_Exception_Table.Last);
8789 Current := Element.Next;
8791 end Prepare_Ada_Naming_Exceptions;
8793 ---------------------
8794 -- Project_Extends --
8795 ---------------------
8797 function Project_Extends
8798 (Extending : Project_Id;
8799 Extended : Project_Id;
8800 In_Tree : Project_Tree_Ref) return Boolean
8802 Current : Project_Id := Extending;
8806 if Current = No_Project then
8809 elsif Current = Extended then
8813 Current := In_Tree.Projects.Table (Current).Extends;
8815 end Project_Extends;
8817 -----------------------
8818 -- Record_Ada_Source --
8819 -----------------------
8821 procedure Record_Ada_Source
8822 (File_Name : File_Name_Type;
8823 Path_Name : Path_Name_Type;
8824 Project : Project_Id;
8825 In_Tree : Project_Tree_Ref;
8826 Data : in out Project_Data;
8827 Location : Source_Ptr;
8828 Current_Source : in out String_List_Id;
8829 Source_Recorded : in out Boolean;
8830 Current_Dir : String)
8832 Canonical_File_Name : File_Name_Type;
8833 Canonical_Path_Name : Path_Name_Type;
8835 Exception_Id : Ada_Naming_Exception_Id;
8836 Unit_Name : Name_Id;
8837 Unit_Kind : Spec_Or_Body;
8838 Unit_Ind : Int := 0;
8840 Name_Index : Name_And_Index;
8841 Needs_Pragma : Boolean;
8843 The_Location : Source_Ptr := Location;
8844 Previous_Source : constant String_List_Id := Current_Source;
8845 Except_Name : Name_And_Index := No_Name_And_Index;
8847 Unit_Prj : Unit_Project;
8849 File_Name_Recorded : Boolean := False;
8852 if Osint.File_Names_Case_Sensitive then
8853 Canonical_File_Name := File_Name;
8854 Canonical_Path_Name := Path_Name;
8856 Get_Name_String (File_Name);
8857 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8858 Canonical_File_Name := Name_Find;
8861 Canonical_Path : constant String :=
8863 (Get_Name_String (Path_Name),
8864 Directory => Current_Dir,
8865 Resolve_Links => Opt.Follow_Links_For_Files,
8866 Case_Sensitive => False);
8869 Add_Str_To_Name_Buffer (Canonical_Path);
8870 Canonical_Path_Name := Name_Find;
8874 -- Find out the unit name, the unit kind and if it needs
8875 -- a specific SFN pragma.
8878 (In_Tree => In_Tree,
8879 Canonical_File_Name => Canonical_File_Name,
8880 Naming => Data.Naming,
8881 Exception_Id => Exception_Id,
8882 Unit_Name => Unit_Name,
8883 Unit_Kind => Unit_Kind,
8884 Needs_Pragma => Needs_Pragma);
8886 if Exception_Id = No_Ada_Naming_Exception
8887 and then Unit_Name = No_Name
8889 if Current_Verbosity = High then
8891 Write_Str (Get_Name_String (Canonical_File_Name));
8892 Write_Line (""" is not a valid source file name (ignored).");
8896 -- Check to see if the source has been hidden by an exception,
8897 -- but only if it is not an exception.
8899 if not Needs_Pragma then
8901 Reverse_Ada_Naming_Exceptions.Get
8902 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8904 if Except_Name /= No_Name_And_Index then
8905 if Current_Verbosity = High then
8907 Write_Str (Get_Name_String (Canonical_File_Name));
8908 Write_Str (""" contains a unit that is found in """);
8909 Write_Str (Get_Name_String (Except_Name.Name));
8910 Write_Line (""" (ignored).");
8913 -- The file is not included in the source of the project since
8914 -- it is hidden by the exception. So, nothing else to do.
8921 if Exception_Id /= No_Ada_Naming_Exception then
8922 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8923 Exception_Id := Info.Next;
8924 Info.Next := No_Ada_Naming_Exception;
8925 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8927 Unit_Name := Info.Unit;
8928 Unit_Ind := Name_Index.Index;
8929 Unit_Kind := Info.Kind;
8932 -- Put the file name in the list of sources of the project
8934 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8935 In_Tree.String_Elements.Table
8936 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8937 (Value => Name_Id (Canonical_File_Name),
8938 Display_Value => Name_Id (File_Name),
8939 Location => No_Location,
8944 if Current_Source = Nil_String then
8946 String_Element_Table.Last (In_Tree.String_Elements);
8948 In_Tree.String_Elements.Table (Current_Source).Next :=
8949 String_Element_Table.Last (In_Tree.String_Elements);
8953 String_Element_Table.Last (In_Tree.String_Elements);
8955 -- Put the unit in unit list
8958 The_Unit : Unit_Index :=
8959 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8961 The_Unit_Data : Unit_Data;
8964 if Current_Verbosity = High then
8965 Write_Str ("Putting ");
8966 Write_Str (Get_Name_String (Unit_Name));
8967 Write_Line (" in the unit list.");
8970 -- The unit is already in the list, but may be it is
8971 -- only the other unit kind (spec or body), or what is
8972 -- in the unit list is a unit of a project we are extending.
8974 if The_Unit /= No_Unit_Index then
8975 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8977 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8980 The_Unit_Data.File_Names
8981 (Unit_Kind).Path.Name = Slash)
8982 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8983 or else Project_Extends
8985 The_Unit_Data.File_Names (Unit_Kind).Project,
8989 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
8991 Remove_Forbidden_File_Name
8992 (The_Unit_Data.File_Names (Unit_Kind).Name);
8995 -- Record the file name in the hash table Files_Htable
8997 Unit_Prj := (Unit => The_Unit, Project => Project);
9000 Canonical_File_Name,
9003 The_Unit_Data.File_Names (Unit_Kind) :=
9004 (Name => Canonical_File_Name,
9006 Display_Name => File_Name,
9007 Path => (Canonical_Path_Name, Path_Name),
9009 Needs_Pragma => Needs_Pragma);
9010 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9011 Source_Recorded := True;
9013 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
9014 and then (Data.Known_Order_Of_Source_Dirs
9016 The_Unit_Data.File_Names
9017 (Unit_Kind).Path.Name = Canonical_Path_Name)
9019 if Previous_Source = Nil_String then
9020 Data.Ada_Sources := Nil_String;
9022 In_Tree.String_Elements.Table (Previous_Source).Next :=
9024 String_Element_Table.Decrement_Last
9025 (In_Tree.String_Elements);
9028 Current_Source := Previous_Source;
9031 -- It is an error to have two units with the same name
9032 -- and the same kind (spec or body).
9034 if The_Location = No_Location then
9036 In_Tree.Projects.Table (Project).Location;
9039 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9041 (Project, In_Tree, "duplicate unit %%", The_Location);
9043 Err_Vars.Error_Msg_Name_1 :=
9044 In_Tree.Projects.Table
9045 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9046 Err_Vars.Error_Msg_File_1 :=
9048 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
9051 "\ project file %%, {", The_Location);
9053 Err_Vars.Error_Msg_Name_1 :=
9054 In_Tree.Projects.Table (Project).Name;
9055 Err_Vars.Error_Msg_File_1 :=
9056 File_Name_Type (Canonical_Path_Name);
9059 "\ project file %%, {", The_Location);
9062 -- It is a new unit, create a new record
9065 -- First, check if there is no other unit with this file
9066 -- name in another project. If it is, report error but note
9067 -- we do that only for the first unit in the source file.
9070 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
9072 if not File_Name_Recorded and then
9073 Unit_Prj /= No_Unit_Project
9075 Error_Msg_File_1 := File_Name;
9077 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9080 "{ is already a source of project %%",
9084 Unit_Table.Increment_Last (In_Tree.Units);
9085 The_Unit := Unit_Table.Last (In_Tree.Units);
9087 (In_Tree.Units_HT, Unit_Name, The_Unit);
9088 Unit_Prj := (Unit => The_Unit, Project => Project);
9091 Canonical_File_Name,
9093 The_Unit_Data.Name := Unit_Name;
9094 The_Unit_Data.File_Names (Unit_Kind) :=
9095 (Name => Canonical_File_Name,
9097 Display_Name => File_Name,
9098 Path => (Canonical_Path_Name, Path_Name),
9100 Needs_Pragma => Needs_Pragma);
9101 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9102 Source_Recorded := True;
9107 exit when Exception_Id = No_Ada_Naming_Exception;
9108 File_Name_Recorded := True;
9111 end Record_Ada_Source;
9117 procedure Remove_Source
9119 Replaced_By : Source_Id;
9120 Project : Project_Id;
9121 Data : in out Project_Data;
9122 In_Tree : Project_Tree_Ref)
9124 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9128 if Current_Verbosity = High then
9129 Write_Str ("Removing source #");
9130 Write_Line (Id'Img);
9133 if Replaced_By /= No_Source then
9134 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9135 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9136 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9139 -- Remove the source from the global source list
9141 Source := In_Tree.First_Source;
9144 In_Tree.First_Source := Src_Data.Next_In_Sources;
9147 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9148 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9151 In_Tree.Sources.Table (Source).Next_In_Sources :=
9152 Src_Data.Next_In_Sources;
9155 -- Remove the source from the project list
9157 if Src_Data.Project = Project then
9158 Source := Data.First_Source;
9161 Data.First_Source := Src_Data.Next_In_Project;
9163 if Src_Data.Next_In_Project = No_Source then
9164 Data.Last_Source := No_Source;
9168 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9169 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9172 In_Tree.Sources.Table (Source).Next_In_Project :=
9173 Src_Data.Next_In_Project;
9175 if Src_Data.Next_In_Project = No_Source then
9176 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9181 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9184 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9185 Src_Data.Next_In_Project;
9187 if Src_Data.Next_In_Project = No_Source then
9188 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9193 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9194 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9197 In_Tree.Sources.Table (Source).Next_In_Project :=
9198 Src_Data.Next_In_Project;
9200 if Src_Data.Next_In_Project = No_Source then
9201 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9206 -- Remove source from the language list
9208 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9211 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9212 Src_Data.Next_In_Lang;
9215 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9216 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9219 In_Tree.Sources.Table (Source).Next_In_Lang :=
9220 Src_Data.Next_In_Lang;
9224 -----------------------
9225 -- Report_No_Sources --
9226 -----------------------
9228 procedure Report_No_Sources
9229 (Project : Project_Id;
9231 In_Tree : Project_Tree_Ref;
9232 Location : Source_Ptr;
9233 Continuation : Boolean := False)
9236 case When_No_Sources is
9240 when Warning | Error =>
9242 Msg : constant String :=
9245 " sources in this project";
9248 Error_Msg_Warn := When_No_Sources = Warning;
9250 if Continuation then
9252 (Project, In_Tree, "\" & Msg, Location);
9256 (Project, In_Tree, Msg, Location);
9260 end Report_No_Sources;
9262 ----------------------
9263 -- Show_Source_Dirs --
9264 ----------------------
9266 procedure Show_Source_Dirs
9267 (Data : Project_Data;
9268 In_Tree : Project_Tree_Ref)
9270 Current : String_List_Id;
9271 Element : String_Element;
9274 Write_Line ("Source_Dirs:");
9276 Current := Data.Source_Dirs;
9277 while Current /= Nil_String loop
9278 Element := In_Tree.String_Elements.Table (Current);
9280 Write_Line (Get_Name_String (Element.Value));
9281 Current := Element.Next;
9284 Write_Line ("end Source_Dirs.");
9285 end Show_Source_Dirs;
9287 -------------------------
9288 -- Warn_If_Not_Sources --
9289 -------------------------
9291 -- comments needed in this body ???
9293 procedure Warn_If_Not_Sources
9294 (Project : Project_Id;
9295 In_Tree : Project_Tree_Ref;
9296 Conventions : Array_Element_Id;
9298 Extending : Boolean)
9300 Conv : Array_Element_Id;
9302 The_Unit_Id : Unit_Index;
9303 The_Unit_Data : Unit_Data;
9304 Location : Source_Ptr;
9307 Conv := Conventions;
9308 while Conv /= No_Array_Element loop
9309 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9310 Error_Msg_Name_1 := Unit;
9311 Get_Name_String (Unit);
9312 To_Lower (Name_Buffer (1 .. Name_Len));
9314 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9315 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9317 if The_Unit_Id = No_Unit_Index then
9318 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9321 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9323 In_Tree.Array_Elements.Table (Conv).Value.Value;
9326 if not Check_Project
9327 (The_Unit_Data.File_Names (Specification).Project,
9328 Project, In_Tree, Extending)
9332 "?source of spec of unit %% (%%)" &
9333 " cannot be found in this project",
9338 if not Check_Project
9339 (The_Unit_Data.File_Names (Body_Part).Project,
9340 Project, In_Tree, Extending)
9344 "?source of body of unit %% (%%)" &
9345 " cannot be found in this project",
9351 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9353 end Warn_If_Not_Sources;