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 Setup_Projects
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 Setup_Projects 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;
1843 elsif Attribute.Name = Name_Max_Command_Line_Length then
1845 Data.Config.Max_Command_Line_Length :=
1846 Natural'Value (Get_Name_String
1847 (Attribute.Value.Value));
1850 when Constraint_Error =>
1854 "value must be positive or equal to 0",
1855 Attribute.Value.Location);
1858 elsif Attribute.Name = Name_Response_File_Format then
1863 Get_Name_String (Attribute.Value.Value);
1864 To_Lower (Name_Buffer (1 .. Name_Len));
1867 if Name = Name_None then
1868 Data.Config.Resp_File_Format := None;
1870 elsif Name = Name_Gnu then
1871 Data.Config.Resp_File_Format := GNU;
1873 elsif Name = Name_Object_List then
1874 Data.Config.Resp_File_Format := Object_List;
1876 elsif Name = Name_Option_List then
1877 Data.Config.Resp_File_Format := Option_List;
1883 "illegal response file format",
1884 Attribute.Value.Location);
1888 elsif Attribute.Name = Name_Response_File_Switches then
1890 Data.Config.Resp_File_Options,
1891 From_List => Attribute.Value.Values,
1892 In_Tree => In_Tree);
1896 Attribute_Id := Attribute.Next;
1900 -- Start of processing for Process_Packages
1903 Packages := Data.Decl.Packages;
1904 while Packages /= No_Package loop
1905 Element := In_Tree.Packages.Table (Packages);
1907 case Element.Name is
1910 -- Process attributes of package Binder
1912 Process_Binder (Element.Decl.Arrays);
1914 when Name_Builder =>
1916 -- Process attributes of package Builder
1918 Process_Builder (Element.Decl.Attributes);
1920 when Name_Compiler =>
1922 -- Process attributes of package Compiler
1924 Process_Compiler (Element.Decl.Arrays);
1928 -- Process attributes of package Linker
1930 Process_Linker (Element.Decl.Attributes);
1934 -- Process attributes of package Naming
1936 Process_Naming (Element.Decl.Attributes);
1937 Process_Naming (Element.Decl.Arrays);
1943 Packages := Element.Next;
1945 end Process_Packages;
1947 ---------------------------------------------
1948 -- Process_Project_Level_Simple_Attributes --
1949 ---------------------------------------------
1951 procedure Process_Project_Level_Simple_Attributes is
1952 Attribute_Id : Variable_Id;
1953 Attribute : Variable;
1954 List : String_List_Id;
1957 -- Process non associated array attribute at project level
1959 Attribute_Id := Data.Decl.Attributes;
1960 while Attribute_Id /= No_Variable loop
1962 In_Tree.Variable_Elements.Table (Attribute_Id);
1964 if not Attribute.Value.Default then
1965 if Attribute.Name = Name_Library_Builder then
1967 -- Attribute Library_Builder: the application to invoke
1968 -- to build libraries.
1970 Data.Config.Library_Builder :=
1971 Path_Name_Type (Attribute.Value.Value);
1973 elsif Attribute.Name = Name_Archive_Builder then
1975 -- Attribute Archive_Builder: the archive builder
1976 -- (usually "ar") and its minimum options (usually "cr").
1978 List := Attribute.Value.Values;
1980 if List = Nil_String then
1984 "archive builder cannot be null",
1985 Attribute.Value.Location);
1988 Put (Into_List => Data.Config.Archive_Builder,
1990 In_Tree => In_Tree);
1992 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1994 -- Attribute Archive_Builder: the archive builder
1995 -- (usually "ar") and its minimum options (usually "cr").
1997 List := Attribute.Value.Values;
1999 if List /= Nil_String then
2001 (Into_List => Data.Config.Archive_Builder_Append_Option,
2003 In_Tree => In_Tree);
2006 elsif Attribute.Name = Name_Archive_Indexer then
2008 -- Attribute Archive_Indexer: the optional archive
2009 -- indexer (usually "ranlib") with its minimum options
2012 List := Attribute.Value.Values;
2014 if List = Nil_String then
2018 "archive indexer cannot be null",
2019 Attribute.Value.Location);
2022 Put (Into_List => Data.Config.Archive_Indexer,
2024 In_Tree => In_Tree);
2026 elsif Attribute.Name = Name_Library_Partial_Linker then
2028 -- Attribute Library_Partial_Linker: the optional linker
2029 -- driver with its minimum options, to partially link
2032 List := Attribute.Value.Values;
2034 if List = Nil_String then
2038 "partial linker cannot be null",
2039 Attribute.Value.Location);
2042 Put (Into_List => Data.Config.Lib_Partial_Linker,
2044 In_Tree => In_Tree);
2046 elsif Attribute.Name = Name_Library_GCC then
2047 Data.Config.Shared_Lib_Driver :=
2048 File_Name_Type (Attribute.Value.Value);
2050 elsif Attribute.Name = Name_Archive_Suffix then
2051 Data.Config.Archive_Suffix :=
2052 File_Name_Type (Attribute.Value.Value);
2054 elsif Attribute.Name = Name_Linker_Executable_Option then
2056 -- Attribute Linker_Executable_Option: optional options
2057 -- to specify an executable name. Defaults to "-o".
2059 List := Attribute.Value.Values;
2061 if List = Nil_String then
2065 "linker executable option cannot be null",
2066 Attribute.Value.Location);
2069 Put (Into_List => Data.Config.Linker_Executable_Option,
2071 In_Tree => In_Tree);
2073 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2075 -- Attribute Linker_Lib_Dir_Option: optional options
2076 -- to specify a library search directory. Defaults to
2079 Get_Name_String (Attribute.Value.Value);
2081 if Name_Len = 0 then
2085 "linker library directory option cannot be empty",
2086 Attribute.Value.Location);
2089 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2091 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2093 -- Attribute Linker_Lib_Name_Option: optional options
2094 -- to specify the name of a library to be linked in.
2095 -- Defaults to "-l".
2097 Get_Name_String (Attribute.Value.Value);
2099 if Name_Len = 0 then
2103 "linker library name option cannot be empty",
2104 Attribute.Value.Location);
2107 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2109 elsif Attribute.Name = Name_Run_Path_Option then
2111 -- Attribute Run_Path_Option: optional options to
2112 -- specify a path for libraries.
2114 List := Attribute.Value.Values;
2116 if List /= Nil_String then
2117 Put (Into_List => Data.Config.Run_Path_Option,
2119 In_Tree => In_Tree);
2122 elsif Attribute.Name = Name_Library_Support then
2124 pragma Unsuppress (All_Checks);
2126 Data.Config.Lib_Support :=
2127 Library_Support'Value (Get_Name_String
2128 (Attribute.Value.Value));
2130 when Constraint_Error =>
2134 "invalid value """ &
2135 Get_Name_String (Attribute.Value.Value) &
2136 """ for Library_Support",
2137 Attribute.Value.Location);
2140 elsif Attribute.Name = Name_Shared_Library_Prefix then
2141 Data.Config.Shared_Lib_Prefix :=
2142 File_Name_Type (Attribute.Value.Value);
2144 elsif Attribute.Name = Name_Shared_Library_Suffix then
2145 Data.Config.Shared_Lib_Suffix :=
2146 File_Name_Type (Attribute.Value.Value);
2148 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2150 pragma Unsuppress (All_Checks);
2152 Data.Config.Symbolic_Link_Supported :=
2153 Boolean'Value (Get_Name_String
2154 (Attribute.Value.Value));
2156 when Constraint_Error =>
2161 & Get_Name_String (Attribute.Value.Value)
2162 & """ for Symbolic_Link_Supported",
2163 Attribute.Value.Location);
2167 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2170 pragma Unsuppress (All_Checks);
2172 Data.Config.Lib_Maj_Min_Id_Supported :=
2173 Boolean'Value (Get_Name_String
2174 (Attribute.Value.Value));
2176 when Constraint_Error =>
2180 "invalid value """ &
2181 Get_Name_String (Attribute.Value.Value) &
2182 """ for Library_Major_Minor_Id_Supported",
2183 Attribute.Value.Location);
2186 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2188 pragma Unsuppress (All_Checks);
2190 Data.Config.Auto_Init_Supported :=
2191 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2193 when Constraint_Error =>
2198 & Get_Name_String (Attribute.Value.Value)
2199 & """ for Library_Auto_Init_Supported",
2200 Attribute.Value.Location);
2203 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2204 List := Attribute.Value.Values;
2206 if List /= Nil_String then
2207 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2209 In_Tree => In_Tree);
2212 elsif Attribute.Name = Name_Library_Version_Switches then
2213 List := Attribute.Value.Values;
2215 if List /= Nil_String then
2216 Put (Into_List => Data.Config.Lib_Version_Options,
2218 In_Tree => In_Tree);
2223 Attribute_Id := Attribute.Next;
2225 end Process_Project_Level_Simple_Attributes;
2227 --------------------------------------------
2228 -- Process_Project_Level_Array_Attributes --
2229 --------------------------------------------
2231 procedure Process_Project_Level_Array_Attributes is
2232 Current_Array_Id : Array_Id;
2233 Current_Array : Array_Data;
2234 Element_Id : Array_Element_Id;
2235 Element : Array_Element;
2236 List : String_List_Id;
2239 -- Process the associative array attributes at project level
2241 Current_Array_Id := Data.Decl.Arrays;
2242 while Current_Array_Id /= No_Array loop
2243 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2245 Element_Id := Current_Array.Value;
2246 while Element_Id /= No_Array_Element loop
2247 Element := In_Tree.Array_Elements.Table (Element_Id);
2249 -- Get the name of the language
2251 Get_Language_Index_Of (Element.Index);
2253 if Lang_Index /= No_Language_Index then
2254 case Current_Array.Name is
2255 when Name_Inherit_Source_Path =>
2256 List := Element.Value.Values;
2258 if List /= Nil_String then
2261 In_Tree.Languages_Data.Table (Lang_Index).
2262 Config.Include_Compatible_Languages,
2265 Lower_Case => True);
2268 when Name_Toolchain_Description =>
2270 -- Attribute Toolchain_Description (<language>)
2272 In_Tree.Languages_Data.Table
2273 (Lang_Index).Config.Toolchain_Description :=
2274 Element.Value.Value;
2276 when Name_Toolchain_Version =>
2278 -- Attribute Toolchain_Version (<language>)
2280 In_Tree.Languages_Data.Table
2281 (Lang_Index).Config.Toolchain_Version :=
2282 Element.Value.Value;
2284 when Name_Runtime_Library_Dir =>
2286 -- Attribute Runtime_Library_Dir (<language>)
2288 In_Tree.Languages_Data.Table
2289 (Lang_Index).Config.Runtime_Library_Dir :=
2290 Element.Value.Value;
2292 when Name_Object_Generated =>
2294 pragma Unsuppress (All_Checks);
2300 (Get_Name_String (Element.Value.Value));
2302 In_Tree.Languages_Data.Table
2303 (Lang_Index).Config.Object_Generated := Value;
2305 -- If no object is generated, no object may be
2309 In_Tree.Languages_Data.Table
2310 (Lang_Index).Config.Objects_Linked := False;
2314 when Constraint_Error =>
2319 & Get_Name_String (Element.Value.Value)
2320 & """ for Object_Generated",
2321 Element.Value.Location);
2324 when Name_Objects_Linked =>
2326 pragma Unsuppress (All_Checks);
2332 (Get_Name_String (Element.Value.Value));
2334 -- No change if Object_Generated is False, as this
2335 -- forces Objects_Linked to be False too.
2337 if In_Tree.Languages_Data.Table
2338 (Lang_Index).Config.Object_Generated
2340 In_Tree.Languages_Data.Table
2341 (Lang_Index).Config.Objects_Linked :=
2346 when Constraint_Error =>
2351 & Get_Name_String (Element.Value.Value)
2352 & """ for Objects_Linked",
2353 Element.Value.Location);
2360 Element_Id := Element.Next;
2363 Current_Array_Id := Current_Array.Next;
2365 end Process_Project_Level_Array_Attributes;
2368 Process_Project_Level_Simple_Attributes;
2369 Process_Project_Level_Array_Attributes;
2372 -- For unit based languages, set Casing, Dot_Replacement and
2373 -- Separate_Suffix in Naming_Data.
2375 Lang_Index := Data.First_Language_Processing;
2376 while Lang_Index /= No_Language_Index loop
2377 if In_Tree.Languages_Data.Table
2378 (Lang_Index).Name = Name_Ada
2380 In_Tree.Languages_Data.Table
2381 (Lang_Index).Config.Naming_Data.Casing := Casing;
2382 In_Tree.Languages_Data.Table
2383 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2386 if Separate_Suffix /= No_File then
2387 In_Tree.Languages_Data.Table
2388 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2395 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2398 -- Give empty names to various prefixes/suffixes, if they have not
2399 -- been specified in the configuration.
2401 if Data.Config.Archive_Suffix = No_File then
2402 Data.Config.Archive_Suffix := Empty_File;
2405 if Data.Config.Shared_Lib_Prefix = No_File then
2406 Data.Config.Shared_Lib_Prefix := Empty_File;
2409 if Data.Config.Shared_Lib_Suffix = No_File then
2410 Data.Config.Shared_Lib_Suffix := Empty_File;
2413 Lang_Index := Data.First_Language_Processing;
2414 while Lang_Index /= No_Language_Index loop
2415 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2417 Current_Language := Lang_Data.Display_Name;
2419 -- For all languages, Compiler_Driver needs to be specified
2421 if Lang_Data.Config.Compiler_Driver = No_File then
2422 Error_Msg_Name_1 := Current_Language;
2426 "?no compiler specified for language %%" &
2427 ", ignoring all its sources",
2430 if Lang_Index = Data.First_Language_Processing then
2431 Data.First_Language_Processing :=
2434 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2438 elsif Lang_Data.Name = Name_Ada then
2439 Prev_Index := Lang_Index;
2441 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2442 -- Body_Suffix need to be specified.
2444 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2448 "Dot_Replacement not specified for Ada",
2452 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2456 "Spec_Suffix not specified for Ada",
2460 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2464 "Body_Suffix not specified for Ada",
2469 Prev_Index := Lang_Index;
2471 -- For file based languages, either Spec_Suffix or Body_Suffix
2472 -- need to be specified.
2474 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2475 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2477 Error_Msg_Name_1 := Current_Language;
2481 "no suffixes specified for %%",
2486 Lang_Index := Lang_Data.Next;
2488 end Check_Configuration;
2490 -------------------------------
2491 -- Check_If_Externally_Built --
2492 -------------------------------
2494 procedure Check_If_Externally_Built
2495 (Project : Project_Id;
2496 In_Tree : Project_Tree_Ref;
2497 Data : in out Project_Data)
2499 Externally_Built : constant Variable_Value :=
2501 (Name_Externally_Built,
2502 Data.Decl.Attributes, In_Tree);
2505 if not Externally_Built.Default then
2506 Get_Name_String (Externally_Built.Value);
2507 To_Lower (Name_Buffer (1 .. Name_Len));
2509 if Name_Buffer (1 .. Name_Len) = "true" then
2510 Data.Externally_Built := True;
2512 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2513 Error_Msg (Project, In_Tree,
2514 "Externally_Built may only be true or false",
2515 Externally_Built.Location);
2519 -- A virtual project extending an externally built project is itself
2520 -- externally built.
2522 if Data.Virtual and then Data.Extends /= No_Project then
2523 Data.Externally_Built :=
2524 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2527 if Current_Verbosity = High then
2528 Write_Str ("Project is ");
2530 if not Data.Externally_Built then
2534 Write_Line ("externally built.");
2536 end Check_If_Externally_Built;
2538 ----------------------
2539 -- Check_Interfaces --
2540 ----------------------
2542 procedure Check_Interfaces
2543 (Project : Project_Id;
2544 In_Tree : Project_Tree_Ref;
2545 Data : in out Project_Data)
2547 Interfaces : constant Prj.Variable_Value :=
2549 (Snames.Name_Interfaces,
2550 Data.Decl.Attributes,
2553 List : String_List_Id;
2554 Element : String_Element;
2555 Name : File_Name_Type;
2559 Project_2 : Project_Id;
2560 Data_2 : Project_Data;
2563 if not Interfaces.Default then
2565 -- Set In_Interfaces to False for all sources. It will be set to True
2566 -- later for the sources in the Interfaces list.
2568 Project_2 := Project;
2571 Source := Data_2.First_Source;
2572 while Source /= No_Source loop
2574 Src_Data : Source_Data renames
2575 In_Tree.Sources.Table (Source);
2577 Src_Data.In_Interfaces := False;
2578 Source := Src_Data.Next_In_Project;
2582 Project_2 := Data_2.Extends;
2584 exit when Project_2 = No_Project;
2586 Data_2 := In_Tree.Projects.Table (Project_2);
2589 List := Interfaces.Values;
2590 while List /= Nil_String loop
2591 Element := In_Tree.String_Elements.Table (List);
2592 Get_Name_String (Element.Value);
2593 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2596 Project_2 := Project;
2600 Source := Data_2.First_Source;
2601 while Source /= No_Source loop
2603 Src_Data : Source_Data renames
2604 In_Tree.Sources.Table (Source);
2607 if Src_Data.File = Name then
2608 if not Src_Data.Locally_Removed then
2609 Src_Data.In_Interfaces := True;
2610 Src_Data.Declared_In_Interfaces := True;
2612 if Src_Data.Other_Part /= No_Source then
2613 In_Tree.Sources.Table
2614 (Src_Data.Other_Part).In_Interfaces := True;
2615 In_Tree.Sources.Table
2616 (Src_Data.Other_Part).Declared_In_Interfaces :=
2620 if Current_Verbosity = High then
2621 Write_Str (" interface: ");
2623 (Get_Name_String (Src_Data.Path.Name));
2630 Source := Src_Data.Next_In_Project;
2634 Project_2 := Data_2.Extends;
2636 exit Big_Loop when Project_2 = No_Project;
2638 Data_2 := In_Tree.Projects.Table (Project_2);
2641 if Source = No_Source then
2642 Error_Msg_File_1 := File_Name_Type (Element.Value);
2643 Error_Msg_Name_1 := Data.Name;
2648 "{ cannot be an interface of project %% " &
2649 "as it is not one of its sources",
2653 List := Element.Next;
2656 Data.Interfaces_Defined := True;
2658 elsif Data.Extends /= No_Project then
2659 Data.Interfaces_Defined :=
2660 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2662 if Data.Interfaces_Defined then
2663 Source := Data.First_Source;
2664 while Source /= No_Source loop
2666 Src_Data : Source_Data renames
2667 In_Tree.Sources.Table (Source);
2670 if not Src_Data.Declared_In_Interfaces then
2671 Src_Data.In_Interfaces := False;
2674 Source := Src_Data.Next_In_Project;
2679 end Check_Interfaces;
2681 --------------------------
2682 -- Check_Naming_Schemes --
2683 --------------------------
2685 procedure Check_Naming_Schemes
2686 (Data : in out Project_Data;
2687 Project : Project_Id;
2688 In_Tree : Project_Tree_Ref)
2690 Naming_Id : constant Package_Id :=
2691 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2692 Naming : Package_Element;
2694 procedure Check_Unit_Names (List : Array_Element_Id);
2695 -- Check that a list of unit names contains only valid names
2697 procedure Get_Exceptions (Kind : Source_Kind);
2698 -- Comment required ???
2700 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2701 -- Comment required ???
2703 ----------------------
2704 -- Check_Unit_Names --
2705 ----------------------
2707 procedure Check_Unit_Names (List : Array_Element_Id) is
2708 Current : Array_Element_Id;
2709 Element : Array_Element;
2710 Unit_Name : Name_Id;
2713 -- Loop through elements of the string list
2716 while Current /= No_Array_Element loop
2717 Element := In_Tree.Array_Elements.Table (Current);
2719 -- Put file name in canonical case
2721 if not Osint.File_Names_Case_Sensitive then
2722 Get_Name_String (Element.Value.Value);
2723 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2724 Element.Value.Value := Name_Find;
2727 -- Check that it contains a valid unit name
2729 Get_Name_String (Element.Index);
2730 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2732 if Unit_Name = No_Name then
2733 Err_Vars.Error_Msg_Name_1 := Element.Index;
2736 "%% is not a valid unit name.",
2737 Element.Value.Location);
2740 if Current_Verbosity = High then
2741 Write_Str (" Unit (""");
2742 Write_Str (Get_Name_String (Unit_Name));
2746 Element.Index := Unit_Name;
2747 In_Tree.Array_Elements.Table (Current) := Element;
2750 Current := Element.Next;
2752 end Check_Unit_Names;
2754 --------------------
2755 -- Get_Exceptions --
2756 --------------------
2758 procedure Get_Exceptions (Kind : Source_Kind) is
2759 Exceptions : Array_Element_Id;
2760 Exception_List : Variable_Value;
2761 Element_Id : String_List_Id;
2762 Element : String_Element;
2763 File_Name : File_Name_Type;
2764 Lang_Id : Language_Index;
2766 Lang_Kind : Language_Kind;
2773 (Name_Implementation_Exceptions,
2774 In_Arrays => Naming.Decl.Arrays,
2775 In_Tree => In_Tree);
2780 (Name_Specification_Exceptions,
2781 In_Arrays => Naming.Decl.Arrays,
2782 In_Tree => In_Tree);
2785 Lang_Id := Data.First_Language_Processing;
2786 while Lang_Id /= No_Language_Index loop
2787 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2790 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2792 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2794 Exception_List := Value_Of
2796 In_Array => Exceptions,
2797 In_Tree => In_Tree);
2799 if Exception_List /= Nil_Variable_Value then
2800 Element_Id := Exception_List.Values;
2801 while Element_Id /= Nil_String loop
2802 Element := In_Tree.String_Elements.Table (Element_Id);
2804 if Osint.File_Names_Case_Sensitive then
2805 File_Name := File_Name_Type (Element.Value);
2807 Get_Name_String (Element.Value);
2808 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2809 File_Name := Name_Find;
2812 Source := Data.First_Source;
2813 while Source /= No_Source
2815 In_Tree.Sources.Table (Source).File /= File_Name
2818 In_Tree.Sources.Table (Source).Next_In_Project;
2821 if Source = No_Source then
2830 File_Name => File_Name,
2831 Display_File => File_Name_Type (Element.Value),
2832 Naming_Exception => True,
2833 Lang_Kind => Lang_Kind);
2836 -- Check if the file name is already recorded for
2837 -- another language or another kind.
2840 In_Tree.Sources.Table (Source).Language /= Lang_Id
2845 "the same file cannot be a source " &
2849 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2853 "the same file cannot be a source " &
2858 -- If the file is already recorded for the same
2859 -- language and the same kind, it means that the file
2860 -- name appears several times in the *_Exceptions
2861 -- attribute; so there is nothing to do.
2865 Element_Id := Element.Next;
2870 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2874 -------------------------
2875 -- Get_Unit_Exceptions --
2876 -------------------------
2878 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2879 Exceptions : Array_Element_Id;
2880 Element : Array_Element;
2883 File_Name : File_Name_Type;
2884 Lang_Id : constant Language_Index :=
2885 Data.Unit_Based_Language_Index;
2886 Lang : constant Name_Id :=
2887 Data.Unit_Based_Language_Name;
2890 Source_To_Replace : Source_Id := No_Source;
2892 Other_Project : Project_Id;
2893 Other_Part : Source_Id := No_Source;
2896 if Lang_Id = No_Language_Index or else Lang = No_Name then
2901 Exceptions := Value_Of
2903 In_Arrays => Naming.Decl.Arrays,
2904 In_Tree => In_Tree);
2906 if Exceptions = No_Array_Element then
2909 (Name_Implementation,
2910 In_Arrays => Naming.Decl.Arrays,
2911 In_Tree => In_Tree);
2918 In_Arrays => Naming.Decl.Arrays,
2919 In_Tree => In_Tree);
2921 if Exceptions = No_Array_Element then
2922 Exceptions := Value_Of
2923 (Name_Specification,
2924 In_Arrays => Naming.Decl.Arrays,
2925 In_Tree => In_Tree);
2930 while Exceptions /= No_Array_Element loop
2931 Element := In_Tree.Array_Elements.Table (Exceptions);
2933 if Osint.File_Names_Case_Sensitive then
2934 File_Name := File_Name_Type (Element.Value.Value);
2936 Get_Name_String (Element.Value.Value);
2937 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2938 File_Name := Name_Find;
2941 Get_Name_String (Element.Index);
2942 To_Lower (Name_Buffer (1 .. Name_Len));
2945 Index := Element.Value.Index;
2947 -- For Ada, check if it is a valid unit name
2949 if Lang = Name_Ada then
2950 Get_Name_String (Element.Index);
2951 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2953 if Unit = No_Name then
2954 Err_Vars.Error_Msg_Name_1 := Element.Index;
2957 "%% is not a valid unit name.",
2958 Element.Value.Location);
2962 if Unit /= No_Name then
2964 -- Check if the source already exists
2966 Source := In_Tree.First_Source;
2967 Source_To_Replace := No_Source;
2969 while Source /= No_Source and then
2970 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2971 In_Tree.Sources.Table (Source).Index /= Index)
2973 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2976 if Source /= No_Source then
2977 if In_Tree.Sources.Table (Source).Kind /= Kind then
2978 Other_Part := Source;
2982 In_Tree.Sources.Table (Source).Next_In_Sources;
2984 exit when Source = No_Source or else
2985 (In_Tree.Sources.Table (Source).Unit = Unit
2987 In_Tree.Sources.Table (Source).Index = Index);
2991 if Source /= No_Source then
2992 Other_Project := In_Tree.Sources.Table (Source).Project;
2994 if Is_Extending (Project, Other_Project, In_Tree) then
2996 In_Tree.Sources.Table (Source).Other_Part;
2998 -- Record the source to be removed
3000 Source_To_Replace := Source;
3001 Source := No_Source;
3004 Error_Msg_Name_1 := Unit;
3006 In_Tree.Projects.Table (Other_Project).Name;
3010 "%% is already a source of project %%",
3011 Element.Value.Location);
3016 if Source = No_Source then
3025 File_Name => File_Name,
3026 Display_File => File_Name_Type (Element.Value.Value),
3027 Lang_Kind => Unit_Based,
3028 Other_Part => Other_Part,
3031 Naming_Exception => True,
3032 Source_To_Replace => Source_To_Replace);
3036 Exceptions := Element.Next;
3039 end Get_Unit_Exceptions;
3041 -- Start of processing for Check_Naming_Schemes
3044 if Get_Mode = Ada_Only then
3046 -- If there is a package Naming, we will put in Data.Naming what is
3047 -- in this package Naming.
3049 if Naming_Id /= No_Package then
3050 Naming := In_Tree.Packages.Table (Naming_Id);
3052 if Current_Verbosity = High then
3053 Write_Line ("Checking ""Naming"" for Ada.");
3057 Bodies : constant Array_Element_Id :=
3059 (Name_Body, Naming.Decl.Arrays, In_Tree);
3061 Specs : constant Array_Element_Id :=
3063 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3066 if Bodies /= No_Array_Element then
3068 -- We have elements in the array Body_Part
3070 if Current_Verbosity = High then
3071 Write_Line ("Found Bodies.");
3074 Data.Naming.Bodies := Bodies;
3075 Check_Unit_Names (Bodies);
3078 if Current_Verbosity = High then
3079 Write_Line ("No Bodies.");
3083 if Specs /= No_Array_Element then
3085 -- We have elements in the array Specs
3087 if Current_Verbosity = High then
3088 Write_Line ("Found Specs.");
3091 Data.Naming.Specs := Specs;
3092 Check_Unit_Names (Specs);
3095 if Current_Verbosity = High then
3096 Write_Line ("No Specs.");
3101 -- We are now checking if variables Dot_Replacement, Casing,
3102 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3104 -- For each variable, if it does not exist, we do nothing,
3105 -- because we already have the default.
3107 -- Check Dot_Replacement
3110 Dot_Replacement : constant Variable_Value :=
3112 (Name_Dot_Replacement,
3113 Naming.Decl.Attributes, In_Tree);
3116 pragma Assert (Dot_Replacement.Kind = Single,
3117 "Dot_Replacement is not a single string");
3119 if not Dot_Replacement.Default then
3120 Get_Name_String (Dot_Replacement.Value);
3122 if Name_Len = 0 then
3125 "Dot_Replacement cannot be empty",
3126 Dot_Replacement.Location);
3129 if Osint.File_Names_Case_Sensitive then
3130 Data.Naming.Dot_Replacement :=
3131 File_Name_Type (Dot_Replacement.Value);
3133 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3134 Data.Naming.Dot_Replacement := Name_Find;
3136 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3141 if Current_Verbosity = High then
3142 Write_Str (" Dot_Replacement = """);
3143 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3151 Casing_String : constant Variable_Value :=
3154 Naming.Decl.Attributes,
3158 pragma Assert (Casing_String.Kind = Single,
3159 "Casing is not a single string");
3161 if not Casing_String.Default then
3163 Casing_Image : constant String :=
3164 Get_Name_String (Casing_String.Value);
3167 Casing_Value : constant Casing_Type :=
3168 Value (Casing_Image);
3170 Data.Naming.Casing := Casing_Value;
3174 when Constraint_Error =>
3175 if Casing_Image'Length = 0 then
3178 "Casing cannot be an empty string",
3179 Casing_String.Location);
3182 Name_Len := Casing_Image'Length;
3183 Name_Buffer (1 .. Name_Len) := Casing_Image;
3184 Err_Vars.Error_Msg_Name_1 := Name_Find;
3187 "%% is not a correct Casing",
3188 Casing_String.Location);
3194 if Current_Verbosity = High then
3195 Write_Str (" Casing = ");
3196 Write_Str (Image (Data.Naming.Casing));
3201 -- Check Spec_Suffix
3204 Ada_Spec_Suffix : constant Variable_Value :=
3208 In_Array => Data.Naming.Spec_Suffix,
3209 In_Tree => In_Tree);
3212 if Ada_Spec_Suffix.Kind = Single
3213 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3215 Get_Name_String (Ada_Spec_Suffix.Value);
3216 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3217 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3218 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3225 Default_Ada_Spec_Suffix);
3229 if Current_Verbosity = High then
3230 Write_Str (" Spec_Suffix = """);
3231 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3236 -- Check Body_Suffix
3239 Ada_Body_Suffix : constant Variable_Value :=
3243 In_Array => Data.Naming.Body_Suffix,
3244 In_Tree => In_Tree);
3247 if Ada_Body_Suffix.Kind = Single
3248 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3250 Get_Name_String (Ada_Body_Suffix.Value);
3251 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3252 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3253 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3260 Default_Ada_Body_Suffix);
3264 if Current_Verbosity = High then
3265 Write_Str (" Body_Suffix = """);
3266 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3271 -- Check Separate_Suffix
3274 Ada_Sep_Suffix : constant Variable_Value :=
3276 (Variable_Name => Name_Separate_Suffix,
3277 In_Variables => Naming.Decl.Attributes,
3278 In_Tree => In_Tree);
3281 if Ada_Sep_Suffix.Default then
3282 Data.Naming.Separate_Suffix :=
3283 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3286 Get_Name_String (Ada_Sep_Suffix.Value);
3288 if Name_Len = 0 then
3291 "Separate_Suffix cannot be empty",
3292 Ada_Sep_Suffix.Location);
3295 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3296 Data.Naming.Separate_Suffix := Name_Find;
3297 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3302 if Current_Verbosity = High then
3303 Write_Str (" Separate_Suffix = """);
3304 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3309 -- Check if Data.Naming is valid
3311 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3314 elsif not In_Configuration then
3316 -- Look into package Naming, if there is one
3318 if Naming_Id /= No_Package then
3319 Naming := In_Tree.Packages.Table (Naming_Id);
3321 if Current_Verbosity = High then
3322 Write_Line ("Checking package Naming.");
3325 -- We are now checking if attribute Dot_Replacement, Casing,
3326 -- and/or Separate_Suffix exist.
3328 -- For each attribute, if it does not exist, we do nothing,
3329 -- because we already have the default.
3330 -- Otherwise, for all unit-based languages, we put the declared
3331 -- value in the language config.
3334 Dot_Repl : constant Variable_Value :=
3336 (Name_Dot_Replacement,
3337 Naming.Decl.Attributes, In_Tree);
3338 Dot_Replacement : File_Name_Type := No_File;
3340 Casing_String : constant Variable_Value :=
3343 Naming.Decl.Attributes,
3346 Casing : Casing_Type := All_Lower_Case;
3347 -- Casing type (junk initialization to stop bad gcc warning)
3349 Casing_Defined : Boolean := False;
3351 Sep_Suffix : constant Variable_Value :=
3353 (Variable_Name => Name_Separate_Suffix,
3354 In_Variables => Naming.Decl.Attributes,
3355 In_Tree => In_Tree);
3357 Separate_Suffix : File_Name_Type := No_File;
3358 Lang_Id : Language_Index;
3361 -- Check attribute Dot_Replacement
3363 if not Dot_Repl.Default then
3364 Get_Name_String (Dot_Repl.Value);
3366 if Name_Len = 0 then
3369 "Dot_Replacement cannot be empty",
3373 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3374 Dot_Replacement := Name_Find;
3376 if Current_Verbosity = High then
3377 Write_Str (" Dot_Replacement = """);
3378 Write_Str (Get_Name_String (Dot_Replacement));
3385 -- Check attribute Casing
3387 if not Casing_String.Default then
3389 Casing_Image : constant String :=
3390 Get_Name_String (Casing_String.Value);
3393 Casing_Value : constant Casing_Type :=
3394 Value (Casing_Image);
3396 Casing := Casing_Value;
3397 Casing_Defined := True;
3399 if Current_Verbosity = High then
3400 Write_Str (" Casing = ");
3401 Write_Str (Image (Casing));
3408 when Constraint_Error =>
3409 if Casing_Image'Length = 0 then
3412 "Casing cannot be an empty string",
3413 Casing_String.Location);
3416 Name_Len := Casing_Image'Length;
3417 Name_Buffer (1 .. Name_Len) := Casing_Image;
3418 Err_Vars.Error_Msg_Name_1 := Name_Find;
3421 "%% is not a correct Casing",
3422 Casing_String.Location);
3427 if not Sep_Suffix.Default then
3428 Get_Name_String (Sep_Suffix.Value);
3430 if Name_Len = 0 then
3433 "Separate_Suffix cannot be empty",
3434 Sep_Suffix.Location);
3437 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3438 Separate_Suffix := Name_Find;
3440 if Current_Verbosity = High then
3441 Write_Str (" Separate_Suffix = """);
3442 Write_Str (Get_Name_String (Separate_Suffix));
3449 -- For all unit based languages, if any, set the specified
3450 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3452 if Dot_Replacement /= No_File
3453 or else Casing_Defined
3454 or else Separate_Suffix /= No_File
3456 Lang_Id := Data.First_Language_Processing;
3457 while Lang_Id /= No_Language_Index loop
3458 if In_Tree.Languages_Data.Table
3459 (Lang_Id).Config.Kind = Unit_Based
3461 if Dot_Replacement /= No_File then
3462 In_Tree.Languages_Data.Table
3463 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3467 if Casing_Defined then
3468 In_Tree.Languages_Data.Table
3469 (Lang_Id).Config.Naming_Data.Casing := Casing;
3472 if Separate_Suffix /= No_File then
3473 In_Tree.Languages_Data.Table
3474 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3480 In_Tree.Languages_Data.Table (Lang_Id).Next;
3485 -- Next, get the spec and body suffixes
3488 Suffix : Variable_Value;
3489 Lang_Id : Language_Index;
3493 Lang_Id := Data.First_Language_Processing;
3494 while Lang_Id /= No_Language_Index loop
3495 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3501 Attribute_Or_Array_Name => Name_Spec_Suffix,
3502 In_Package => Naming_Id,
3503 In_Tree => In_Tree);
3505 if Suffix = Nil_Variable_Value then
3508 Attribute_Or_Array_Name => Name_Specification_Suffix,
3509 In_Package => Naming_Id,
3510 In_Tree => In_Tree);
3513 if Suffix /= Nil_Variable_Value then
3514 In_Tree.Languages_Data.Table (Lang_Id).
3515 Config.Naming_Data.Spec_Suffix :=
3516 File_Name_Type (Suffix.Value);
3523 Attribute_Or_Array_Name => Name_Body_Suffix,
3524 In_Package => Naming_Id,
3525 In_Tree => In_Tree);
3527 if Suffix = Nil_Variable_Value then
3530 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3531 In_Package => Naming_Id,
3532 In_Tree => In_Tree);
3535 if Suffix /= Nil_Variable_Value then
3536 In_Tree.Languages_Data.Table (Lang_Id).
3537 Config.Naming_Data.Body_Suffix :=
3538 File_Name_Type (Suffix.Value);
3541 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3545 -- Get the exceptions for file based languages
3547 Get_Exceptions (Spec);
3548 Get_Exceptions (Impl);
3550 -- Get the exceptions for unit based languages
3552 Get_Unit_Exceptions (Spec);
3553 Get_Unit_Exceptions (Impl);
3557 end Check_Naming_Schemes;
3559 ------------------------------
3560 -- Check_Library_Attributes --
3561 ------------------------------
3563 procedure Check_Library_Attributes
3564 (Project : Project_Id;
3565 In_Tree : Project_Tree_Ref;
3566 Current_Dir : String;
3567 Data : in out Project_Data)
3569 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3571 Lib_Dir : constant Prj.Variable_Value :=
3573 (Snames.Name_Library_Dir, Attributes, In_Tree);
3575 Lib_Name : constant Prj.Variable_Value :=
3577 (Snames.Name_Library_Name, Attributes, In_Tree);
3579 Lib_Version : constant Prj.Variable_Value :=
3581 (Snames.Name_Library_Version, Attributes, In_Tree);
3583 Lib_ALI_Dir : constant Prj.Variable_Value :=
3585 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3587 The_Lib_Kind : constant Prj.Variable_Value :=
3589 (Snames.Name_Library_Kind, Attributes, In_Tree);
3591 Imported_Project_List : Project_List := Empty_Project_List;
3593 Continuation : String_Access := No_Continuation_String'Access;
3595 Support_For_Libraries : Library_Support;
3597 Library_Directory_Present : Boolean;
3599 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3600 -- Check if an imported or extended project if also a library project
3606 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3607 Proj_Data : Project_Data;
3611 if Proj /= No_Project then
3612 Proj_Data := In_Tree.Projects.Table (Proj);
3614 if not Proj_Data.Library then
3616 -- The only not library projects that are OK are those that
3617 -- have no sources. However, header files from non-Ada
3618 -- languages are OK, as there is nothing to compile.
3620 Src_Id := Proj_Data.First_Source;
3621 while Src_Id /= No_Source loop
3623 Src : Source_Data renames In_Tree.Sources.Table (Src_Id);
3625 exit when Src.Lang_Kind /= File_Based
3626 or else Src.Kind /= Spec;
3627 Src_Id := Src.Next_In_Project;
3631 if Src_Id /= No_Source then
3632 Error_Msg_Name_1 := Data.Name;
3633 Error_Msg_Name_2 := Proj_Data.Name;
3636 if Data.Library_Kind /= Static then
3640 "shared library project %% cannot extend " &
3641 "project %% that is not a library project",
3643 Continuation := Continuation_String'Access;
3646 elsif Data.Library_Kind /= Static then
3650 "shared library project %% cannot import project %% " &
3651 "that is not a shared library project",
3653 Continuation := Continuation_String'Access;
3657 elsif Data.Library_Kind /= Static and then
3658 Proj_Data.Library_Kind = Static
3660 Error_Msg_Name_1 := Data.Name;
3661 Error_Msg_Name_2 := Proj_Data.Name;
3667 "shared library project %% cannot extend static " &
3668 "library project %%",
3675 "shared library project %% cannot import static " &
3676 "library project %%",
3680 Continuation := Continuation_String'Access;
3685 -- Start of processing for Check_Library_Attributes
3688 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3690 -- Special case of extending project
3692 if Data.Extends /= No_Project then
3694 Extended_Data : constant Project_Data :=
3695 In_Tree.Projects.Table (Data.Extends);
3698 -- If the project extended is a library project, we inherit the
3699 -- library name, if it is not redefined; we check that the library
3700 -- directory is specified.
3702 if Extended_Data.Library then
3703 if Data.Qualifier = Standard then
3706 "a standard project cannot extend a library project",
3710 if Lib_Name.Default then
3711 Data.Library_Name := Extended_Data.Library_Name;
3714 if Lib_Dir.Default then
3715 if not Data.Virtual then
3718 "a project extending a library project must " &
3719 "specify an attribute Library_Dir",
3723 -- For a virtual project extending a library project,
3724 -- inherit library directory.
3726 Data.Library_Dir := Extended_Data.Library_Dir;
3727 Library_Directory_Present := True;
3735 pragma Assert (Lib_Name.Kind = Single);
3737 if Lib_Name.Value = Empty_String then
3738 if Current_Verbosity = High
3739 and then Data.Library_Name = No_Name
3741 Write_Line ("No library name");
3745 -- There is no restriction on the syntax of library names
3747 Data.Library_Name := Lib_Name.Value;
3750 if Data.Library_Name /= No_Name then
3751 if Current_Verbosity = High then
3752 Write_Str ("Library name = """);
3753 Write_Str (Get_Name_String (Data.Library_Name));
3757 pragma Assert (Lib_Dir.Kind = Single);
3759 if not Library_Directory_Present then
3760 if Current_Verbosity = High then
3761 Write_Line ("No library directory");
3765 -- Find path name (unless inherited), check that it is a directory
3767 if Data.Library_Dir = No_Path_Information then
3771 File_Name_Type (Lib_Dir.Value),
3772 Data.Directory.Display_Name,
3773 Data.Library_Dir.Name,
3774 Data.Library_Dir.Display_Name,
3775 Create => "library",
3776 Current_Dir => Current_Dir,
3777 Location => Lib_Dir.Location);
3780 if Data.Library_Dir = No_Path_Information then
3782 -- Get the absolute name of the library directory that
3783 -- does not exist, to report an error.
3786 Dir_Name : constant String :=
3787 Get_Name_String (Lib_Dir.Value);
3790 if Is_Absolute_Path (Dir_Name) then
3791 Err_Vars.Error_Msg_File_1 :=
3792 File_Name_Type (Lib_Dir.Value);
3795 Get_Name_String (Data.Directory.Display_Name);
3797 if Name_Buffer (Name_Len) /= Directory_Separator then
3798 Name_Len := Name_Len + 1;
3799 Name_Buffer (Name_Len) := Directory_Separator;
3803 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3805 Name_Len := Name_Len + Dir_Name'Length;
3806 Err_Vars.Error_Msg_File_1 := Name_Find;
3813 "library directory { does not exist",
3817 -- The library directory cannot be the same as the Object
3820 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3823 "library directory cannot be the same " &
3824 "as object directory",
3826 Data.Library_Dir := No_Path_Information;
3830 OK : Boolean := True;
3831 Dirs_Id : String_List_Id;
3832 Dir_Elem : String_Element;
3835 -- The library directory cannot be the same as a source
3836 -- directory of the current project.
3838 Dirs_Id := Data.Source_Dirs;
3839 while Dirs_Id /= Nil_String loop
3840 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3841 Dirs_Id := Dir_Elem.Next;
3844 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3846 Err_Vars.Error_Msg_File_1 :=
3847 File_Name_Type (Dir_Elem.Value);
3850 "library directory cannot be the same " &
3851 "as source directory {",
3860 -- The library directory cannot be the same as a source
3861 -- directory of another project either.
3864 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3865 if Pid /= Project then
3866 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3868 Dir_Loop : while Dirs_Id /= Nil_String loop
3870 In_Tree.String_Elements.Table (Dirs_Id);
3871 Dirs_Id := Dir_Elem.Next;
3873 if Data.Library_Dir.Name =
3874 Path_Name_Type (Dir_Elem.Value)
3876 Err_Vars.Error_Msg_File_1 :=
3877 File_Name_Type (Dir_Elem.Value);
3878 Err_Vars.Error_Msg_Name_1 :=
3879 In_Tree.Projects.Table (Pid).Name;
3883 "library directory cannot be the same " &
3884 "as source directory { of project %%",
3891 end loop Project_Loop;
3895 Data.Library_Dir := No_Path_Information;
3897 elsif Current_Verbosity = High then
3899 -- Display the Library directory in high verbosity
3901 Write_Str ("Library directory =""");
3903 (Get_Name_String (Data.Library_Dir.Display_Name));
3913 Data.Library_Dir /= No_Path_Information
3915 Data.Library_Name /= No_Name;
3917 if Data.Extends = No_Project then
3918 case Data.Qualifier is
3920 if Data.Library then
3923 "a standard project cannot be a library project",
3928 if not Data.Library then
3929 if Data.Library_Dir = No_Path_Information then
3932 "\attribute Library_Dir not declared",
3936 if Data.Library_Name = No_Name then
3939 "\attribute Library_Name not declared",
3950 if Data.Library then
3951 if Get_Mode = Multi_Language then
3952 Support_For_Libraries := Data.Config.Lib_Support;
3955 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3958 if Support_For_Libraries = Prj.None then
3961 "?libraries are not supported on this platform",
3963 Data.Library := False;
3966 if Lib_ALI_Dir.Value = Empty_String then
3967 if Current_Verbosity = High then
3968 Write_Line ("No library ALI directory specified");
3970 Data.Library_ALI_Dir := Data.Library_Dir;
3973 -- Find path name, check that it is a directory
3978 File_Name_Type (Lib_ALI_Dir.Value),
3979 Data.Directory.Display_Name,
3980 Data.Library_ALI_Dir.Name,
3981 Data.Library_ALI_Dir.Display_Name,
3982 Create => "library ALI",
3983 Current_Dir => Current_Dir,
3984 Location => Lib_ALI_Dir.Location);
3986 if Data.Library_ALI_Dir = No_Path_Information then
3988 -- Get the absolute name of the library ALI directory that
3989 -- does not exist, to report an error.
3992 Dir_Name : constant String :=
3993 Get_Name_String (Lib_ALI_Dir.Value);
3996 if Is_Absolute_Path (Dir_Name) then
3997 Err_Vars.Error_Msg_File_1 :=
3998 File_Name_Type (Lib_Dir.Value);
4001 Get_Name_String (Data.Directory.Display_Name);
4003 if Name_Buffer (Name_Len) /= Directory_Separator then
4004 Name_Len := Name_Len + 1;
4005 Name_Buffer (Name_Len) := Directory_Separator;
4009 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
4011 Name_Len := Name_Len + Dir_Name'Length;
4012 Err_Vars.Error_Msg_File_1 := Name_Find;
4019 "library 'A'L'I directory { does not exist",
4020 Lib_ALI_Dir.Location);
4024 if Data.Library_ALI_Dir /= Data.Library_Dir then
4026 -- The library ALI directory cannot be the same as the
4027 -- Object directory.
4029 if Data.Library_ALI_Dir = Data.Object_Directory then
4032 "library 'A'L'I directory cannot be the same " &
4033 "as object directory",
4034 Lib_ALI_Dir.Location);
4035 Data.Library_ALI_Dir := No_Path_Information;
4039 OK : Boolean := True;
4040 Dirs_Id : String_List_Id;
4041 Dir_Elem : String_Element;
4044 -- The library ALI directory cannot be the same as
4045 -- a source directory of the current project.
4047 Dirs_Id := Data.Source_Dirs;
4048 while Dirs_Id /= Nil_String loop
4049 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4050 Dirs_Id := Dir_Elem.Next;
4052 if Data.Library_ALI_Dir.Name =
4053 Path_Name_Type (Dir_Elem.Value)
4055 Err_Vars.Error_Msg_File_1 :=
4056 File_Name_Type (Dir_Elem.Value);
4059 "library 'A'L'I directory cannot be " &
4060 "the same as source directory {",
4061 Lib_ALI_Dir.Location);
4069 -- The library ALI directory cannot be the same as
4070 -- a source directory of another project either.
4074 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4076 if Pid /= Project then
4078 In_Tree.Projects.Table (Pid).Source_Dirs;
4081 while Dirs_Id /= Nil_String loop
4083 In_Tree.String_Elements.Table (Dirs_Id);
4084 Dirs_Id := Dir_Elem.Next;
4086 if Data.Library_ALI_Dir.Name =
4087 Path_Name_Type (Dir_Elem.Value)
4089 Err_Vars.Error_Msg_File_1 :=
4090 File_Name_Type (Dir_Elem.Value);
4091 Err_Vars.Error_Msg_Name_1 :=
4092 In_Tree.Projects.Table (Pid).Name;
4096 "library 'A'L'I directory cannot " &
4097 "be the same as source directory " &
4099 Lib_ALI_Dir.Location);
4101 exit ALI_Project_Loop;
4103 end loop ALI_Dir_Loop;
4105 end loop ALI_Project_Loop;
4109 Data.Library_ALI_Dir := No_Path_Information;
4111 elsif Current_Verbosity = High then
4113 -- Display the Library ALI directory in high
4116 Write_Str ("Library ALI directory =""");
4119 (Data.Library_ALI_Dir.Display_Name));
4127 pragma Assert (Lib_Version.Kind = Single);
4129 if Lib_Version.Value = Empty_String then
4130 if Current_Verbosity = High then
4131 Write_Line ("No library version specified");
4135 Data.Lib_Internal_Name := Lib_Version.Value;
4138 pragma Assert (The_Lib_Kind.Kind = Single);
4140 if The_Lib_Kind.Value = Empty_String then
4141 if Current_Verbosity = High then
4142 Write_Line ("No library kind specified");
4146 Get_Name_String (The_Lib_Kind.Value);
4149 Kind_Name : constant String :=
4150 To_Lower (Name_Buffer (1 .. Name_Len));
4152 OK : Boolean := True;
4155 if Kind_Name = "static" then
4156 Data.Library_Kind := Static;
4158 elsif Kind_Name = "dynamic" then
4159 Data.Library_Kind := Dynamic;
4161 elsif Kind_Name = "relocatable" then
4162 Data.Library_Kind := Relocatable;
4167 "illegal value for Library_Kind",
4168 The_Lib_Kind.Location);
4172 if Current_Verbosity = High and then OK then
4173 Write_Str ("Library kind = ");
4174 Write_Line (Kind_Name);
4177 if Data.Library_Kind /= Static and then
4178 Support_For_Libraries = Prj.Static_Only
4182 "only static libraries are supported " &
4184 The_Lib_Kind.Location);
4185 Data.Library := False;
4190 if Data.Library then
4191 if Current_Verbosity = High then
4192 Write_Line ("This is a library project file");
4195 if Get_Mode = Multi_Language then
4196 Check_Library (Data.Extends, Extends => True);
4198 Imported_Project_List := Data.Imported_Projects;
4199 while Imported_Project_List /= Empty_Project_List loop
4201 (In_Tree.Project_Lists.Table
4202 (Imported_Project_List).Project,
4204 Imported_Project_List :=
4205 In_Tree.Project_Lists.Table
4206 (Imported_Project_List).Next;
4214 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4215 -- Warn if they are declared, as it is a common error to think that
4216 -- library are "linked" with Linker switches.
4218 if Data.Library then
4220 Linker_Package_Id : constant Package_Id :=
4222 (Name_Linker, Data.Decl.Packages, In_Tree);
4223 Linker_Package : Package_Element;
4224 Switches : Array_Element_Id := No_Array_Element;
4227 if Linker_Package_Id /= No_Package then
4228 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4232 (Name => Name_Switches,
4233 In_Arrays => Linker_Package.Decl.Arrays,
4234 In_Tree => In_Tree);
4236 if Switches = No_Array_Element then
4239 (Name => Name_Default_Switches,
4240 In_Arrays => Linker_Package.Decl.Arrays,
4241 In_Tree => In_Tree);
4244 if Switches /= No_Array_Element then
4247 "?Linker switches not taken into account in library " &
4255 if Data.Extends /= No_Project then
4256 In_Tree.Projects.Table (Data.Extends).Library := False;
4258 end Check_Library_Attributes;
4260 --------------------------
4261 -- Check_Package_Naming --
4262 --------------------------
4264 procedure Check_Package_Naming
4265 (Project : Project_Id;
4266 In_Tree : Project_Tree_Ref;
4267 Data : in out Project_Data)
4269 Naming_Id : constant Package_Id :=
4270 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4272 Naming : Package_Element;
4275 -- If there is a package Naming, we will put in Data.Naming
4276 -- what is in this package Naming.
4278 if Naming_Id /= No_Package then
4279 Naming := In_Tree.Packages.Table (Naming_Id);
4281 if Current_Verbosity = High then
4282 Write_Line ("Checking ""Naming"".");
4285 -- Check Spec_Suffix
4288 Spec_Suffixs : Array_Element_Id :=
4294 Suffix : Array_Element_Id;
4295 Element : Array_Element;
4296 Suffix2 : Array_Element_Id;
4299 -- If some suffixes have been specified, we make sure that
4300 -- for each language for which a default suffix has been
4301 -- specified, there is a suffix specified, either the one
4302 -- in the project file or if there were none, the default.
4304 if Spec_Suffixs /= No_Array_Element then
4305 Suffix := Data.Naming.Spec_Suffix;
4307 while Suffix /= No_Array_Element loop
4309 In_Tree.Array_Elements.Table (Suffix);
4310 Suffix2 := Spec_Suffixs;
4312 while Suffix2 /= No_Array_Element loop
4313 exit when In_Tree.Array_Elements.Table
4314 (Suffix2).Index = Element.Index;
4315 Suffix2 := In_Tree.Array_Elements.Table
4319 -- There is a registered default suffix, but no
4320 -- suffix specified in the project file.
4321 -- Add the default to the array.
4323 if Suffix2 = No_Array_Element then
4324 Array_Element_Table.Increment_Last
4325 (In_Tree.Array_Elements);
4326 In_Tree.Array_Elements.Table
4327 (Array_Element_Table.Last
4328 (In_Tree.Array_Elements)) :=
4329 (Index => Element.Index,
4330 Src_Index => Element.Src_Index,
4331 Index_Case_Sensitive => False,
4332 Value => Element.Value,
4333 Next => Spec_Suffixs);
4334 Spec_Suffixs := Array_Element_Table.Last
4335 (In_Tree.Array_Elements);
4338 Suffix := Element.Next;
4341 -- Put the resulting array as the specification suffixes
4343 Data.Naming.Spec_Suffix := Spec_Suffixs;
4348 Current : Array_Element_Id;
4349 Element : Array_Element;
4352 Current := Data.Naming.Spec_Suffix;
4353 while Current /= No_Array_Element loop
4354 Element := In_Tree.Array_Elements.Table (Current);
4355 Get_Name_String (Element.Value.Value);
4357 if Name_Len = 0 then
4360 "Spec_Suffix cannot be empty",
4361 Element.Value.Location);
4364 In_Tree.Array_Elements.Table (Current) := Element;
4365 Current := Element.Next;
4369 -- Check Body_Suffix
4372 Impl_Suffixs : Array_Element_Id :=
4378 Suffix : Array_Element_Id;
4379 Element : Array_Element;
4380 Suffix2 : Array_Element_Id;
4383 -- If some suffixes have been specified, we make sure that
4384 -- for each language for which a default suffix has been
4385 -- specified, there is a suffix specified, either the one
4386 -- in the project file or if there were none, the default.
4388 if Impl_Suffixs /= No_Array_Element then
4389 Suffix := Data.Naming.Body_Suffix;
4390 while Suffix /= No_Array_Element loop
4392 In_Tree.Array_Elements.Table (Suffix);
4394 Suffix2 := Impl_Suffixs;
4395 while Suffix2 /= No_Array_Element loop
4396 exit when In_Tree.Array_Elements.Table
4397 (Suffix2).Index = Element.Index;
4398 Suffix2 := In_Tree.Array_Elements.Table
4402 -- There is a registered default suffix, but no suffix was
4403 -- specified in the project file. Add default to the array.
4405 if Suffix2 = No_Array_Element then
4406 Array_Element_Table.Increment_Last
4407 (In_Tree.Array_Elements);
4408 In_Tree.Array_Elements.Table
4409 (Array_Element_Table.Last
4410 (In_Tree.Array_Elements)) :=
4411 (Index => Element.Index,
4412 Src_Index => Element.Src_Index,
4413 Index_Case_Sensitive => False,
4414 Value => Element.Value,
4415 Next => Impl_Suffixs);
4416 Impl_Suffixs := Array_Element_Table.Last
4417 (In_Tree.Array_Elements);
4420 Suffix := Element.Next;
4423 -- Put the resulting array as the implementation suffixes
4425 Data.Naming.Body_Suffix := Impl_Suffixs;
4430 Current : Array_Element_Id;
4431 Element : Array_Element;
4434 Current := Data.Naming.Body_Suffix;
4435 while Current /= No_Array_Element loop
4436 Element := In_Tree.Array_Elements.Table (Current);
4437 Get_Name_String (Element.Value.Value);
4439 if Name_Len = 0 then
4442 "Body_Suffix cannot be empty",
4443 Element.Value.Location);
4446 In_Tree.Array_Elements.Table (Current) := Element;
4447 Current := Element.Next;
4451 -- Get the exceptions, if any
4453 Data.Naming.Specification_Exceptions :=
4455 (Name_Specification_Exceptions,
4456 In_Arrays => Naming.Decl.Arrays,
4457 In_Tree => In_Tree);
4459 Data.Naming.Implementation_Exceptions :=
4461 (Name_Implementation_Exceptions,
4462 In_Arrays => Naming.Decl.Arrays,
4463 In_Tree => In_Tree);
4465 end Check_Package_Naming;
4467 ---------------------------------
4468 -- Check_Programming_Languages --
4469 ---------------------------------
4471 procedure Check_Programming_Languages
4472 (In_Tree : Project_Tree_Ref;
4473 Project : Project_Id;
4474 Data : in out Project_Data)
4476 Languages : Variable_Value := Nil_Variable_Value;
4477 Def_Lang : Variable_Value := Nil_Variable_Value;
4478 Def_Lang_Id : Name_Id;
4481 Data.First_Language_Processing := No_Language_Index;
4483 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4486 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4487 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4488 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4490 if Data.Source_Dirs /= Nil_String then
4492 -- Check if languages are specified in this project
4494 if Languages.Default then
4496 -- Attribute Languages is not specified. So, it defaults to
4497 -- a project of the default language only.
4499 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4500 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4502 -- In Ada_Only mode, the default language is Ada
4504 if Get_Mode = Ada_Only then
4505 In_Tree.Name_Lists.Table (Data.Languages) :=
4506 (Name => Name_Ada, Next => No_Name_List);
4508 -- Attribute Languages is not specified. So, it defaults to
4509 -- a project of language Ada only. No sources of languages
4512 Data.Other_Sources_Present := False;
4515 -- Fail if there is no default language defined
4517 if Def_Lang.Default then
4518 if not Default_Language_Is_Ada then
4522 "no languages defined for this project",
4524 Def_Lang_Id := No_Name;
4526 Def_Lang_Id := Name_Ada;
4530 Get_Name_String (Def_Lang.Value);
4531 To_Lower (Name_Buffer (1 .. Name_Len));
4532 Def_Lang_Id := Name_Find;
4535 if Def_Lang_Id /= No_Name then
4536 In_Tree.Name_Lists.Table (Data.Languages) :=
4537 (Name => Def_Lang_Id, Next => No_Name_List);
4539 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4541 Data.First_Language_Processing :=
4542 Language_Data_Table.Last (In_Tree.Languages_Data);
4543 In_Tree.Languages_Data.Table
4544 (Data.First_Language_Processing) := No_Language_Data;
4545 In_Tree.Languages_Data.Table
4546 (Data.First_Language_Processing).Name := Def_Lang_Id;
4547 Get_Name_String (Def_Lang_Id);
4548 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4549 In_Tree.Languages_Data.Table
4550 (Data.First_Language_Processing).Display_Name := Name_Find;
4552 if Def_Lang_Id = Name_Ada then
4553 In_Tree.Languages_Data.Table
4554 (Data.First_Language_Processing).Config.Kind
4556 In_Tree.Languages_Data.Table
4557 (Data.First_Language_Processing).Config.Dependency_Kind
4559 Data.Unit_Based_Language_Name := Name_Ada;
4560 Data.Unit_Based_Language_Index :=
4561 Data.First_Language_Processing;
4563 In_Tree.Languages_Data.Table
4564 (Data.First_Language_Processing).Config.Kind
4572 Current : String_List_Id := Languages.Values;
4573 Element : String_Element;
4574 Lang_Name : Name_Id;
4575 Index : Language_Index;
4576 Lang_Data : Language_Data;
4577 NL_Id : Name_List_Index := No_Name_List;
4580 -- Assume there are no language declared
4582 Data.Ada_Sources_Present := False;
4583 Data.Other_Sources_Present := False;
4585 -- If there are no languages declared, there are no sources
4587 if Current = Nil_String then
4588 Data.Source_Dirs := Nil_String;
4590 if Data.Qualifier = Standard then
4594 "a standard project cannot have no language declared",
4595 Languages.Location);
4599 -- Look through all the languages specified in attribute
4602 while Current /= Nil_String loop
4604 In_Tree.String_Elements.Table (Current);
4605 Get_Name_String (Element.Value);
4606 To_Lower (Name_Buffer (1 .. Name_Len));
4607 Lang_Name := Name_Find;
4609 NL_Id := Data.Languages;
4610 while NL_Id /= No_Name_List loop
4612 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4613 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4616 if NL_Id = No_Name_List then
4617 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4619 if Data.Languages = No_Name_List then
4621 Name_List_Table.Last (In_Tree.Name_Lists);
4624 NL_Id := Data.Languages;
4625 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4628 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4631 In_Tree.Name_Lists.Table (NL_Id).Next :=
4632 Name_List_Table.Last (In_Tree.Name_Lists);
4635 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4636 In_Tree.Name_Lists.Table (NL_Id) :=
4637 (Lang_Name, No_Name_List);
4639 if Get_Mode = Ada_Only then
4640 -- Check for language Ada
4642 if Lang_Name = Name_Ada then
4643 Data.Ada_Sources_Present := True;
4646 Data.Other_Sources_Present := True;
4650 Language_Data_Table.Increment_Last
4651 (In_Tree.Languages_Data);
4653 Language_Data_Table.Last (In_Tree.Languages_Data);
4654 Lang_Data.Name := Lang_Name;
4655 Lang_Data.Display_Name := Element.Value;
4656 Lang_Data.Next := Data.First_Language_Processing;
4658 if Lang_Name = Name_Ada then
4659 Lang_Data.Config.Kind := Unit_Based;
4660 Lang_Data.Config.Dependency_Kind := ALI_File;
4661 Data.Unit_Based_Language_Name := Name_Ada;
4662 Data.Unit_Based_Language_Index := Index;
4665 Lang_Data.Config.Kind := File_Based;
4666 Lang_Data.Config.Dependency_Kind := None;
4669 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4670 Data.First_Language_Processing := Index;
4674 Current := Element.Next;
4680 end Check_Programming_Languages;
4686 function Check_Project
4688 Root_Project : Project_Id;
4689 In_Tree : Project_Tree_Ref;
4690 Extending : Boolean) return Boolean
4693 if P = Root_Project then
4696 elsif Extending then
4698 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4701 while Data.Extends /= No_Project loop
4702 if P = Data.Extends then
4706 Data := In_Tree.Projects.Table (Data.Extends);
4714 -------------------------------
4715 -- Check_Stand_Alone_Library --
4716 -------------------------------
4718 procedure Check_Stand_Alone_Library
4719 (Project : Project_Id;
4720 In_Tree : Project_Tree_Ref;
4721 Data : in out Project_Data;
4722 Current_Dir : String;
4723 Extending : Boolean)
4725 Lib_Interfaces : constant Prj.Variable_Value :=
4727 (Snames.Name_Library_Interface,
4728 Data.Decl.Attributes,
4731 Lib_Auto_Init : constant Prj.Variable_Value :=
4733 (Snames.Name_Library_Auto_Init,
4734 Data.Decl.Attributes,
4737 Lib_Src_Dir : constant Prj.Variable_Value :=
4739 (Snames.Name_Library_Src_Dir,
4740 Data.Decl.Attributes,
4743 Lib_Symbol_File : constant Prj.Variable_Value :=
4745 (Snames.Name_Library_Symbol_File,
4746 Data.Decl.Attributes,
4749 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4751 (Snames.Name_Library_Symbol_Policy,
4752 Data.Decl.Attributes,
4755 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4757 (Snames.Name_Library_Reference_Symbol_File,
4758 Data.Decl.Attributes,
4761 Auto_Init_Supported : Boolean;
4762 OK : Boolean := True;
4764 Next_Proj : Project_Id;
4767 if Get_Mode = Multi_Language then
4768 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4770 Auto_Init_Supported :=
4771 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4774 pragma Assert (Lib_Interfaces.Kind = List);
4776 -- It is a stand-alone library project file if attribute
4777 -- Library_Interface is defined.
4779 if not Lib_Interfaces.Default then
4780 SAL_Library : declare
4781 Interfaces : String_List_Id := Lib_Interfaces.Values;
4782 Interface_ALIs : String_List_Id := Nil_String;
4784 The_Unit_Id : Unit_Index;
4785 The_Unit_Data : Unit_Data;
4787 procedure Add_ALI_For (Source : File_Name_Type);
4788 -- Add an ALI file name to the list of Interface ALIs
4794 procedure Add_ALI_For (Source : File_Name_Type) is
4796 Get_Name_String (Source);
4799 ALI : constant String :=
4800 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4801 ALI_Name_Id : Name_Id;
4804 Name_Len := ALI'Length;
4805 Name_Buffer (1 .. Name_Len) := ALI;
4806 ALI_Name_Id := Name_Find;
4808 String_Element_Table.Increment_Last
4809 (In_Tree.String_Elements);
4810 In_Tree.String_Elements.Table
4811 (String_Element_Table.Last
4812 (In_Tree.String_Elements)) :=
4813 (Value => ALI_Name_Id,
4815 Display_Value => ALI_Name_Id,
4817 In_Tree.String_Elements.Table
4818 (Interfaces).Location,
4820 Next => Interface_ALIs);
4821 Interface_ALIs := String_Element_Table.Last
4822 (In_Tree.String_Elements);
4826 -- Start of processing for SAL_Library
4829 Data.Standalone_Library := True;
4831 -- Library_Interface cannot be an empty list
4833 if Interfaces = Nil_String then
4836 "Library_Interface cannot be an empty list",
4837 Lib_Interfaces.Location);
4840 -- Process each unit name specified in the attribute
4841 -- Library_Interface.
4843 while Interfaces /= Nil_String loop
4845 (In_Tree.String_Elements.Table (Interfaces).Value);
4846 To_Lower (Name_Buffer (1 .. Name_Len));
4848 if Name_Len = 0 then
4851 "an interface cannot be an empty string",
4852 In_Tree.String_Elements.Table (Interfaces).Location);
4856 Error_Msg_Name_1 := Unit;
4858 if Get_Mode = Ada_Only then
4860 Units_Htable.Get (In_Tree.Units_HT, Unit);
4862 if The_Unit_Id = No_Unit_Index then
4866 In_Tree.String_Elements.Table
4867 (Interfaces).Location);
4870 -- Check that the unit is part of the project
4873 In_Tree.Units.Table (The_Unit_Id);
4875 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4876 and then The_Unit_Data.File_Names
4877 (Body_Part).Path.Name /= Slash
4880 (The_Unit_Data.File_Names (Body_Part).Project,
4881 Project, In_Tree, Extending)
4883 -- There is a body for this unit.
4884 -- If there is no spec, we need to check
4885 -- that it is not a subunit.
4887 if The_Unit_Data.File_Names
4888 (Specification).Name = No_File
4891 Src_Ind : Source_File_Index;
4894 Src_Ind := Sinput.P.Load_Project_File
4896 (The_Unit_Data.File_Names
4897 (Body_Part).Path.Name));
4899 if Sinput.P.Source_File_Is_Subunit
4904 "%% is a subunit; " &
4905 "it cannot be an interface",
4907 String_Elements.Table
4908 (Interfaces).Location);
4913 -- The unit is not a subunit, so we add
4914 -- to the Interface ALIs the ALI file
4915 -- corresponding to the body.
4918 (The_Unit_Data.File_Names (Body_Part).Name);
4923 "%% is not an unit of this project",
4924 In_Tree.String_Elements.Table
4925 (Interfaces).Location);
4928 elsif The_Unit_Data.File_Names
4929 (Specification).Name /= No_File
4930 and then The_Unit_Data.File_Names
4931 (Specification).Path.Name /= Slash
4932 and then Check_Project
4933 (The_Unit_Data.File_Names
4934 (Specification).Project,
4935 Project, In_Tree, Extending)
4938 -- The unit is part of the project, it has
4939 -- a spec, but no body. We add to the Interface
4940 -- ALIs the ALI file corresponding to the spec.
4943 (The_Unit_Data.File_Names (Specification).Name);
4948 "%% is not an unit of this project",
4949 In_Tree.String_Elements.Table
4950 (Interfaces).Location);
4955 -- Multi_Language mode
4957 Next_Proj := Data.Extends;
4958 Source := Data.First_Source;
4961 while Source /= No_Source and then
4962 In_Tree.Sources.Table (Source).Unit /= Unit
4965 In_Tree.Sources.Table (Source).Next_In_Project;
4968 exit when Source /= No_Source or else
4969 Next_Proj = No_Project;
4972 In_Tree.Projects.Table (Next_Proj).First_Source;
4974 In_Tree.Projects.Table (Next_Proj).Extends;
4977 if Source /= No_Source then
4978 if In_Tree.Sources.Table (Source).Kind = Sep then
4979 Source := No_Source;
4981 elsif In_Tree.Sources.Table (Source).Kind = Spec
4983 In_Tree.Sources.Table (Source).Other_Part /=
4986 Source := In_Tree.Sources.Table (Source).Other_Part;
4990 if Source /= No_Source then
4991 if In_Tree.Sources.Table (Source).Project /= Project
4995 In_Tree.Sources.Table (Source).Project,
4998 Source := No_Source;
5002 if Source = No_Source then
5005 "%% is not an unit of this project",
5006 In_Tree.String_Elements.Table
5007 (Interfaces).Location);
5010 if In_Tree.Sources.Table (Source).Kind = Spec and then
5011 In_Tree.Sources.Table (Source).Other_Part /=
5014 Source := In_Tree.Sources.Table (Source).Other_Part;
5017 String_Element_Table.Increment_Last
5018 (In_Tree.String_Elements);
5019 In_Tree.String_Elements.Table
5020 (String_Element_Table.Last
5021 (In_Tree.String_Elements)) :=
5023 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5026 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5028 In_Tree.String_Elements.Table
5029 (Interfaces).Location,
5031 Next => Interface_ALIs);
5032 Interface_ALIs := String_Element_Table.Last
5033 (In_Tree.String_Elements);
5041 In_Tree.String_Elements.Table (Interfaces).Next;
5044 -- Put the list of Interface ALIs in the project data
5046 Data.Lib_Interface_ALIs := Interface_ALIs;
5048 -- Check value of attribute Library_Auto_Init and set
5049 -- Lib_Auto_Init accordingly.
5051 if Lib_Auto_Init.Default then
5053 -- If no attribute Library_Auto_Init is declared, then set auto
5054 -- init only if it is supported.
5056 Data.Lib_Auto_Init := Auto_Init_Supported;
5059 Get_Name_String (Lib_Auto_Init.Value);
5060 To_Lower (Name_Buffer (1 .. Name_Len));
5062 if Name_Buffer (1 .. Name_Len) = "false" then
5063 Data.Lib_Auto_Init := False;
5065 elsif Name_Buffer (1 .. Name_Len) = "true" then
5066 if Auto_Init_Supported then
5067 Data.Lib_Auto_Init := True;
5070 -- Library_Auto_Init cannot be "true" if auto init is not
5075 "library auto init not supported " &
5077 Lib_Auto_Init.Location);
5083 "invalid value for attribute Library_Auto_Init",
5084 Lib_Auto_Init.Location);
5089 -- If attribute Library_Src_Dir is defined and not the empty string,
5090 -- check if the directory exist and is not the object directory or
5091 -- one of the source directories. This is the directory where copies
5092 -- of the interface sources will be copied. Note that this directory
5093 -- may be the library directory.
5095 if Lib_Src_Dir.Value /= Empty_String then
5097 Dir_Id : constant File_Name_Type :=
5098 File_Name_Type (Lib_Src_Dir.Value);
5105 Data.Directory.Display_Name,
5106 Data.Library_Src_Dir.Name,
5107 Data.Library_Src_Dir.Display_Name,
5108 Create => "library source copy",
5109 Current_Dir => Current_Dir,
5110 Location => Lib_Src_Dir.Location);
5112 -- If directory does not exist, report an error
5114 if Data.Library_Src_Dir = No_Path_Information then
5116 -- Get the absolute name of the library directory that does
5117 -- not exist, to report an error.
5120 Dir_Name : constant String :=
5121 Get_Name_String (Dir_Id);
5124 if Is_Absolute_Path (Dir_Name) then
5125 Err_Vars.Error_Msg_File_1 := Dir_Id;
5128 Get_Name_String (Data.Directory.Name);
5130 if Name_Buffer (Name_Len) /=
5133 Name_Len := Name_Len + 1;
5134 Name_Buffer (Name_Len) :=
5135 Directory_Separator;
5140 Name_Len + Dir_Name'Length) :=
5142 Name_Len := Name_Len + Dir_Name'Length;
5143 Err_Vars.Error_Msg_Name_1 := Name_Find;
5148 Error_Msg_File_1 := Dir_Id;
5151 "Directory { does not exist",
5152 Lib_Src_Dir.Location);
5155 -- Report error if it is the same as the object directory
5157 elsif Data.Library_Src_Dir = Data.Object_Directory then
5160 "directory to copy interfaces cannot be " &
5161 "the object directory",
5162 Lib_Src_Dir.Location);
5163 Data.Library_Src_Dir := No_Path_Information;
5167 Src_Dirs : String_List_Id;
5168 Src_Dir : String_Element;
5171 -- Interface copy directory cannot be one of the source
5172 -- directory of the current project.
5174 Src_Dirs := Data.Source_Dirs;
5175 while Src_Dirs /= Nil_String loop
5176 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5178 -- Report error if it is one of the source directories
5180 if Data.Library_Src_Dir.Name =
5181 Path_Name_Type (Src_Dir.Value)
5185 "directory to copy interfaces cannot " &
5186 "be one of the source directories",
5187 Lib_Src_Dir.Location);
5188 Data.Library_Src_Dir := No_Path_Information;
5192 Src_Dirs := Src_Dir.Next;
5195 if Data.Library_Src_Dir /= No_Path_Information then
5197 -- It cannot be a source directory of any other
5200 Project_Loop : for Pid in 1 ..
5201 Project_Table.Last (In_Tree.Projects)
5204 In_Tree.Projects.Table (Pid).Source_Dirs;
5205 Dir_Loop : while Src_Dirs /= Nil_String loop
5207 In_Tree.String_Elements.Table (Src_Dirs);
5209 -- Report error if it is one of the source
5212 if Data.Library_Src_Dir.Name =
5213 Path_Name_Type (Src_Dir.Value)
5216 File_Name_Type (Src_Dir.Value);
5218 In_Tree.Projects.Table (Pid).Name;
5221 "directory to copy interfaces cannot " &
5222 "be the same as source directory { of " &
5224 Lib_Src_Dir.Location);
5225 Data.Library_Src_Dir := No_Path_Information;
5229 Src_Dirs := Src_Dir.Next;
5231 end loop Project_Loop;
5235 -- In high verbosity, if there is a valid Library_Src_Dir,
5236 -- display its path name.
5238 if Data.Library_Src_Dir /= No_Path_Information
5239 and then Current_Verbosity = High
5241 Write_Str ("Directory to copy interfaces =""");
5242 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5249 -- Check the symbol related attributes
5251 -- First, the symbol policy
5253 if not Lib_Symbol_Policy.Default then
5255 Value : constant String :=
5257 (Get_Name_String (Lib_Symbol_Policy.Value));
5260 -- Symbol policy must hove one of a limited number of values
5262 if Value = "autonomous" or else Value = "default" then
5263 Data.Symbol_Data.Symbol_Policy := Autonomous;
5265 elsif Value = "compliant" then
5266 Data.Symbol_Data.Symbol_Policy := Compliant;
5268 elsif Value = "controlled" then
5269 Data.Symbol_Data.Symbol_Policy := Controlled;
5271 elsif Value = "restricted" then
5272 Data.Symbol_Data.Symbol_Policy := Restricted;
5274 elsif Value = "direct" then
5275 Data.Symbol_Data.Symbol_Policy := Direct;
5280 "illegal value for Library_Symbol_Policy",
5281 Lib_Symbol_Policy.Location);
5286 -- If attribute Library_Symbol_File is not specified, symbol policy
5287 -- cannot be Restricted.
5289 if Lib_Symbol_File.Default then
5290 if Data.Symbol_Data.Symbol_Policy = Restricted then
5293 "Library_Symbol_File needs to be defined when " &
5294 "symbol policy is Restricted",
5295 Lib_Symbol_Policy.Location);
5299 -- Library_Symbol_File is defined
5301 Data.Symbol_Data.Symbol_File :=
5302 Path_Name_Type (Lib_Symbol_File.Value);
5304 Get_Name_String (Lib_Symbol_File.Value);
5306 if Name_Len = 0 then
5309 "symbol file name cannot be an empty string",
5310 Lib_Symbol_File.Location);
5313 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5316 for J in 1 .. Name_Len loop
5317 if Name_Buffer (J) = '/'
5318 or else Name_Buffer (J) = Directory_Separator
5327 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5330 "symbol file name { is illegal. " &
5331 "Name cannot include directory info.",
5332 Lib_Symbol_File.Location);
5337 -- If attribute Library_Reference_Symbol_File is not defined,
5338 -- symbol policy cannot be Compliant or Controlled.
5340 if Lib_Ref_Symbol_File.Default then
5341 if Data.Symbol_Data.Symbol_Policy = Compliant
5342 or else Data.Symbol_Data.Symbol_Policy = Controlled
5346 "a reference symbol file need to be defined",
5347 Lib_Symbol_Policy.Location);
5351 -- Library_Reference_Symbol_File is defined, check file exists
5353 Data.Symbol_Data.Reference :=
5354 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5356 Get_Name_String (Lib_Ref_Symbol_File.Value);
5358 if Name_Len = 0 then
5361 "reference symbol file name cannot be an empty string",
5362 Lib_Symbol_File.Location);
5365 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5367 Add_Str_To_Name_Buffer
5368 (Get_Name_String (Data.Directory.Name));
5369 Add_Char_To_Name_Buffer (Directory_Separator);
5370 Add_Str_To_Name_Buffer
5371 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5372 Data.Symbol_Data.Reference := Name_Find;
5375 if not Is_Regular_File
5376 (Get_Name_String (Data.Symbol_Data.Reference))
5379 File_Name_Type (Lib_Ref_Symbol_File.Value);
5381 -- For controlled and direct symbol policies, it is an error
5382 -- if the reference symbol file does not exist. For other
5383 -- symbol policies, this is just a warning
5386 Data.Symbol_Data.Symbol_Policy /= Controlled
5387 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5391 "<library reference symbol file { does not exist",
5392 Lib_Ref_Symbol_File.Location);
5394 -- In addition in the non-controlled case, if symbol policy
5395 -- is Compliant, it is changed to Autonomous, because there
5396 -- is no reference to check against, and we don't want to
5397 -- fail in this case.
5399 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5400 if Data.Symbol_Data.Symbol_Policy = Compliant then
5401 Data.Symbol_Data.Symbol_Policy := Autonomous;
5406 -- If both the reference symbol file and the symbol file are
5407 -- defined, then check that they are not the same file.
5409 if Data.Symbol_Data.Symbol_File /= No_Path then
5410 Get_Name_String (Data.Symbol_Data.Symbol_File);
5412 if Name_Len > 0 then
5414 Symb_Path : constant String :=
5417 (Data.Object_Directory.Name) &
5418 Directory_Separator &
5419 Name_Buffer (1 .. Name_Len),
5420 Directory => Current_Dir,
5422 Opt.Follow_Links_For_Files);
5423 Ref_Path : constant String :=
5426 (Data.Symbol_Data.Reference),
5427 Directory => Current_Dir,
5429 Opt.Follow_Links_For_Files);
5431 if Symb_Path = Ref_Path then
5434 "library reference symbol file and library" &
5435 " symbol file cannot be the same file",
5436 Lib_Ref_Symbol_File.Location);
5444 end Check_Stand_Alone_Library;
5446 ----------------------------
5447 -- Compute_Directory_Last --
5448 ----------------------------
5450 function Compute_Directory_Last (Dir : String) return Natural is
5453 and then (Dir (Dir'Last - 1) = Directory_Separator
5454 or else Dir (Dir'Last - 1) = '/')
5456 return Dir'Last - 1;
5460 end Compute_Directory_Last;
5467 (Project : Project_Id;
5468 In_Tree : Project_Tree_Ref;
5470 Flag_Location : Source_Ptr)
5472 Real_Location : Source_Ptr := Flag_Location;
5473 Error_Buffer : String (1 .. 5_000);
5474 Error_Last : Natural := 0;
5475 Name_Number : Natural := 0;
5476 File_Number : Natural := 0;
5477 First : Positive := Msg'First;
5480 procedure Add (C : Character);
5481 -- Add a character to the buffer
5483 procedure Add (S : String);
5484 -- Add a string to the buffer
5487 -- Add a name to the buffer
5490 -- Add a file name to the buffer
5496 procedure Add (C : Character) is
5498 Error_Last := Error_Last + 1;
5499 Error_Buffer (Error_Last) := C;
5502 procedure Add (S : String) is
5504 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5505 Error_Last := Error_Last + S'Length;
5512 procedure Add_File is
5513 File : File_Name_Type;
5517 File_Number := File_Number + 1;
5521 File := Err_Vars.Error_Msg_File_1;
5523 File := Err_Vars.Error_Msg_File_2;
5525 File := Err_Vars.Error_Msg_File_3;
5530 Get_Name_String (File);
5531 Add (Name_Buffer (1 .. Name_Len));
5539 procedure Add_Name is
5544 Name_Number := Name_Number + 1;
5548 Name := Err_Vars.Error_Msg_Name_1;
5550 Name := Err_Vars.Error_Msg_Name_2;
5552 Name := Err_Vars.Error_Msg_Name_3;
5557 Get_Name_String (Name);
5558 Add (Name_Buffer (1 .. Name_Len));
5562 -- Start of processing for Error_Msg
5565 -- If location of error is unknown, use the location of the project
5567 if Real_Location = No_Location then
5568 Real_Location := In_Tree.Projects.Table (Project).Location;
5571 if Error_Report = null then
5572 Prj.Err.Error_Msg (Msg, Real_Location);
5576 -- Ignore continuation character
5578 if Msg (First) = '\' then
5582 -- Warning character is always the first one in this package
5583 -- this is an undocumented kludge???
5585 if Msg (First) = '?' then
5589 elsif Msg (First) = '<' then
5592 if Err_Vars.Error_Msg_Warn then
5598 while Index <= Msg'Last loop
5599 if Msg (Index) = '{' then
5602 elsif Msg (Index) = '%' then
5603 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5615 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5618 ----------------------
5619 -- Find_Ada_Sources --
5620 ----------------------
5622 procedure Find_Ada_Sources
5623 (Project : Project_Id;
5624 In_Tree : Project_Tree_Ref;
5625 Data : in out Project_Data;
5626 Current_Dir : String)
5628 Source_Dir : String_List_Id := Data.Source_Dirs;
5629 Element : String_Element;
5631 Current_Source : String_List_Id := Nil_String;
5632 Source_Recorded : Boolean := False;
5635 if Current_Verbosity = High then
5636 Write_Line ("Looking for sources:");
5639 -- For each subdirectory
5641 while Source_Dir /= Nil_String loop
5643 Source_Recorded := False;
5644 Element := In_Tree.String_Elements.Table (Source_Dir);
5645 if Element.Value /= No_Name then
5646 Get_Name_String (Element.Display_Value);
5649 Source_Directory : constant String :=
5650 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5651 Dir_Last : constant Natural :=
5652 Compute_Directory_Last (Source_Directory);
5655 if Current_Verbosity = High then
5656 Write_Str ("Source_Dir = ");
5657 Write_Line (Source_Directory);
5660 -- We look at every entry in the source directory
5663 Source_Directory (Source_Directory'First .. Dir_Last));
5666 Read (Dir, Name_Buffer, Name_Len);
5668 if Current_Verbosity = High then
5669 Write_Str (" Checking ");
5670 Write_Line (Name_Buffer (1 .. Name_Len));
5673 exit when Name_Len = 0;
5676 File_Name : constant File_Name_Type := Name_Find;
5678 -- ??? We could probably optimize the following call:
5679 -- we need to resolve links only once for the
5680 -- directory itself, and then do a single call to
5681 -- readlink() for each file. Unfortunately that would
5682 -- require a change in Normalize_Pathname so that it
5683 -- has the option of not resolving links for its
5684 -- Directory parameter, only for Name.
5686 Path : constant String :=
5688 (Name => Name_Buffer (1 .. Name_Len),
5691 (Source_Directory'First .. Dir_Last),
5693 Opt.Follow_Links_For_Files,
5694 Case_Sensitive => True);
5696 Path_Name : Path_Name_Type;
5699 Name_Len := Path'Length;
5700 Name_Buffer (1 .. Name_Len) := Path;
5701 Path_Name := Name_Find;
5703 -- We attempt to register it as a source. However,
5704 -- there is no error if the file does not contain a
5705 -- valid source. But there is an error if we have a
5706 -- duplicate unit name.
5709 (File_Name => File_Name,
5710 Path_Name => Path_Name,
5714 Location => No_Location,
5715 Current_Source => Current_Source,
5716 Source_Recorded => Source_Recorded,
5717 Current_Dir => Current_Dir);
5726 when Directory_Error =>
5730 if Source_Recorded then
5731 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5735 Source_Dir := Element.Next;
5738 if Current_Verbosity = High then
5739 Write_Line ("end Looking for sources.");
5742 end Find_Ada_Sources;
5744 --------------------------------
5745 -- Free_Ada_Naming_Exceptions --
5746 --------------------------------
5748 procedure Free_Ada_Naming_Exceptions is
5750 Ada_Naming_Exception_Table.Set_Last (0);
5751 Ada_Naming_Exceptions.Reset;
5752 Reverse_Ada_Naming_Exceptions.Reset;
5753 end Free_Ada_Naming_Exceptions;
5755 ---------------------
5756 -- Get_Directories --
5757 ---------------------
5759 procedure Get_Directories
5760 (Project : Project_Id;
5761 In_Tree : Project_Tree_Ref;
5762 Current_Dir : String;
5763 Data : in out Project_Data)
5765 Object_Dir : constant Variable_Value :=
5767 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5769 Exec_Dir : constant Variable_Value :=
5771 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5773 Source_Dirs : constant Variable_Value :=
5775 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5777 Excluded_Source_Dirs : constant Variable_Value :=
5779 (Name_Excluded_Source_Dirs,
5780 Data.Decl.Attributes,
5783 Source_Files : constant Variable_Value :=
5785 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5787 Last_Source_Dir : String_List_Id := Nil_String;
5789 procedure Find_Source_Dirs
5790 (From : File_Name_Type;
5791 Location : Source_Ptr;
5792 Removed : Boolean := False);
5793 -- Find one or several source directories, and add (or remove, if
5794 -- Removed is True) them to list of source directories of the project.
5796 ----------------------
5797 -- Find_Source_Dirs --
5798 ----------------------
5800 procedure Find_Source_Dirs
5801 (From : File_Name_Type;
5802 Location : Source_Ptr;
5803 Removed : Boolean := False)
5805 Directory : constant String := Get_Name_String (From);
5806 Element : String_Element;
5808 procedure Recursive_Find_Dirs (Path : Name_Id);
5809 -- Find all the subdirectories (recursively) of Path and add them
5810 -- to the list of source directories of the project.
5812 -------------------------
5813 -- Recursive_Find_Dirs --
5814 -------------------------
5816 procedure Recursive_Find_Dirs (Path : Name_Id) is
5818 Name : String (1 .. 250);
5820 List : String_List_Id;
5821 Prev : String_List_Id;
5822 Element : String_Element;
5823 Found : Boolean := False;
5825 Non_Canonical_Path : Name_Id := No_Name;
5826 Canonical_Path : Name_Id := No_Name;
5828 The_Path : constant String :=
5830 (Get_Name_String (Path),
5831 Directory => Current_Dir,
5832 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5833 Directory_Separator;
5835 The_Path_Last : constant Natural :=
5836 Compute_Directory_Last (The_Path);
5839 Name_Len := The_Path_Last - The_Path'First + 1;
5840 Name_Buffer (1 .. Name_Len) :=
5841 The_Path (The_Path'First .. The_Path_Last);
5842 Non_Canonical_Path := Name_Find;
5844 if Osint.File_Names_Case_Sensitive then
5845 Canonical_Path := Non_Canonical_Path;
5847 Get_Name_String (Non_Canonical_Path);
5848 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5849 Canonical_Path := Name_Find;
5852 -- To avoid processing the same directory several times, check
5853 -- if the directory is already in Recursive_Dirs. If it is, then
5854 -- there is nothing to do, just return. If it is not, put it there
5855 -- and continue recursive processing.
5858 if Recursive_Dirs.Get (Canonical_Path) then
5861 Recursive_Dirs.Set (Canonical_Path, True);
5865 -- Check if directory is already in list
5867 List := Data.Source_Dirs;
5869 while List /= Nil_String loop
5870 Element := In_Tree.String_Elements.Table (List);
5872 if Element.Value /= No_Name then
5873 Found := Element.Value = Canonical_Path;
5878 List := Element.Next;
5881 -- If directory is not already in list, put it there
5883 if (not Removed) and (not Found) then
5884 if Current_Verbosity = High then
5886 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5889 String_Element_Table.Increment_Last
5890 (In_Tree.String_Elements);
5892 (Value => Canonical_Path,
5893 Display_Value => Non_Canonical_Path,
5894 Location => No_Location,
5899 -- Case of first source directory
5901 if Last_Source_Dir = Nil_String then
5902 Data.Source_Dirs := String_Element_Table.Last
5903 (In_Tree.String_Elements);
5905 -- Here we already have source directories
5908 -- Link the previous last to the new one
5910 In_Tree.String_Elements.Table
5911 (Last_Source_Dir).Next :=
5912 String_Element_Table.Last
5913 (In_Tree.String_Elements);
5916 -- And register this source directory as the new last
5918 Last_Source_Dir := String_Element_Table.Last
5919 (In_Tree.String_Elements);
5920 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5923 elsif Removed and Found then
5924 if Prev = Nil_String then
5926 In_Tree.String_Elements.Table (List).Next;
5928 In_Tree.String_Elements.Table (Prev).Next :=
5929 In_Tree.String_Elements.Table (List).Next;
5933 -- Now look for subdirectories. We do that even when this
5934 -- directory is already in the list, because some of its
5935 -- subdirectories may not be in the list yet.
5937 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5940 Read (Dir, Name, Last);
5943 if Name (1 .. Last) /= "."
5944 and then Name (1 .. Last) /= ".."
5946 -- Avoid . and .. directories
5948 if Current_Verbosity = High then
5949 Write_Str (" Checking ");
5950 Write_Line (Name (1 .. Last));
5954 Path_Name : constant String :=
5956 (Name => Name (1 .. Last),
5958 The_Path (The_Path'First .. The_Path_Last),
5959 Resolve_Links => Opt.Follow_Links_For_Dirs,
5960 Case_Sensitive => True);
5963 if Is_Directory (Path_Name) then
5964 -- We have found a new subdirectory, call self
5966 Name_Len := Path_Name'Length;
5967 Name_Buffer (1 .. Name_Len) := Path_Name;
5968 Recursive_Find_Dirs (Name_Find);
5977 when Directory_Error =>
5979 end Recursive_Find_Dirs;
5981 -- Start of processing for Find_Source_Dirs
5984 if Current_Verbosity = High and then not Removed then
5985 Write_Str ("Find_Source_Dirs (""");
5986 Write_Str (Directory);
5990 -- First, check if we are looking for a directory tree, indicated
5991 -- by "/**" at the end.
5993 if Directory'Length >= 3
5994 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5995 and then (Directory (Directory'Last - 2) = '/'
5997 Directory (Directory'Last - 2) = Directory_Separator)
6000 Data.Known_Order_Of_Source_Dirs := False;
6003 Name_Len := Directory'Length - 3;
6005 if Name_Len = 0 then
6007 -- Case of "/**": all directories in file system
6010 Name_Buffer (1) := Directory (Directory'First);
6013 Name_Buffer (1 .. Name_Len) :=
6014 Directory (Directory'First .. Directory'Last - 3);
6017 if Current_Verbosity = High then
6018 Write_Str ("Looking for all subdirectories of """);
6019 Write_Str (Name_Buffer (1 .. Name_Len));
6024 Base_Dir : constant File_Name_Type := Name_Find;
6025 Root_Dir : constant String :=
6027 (Name => Get_Name_String (Base_Dir),
6029 Get_Name_String (Data.Directory.Display_Name),
6030 Resolve_Links => False,
6031 Case_Sensitive => True);
6034 if Root_Dir'Length = 0 then
6035 Err_Vars.Error_Msg_File_1 := Base_Dir;
6037 if Location = No_Location then
6040 "{ is not a valid directory.",
6045 "{ is not a valid directory.",
6050 -- We have an existing directory, we register it and all of
6051 -- its subdirectories.
6053 if Current_Verbosity = High then
6054 Write_Line ("Looking for source directories:");
6057 Name_Len := Root_Dir'Length;
6058 Name_Buffer (1 .. Name_Len) := Root_Dir;
6059 Recursive_Find_Dirs (Name_Find);
6061 if Current_Verbosity = High then
6062 Write_Line ("End of looking for source directories.");
6067 -- We have a single directory
6071 Path_Name : Path_Name_Type;
6072 Display_Path_Name : Path_Name_Type;
6073 List : String_List_Id;
6074 Prev : String_List_Id;
6078 (Project => Project,
6081 Parent => Data.Directory.Display_Name,
6083 Display => Display_Path_Name,
6084 Current_Dir => Current_Dir);
6086 if Path_Name = No_Path then
6087 Err_Vars.Error_Msg_File_1 := From;
6089 if Location = No_Location then
6092 "{ is not a valid directory",
6097 "{ is not a valid directory",
6103 Path : constant String :=
6104 Get_Name_String (Path_Name) &
6105 Directory_Separator;
6106 Last_Path : constant Natural :=
6107 Compute_Directory_Last (Path);
6109 Display_Path : constant String :=
6111 (Display_Path_Name) &
6112 Directory_Separator;
6113 Last_Display_Path : constant Natural :=
6114 Compute_Directory_Last
6116 Display_Path_Id : Name_Id;
6120 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6121 Path_Id := Name_Find;
6123 Add_Str_To_Name_Buffer
6125 (Display_Path'First .. Last_Display_Path));
6126 Display_Path_Id := Name_Find;
6130 -- As it is an existing directory, we add it to the
6131 -- list of directories.
6133 String_Element_Table.Increment_Last
6134 (In_Tree.String_Elements);
6138 Display_Value => Display_Path_Id,
6139 Location => No_Location,
6141 Next => Nil_String);
6143 if Last_Source_Dir = Nil_String then
6145 -- This is the first source directory
6147 Data.Source_Dirs := String_Element_Table.Last
6148 (In_Tree.String_Elements);
6151 -- We already have source directories, link the
6152 -- previous last to the new one.
6154 In_Tree.String_Elements.Table
6155 (Last_Source_Dir).Next :=
6156 String_Element_Table.Last
6157 (In_Tree.String_Elements);
6160 -- And register this source directory as the new last
6162 Last_Source_Dir := String_Element_Table.Last
6163 (In_Tree.String_Elements);
6164 In_Tree.String_Elements.Table
6165 (Last_Source_Dir) := Element;
6168 -- Remove source dir, if present
6170 List := Data.Source_Dirs;
6173 -- Look for source dir in current list
6175 while List /= Nil_String loop
6176 Element := In_Tree.String_Elements.Table (List);
6177 exit when Element.Value = Path_Id;
6179 List := Element.Next;
6182 if List /= Nil_String then
6183 -- Source dir was found, remove it from the list
6185 if Prev = Nil_String then
6187 In_Tree.String_Elements.Table (List).Next;
6190 In_Tree.String_Elements.Table (Prev).Next :=
6191 In_Tree.String_Elements.Table (List).Next;
6199 end Find_Source_Dirs;
6201 -- Start of processing for Get_Directories
6204 if Current_Verbosity = High then
6205 Write_Line ("Starting to look for directories");
6208 -- Check the object directory
6210 pragma Assert (Object_Dir.Kind = Single,
6211 "Object_Dir is not a single string");
6213 -- We set the object directory to its default
6215 Data.Object_Directory := Data.Directory;
6217 if Object_Dir.Value /= Empty_String then
6218 Get_Name_String (Object_Dir.Value);
6220 if Name_Len = 0 then
6223 "Object_Dir cannot be empty",
6224 Object_Dir.Location);
6227 -- We check that the specified object directory does exist
6232 File_Name_Type (Object_Dir.Value),
6233 Data.Directory.Display_Name,
6234 Data.Object_Directory.Name,
6235 Data.Object_Directory.Display_Name,
6237 Location => Object_Dir.Location,
6238 Current_Dir => Current_Dir);
6240 if Data.Object_Directory = No_Path_Information then
6242 -- The object directory does not exist, report an error if the
6243 -- project is not externally built.
6245 if not Data.Externally_Built then
6246 Err_Vars.Error_Msg_File_1 :=
6247 File_Name_Type (Object_Dir.Value);
6250 "the object directory { cannot be found",
6254 -- Do not keep a nil Object_Directory. Set it to the specified
6255 -- (relative or absolute) path. This is for the benefit of
6256 -- tools that recover from errors; for example, these tools
6257 -- could create the non existent directory.
6259 Data.Object_Directory.Display_Name :=
6260 Path_Name_Type (Object_Dir.Value);
6262 if Osint.File_Names_Case_Sensitive then
6263 Data.Object_Directory.Name :=
6264 Path_Name_Type (Object_Dir.Value);
6266 Get_Name_String (Object_Dir.Value);
6267 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6268 Data.Object_Directory.Name := Name_Find;
6273 elsif Subdirs /= null then
6275 Name_Buffer (1) := '.';
6280 Data.Directory.Display_Name,
6281 Data.Object_Directory.Name,
6282 Data.Object_Directory.Display_Name,
6284 Location => Object_Dir.Location,
6285 Current_Dir => Current_Dir);
6288 if Current_Verbosity = High then
6289 if Data.Object_Directory = No_Path_Information then
6290 Write_Line ("No object directory");
6292 Write_Str ("Object directory: """);
6293 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6298 -- Check the exec directory
6300 pragma Assert (Exec_Dir.Kind = Single,
6301 "Exec_Dir is not a single string");
6303 -- We set the object directory to its default
6305 Data.Exec_Directory := Data.Object_Directory;
6307 if Exec_Dir.Value /= Empty_String then
6308 Get_Name_String (Exec_Dir.Value);
6310 if Name_Len = 0 then
6313 "Exec_Dir cannot be empty",
6317 -- We check that the specified exec directory does exist
6322 File_Name_Type (Exec_Dir.Value),
6323 Data.Directory.Display_Name,
6324 Data.Exec_Directory.Name,
6325 Data.Exec_Directory.Display_Name,
6327 Location => Exec_Dir.Location,
6328 Current_Dir => Current_Dir);
6330 if Data.Exec_Directory = No_Path_Information then
6331 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6334 "the exec directory { cannot be found",
6340 if Current_Verbosity = High then
6341 if Data.Exec_Directory = No_Path_Information then
6342 Write_Line ("No exec directory");
6344 Write_Str ("Exec directory: """);
6345 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6350 -- Look for the source directories
6352 if Current_Verbosity = High then
6353 Write_Line ("Starting to look for source directories");
6356 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6358 if (not Source_Files.Default) and then
6359 Source_Files.Values = Nil_String
6361 Data.Source_Dirs := Nil_String;
6363 if Data.Qualifier = Standard then
6367 "a standard project cannot have no sources",
6368 Source_Files.Location);
6371 if Data.Extends = No_Project
6372 and then Data.Object_Directory = Data.Directory
6374 Data.Object_Directory := No_Path_Information;
6377 elsif Source_Dirs.Default then
6379 -- No Source_Dirs specified: the single source directory is the one
6380 -- containing the project file
6382 String_Element_Table.Increment_Last
6383 (In_Tree.String_Elements);
6384 Data.Source_Dirs := String_Element_Table.Last
6385 (In_Tree.String_Elements);
6386 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6387 (Value => Name_Id (Data.Directory.Name),
6388 Display_Value => Name_Id (Data.Directory.Display_Name),
6389 Location => No_Location,
6394 if Current_Verbosity = High then
6395 Write_Line ("Single source directory:");
6397 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6401 elsif Source_Dirs.Values = Nil_String then
6402 if Data.Qualifier = Standard then
6406 "a standard project cannot have no source directories",
6407 Source_Dirs.Location);
6410 -- If Source_Dirs is an empty string list, this means that this
6411 -- project contains no source. For projects that don't extend other
6412 -- projects, this also means that there is no need for an object
6413 -- directory, if not specified.
6415 if Data.Extends = No_Project
6416 and then Data.Object_Directory = Data.Directory
6418 Data.Object_Directory := No_Path_Information;
6421 Data.Source_Dirs := Nil_String;
6425 Source_Dir : String_List_Id;
6426 Element : String_Element;
6429 -- Process the source directories for each element of the list
6431 Source_Dir := Source_Dirs.Values;
6432 while Source_Dir /= Nil_String loop
6433 Element := In_Tree.String_Elements.Table (Source_Dir);
6435 (File_Name_Type (Element.Value), Element.Location);
6436 Source_Dir := Element.Next;
6441 if not Excluded_Source_Dirs.Default
6442 and then Excluded_Source_Dirs.Values /= Nil_String
6445 Source_Dir : String_List_Id;
6446 Element : String_Element;
6449 -- Process the source directories for each element of the list
6451 Source_Dir := Excluded_Source_Dirs.Values;
6452 while Source_Dir /= Nil_String loop
6453 Element := In_Tree.String_Elements.Table (Source_Dir);
6455 (File_Name_Type (Element.Value),
6458 Source_Dir := Element.Next;
6463 if Current_Verbosity = High then
6464 Write_Line ("Putting source directories in canonical cases");
6468 Current : String_List_Id := Data.Source_Dirs;
6469 Element : String_Element;
6472 while Current /= Nil_String loop
6473 Element := In_Tree.String_Elements.Table (Current);
6474 if Element.Value /= No_Name then
6475 if not Osint.File_Names_Case_Sensitive then
6476 Get_Name_String (Element.Value);
6477 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6478 Element.Value := Name_Find;
6481 In_Tree.String_Elements.Table (Current) := Element;
6484 Current := Element.Next;
6488 end Get_Directories;
6495 (Project : Project_Id;
6496 In_Tree : Project_Tree_Ref;
6497 Data : in out Project_Data)
6499 Mains : constant Variable_Value :=
6500 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6501 List : String_List_Id;
6502 Elem : String_Element;
6505 Data.Mains := Mains.Values;
6507 -- If no Mains were specified, and if we are an extending project,
6508 -- inherit the Mains from the project we are extending.
6510 if Mains.Default then
6511 if not Data.Library and then Data.Extends /= No_Project then
6513 In_Tree.Projects.Table (Data.Extends).Mains;
6516 -- In a library project file, Main cannot be specified
6518 elsif Data.Library then
6521 "a library project file cannot have Main specified",
6525 List := Mains.Values;
6526 while List /= Nil_String loop
6527 Elem := In_Tree.String_Elements.Table (List);
6529 if Length_Of_Name (Elem.Value) = 0 then
6532 "?a main cannot have an empty name",
6542 ---------------------------
6543 -- Get_Sources_From_File --
6544 ---------------------------
6546 procedure Get_Sources_From_File
6548 Location : Source_Ptr;
6549 Project : Project_Id;
6550 In_Tree : Project_Tree_Ref)
6552 File : Prj.Util.Text_File;
6553 Line : String (1 .. 250);
6555 Source_Name : File_Name_Type;
6556 Name_Loc : Name_Location;
6559 if Get_Mode = Ada_Only then
6563 if Current_Verbosity = High then
6564 Write_Str ("Opening """);
6571 Prj.Util.Open (File, Path);
6573 if not Prj.Util.Is_Valid (File) then
6574 Error_Msg (Project, In_Tree, "file does not exist", Location);
6577 -- Read the lines one by one
6579 while not Prj.Util.End_Of_File (File) loop
6580 Prj.Util.Get_Line (File, Line, Last);
6582 -- A non empty, non comment line should contain a file name
6585 and then (Last = 1 or else Line (1 .. 2) /= "--")
6588 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6589 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6590 Source_Name := Name_Find;
6592 -- Check that there is no directory information
6594 for J in 1 .. Last loop
6595 if Line (J) = '/' or else Line (J) = Directory_Separator then
6596 Error_Msg_File_1 := Source_Name;
6600 "file name cannot include directory information ({)",
6606 Name_Loc := Source_Names.Get (Source_Name);
6608 if Name_Loc = No_Name_Location then
6610 (Name => Source_Name,
6611 Location => Location,
6612 Source => No_Source,
6617 Source_Names.Set (Source_Name, Name_Loc);
6621 Prj.Util.Close (File);
6624 end Get_Sources_From_File;
6631 (In_Tree : Project_Tree_Ref;
6632 Canonical_File_Name : File_Name_Type;
6633 Naming : Naming_Data;
6634 Exception_Id : out Ada_Naming_Exception_Id;
6635 Unit_Name : out Name_Id;
6636 Unit_Kind : out Spec_Or_Body;
6637 Needs_Pragma : out Boolean)
6639 Info_Id : Ada_Naming_Exception_Id :=
6640 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6641 VMS_Name : File_Name_Type;
6644 if Info_Id = No_Ada_Naming_Exception then
6645 if Hostparm.OpenVMS then
6646 VMS_Name := Canonical_File_Name;
6647 Get_Name_String (VMS_Name);
6649 if Name_Buffer (Name_Len) = '.' then
6650 Name_Len := Name_Len - 1;
6651 VMS_Name := Name_Find;
6654 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6659 if Info_Id /= No_Ada_Naming_Exception then
6660 Exception_Id := Info_Id;
6661 Unit_Name := No_Name;
6662 Unit_Kind := Specification;
6663 Needs_Pragma := True;
6667 Needs_Pragma := False;
6668 Exception_Id := No_Ada_Naming_Exception;
6670 Get_Name_String (Canonical_File_Name);
6672 -- How about some comments and a name for this declare block ???
6673 -- In fact the whole code below needs more comments ???
6676 File : String := Name_Buffer (1 .. Name_Len);
6677 First : constant Positive := File'First;
6678 Last : Natural := File'Last;
6679 Standard_GNAT : Boolean;
6680 Spec : constant File_Name_Type :=
6681 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6682 Body_Suff : constant File_Name_Type :=
6683 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6686 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6687 and then Body_Suff = Default_Ada_Body_Suffix;
6690 Spec_Suffix : constant String := Get_Name_String (Spec);
6691 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6692 Sep_Suffix : constant String :=
6693 Get_Name_String (Naming.Separate_Suffix);
6695 May_Be_Spec : Boolean;
6696 May_Be_Body : Boolean;
6697 May_Be_Sep : Boolean;
6701 File'Length > Spec_Suffix'Length
6703 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6706 File'Length > Body_Suffix'Length
6708 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6711 File'Length > Sep_Suffix'Length
6713 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6715 -- If two May_Be_ booleans are True, always choose the longer one
6718 if May_Be_Body and then
6719 Spec_Suffix'Length < Body_Suffix'Length
6721 Unit_Kind := Body_Part;
6723 if May_Be_Sep and then
6724 Body_Suffix'Length < Sep_Suffix'Length
6726 Last := Last - Sep_Suffix'Length;
6727 May_Be_Body := False;
6730 Last := Last - Body_Suffix'Length;
6731 May_Be_Sep := False;
6734 elsif May_Be_Sep and then
6735 Spec_Suffix'Length < Sep_Suffix'Length
6737 Unit_Kind := Body_Part;
6738 Last := Last - Sep_Suffix'Length;
6741 Unit_Kind := Specification;
6742 Last := Last - Spec_Suffix'Length;
6745 elsif May_Be_Body then
6746 Unit_Kind := Body_Part;
6748 if May_Be_Sep and then
6749 Body_Suffix'Length < Sep_Suffix'Length
6751 Last := Last - Sep_Suffix'Length;
6752 May_Be_Body := False;
6754 Last := Last - Body_Suffix'Length;
6755 May_Be_Sep := False;
6758 elsif May_Be_Sep then
6759 Unit_Kind := Body_Part;
6760 Last := Last - Sep_Suffix'Length;
6768 -- This is not a source file
6770 Unit_Name := No_Name;
6771 Unit_Kind := Specification;
6773 if Current_Verbosity = High then
6774 Write_Line (" Not a valid file name.");
6779 elsif Current_Verbosity = High then
6781 when Specification =>
6782 Write_Str (" Specification: ");
6783 Write_Line (File (First .. Last + Spec_Suffix'Length));
6787 Write_Str (" Body: ");
6788 Write_Line (File (First .. Last + Body_Suffix'Length));
6791 Write_Str (" Separate: ");
6792 Write_Line (File (First .. Last + Sep_Suffix'Length));
6798 Get_Name_String (Naming.Dot_Replacement);
6800 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6802 if Name_Buffer (1 .. Name_Len) /= "." then
6804 -- If Dot_Replacement is not a single dot, then there should not
6805 -- be any dot in the name.
6807 for Index in First .. Last loop
6808 if File (Index) = '.' then
6809 if Current_Verbosity = High then
6811 (" Not a valid file name (some dot not replaced).");
6814 Unit_Name := No_Name;
6820 -- Replace the substring Dot_Replacement with dots
6823 Index : Positive := First;
6826 while Index <= Last - Name_Len + 1 loop
6828 if File (Index .. Index + Name_Len - 1) =
6829 Name_Buffer (1 .. Name_Len)
6831 File (Index) := '.';
6833 if Name_Len > 1 and then Index < Last then
6834 File (Index + 1 .. Last - Name_Len + 1) :=
6835 File (Index + Name_Len .. Last);
6838 Last := Last - Name_Len + 1;
6846 -- Check if the file casing is right
6849 Src : String := File (First .. Last);
6850 Src_Last : Positive := Last;
6853 -- If casing is significant, deal with upper/lower case translate
6855 if File_Names_Case_Sensitive then
6856 case Naming.Casing is
6857 when All_Lower_Case =>
6860 Mapping => Lower_Case_Map);
6862 when All_Upper_Case =>
6865 Mapping => Upper_Case_Map);
6867 when Mixed_Case | Unknown =>
6871 if Src /= File (First .. Last) then
6872 if Current_Verbosity = High then
6873 Write_Line (" Not a valid file name (casing).");
6876 Unit_Name := No_Name;
6881 -- Put the name in lower case
6885 Mapping => Lower_Case_Map);
6887 -- In the standard GNAT naming scheme, check for special cases:
6888 -- children or separates of A, G, I or S, and run time sources.
6890 if Standard_GNAT and then Src'Length >= 3 then
6892 S1 : constant Character := Src (Src'First);
6893 S2 : constant Character := Src (Src'First + 1);
6894 S3 : constant Character := Src (Src'First + 2);
6902 -- Children or separates of packages A, G, I or S. These
6903 -- names are x__ ... or x~... (where x is a, g, i, or s).
6904 -- Both versions (x__... and x~...) are allowed in all
6905 -- platforms, because it is not possible to know the
6906 -- platform before processing of the project files.
6908 if S2 = '_' and then S3 = '_' then
6909 Src (Src'First + 1) := '.';
6910 Src_Last := Src_Last - 1;
6911 Src (Src'First + 2 .. Src_Last) :=
6912 Src (Src'First + 3 .. Src_Last + 1);
6915 Src (Src'First + 1) := '.';
6917 -- If it is potentially a run time source, disable
6918 -- filling of the mapping file to avoid warnings.
6921 Set_Mapping_File_Initial_State_To_Empty;
6927 if Current_Verbosity = High then
6929 Write_Line (Src (Src'First .. Src_Last));
6932 -- Now, we check if this name is a valid unit name
6935 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6945 function Hash (Unit : Unit_Info) return Header_Num is
6947 return Header_Num (Unit.Unit mod 2048);
6950 -----------------------
6951 -- Is_Illegal_Suffix --
6952 -----------------------
6954 function Is_Illegal_Suffix
6956 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6959 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6963 -- If dot replacement is a single dot, and first character of suffix is
6966 if Dot_Replacement_Is_A_Single_Dot
6967 and then Suffix (Suffix'First) = '.'
6969 for Index in Suffix'First + 1 .. Suffix'Last loop
6971 -- If there is another dot
6973 if Suffix (Index) = '.' then
6975 -- It is illegal to have a letter following the initial dot
6977 return Is_Letter (Suffix (Suffix'First + 1));
6985 end Is_Illegal_Suffix;
6987 ----------------------
6988 -- Locate_Directory --
6989 ----------------------
6991 procedure Locate_Directory
6992 (Project : Project_Id;
6993 In_Tree : Project_Tree_Ref;
6994 Name : File_Name_Type;
6995 Parent : Path_Name_Type;
6996 Dir : out Path_Name_Type;
6997 Display : out Path_Name_Type;
6998 Create : String := "";
6999 Current_Dir : String;
7000 Location : Source_Ptr := No_Location)
7002 The_Parent : constant String :=
7003 Get_Name_String (Parent) & Directory_Separator;
7005 The_Parent_Last : constant Natural :=
7006 Compute_Directory_Last (The_Parent);
7008 Full_Name : File_Name_Type;
7010 The_Name : File_Name_Type;
7013 Get_Name_String (Name);
7015 -- Add Subdirs.all if it is a directory that may be created and
7016 -- Subdirs is not null;
7018 if Create /= "" and then Subdirs /= null then
7019 if Name_Buffer (Name_Len) /= Directory_Separator then
7020 Add_Char_To_Name_Buffer (Directory_Separator);
7023 Add_Str_To_Name_Buffer (Subdirs.all);
7026 -- Convert '/' to directory separator (for Windows)
7028 for J in 1 .. Name_Len loop
7029 if Name_Buffer (J) = '/' then
7030 Name_Buffer (J) := Directory_Separator;
7034 The_Name := Name_Find;
7036 if Current_Verbosity = High then
7037 Write_Str ("Locate_Directory (""");
7038 Write_Str (Get_Name_String (The_Name));
7039 Write_Str (""", """);
7040 Write_Str (The_Parent);
7047 if Is_Absolute_Path (Get_Name_String (The_Name)) then
7048 Full_Name := The_Name;
7052 Add_Str_To_Name_Buffer
7053 (The_Parent (The_Parent'First .. The_Parent_Last));
7054 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7055 Full_Name := Name_Find;
7059 Full_Path_Name : constant String := Get_Name_String (Full_Name);
7062 if (Setup_Projects or else Subdirs /= null)
7063 and then Create'Length > 0
7064 and then not Is_Directory (Full_Path_Name)
7067 Create_Path (Full_Path_Name);
7069 if not Quiet_Output then
7071 Write_Str (" directory """);
7072 Write_Str (Full_Path_Name);
7073 Write_Line (""" created");
7080 "could not create " & Create &
7081 " directory " & Full_Path_Name,
7086 if Is_Directory (Full_Path_Name) then
7088 Normed : constant String :=
7091 Directory => Current_Dir,
7092 Resolve_Links => False,
7093 Case_Sensitive => True);
7095 Canonical_Path : constant String :=
7098 Directory => Current_Dir,
7100 Opt.Follow_Links_For_Dirs,
7101 Case_Sensitive => False);
7104 Name_Len := Normed'Length;
7105 Name_Buffer (1 .. Name_Len) := Normed;
7106 Display := Name_Find;
7108 Name_Len := Canonical_Path'Length;
7109 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7114 end Locate_Directory;
7116 ---------------------------
7117 -- Find_Excluded_Sources --
7118 ---------------------------
7120 procedure Find_Excluded_Sources
7121 (Project : Project_Id;
7122 In_Tree : Project_Tree_Ref;
7123 Data : Project_Data)
7125 Excluded_Sources : Variable_Value;
7127 Excluded_Source_List_File : Variable_Value;
7129 Current : String_List_Id;
7131 Element : String_Element;
7133 Location : Source_Ptr;
7135 Name : File_Name_Type;
7137 File : Prj.Util.Text_File;
7138 Line : String (1 .. 300);
7141 Locally_Removed : Boolean := False;
7143 Excluded_Source_List_File :=
7145 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7149 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7151 -- If Excluded_Source_Files is not declared, check
7152 -- Locally_Removed_Files.
7154 if Excluded_Sources.Default then
7155 Locally_Removed := True;
7158 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7161 Excluded_Sources_Htable.Reset;
7163 -- If there are excluded sources, put them in the table
7165 if not Excluded_Sources.Default then
7166 if not Excluded_Source_List_File.Default then
7167 if Locally_Removed then
7170 "?both attributes Locally_Removed_Files and " &
7171 "Excluded_Source_List_File are present",
7172 Excluded_Source_List_File.Location);
7176 "?both attributes Excluded_Source_Files and " &
7177 "Excluded_Source_List_File are present",
7178 Excluded_Source_List_File.Location);
7182 Current := Excluded_Sources.Values;
7183 while Current /= Nil_String loop
7184 Element := In_Tree.String_Elements.Table (Current);
7186 if Osint.File_Names_Case_Sensitive then
7187 Name := File_Name_Type (Element.Value);
7189 Get_Name_String (Element.Value);
7190 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7194 -- If the element has no location, then use the location
7195 -- of Excluded_Sources to report possible errors.
7197 if Element.Location = No_Location then
7198 Location := Excluded_Sources.Location;
7200 Location := Element.Location;
7203 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7204 Current := Element.Next;
7207 elsif not Excluded_Source_List_File.Default then
7208 Location := Excluded_Source_List_File.Location;
7211 Source_File_Path_Name : constant String :=
7214 (Excluded_Source_List_File.Value),
7215 Data.Directory.Name);
7218 if Source_File_Path_Name'Length = 0 then
7219 Err_Vars.Error_Msg_File_1 :=
7220 File_Name_Type (Excluded_Source_List_File.Value);
7223 "file with excluded sources { does not exist",
7224 Excluded_Source_List_File.Location);
7229 Prj.Util.Open (File, Source_File_Path_Name);
7231 if not Prj.Util.Is_Valid (File) then
7233 (Project, In_Tree, "file does not exist", Location);
7235 -- Read the lines one by one
7237 while not Prj.Util.End_Of_File (File) loop
7238 Prj.Util.Get_Line (File, Line, Last);
7240 -- A non empty, non comment line should contain a file
7244 and then (Last = 1 or else Line (1 .. 2) /= "--")
7247 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7248 Canonical_Case_File_Name
7249 (Name_Buffer (1 .. Name_Len));
7252 -- Check that there is no directory information
7254 for J in 1 .. Last loop
7256 or else Line (J) = Directory_Separator
7258 Error_Msg_File_1 := Name;
7262 "file name cannot include " &
7263 "directory information ({)",
7269 Excluded_Sources_Htable.Set
7270 (Name, (Name, False, Location));
7274 Prj.Util.Close (File);
7279 end Find_Excluded_Sources;
7281 ---------------------------
7282 -- Find_Explicit_Sources --
7283 ---------------------------
7285 procedure Find_Explicit_Sources
7286 (Current_Dir : String;
7287 Project : Project_Id;
7288 In_Tree : Project_Tree_Ref;
7289 Data : in out Project_Data)
7291 Sources : constant Variable_Value :=
7294 Data.Decl.Attributes,
7296 Source_List_File : constant Variable_Value :=
7298 (Name_Source_List_File,
7299 Data.Decl.Attributes,
7301 Name_Loc : Name_Location;
7304 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7306 (Source_List_File.Kind = Single,
7307 "Source_List_File is not a single string");
7309 -- If the user has specified a Sources attribute
7311 if not Sources.Default then
7312 if not Source_List_File.Default then
7315 "?both attributes source_files and " &
7316 "source_list_file are present",
7317 Source_List_File.Location);
7320 -- Sources is a list of file names
7323 Current : String_List_Id := Sources.Values;
7324 Element : String_Element;
7325 Location : Source_Ptr;
7326 Name : File_Name_Type;
7329 if Get_Mode = Ada_Only then
7330 Data.Ada_Sources_Present := Current /= Nil_String;
7333 if Get_Mode = Multi_Language then
7334 if Current = Nil_String then
7335 Data.First_Language_Processing := No_Language_Index;
7337 -- This project contains no source. For projects that
7338 -- don't extend other projects, this also means that
7339 -- there is no need for an object directory, if not
7342 if Data.Extends = No_Project
7343 and then Data.Object_Directory = Data.Directory
7345 Data.Object_Directory := No_Path_Information;
7350 while Current /= Nil_String loop
7351 Element := In_Tree.String_Elements.Table (Current);
7352 Get_Name_String (Element.Value);
7354 if Osint.File_Names_Case_Sensitive then
7355 Name := File_Name_Type (Element.Value);
7357 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7361 -- If the element has no location, then use the
7362 -- location of Sources to report possible errors.
7364 if Element.Location = No_Location then
7365 Location := Sources.Location;
7367 Location := Element.Location;
7370 -- Check that there is no directory information
7372 for J in 1 .. Name_Len loop
7373 if Name_Buffer (J) = '/'
7374 or else Name_Buffer (J) = Directory_Separator
7376 Error_Msg_File_1 := Name;
7380 "file name cannot include directory " &
7387 -- In Multi_Language mode, check whether the file is
7388 -- already there: the same file name may be in the list; if
7389 -- the source is missing, the error will be on the first
7390 -- mention of the source file name.
7394 Name_Loc := No_Name_Location;
7395 when Multi_Language =>
7396 Name_Loc := Source_Names.Get (Name);
7399 if Name_Loc = No_Name_Location then
7402 Location => Location,
7403 Source => No_Source,
7406 Source_Names.Set (Name, Name_Loc);
7409 Current := Element.Next;
7412 if Get_Mode = Ada_Only then
7413 Get_Path_Names_And_Record_Ada_Sources
7414 (Project, In_Tree, Data, Current_Dir);
7418 -- If we have no Source_Files attribute, check the Source_List_File
7421 elsif not Source_List_File.Default then
7423 -- Source_List_File is the name of the file
7424 -- that contains the source file names
7427 Source_File_Path_Name : constant String :=
7429 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7432 if Source_File_Path_Name'Length = 0 then
7433 Err_Vars.Error_Msg_File_1 :=
7434 File_Name_Type (Source_List_File.Value);
7437 "file with sources { does not exist",
7438 Source_List_File.Location);
7441 Get_Sources_From_File
7442 (Source_File_Path_Name, Source_List_File.Location,
7445 if Get_Mode = Ada_Only then
7446 -- Look in the source directories to find those sources
7448 Get_Path_Names_And_Record_Ada_Sources
7449 (Project, In_Tree, Data, Current_Dir);
7455 -- Neither Source_Files nor Source_List_File has been
7456 -- specified. Find all the files that satisfy the naming
7457 -- scheme in all the source directories.
7459 if Get_Mode = Ada_Only then
7460 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7464 if Get_Mode = Multi_Language then
7466 (Project, In_Tree, Data,
7468 Sources.Default and then Source_List_File.Default);
7470 -- Check if all exceptions have been found.
7471 -- For Ada, it is an error if an exception is not found.
7472 -- For other language, the source is simply removed.
7478 Source := Data.First_Source;
7479 while Source /= No_Source loop
7481 Src_Data : Source_Data renames
7482 In_Tree.Sources.Table (Source);
7485 if Src_Data.Naming_Exception
7486 and then Src_Data.Path = No_Path_Information
7488 if Src_Data.Unit /= No_Name then
7489 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7490 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7493 "source file %% for unit %% not found",
7497 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7500 Source := Src_Data.Next_In_Project;
7505 -- Check that all sources in Source_Files or the file
7506 -- Source_List_File has been found.
7509 Name_Loc : Name_Location;
7512 Name_Loc := Source_Names.Get_First;
7513 while Name_Loc /= No_Name_Location loop
7514 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7515 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7519 "file %% not found",
7523 Name_Loc := Source_Names.Get_Next;
7528 if Get_Mode = Ada_Only
7529 and then Data.Extends = No_Project
7531 -- We should have found at least one source, if not report an error
7533 if Data.Ada_Sources = Nil_String then
7535 (Project, "Ada", In_Tree, Source_List_File.Location);
7539 end Find_Explicit_Sources;
7541 -------------------------------------------
7542 -- Get_Path_Names_And_Record_Ada_Sources --
7543 -------------------------------------------
7545 procedure Get_Path_Names_And_Record_Ada_Sources
7546 (Project : Project_Id;
7547 In_Tree : Project_Tree_Ref;
7548 Data : in out Project_Data;
7549 Current_Dir : String)
7551 Source_Dir : String_List_Id;
7552 Element : String_Element;
7553 Path : Path_Name_Type;
7555 Name : File_Name_Type;
7556 Canonical_Name : File_Name_Type;
7557 Name_Str : String (1 .. 1_024);
7558 Last : Natural := 0;
7560 Current_Source : String_List_Id := Nil_String;
7561 First_Error : Boolean := True;
7562 Source_Recorded : Boolean := False;
7565 -- We look in all source directories for the file names in the hash
7566 -- table Source_Names.
7568 Source_Dir := Data.Source_Dirs;
7569 while Source_Dir /= Nil_String loop
7570 Source_Recorded := False;
7571 Element := In_Tree.String_Elements.Table (Source_Dir);
7574 Dir_Path : constant String :=
7575 Get_Name_String (Element.Display_Value);
7577 if Current_Verbosity = High then
7578 Write_Str ("checking directory """);
7579 Write_Str (Dir_Path);
7583 Open (Dir, Dir_Path);
7586 Read (Dir, Name_Str, Last);
7590 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7593 if Osint.File_Names_Case_Sensitive then
7594 Canonical_Name := Name;
7596 Canonical_Case_File_Name (Name_Str (1 .. Last));
7597 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7598 Canonical_Name := Name_Find;
7601 NL := Source_Names.Get (Canonical_Name);
7603 if NL /= No_Name_Location and then not NL.Found then
7605 Source_Names.Set (Canonical_Name, NL);
7606 Name_Len := Dir_Path'Length;
7607 Name_Buffer (1 .. Name_Len) := Dir_Path;
7609 if Name_Buffer (Name_Len) /= Directory_Separator then
7610 Add_Char_To_Name_Buffer (Directory_Separator);
7613 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7616 if Current_Verbosity = High then
7617 Write_Str (" found ");
7618 Write_Line (Get_Name_String (Name));
7621 -- Register the source if it is an Ada compilation unit
7629 Location => NL.Location,
7630 Current_Source => Current_Source,
7631 Source_Recorded => Source_Recorded,
7632 Current_Dir => Current_Dir);
7639 if Source_Recorded then
7640 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7644 Source_Dir := Element.Next;
7647 -- It is an error if a source file name in a source list or
7648 -- in a source list file is not found.
7650 NL := Source_Names.Get_First;
7651 while NL /= No_Name_Location loop
7652 if not NL.Found then
7653 Err_Vars.Error_Msg_File_1 := NL.Name;
7658 "source file { cannot be found",
7660 First_Error := False;
7665 "\source file { cannot be found",
7670 NL := Source_Names.Get_Next;
7672 end Get_Path_Names_And_Record_Ada_Sources;
7674 --------------------------
7675 -- Check_Naming_Schemes --
7676 --------------------------
7678 procedure Check_Naming_Schemes
7679 (In_Tree : Project_Tree_Ref;
7680 Data : in out Project_Data;
7682 File_Name : File_Name_Type;
7683 Alternate_Languages : out Alternate_Language_Id;
7684 Language : out Language_Index;
7685 Language_Name : out Name_Id;
7686 Display_Language_Name : out Name_Id;
7688 Lang_Kind : out Language_Kind;
7689 Kind : out Source_Kind)
7691 Last : Positive := Filename'Last;
7692 Config : Language_Config;
7693 Lang : Name_List_Index := Data.Languages;
7694 Header_File : Boolean := False;
7695 First_Language : Language_Index;
7698 Last_Spec : Natural;
7699 Last_Body : Natural;
7704 Alternate_Languages := No_Alternate_Language;
7706 while Lang /= No_Name_List loop
7707 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7708 Language := Data.First_Language_Processing;
7710 if Current_Verbosity = High then
7712 (" Testing language "
7713 & Get_Name_String (Language_Name)
7714 & " Header_File=" & Header_File'Img);
7717 while Language /= No_Language_Index loop
7718 if In_Tree.Languages_Data.Table (Language).Name =
7721 Display_Language_Name :=
7722 In_Tree.Languages_Data.Table (Language).Display_Name;
7723 Config := In_Tree.Languages_Data.Table (Language).Config;
7724 Lang_Kind := Config.Kind;
7726 if Config.Kind = File_Based then
7728 -- For file based languages, there is no Unit. Just
7729 -- check if the file name has the implementation or,
7730 -- if it is specified, the template suffix of the
7736 and then Config.Naming_Data.Body_Suffix /= No_File
7739 Impl_Suffix : constant String :=
7740 Get_Name_String (Config.Naming_Data.Body_Suffix);
7743 if Filename'Length > Impl_Suffix'Length
7746 (Last - Impl_Suffix'Length + 1 .. Last) =
7751 if Current_Verbosity = High then
7752 Write_Str (" source of language ");
7754 (Get_Name_String (Display_Language_Name));
7762 if Config.Naming_Data.Spec_Suffix /= No_File then
7764 Spec_Suffix : constant String :=
7766 (Config.Naming_Data.Spec_Suffix);
7769 if Filename'Length > Spec_Suffix'Length
7772 (Last - Spec_Suffix'Length + 1 .. Last) =
7777 if Current_Verbosity = High then
7778 Write_Str (" header file of language ");
7780 (Get_Name_String (Display_Language_Name));
7784 Alternate_Language_Table.Increment_Last
7785 (In_Tree.Alt_Langs);
7786 In_Tree.Alt_Langs.Table
7787 (Alternate_Language_Table.Last
7788 (In_Tree.Alt_Langs)) :=
7789 (Language => Language,
7790 Next => Alternate_Languages);
7791 Alternate_Languages :=
7792 Alternate_Language_Table.Last
7793 (In_Tree.Alt_Langs);
7795 Header_File := True;
7796 First_Language := Language;
7802 elsif not Header_File then
7803 -- Unit based language
7805 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7810 -- ??? Are we doing this once per file in the project ?
7811 -- It should be done only once per project.
7813 case Config.Naming_Data.Casing is
7814 when All_Lower_Case =>
7815 for J in Filename'Range loop
7816 if Is_Letter (Filename (J)) then
7817 if not Is_Lower (Filename (J)) then
7824 when All_Upper_Case =>
7825 for J in Filename'Range loop
7826 if Is_Letter (Filename (J)) then
7827 if not Is_Upper (Filename (J)) then
7843 Last_Spec := Natural'Last;
7844 Last_Body := Natural'Last;
7845 Last_Sep := Natural'Last;
7847 if Config.Naming_Data.Separate_Suffix /= No_File
7849 Config.Naming_Data.Separate_Suffix /=
7850 Config.Naming_Data.Body_Suffix
7853 Suffix : constant String :=
7855 (Config.Naming_Data.Separate_Suffix);
7857 if Filename'Length > Suffix'Length
7860 (Last - Suffix'Length + 1 .. Last) =
7863 Last_Sep := Last - Suffix'Length;
7868 if Config.Naming_Data.Body_Suffix /= No_File then
7870 Suffix : constant String :=
7872 (Config.Naming_Data.Body_Suffix);
7874 if Filename'Length > Suffix'Length
7877 (Last - Suffix'Length + 1 .. Last) =
7880 Last_Body := Last - Suffix'Length;
7885 if Config.Naming_Data.Spec_Suffix /= No_File then
7887 Suffix : constant String :=
7889 (Config.Naming_Data.Spec_Suffix);
7891 if Filename'Length > Suffix'Length
7894 (Last - Suffix'Length + 1 .. Last) =
7897 Last_Spec := Last - Suffix'Length;
7903 Last_Min : constant Natural :=
7904 Natural'Min (Natural'Min (Last_Spec,
7909 OK := Last_Min < Last;
7914 if Last_Min = Last_Spec then
7917 elsif Last_Min = Last_Body then
7929 -- Replace dot replacements with dots
7934 J : Positive := Filename'First;
7936 Dot_Replacement : constant String :=
7938 (Config.Naming_Data.
7941 Max : constant Positive :=
7942 Last - Dot_Replacement'Length + 1;
7946 Name_Len := Name_Len + 1;
7948 if J <= Max and then
7950 (J .. J + Dot_Replacement'Length - 1) =
7953 Name_Buffer (Name_Len) := '.';
7954 J := J + Dot_Replacement'Length;
7957 if Filename (J) = '.' then
7962 Name_Buffer (Name_Len) :=
7963 GNAT.Case_Util.To_Lower (Filename (J));
7974 -- The name buffer should contain the name of the
7975 -- the unit, if it is one.
7977 -- Check that this is a valid unit name
7979 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7981 if Unit /= No_Name then
7983 if Current_Verbosity = High then
7985 Write_Str (" spec of ");
7987 Write_Str (" body of ");
7990 Write_Str (Get_Name_String (Unit));
7991 Write_Str (" (language ");
7993 (Get_Name_String (Display_Language_Name));
7997 -- Comments required, declare block should
8001 Unit_Except : constant Unit_Exception :=
8002 Unit_Exceptions.Get (Unit);
8004 procedure Masked_Unit (Spec : Boolean);
8005 -- Indicate that there is an exception for
8006 -- the same unit, so the file is not a
8007 -- source for the unit.
8013 procedure Masked_Unit (Spec : Boolean) is
8015 if Current_Verbosity = High then
8017 Write_Str (Filename);
8018 Write_Str (""" contains the ");
8027 (" of a unit that is found in """);
8032 (Unit_Except.Spec));
8036 (Unit_Except.Impl));
8039 Write_Line (""" (ignored)");
8042 Language := No_Language_Index;
8047 if Unit_Except.Spec /= No_File
8048 and then Unit_Except.Spec /= File_Name
8050 Masked_Unit (Spec => True);
8054 if Unit_Except.Impl /= No_File
8055 and then Unit_Except.Impl /= File_Name
8057 Masked_Unit (Spec => False);
8068 Language := In_Tree.Languages_Data.Table (Language).Next;
8071 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8074 -- Comment needed here ???
8077 Language := First_Language;
8080 Language := No_Language_Index;
8082 if Current_Verbosity = High then
8083 Write_Line (" not a source of any language");
8086 end Check_Naming_Schemes;
8092 procedure Check_File
8093 (Project : Project_Id;
8094 In_Tree : Project_Tree_Ref;
8095 Data : in out Project_Data;
8097 File_Name : File_Name_Type;
8098 Display_File_Name : File_Name_Type;
8099 Source_Directory : String;
8100 For_All_Sources : Boolean)
8102 Display_Path : constant String :=
8105 Directory => Source_Directory,
8106 Resolve_Links => Opt.Follow_Links_For_Files,
8107 Case_Sensitive => True);
8109 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8110 Path_Id : Path_Name_Type;
8111 Display_Path_Id : Path_Name_Type;
8112 Check_Name : Boolean := False;
8113 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8114 Language : Language_Index;
8116 Other_Part : Source_Id;
8118 Src_Ind : Source_File_Index;
8120 Source_To_Replace : Source_Id := No_Source;
8121 Language_Name : Name_Id;
8122 Display_Language_Name : Name_Id;
8123 Lang_Kind : Language_Kind;
8124 Kind : Source_Kind := Spec;
8127 Name_Len := Display_Path'Length;
8128 Name_Buffer (1 .. Name_Len) := Display_Path;
8129 Display_Path_Id := Name_Find;
8131 if Osint.File_Names_Case_Sensitive then
8132 Path_Id := Display_Path_Id;
8134 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8135 Path_Id := Name_Find;
8138 if Name_Loc = No_Name_Location then
8139 Check_Name := For_All_Sources;
8142 if Name_Loc.Found then
8144 -- Check if it is OK to have the same file name in several
8145 -- source directories.
8147 if not Data.Known_Order_Of_Source_Dirs then
8148 Error_Msg_File_1 := File_Name;
8151 "{ is found in several source directories",
8156 Name_Loc.Found := True;
8158 Source_Names.Set (File_Name, Name_Loc);
8160 if Name_Loc.Source = No_Source then
8164 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8165 (Path_Id, Display_Path_Id);
8167 Source_Paths_Htable.Set
8168 (In_Tree.Source_Paths_HT,
8172 -- Check if this is a subunit
8174 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8176 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8178 Src_Ind := Sinput.P.Load_Project_File
8179 (Get_Name_String (Path_Id));
8181 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8182 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8190 Other_Part := No_Source;
8192 Check_Naming_Schemes
8193 (In_Tree => In_Tree,
8195 Filename => Get_Name_String (File_Name),
8196 File_Name => File_Name,
8197 Alternate_Languages => Alternate_Languages,
8198 Language => Language,
8199 Language_Name => Language_Name,
8200 Display_Language_Name => Display_Language_Name,
8202 Lang_Kind => Lang_Kind,
8205 if Language = No_Language_Index then
8207 -- A file name in a list must be a source of a language
8209 if Name_Loc.Found then
8210 Error_Msg_File_1 := File_Name;
8214 "language unknown for {",
8219 -- Check if the same file name or unit is used in the prj tree
8221 Source := In_Tree.First_Source;
8223 while Source /= No_Source loop
8225 Src_Data : Source_Data renames
8226 In_Tree.Sources.Table (Source);
8230 and then Src_Data.Unit = Unit
8232 ((Src_Data.Kind = Spec and then Kind = Impl)
8234 (Src_Data.Kind = Impl and then Kind = Spec))
8236 Other_Part := Source;
8238 elsif (Unit /= No_Name
8239 and then Src_Data.Unit = Unit
8241 (Src_Data.Kind = Kind
8243 (Src_Data.Kind = Sep and then Kind = Impl)
8245 (Src_Data.Kind = Impl and then Kind = Sep)))
8247 (Unit = No_Name and then Src_Data.File = File_Name)
8249 -- Duplication of file/unit in same project is only
8250 -- allowed if order of source directories is known.
8252 if Project = Src_Data.Project then
8253 if Data.Known_Order_Of_Source_Dirs then
8256 elsif Unit /= No_Name then
8257 Error_Msg_Name_1 := Unit;
8259 (Project, In_Tree, "duplicate unit %%",
8264 Error_Msg_File_1 := File_Name;
8266 (Project, In_Tree, "duplicate source file name {",
8271 -- Do not allow the same unit name in different
8272 -- projects, except if one is extending the other.
8274 -- For a file based language, the same file name
8275 -- replaces a file in a project being extended, but
8276 -- it is allowed to have the same file name in
8277 -- unrelated projects.
8280 (Project, Src_Data.Project, In_Tree)
8282 Source_To_Replace := Source;
8284 elsif Unit /= No_Name
8285 and then not Src_Data.Locally_Removed
8287 Error_Msg_Name_1 := Unit;
8290 "unit %% cannot belong to several projects",
8294 In_Tree.Projects.Table (Project).Name;
8295 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8297 (Project, In_Tree, "\ project %%, %%", No_Location);
8300 In_Tree.Projects.Table (Src_Data.Project).Name;
8302 Name_Id (Src_Data.Path.Display_Name);
8304 (Project, In_Tree, "\ project %%, %%", No_Location);
8310 Source := Src_Data.Next_In_Sources;
8320 Lang => Language_Name,
8321 Lang_Id => Language,
8322 Lang_Kind => Lang_Kind,
8324 Alternate_Languages => Alternate_Languages,
8325 File_Name => File_Name,
8326 Display_File => Display_File_Name,
8327 Other_Part => Other_Part,
8330 Display_Path => Display_Path_Id,
8331 Source_To_Replace => Source_To_Replace);
8337 ------------------------
8338 -- Search_Directories --
8339 ------------------------
8341 procedure Search_Directories
8342 (Project : Project_Id;
8343 In_Tree : Project_Tree_Ref;
8344 Data : in out Project_Data;
8345 For_All_Sources : Boolean)
8347 Source_Dir : String_List_Id;
8348 Element : String_Element;
8350 Name : String (1 .. 1_000);
8352 File_Name : File_Name_Type;
8353 Display_File_Name : File_Name_Type;
8356 if Current_Verbosity = High then
8357 Write_Line ("Looking for sources:");
8360 -- Loop through subdirectories
8362 Source_Dir := Data.Source_Dirs;
8363 while Source_Dir /= Nil_String loop
8365 Element := In_Tree.String_Elements.Table (Source_Dir);
8366 if Element.Value /= No_Name then
8367 Get_Name_String (Element.Display_Value);
8370 Source_Directory : constant String :=
8371 Name_Buffer (1 .. Name_Len) &
8372 Directory_Separator;
8374 Dir_Last : constant Natural :=
8375 Compute_Directory_Last
8379 if Current_Verbosity = High then
8380 Write_Str ("Source_Dir = ");
8381 Write_Line (Source_Directory);
8384 -- We look to every entry in the source directory
8386 Open (Dir, Source_Directory);
8389 Read (Dir, Name, Last);
8393 -- ??? Duplicate system call here, we just did a
8394 -- a similar one. Maybe Ada.Directories would be more
8398 (Source_Directory & Name (1 .. Last))
8400 if Current_Verbosity = High then
8401 Write_Str (" Checking ");
8402 Write_Line (Name (1 .. Last));
8406 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8407 Display_File_Name := Name_Find;
8409 if Osint.File_Names_Case_Sensitive then
8410 File_Name := Display_File_Name;
8412 Canonical_Case_File_Name
8413 (Name_Buffer (1 .. Name_Len));
8414 File_Name := Name_Find;
8419 Excluded_Sources_Htable.Get (File_Name);
8422 if FF /= No_File_Found then
8423 if not FF.Found then
8425 Excluded_Sources_Htable.Set
8428 if Current_Verbosity = High then
8429 Write_Str (" excluded source """);
8430 Write_Str (Get_Name_String (File_Name));
8437 (Project => Project,
8440 Name => Name (1 .. Last),
8441 File_Name => File_Name,
8442 Display_File_Name => Display_File_Name,
8443 Source_Directory => Source_Directory
8444 (Source_Directory'First .. Dir_Last),
8445 For_All_Sources => For_All_Sources);
8456 when Directory_Error =>
8460 Source_Dir := Element.Next;
8463 if Current_Verbosity = High then
8464 Write_Line ("end Looking for sources.");
8466 end Search_Directories;
8468 ----------------------
8469 -- Look_For_Sources --
8470 ----------------------
8472 procedure Look_For_Sources
8473 (Project : Project_Id;
8474 In_Tree : Project_Tree_Ref;
8475 Data : in out Project_Data;
8476 Current_Dir : String)
8478 procedure Remove_Locally_Removed_Files_From_Units;
8479 -- Mark all locally removed sources as such in the Units table
8481 procedure Process_Sources_In_Multi_Language_Mode;
8482 -- Find all source files when in multi language mode
8484 ---------------------------------------------
8485 -- Remove_Locally_Removed_Files_From_Units --
8486 ---------------------------------------------
8488 procedure Remove_Locally_Removed_Files_From_Units is
8489 Excluded : File_Found;
8492 Extended : Project_Id;
8495 Excluded := Excluded_Sources_Htable.Get_First;
8496 while Excluded /= No_File_Found loop
8500 for Index in Unit_Table.First ..
8501 Unit_Table.Last (In_Tree.Units)
8503 Unit := In_Tree.Units.Table (Index);
8505 for Kind in Spec_Or_Body'Range loop
8506 if Unit.File_Names (Kind).Name = Excluded.File then
8509 -- Check that this is from the current project or
8510 -- that the current project extends.
8512 Extended := Unit.File_Names (Kind).Project;
8514 if Extended = Project
8515 or else Project_Extends (Project, Extended, In_Tree)
8517 Unit.File_Names (Kind).Path.Name := Slash;
8518 Unit.File_Names (Kind).Needs_Pragma := False;
8519 In_Tree.Units.Table (Index) := Unit;
8520 Add_Forbidden_File_Name
8521 (Unit.File_Names (Kind).Name);
8525 "cannot remove a source from " &
8532 end loop For_Each_Unit;
8535 Err_Vars.Error_Msg_File_1 := Excluded.File;
8537 (Project, In_Tree, "unknown file {", Excluded.Location);
8540 Excluded := Excluded_Sources_Htable.Get_Next;
8542 end Remove_Locally_Removed_Files_From_Units;
8544 --------------------------------------------
8545 -- Process_Sources_In_Multi_Language_Mode --
8546 --------------------------------------------
8548 procedure Process_Sources_In_Multi_Language_Mode is
8550 Name_Loc : Name_Location;
8555 -- First, put all naming exceptions if any, in the Source_Names table
8557 Unit_Exceptions.Reset;
8559 Source := Data.First_Source;
8560 while Source /= No_Source loop
8562 Src_Data : Source_Data renames In_Tree.Sources.Table (Source);
8565 -- An excluded file cannot also be an exception file name
8567 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8570 Error_Msg_File_1 := Src_Data.File;
8573 "{ cannot be both excluded and an exception file name",
8577 Name_Loc := (Name => Src_Data.File,
8578 Location => No_Location,
8580 Except => Src_Data.Unit /= No_Name,
8583 if Current_Verbosity = High then
8584 Write_Str ("Putting source #");
8585 Write_Str (Source'Img);
8586 Write_Str (", file ");
8587 Write_Str (Get_Name_String (Src_Data.File));
8588 Write_Line (" in Source_Names");
8591 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8593 -- If this is an Ada exception, record in table Unit_Exceptions
8595 if Src_Data.Unit /= No_Name then
8597 Unit_Except : Unit_Exception :=
8598 Unit_Exceptions.Get (Src_Data.Unit);
8601 Unit_Except.Name := Src_Data.Unit;
8603 if Src_Data.Kind = Spec then
8604 Unit_Except.Spec := Src_Data.File;
8606 Unit_Except.Impl := Src_Data.File;
8609 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8613 Source := Src_Data.Next_In_Project;
8617 Find_Explicit_Sources
8618 (Current_Dir, Project, In_Tree, Data);
8620 -- Mark as such the sources that are declared as excluded
8622 FF := Excluded_Sources_Htable.Get_First;
8623 while FF /= No_File_Found loop
8625 Source := In_Tree.First_Source;
8626 while Source /= No_Source loop
8628 Src_Data : Source_Data renames
8629 In_Tree.Sources.Table (Source);
8632 if Src_Data.File = FF.File then
8634 -- Check that this is from this project or a project that
8635 -- the current project extends.
8637 if Src_Data.Project = Project or else
8638 Is_Extending (Project, Src_Data.Project, In_Tree)
8640 Src_Data.Locally_Removed := True;
8641 Src_Data.In_Interfaces := False;
8642 Add_Forbidden_File_Name (FF.File);
8648 Source := Src_Data.Next_In_Sources;
8652 if not FF.Found and not OK then
8653 Err_Vars.Error_Msg_File_1 := FF.File;
8654 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8657 FF := Excluded_Sources_Htable.Get_Next;
8660 -- Check that two sources of this project do not have the same object
8663 Check_Object_File_Names : declare
8665 Source_Name : File_Name_Type;
8667 procedure Check_Object (Src_Data : Source_Data);
8668 -- Check if object file name of the current source is already in
8669 -- hash table Object_File_Names. If it is, report an error. If it
8670 -- is not, put it there with the file name of the current source.
8676 procedure Check_Object (Src_Data : Source_Data) is
8678 Source_Name := Object_File_Names.Get (Src_Data.Object);
8680 if Source_Name /= No_File then
8681 Error_Msg_File_1 := Src_Data.File;
8682 Error_Msg_File_2 := Source_Name;
8686 "{ and { have the same object file name",
8690 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8694 -- Start of processing for Check_Object_File_Names
8697 Object_File_Names.Reset;
8698 Src_Id := In_Tree.First_Source;
8699 while Src_Id /= No_Source loop
8701 Src_Data : Source_Data renames
8702 In_Tree.Sources.Table (Src_Id);
8705 if Src_Data.Compiled and then Src_Data.Object_Exists
8706 and then Project_Extends
8707 (Project, Src_Data.Project, In_Tree)
8709 if Src_Data.Unit = No_Name then
8710 if Src_Data.Kind = Impl then
8711 Check_Object (Src_Data);
8715 case Src_Data.Kind is
8717 if Src_Data.Other_Part = No_Source then
8718 Check_Object (Src_Data);
8725 if Src_Data.Other_Part /= No_Source then
8726 Check_Object (Src_Data);
8729 -- Check if it is a subunit
8732 Src_Ind : constant Source_File_Index :=
8733 Sinput.P.Load_Project_File
8735 (Src_Data.Path.Name));
8737 if Sinput.P.Source_File_Is_Subunit
8740 In_Tree.Sources.Table (Src_Id).Kind :=
8743 Check_Object (Src_Data);
8751 Src_Id := Src_Data.Next_In_Sources;
8754 end Check_Object_File_Names;
8755 end Process_Sources_In_Multi_Language_Mode;
8757 -- Start of processing for Look_For_Sources
8761 Find_Excluded_Sources (Project, In_Tree, Data);
8765 if Is_A_Language (In_Tree, Data, Name_Ada) then
8766 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8767 Remove_Locally_Removed_Files_From_Units;
8770 when Multi_Language =>
8771 if Data.First_Language_Processing /= No_Language_Index then
8772 Process_Sources_In_Multi_Language_Mode;
8775 end Look_For_Sources;
8781 function Path_Name_Of
8782 (File_Name : File_Name_Type;
8783 Directory : Path_Name_Type) return String
8785 Result : String_Access;
8786 The_Directory : constant String := Get_Name_String (Directory);
8789 Get_Name_String (File_Name);
8792 (File_Name => Name_Buffer (1 .. Name_Len),
8793 Path => The_Directory);
8795 if Result = null then
8798 Canonical_Case_File_Name (Result.all);
8803 -------------------------------
8804 -- Prepare_Ada_Naming_Exceptions --
8805 -------------------------------
8807 procedure Prepare_Ada_Naming_Exceptions
8808 (List : Array_Element_Id;
8809 In_Tree : Project_Tree_Ref;
8810 Kind : Spec_Or_Body)
8812 Current : Array_Element_Id;
8813 Element : Array_Element;
8817 -- Traverse the list
8820 while Current /= No_Array_Element loop
8821 Element := In_Tree.Array_Elements.Table (Current);
8823 if Element.Index /= No_Name then
8826 Unit => Element.Index,
8827 Next => No_Ada_Naming_Exception);
8828 Reverse_Ada_Naming_Exceptions.Set
8829 (Unit, (Element.Value.Value, Element.Value.Index));
8831 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8832 Ada_Naming_Exception_Table.Increment_Last;
8833 Ada_Naming_Exception_Table.Table
8834 (Ada_Naming_Exception_Table.Last) := Unit;
8835 Ada_Naming_Exceptions.Set
8836 (File_Name_Type (Element.Value.Value),
8837 Ada_Naming_Exception_Table.Last);
8840 Current := Element.Next;
8842 end Prepare_Ada_Naming_Exceptions;
8844 ---------------------
8845 -- Project_Extends --
8846 ---------------------
8848 function Project_Extends
8849 (Extending : Project_Id;
8850 Extended : Project_Id;
8851 In_Tree : Project_Tree_Ref) return Boolean
8853 Current : Project_Id := Extending;
8857 if Current = No_Project then
8860 elsif Current = Extended then
8864 Current := In_Tree.Projects.Table (Current).Extends;
8866 end Project_Extends;
8868 -----------------------
8869 -- Record_Ada_Source --
8870 -----------------------
8872 procedure Record_Ada_Source
8873 (File_Name : File_Name_Type;
8874 Path_Name : Path_Name_Type;
8875 Project : Project_Id;
8876 In_Tree : Project_Tree_Ref;
8877 Data : in out Project_Data;
8878 Location : Source_Ptr;
8879 Current_Source : in out String_List_Id;
8880 Source_Recorded : in out Boolean;
8881 Current_Dir : String)
8883 Canonical_File_Name : File_Name_Type;
8884 Canonical_Path_Name : Path_Name_Type;
8886 Exception_Id : Ada_Naming_Exception_Id;
8887 Unit_Name : Name_Id;
8888 Unit_Kind : Spec_Or_Body;
8889 Unit_Ind : Int := 0;
8891 Name_Index : Name_And_Index;
8892 Needs_Pragma : Boolean;
8894 The_Location : Source_Ptr := Location;
8895 Previous_Source : constant String_List_Id := Current_Source;
8896 Except_Name : Name_And_Index := No_Name_And_Index;
8898 Unit_Prj : Unit_Project;
8900 File_Name_Recorded : Boolean := False;
8903 if Osint.File_Names_Case_Sensitive then
8904 Canonical_File_Name := File_Name;
8905 Canonical_Path_Name := Path_Name;
8907 Get_Name_String (File_Name);
8908 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8909 Canonical_File_Name := Name_Find;
8912 Canonical_Path : constant String :=
8914 (Get_Name_String (Path_Name),
8915 Directory => Current_Dir,
8916 Resolve_Links => Opt.Follow_Links_For_Files,
8917 Case_Sensitive => False);
8920 Add_Str_To_Name_Buffer (Canonical_Path);
8921 Canonical_Path_Name := Name_Find;
8925 -- Find out the unit name, the unit kind and if it needs
8926 -- a specific SFN pragma.
8929 (In_Tree => In_Tree,
8930 Canonical_File_Name => Canonical_File_Name,
8931 Naming => Data.Naming,
8932 Exception_Id => Exception_Id,
8933 Unit_Name => Unit_Name,
8934 Unit_Kind => Unit_Kind,
8935 Needs_Pragma => Needs_Pragma);
8937 if Exception_Id = No_Ada_Naming_Exception
8938 and then Unit_Name = No_Name
8940 if Current_Verbosity = High then
8942 Write_Str (Get_Name_String (Canonical_File_Name));
8943 Write_Line (""" is not a valid source file name (ignored).");
8947 -- Check to see if the source has been hidden by an exception,
8948 -- but only if it is not an exception.
8950 if not Needs_Pragma then
8952 Reverse_Ada_Naming_Exceptions.Get
8953 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8955 if Except_Name /= No_Name_And_Index then
8956 if Current_Verbosity = High then
8958 Write_Str (Get_Name_String (Canonical_File_Name));
8959 Write_Str (""" contains a unit that is found in """);
8960 Write_Str (Get_Name_String (Except_Name.Name));
8961 Write_Line (""" (ignored).");
8964 -- The file is not included in the source of the project since
8965 -- it is hidden by the exception. So, nothing else to do.
8972 if Exception_Id /= No_Ada_Naming_Exception then
8973 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8974 Exception_Id := Info.Next;
8975 Info.Next := No_Ada_Naming_Exception;
8976 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8978 Unit_Name := Info.Unit;
8979 Unit_Ind := Name_Index.Index;
8980 Unit_Kind := Info.Kind;
8983 -- Put the file name in the list of sources of the project
8985 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8986 In_Tree.String_Elements.Table
8987 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8988 (Value => Name_Id (Canonical_File_Name),
8989 Display_Value => Name_Id (File_Name),
8990 Location => No_Location,
8995 if Current_Source = Nil_String then
8997 String_Element_Table.Last (In_Tree.String_Elements);
8999 In_Tree.String_Elements.Table (Current_Source).Next :=
9000 String_Element_Table.Last (In_Tree.String_Elements);
9004 String_Element_Table.Last (In_Tree.String_Elements);
9006 -- Put the unit in unit list
9009 The_Unit : Unit_Index :=
9010 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
9012 The_Unit_Data : Unit_Data;
9015 if Current_Verbosity = High then
9016 Write_Str ("Putting ");
9017 Write_Str (Get_Name_String (Unit_Name));
9018 Write_Line (" in the unit list.");
9021 -- The unit is already in the list, but may be it is
9022 -- only the other unit kind (spec or body), or what is
9023 -- in the unit list is a unit of a project we are extending.
9025 if The_Unit /= No_Unit_Index then
9026 The_Unit_Data := In_Tree.Units.Table (The_Unit);
9028 if (The_Unit_Data.File_Names (Unit_Kind).Name =
9031 The_Unit_Data.File_Names
9032 (Unit_Kind).Path.Name = Slash)
9033 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
9034 or else Project_Extends
9036 The_Unit_Data.File_Names (Unit_Kind).Project,
9040 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
9042 Remove_Forbidden_File_Name
9043 (The_Unit_Data.File_Names (Unit_Kind).Name);
9046 -- Record the file name in the hash table Files_Htable
9048 Unit_Prj := (Unit => The_Unit, Project => Project);
9051 Canonical_File_Name,
9054 The_Unit_Data.File_Names (Unit_Kind) :=
9055 (Name => Canonical_File_Name,
9057 Display_Name => File_Name,
9058 Path => (Canonical_Path_Name, Path_Name),
9060 Needs_Pragma => Needs_Pragma);
9061 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9062 Source_Recorded := True;
9064 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
9065 and then (Data.Known_Order_Of_Source_Dirs
9067 The_Unit_Data.File_Names
9068 (Unit_Kind).Path.Name = Canonical_Path_Name)
9070 if Previous_Source = Nil_String then
9071 Data.Ada_Sources := Nil_String;
9073 In_Tree.String_Elements.Table (Previous_Source).Next :=
9075 String_Element_Table.Decrement_Last
9076 (In_Tree.String_Elements);
9079 Current_Source := Previous_Source;
9082 -- It is an error to have two units with the same name
9083 -- and the same kind (spec or body).
9085 if The_Location = No_Location then
9087 In_Tree.Projects.Table (Project).Location;
9090 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9092 (Project, In_Tree, "duplicate unit %%", The_Location);
9094 Err_Vars.Error_Msg_Name_1 :=
9095 In_Tree.Projects.Table
9096 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9097 Err_Vars.Error_Msg_File_1 :=
9099 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
9102 "\ project file %%, {", The_Location);
9104 Err_Vars.Error_Msg_Name_1 :=
9105 In_Tree.Projects.Table (Project).Name;
9106 Err_Vars.Error_Msg_File_1 :=
9107 File_Name_Type (Canonical_Path_Name);
9110 "\ project file %%, {", The_Location);
9113 -- It is a new unit, create a new record
9116 -- First, check if there is no other unit with this file
9117 -- name in another project. If it is, report error but note
9118 -- we do that only for the first unit in the source file.
9121 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
9123 if not File_Name_Recorded and then
9124 Unit_Prj /= No_Unit_Project
9126 Error_Msg_File_1 := File_Name;
9128 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9131 "{ is already a source of project %%",
9135 Unit_Table.Increment_Last (In_Tree.Units);
9136 The_Unit := Unit_Table.Last (In_Tree.Units);
9138 (In_Tree.Units_HT, Unit_Name, The_Unit);
9139 Unit_Prj := (Unit => The_Unit, Project => Project);
9142 Canonical_File_Name,
9144 The_Unit_Data.Name := Unit_Name;
9145 The_Unit_Data.File_Names (Unit_Kind) :=
9146 (Name => Canonical_File_Name,
9148 Display_Name => File_Name,
9149 Path => (Canonical_Path_Name, Path_Name),
9151 Needs_Pragma => Needs_Pragma);
9152 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9153 Source_Recorded := True;
9158 exit when Exception_Id = No_Ada_Naming_Exception;
9159 File_Name_Recorded := True;
9162 end Record_Ada_Source;
9168 procedure Remove_Source
9170 Replaced_By : Source_Id;
9171 Project : Project_Id;
9172 Data : in out Project_Data;
9173 In_Tree : Project_Tree_Ref)
9175 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9179 if Current_Verbosity = High then
9180 Write_Str ("Removing source #");
9181 Write_Line (Id'Img);
9184 if Replaced_By /= No_Source then
9185 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9186 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9187 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9190 -- Remove the source from the global source list
9192 Source := In_Tree.First_Source;
9195 In_Tree.First_Source := Src_Data.Next_In_Sources;
9198 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9199 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9202 In_Tree.Sources.Table (Source).Next_In_Sources :=
9203 Src_Data.Next_In_Sources;
9206 -- Remove the source from the project list
9208 if Src_Data.Project = Project then
9209 Source := Data.First_Source;
9212 Data.First_Source := Src_Data.Next_In_Project;
9214 if Src_Data.Next_In_Project = No_Source then
9215 Data.Last_Source := No_Source;
9219 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9220 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9223 In_Tree.Sources.Table (Source).Next_In_Project :=
9224 Src_Data.Next_In_Project;
9226 if Src_Data.Next_In_Project = No_Source then
9227 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9232 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9235 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9236 Src_Data.Next_In_Project;
9238 if Src_Data.Next_In_Project = No_Source then
9239 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9244 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9245 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9248 In_Tree.Sources.Table (Source).Next_In_Project :=
9249 Src_Data.Next_In_Project;
9251 if Src_Data.Next_In_Project = No_Source then
9252 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9257 -- Remove source from the language list
9259 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9262 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9263 Src_Data.Next_In_Lang;
9266 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9267 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9270 In_Tree.Sources.Table (Source).Next_In_Lang :=
9271 Src_Data.Next_In_Lang;
9275 -----------------------
9276 -- Report_No_Sources --
9277 -----------------------
9279 procedure Report_No_Sources
9280 (Project : Project_Id;
9282 In_Tree : Project_Tree_Ref;
9283 Location : Source_Ptr;
9284 Continuation : Boolean := False)
9287 case When_No_Sources is
9291 when Warning | Error =>
9293 Msg : constant String :=
9296 " sources in this project";
9299 Error_Msg_Warn := When_No_Sources = Warning;
9301 if Continuation then
9303 (Project, In_Tree, "\" & Msg, Location);
9307 (Project, In_Tree, Msg, Location);
9311 end Report_No_Sources;
9313 ----------------------
9314 -- Show_Source_Dirs --
9315 ----------------------
9317 procedure Show_Source_Dirs
9318 (Data : Project_Data;
9319 In_Tree : Project_Tree_Ref)
9321 Current : String_List_Id;
9322 Element : String_Element;
9325 Write_Line ("Source_Dirs:");
9327 Current := Data.Source_Dirs;
9328 while Current /= Nil_String loop
9329 Element := In_Tree.String_Elements.Table (Current);
9331 Write_Line (Get_Name_String (Element.Value));
9332 Current := Element.Next;
9335 Write_Line ("end Source_Dirs.");
9336 end Show_Source_Dirs;
9338 -------------------------
9339 -- Warn_If_Not_Sources --
9340 -------------------------
9342 -- comments needed in this body ???
9344 procedure Warn_If_Not_Sources
9345 (Project : Project_Id;
9346 In_Tree : Project_Tree_Ref;
9347 Conventions : Array_Element_Id;
9349 Extending : Boolean)
9351 Conv : Array_Element_Id;
9353 The_Unit_Id : Unit_Index;
9354 The_Unit_Data : Unit_Data;
9355 Location : Source_Ptr;
9358 Conv := Conventions;
9359 while Conv /= No_Array_Element loop
9360 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9361 Error_Msg_Name_1 := Unit;
9362 Get_Name_String (Unit);
9363 To_Lower (Name_Buffer (1 .. Name_Len));
9365 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9366 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9368 if The_Unit_Id = No_Unit_Index then
9369 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9372 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9374 In_Tree.Array_Elements.Table (Conv).Value.Value;
9377 if not Check_Project
9378 (The_Unit_Data.File_Names (Specification).Project,
9379 Project, In_Tree, Extending)
9383 "?source of spec of unit %% (%%)" &
9384 " cannot be found in this project",
9389 if not Check_Project
9390 (The_Unit_Data.File_Names (Body_Part).Project,
9391 Project, In_Tree, Extending)
9395 "?source of body of unit %% (%%)" &
9396 " cannot be found in this project",
9402 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9404 end Warn_If_Not_Sources;