1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
30 with Err_Vars; use Err_Vars;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
39 with Prj.Util; use Prj.Util;
41 with Snames; use Snames;
42 with Table; use Table;
43 with Targparm; use Targparm;
45 with Ada.Characters.Handling; use Ada.Characters.Handling;
46 with Ada.Directories; use Ada.Directories;
47 with Ada.Strings; use Ada.Strings;
48 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
49 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
51 package body Prj.Nmsc is
53 No_Continuation_String : aliased String := "";
54 Continuation_String : aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
68 type Name_Location is record
69 Name : File_Name_Type;
70 Location : Source_Ptr;
71 Source : Source_Id := No_Source;
72 Except : Boolean := False;
73 Found : Boolean := False;
75 -- Information about file names found in string list attribute
76 -- Source_Files or in a source list file, stored in hash table
77 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
79 No_Name_Location : constant Name_Location :=
81 Location => No_Location,
86 package Source_Names is new GNAT.HTable.Simple_HTable
87 (Header_Num => Header_Num,
88 Element => Name_Location,
89 No_Element => No_Name_Location,
90 Key => File_Name_Type,
93 -- Hash table to store file names found in string list attribute
94 -- Source_Files or in a source list file, stored in hash table
95 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97 -- More documentation needed on what unit exceptions are about ???
99 type Unit_Exception is record
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
105 No_Unit_Exception : constant Unit_Exception :=
110 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
111 (Header_Num => Header_Num,
112 Element => Unit_Exception,
113 No_Element => No_Unit_Exception,
117 -- Hash table to store the unit exceptions
119 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
120 (Header_Num => Header_Num,
126 -- Hash table to store recursive source directories, to avoid looking
127 -- several times, and to avoid cycles that may be introduced by symbolic
130 type Ada_Naming_Exception_Id is new Nat;
131 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
133 type Unit_Info is record
136 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
140 -- Why is the following commented out ???
141 -- No_Unit : constant Unit_Info :=
142 -- (Specification, No_Name, No_Ada_Naming_Exception);
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
149 Table_Increment => 100,
150 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
152 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
153 (Header_Num => Header_Num,
154 Element => Ada_Naming_Exception_Id,
155 No_Element => No_Ada_Naming_Exception,
156 Key => File_Name_Type,
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 package Object_File_Names is new GNAT.HTable.Simple_HTable
163 (Header_Num => Header_Num,
164 Element => File_Name_Type,
165 No_Element => No_File,
166 Key => File_Name_Type,
169 -- A hash table to store the object file names for a project, to check that
170 -- two different sources have different object file names.
172 type File_Found is record
173 File : File_Name_Type := No_File;
174 Found : Boolean := False;
175 Location : Source_Ptr := No_Location;
177 No_File_Found : constant File_Found := (No_File, False, No_Location);
178 -- Comments needed ???
180 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
181 (Header_Num => Header_Num,
182 Element => File_Found,
183 No_Element => No_File_Found,
184 Key => File_Name_Type,
187 -- A hash table to store the excluded files, if any. This is filled by
188 -- Find_Excluded_Sources below.
190 procedure Find_Excluded_Sources
191 (Project : Project_Id;
192 In_Tree : Project_Tree_Ref;
193 Data : Project_Data);
194 -- Find the list of files that should not be considered as source files
195 -- for this project. Sets the list in the Excluded_Sources_Htable.
197 function Hash (Unit : Unit_Info) return Header_Num;
199 type Name_And_Index is record
200 Name : Name_Id := No_Name;
203 No_Name_And_Index : constant Name_And_Index :=
204 (Name => No_Name, Index => 0);
206 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
207 (Header_Num => Header_Num,
208 Element => Name_And_Index,
209 No_Element => No_Name_And_Index,
213 -- A table to check if a unit with an exceptional name will hide a source
214 -- with a file name following the naming convention.
218 Data : in out Project_Data;
219 In_Tree : Project_Tree_Ref;
220 Project : Project_Id;
222 Lang_Id : Language_Index;
224 File_Name : File_Name_Type;
225 Display_File : File_Name_Type;
226 Lang_Kind : Language_Kind;
227 Naming_Exception : Boolean := False;
228 Path : Path_Name_Type := No_Path;
229 Display_Path : Path_Name_Type := No_Path;
230 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
231 Other_Part : Source_Id := No_Source;
232 Unit : Name_Id := No_Name;
234 Source_To_Replace : Source_Id := No_Source);
235 -- Add a new source to the different lists: list of all sources in the
236 -- project tree, list of source of a project and list of sources of a
239 -- If Path is specified, the file is also added to Source_Paths_HT.
240 -- If Source_To_Replace is specified, it points to the source in the
241 -- extended project that the new file is overriding.
243 function ALI_File_Name (Source : String) return String;
244 -- Return the ALI file name corresponding to a source
246 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
247 -- Check that a name is a valid Ada unit name
249 procedure Check_Naming_Schemes
250 (Data : in out Project_Data;
251 Project : Project_Id;
252 In_Tree : Project_Tree_Ref);
253 -- Check the naming scheme part of Data
255 procedure Check_Ada_Naming_Scheme_Validity
256 (Project : Project_Id;
257 In_Tree : Project_Tree_Ref;
258 Naming : Naming_Data);
259 -- Check that the package Naming is correct
261 procedure Check_Configuration
262 (Project : Project_Id;
263 In_Tree : Project_Tree_Ref;
264 Data : in out Project_Data);
265 -- Check the configuration attributes for the project
267 procedure Check_If_Externally_Built
268 (Project : Project_Id;
269 In_Tree : Project_Tree_Ref;
270 Data : in out Project_Data);
271 -- Check attribute Externally_Built of project Project in project tree
272 -- In_Tree and modify its data Data if it has the value "true".
274 procedure Check_Interfaces
275 (Project : Project_Id;
276 In_Tree : Project_Tree_Ref;
277 Data : in out Project_Data);
278 -- If a list of sources is specified in attribute Interfaces, set
279 -- In_Interfaces only for the sources specified in the list.
281 procedure Check_Library_Attributes
282 (Project : Project_Id;
283 In_Tree : Project_Tree_Ref;
284 Current_Dir : String;
285 Data : in out Project_Data);
286 -- Check the library attributes of project Project in project tree In_Tree
287 -- and modify its data Data accordingly.
288 -- Current_Dir should represent the current directory, and is passed for
289 -- efficiency to avoid system calls to recompute it.
291 procedure Check_Package_Naming
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Data : in out Project_Data);
295 -- Check package Naming of project Project in project tree In_Tree and
296 -- modify its data Data accordingly.
298 procedure Check_Programming_Languages
299 (In_Tree : Project_Tree_Ref;
300 Project : Project_Id;
301 Data : in out Project_Data);
302 -- Check attribute Languages for the project with data Data in project
303 -- tree In_Tree and set the components of Data for all the programming
304 -- languages indicated in attribute Languages, if any.
306 function Check_Project
308 Root_Project : Project_Id;
309 In_Tree : Project_Tree_Ref;
310 Extending : Boolean) return Boolean;
311 -- Returns True if P is Root_Project or, if Extending is True, a project
312 -- extended by Root_Project.
314 procedure Check_Stand_Alone_Library
315 (Project : Project_Id;
316 In_Tree : Project_Tree_Ref;
317 Data : in out Project_Data;
318 Current_Dir : String;
319 Extending : Boolean);
320 -- Check if project Project in project tree In_Tree is a Stand-Alone
321 -- Library project, and modify its data Data accordingly if it is one.
322 -- Current_Dir should represent the current directory, and is passed for
323 -- efficiency to avoid system calls to recompute it.
325 procedure Get_Path_Names_And_Record_Ada_Sources
326 (Project : Project_Id;
327 In_Tree : Project_Tree_Ref;
328 Data : in out Project_Data;
329 Current_Dir : String);
330 -- Find the path names of the source files in the Source_Names table
331 -- in the source directories and record those that are Ada sources.
333 function Compute_Directory_Last (Dir : String) return Natural;
334 -- Return the index of the last significant character in Dir. This is used
335 -- to avoid duplicate '/' (slash) characters at the end of directory names.
338 (Project : Project_Id;
339 In_Tree : Project_Tree_Ref;
341 Flag_Location : Source_Ptr);
342 -- Output an error message. If Error_Report is null, simply call
343 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
346 procedure Find_Ada_Sources
347 (Project : Project_Id;
348 In_Tree : Project_Tree_Ref;
349 Data : in out Project_Data;
350 Current_Dir : String);
351 -- Find all the Ada sources in all of the source directories of a project
352 -- Current_Dir should represent the current directory, and is passed for
353 -- efficiency to avoid system calls to recompute it.
355 procedure Search_Directories
356 (Project : Project_Id;
357 In_Tree : Project_Tree_Ref;
358 Data : in out Project_Data;
359 For_All_Sources : Boolean);
360 -- Search the source directories to find the sources.
361 -- If For_All_Sources is True, check each regular file name against the
362 -- naming schemes of the different languages. Otherwise consider only the
363 -- file names in the hash table Source_Names.
366 (Project : Project_Id;
367 In_Tree : Project_Tree_Ref;
368 Data : in out Project_Data;
370 File_Name : File_Name_Type;
371 Display_File_Name : File_Name_Type;
372 Source_Directory : String;
373 For_All_Sources : Boolean);
374 -- Check if file File_Name is a valid source of the project. This is used
375 -- in multi-language mode only.
376 -- When the file matches one of the naming schemes, it is added to
377 -- various htables through Add_Source and to Source_Paths_Htable.
379 -- Name is the name of the candidate file. It hasn't been normalized yet
380 -- and is the direct result of readdir().
382 -- File_Name is the same as Name, but has been normalized.
383 -- Display_File_Name, however, has not been normalized.
385 -- Source_Directory is the directory in which the file
386 -- was found. It hasn't been normalized (nor has had links resolved).
387 -- It should not end with a directory separator, to avoid duplicates
390 -- If For_All_Sources is True, then all possible file names are analyzed
391 -- otherwise only those currently set in the Source_Names htable.
393 procedure Check_Naming_Schemes
394 (In_Tree : Project_Tree_Ref;
395 Data : in out Project_Data;
397 File_Name : File_Name_Type;
398 Alternate_Languages : out Alternate_Language_Id;
399 Language : out Language_Index;
400 Language_Name : out Name_Id;
401 Display_Language_Name : out Name_Id;
403 Lang_Kind : out Language_Kind;
404 Kind : out Source_Kind);
405 -- Check if the file name File_Name conforms to one of the naming
406 -- schemes of the project.
408 -- If the file does not match one of the naming schemes, set Language
409 -- to No_Language_Index.
411 -- Filename is the name of the file being investigated. It has been
412 -- normalized (case-folded). File_Name is the same value.
414 procedure Free_Ada_Naming_Exceptions;
415 -- Free the internal hash tables used for checking naming exceptions
417 procedure Get_Directories
418 (Project : Project_Id;
419 In_Tree : Project_Tree_Ref;
420 Current_Dir : String;
421 Data : in out Project_Data);
422 -- Get the object directory, the exec directory and the source directories
425 -- Current_Dir should represent the current directory, and is passed for
426 -- efficiency to avoid system calls to recompute it.
429 (Project : Project_Id;
430 In_Tree : Project_Tree_Ref;
431 Data : in out Project_Data);
432 -- Get the mains of a project from attribute Main, if it exists, and put
433 -- them in the project data.
435 procedure Get_Sources_From_File
437 Location : Source_Ptr;
438 Project : Project_Id;
439 In_Tree : Project_Tree_Ref);
440 -- Get the list of sources from a text file and put them in hash table
443 procedure Find_Explicit_Sources
444 (Current_Dir : String;
445 Project : Project_Id;
446 In_Tree : Project_Tree_Ref;
447 Data : in out Project_Data);
448 -- Process the Source_Files and Source_List_File attributes, and store
449 -- the list of source files into the Source_Names htable.
451 -- Lang indicates which language is being processed when in Ada_Only mode
452 -- (all languages are processed anyway when in Multi_Language mode).
455 (In_Tree : Project_Tree_Ref;
456 Canonical_File_Name : File_Name_Type;
457 Naming : Naming_Data;
458 Exception_Id : out Ada_Naming_Exception_Id;
459 Unit_Name : out Name_Id;
460 Unit_Kind : out Spec_Or_Body;
461 Needs_Pragma : out Boolean);
462 -- Find out, from a file name, the unit name, the unit kind and if a
463 -- specific SFN pragma is needed. If the file name corresponds to no unit,
464 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
465 -- exception to the naming scheme, then Exception_Id is set to the unit or
466 -- units that the source contains.
468 function Is_Illegal_Suffix
470 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
471 -- Returns True if the string Suffix cannot be used as a spec suffix, a
472 -- body suffix or a separate suffix.
474 procedure Locate_Directory
475 (Project : Project_Id;
476 In_Tree : Project_Tree_Ref;
477 Name : File_Name_Type;
478 Parent : Path_Name_Type;
479 Dir : out Path_Name_Type;
480 Display : out Path_Name_Type;
481 Create : String := "";
482 Current_Dir : String;
483 Location : Source_Ptr := No_Location);
484 -- Locate a directory. Name is the directory name. Parent is the root
485 -- directory, if Name a relative path name. Dir is set to the canonical
486 -- case path name of the directory, and Display is the directory path name
487 -- for display purposes. If the directory does not exist and Project_Setup
488 -- is True and Create is a non null string, an attempt is made to create
489 -- the directory. If the directory does not exist and Project_Setup is
490 -- false, then Dir and Display are set to No_Name.
492 -- Current_Dir should represent the current directory, and is passed for
493 -- efficiency to avoid system calls to recompute it.
495 procedure Look_For_Sources
496 (Project : Project_Id;
497 In_Tree : Project_Tree_Ref;
498 Data : in out Project_Data;
499 Current_Dir : String);
500 -- Find all the sources of project Project in project tree In_Tree and
501 -- update its Data accordingly.
503 -- Current_Dir should represent the current directory, and is passed for
504 -- efficiency to avoid system calls to recompute it.
506 function Path_Name_Of
507 (File_Name : File_Name_Type;
508 Directory : Path_Name_Type) return String;
509 -- Returns the path name of a (non project) file. Returns an empty string
510 -- if file cannot be found.
512 procedure Prepare_Ada_Naming_Exceptions
513 (List : Array_Element_Id;
514 In_Tree : Project_Tree_Ref;
515 Kind : Spec_Or_Body);
516 -- Prepare the internal hash tables used for checking naming exceptions
517 -- for Ada. Insert all elements of List in the tables.
519 function Project_Extends
520 (Extending : Project_Id;
521 Extended : Project_Id;
522 In_Tree : Project_Tree_Ref) return Boolean;
523 -- Returns True if Extending is extending Extended either directly or
526 procedure Record_Ada_Source
527 (File_Name : File_Name_Type;
528 Path_Name : Path_Name_Type;
529 Project : Project_Id;
530 In_Tree : Project_Tree_Ref;
531 Data : in out Project_Data;
532 Location : Source_Ptr;
533 Current_Source : in out String_List_Id;
534 Source_Recorded : in out Boolean;
535 Current_Dir : String);
536 -- Put a unit in the list of units of a project, if the file name
537 -- corresponds to a valid unit name.
539 -- Current_Dir should represent the current directory, and is passed for
540 -- efficiency to avoid system calls to recompute it.
542 procedure Remove_Source
544 Replaced_By : Source_Id;
545 Project : Project_Id;
546 Data : in out Project_Data;
547 In_Tree : Project_Tree_Ref);
550 procedure Report_No_Sources
551 (Project : Project_Id;
553 In_Tree : Project_Tree_Ref;
554 Location : Source_Ptr;
555 Continuation : Boolean := False);
556 -- Report an error or a warning depending on the value of When_No_Sources
557 -- when there are no sources for language Lang_Name.
559 procedure Show_Source_Dirs
560 (Data : Project_Data; In_Tree : Project_Tree_Ref);
561 -- List all the source directories of a project
563 procedure Warn_If_Not_Sources
564 (Project : Project_Id;
565 In_Tree : Project_Tree_Ref;
566 Conventions : Array_Element_Id;
568 Extending : Boolean);
569 -- Check that individual naming conventions apply to immediate sources of
570 -- the project. If not, issue a warning.
578 Data : in out Project_Data;
579 In_Tree : Project_Tree_Ref;
580 Project : Project_Id;
582 Lang_Id : Language_Index;
584 File_Name : File_Name_Type;
585 Display_File : File_Name_Type;
586 Lang_Kind : Language_Kind;
587 Naming_Exception : Boolean := False;
588 Path : Path_Name_Type := No_Path;
589 Display_Path : Path_Name_Type := No_Path;
590 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
591 Other_Part : Source_Id := No_Source;
592 Unit : Name_Id := No_Name;
594 Source_To_Replace : Source_Id := No_Source)
596 Source : constant Source_Id := Data.Last_Source;
597 Src_Data : Source_Data := No_Source_Data;
598 Config : constant Language_Config :=
599 In_Tree.Languages_Data.Table (Lang_Id).Config;
602 -- This is a new source so create an entry for it in the Sources table
604 Source_Data_Table.Increment_Last (In_Tree.Sources);
605 Id := Source_Data_Table.Last (In_Tree.Sources);
607 if Current_Verbosity = High then
608 Write_Str ("Adding source #");
610 Write_Str (", File : ");
611 Write_Str (Get_Name_String (File_Name));
613 if Lang_Kind = Unit_Based then
614 Write_Str (", Unit : ");
615 Write_Str (Get_Name_String (Unit));
621 Src_Data.Project := Project;
622 Src_Data.Language_Name := Lang;
623 Src_Data.Language := Lang_Id;
624 Src_Data.Lang_Kind := Lang_Kind;
625 Src_Data.Compiled := In_Tree.Languages_Data.Table
626 (Lang_Id).Config.Compiler_Driver /=
628 Src_Data.Kind := Kind;
629 Src_Data.Alternate_Languages := Alternate_Languages;
630 Src_Data.Other_Part := Other_Part;
632 Src_Data.Object_Exists := Config.Object_Generated;
633 Src_Data.Object_Linked := Config.Objects_Linked;
635 if Other_Part /= No_Source then
636 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
639 Src_Data.Unit := Unit;
640 Src_Data.Index := Index;
641 Src_Data.File := File_Name;
642 Src_Data.Display_File := Display_File;
643 Src_Data.Dependency := In_Tree.Languages_Data.Table
644 (Lang_Id).Config.Dependency_Kind;
645 Src_Data.Naming_Exception := Naming_Exception;
647 if Src_Data.Compiled and then Src_Data.Object_Exists then
648 Src_Data.Object := Object_Name (File_Name);
650 Dependency_Name (File_Name, Src_Data.Dependency);
651 Src_Data.Switches := Switches_Name (File_Name);
654 if Path /= No_Path then
655 Src_Data.Path := (Path, Display_Path);
656 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
659 -- Add the source to the global list
661 Src_Data.Next_In_Sources := In_Tree.First_Source;
662 In_Tree.First_Source := Id;
664 -- Add the source to the project list
666 if Source = No_Source then
667 Data.First_Source := Id;
669 In_Tree.Sources.Table (Source).Next_In_Project := Id;
672 Data.Last_Source := Id;
674 -- Add the source to the language list
676 Src_Data.Next_In_Lang :=
677 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
678 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
680 In_Tree.Sources.Table (Id) := Src_Data;
682 if Source_To_Replace /= No_Source then
683 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
691 function ALI_File_Name (Source : String) return String is
693 -- If the source name has an extension, then replace it with
696 for Index in reverse Source'First + 1 .. Source'Last loop
697 if Source (Index) = '.' then
698 return Source (Source'First .. Index - 1) & ALI_Suffix;
702 -- If there is no dot, or if it is the first character, just add the
705 return Source & ALI_Suffix;
713 (Project : Project_Id;
714 In_Tree : Project_Tree_Ref;
715 Report_Error : Put_Line_Access;
716 When_No_Sources : Error_Warning;
717 Current_Dir : String)
719 Data : Project_Data := In_Tree.Projects.Table (Project);
720 Extending : Boolean := False;
723 Nmsc.When_No_Sources := When_No_Sources;
724 Error_Report := Report_Error;
726 Recursive_Dirs.Reset;
728 Check_If_Externally_Built (Project, In_Tree, Data);
730 -- Object, exec and source directories
732 Get_Directories (Project, In_Tree, Current_Dir, Data);
734 -- Get the programming languages
736 Check_Programming_Languages (In_Tree, Project, Data);
738 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
741 "an abstract project need to have no language, no sources or no " &
742 "source directories",
746 -- Check configuration in multi language mode
748 if Must_Check_Configuration then
749 Check_Configuration (Project, In_Tree, Data);
752 -- Library attributes
754 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
756 if Current_Verbosity = High then
757 Show_Source_Dirs (Data, In_Tree);
760 Check_Package_Naming (Project, In_Tree, Data);
762 Extending := Data.Extends /= No_Project;
764 Check_Naming_Schemes (Data, Project, In_Tree);
766 if Get_Mode = Ada_Only then
767 Prepare_Ada_Naming_Exceptions
768 (Data.Naming.Bodies, In_Tree, Body_Part);
769 Prepare_Ada_Naming_Exceptions
770 (Data.Naming.Specs, In_Tree, Specification);
775 if Data.Source_Dirs /= Nil_String then
776 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
778 if Get_Mode = Ada_Only then
780 -- Check that all individual naming conventions apply to sources
781 -- of this project file.
784 (Project, In_Tree, Data.Naming.Bodies,
786 Extending => Extending);
788 (Project, In_Tree, Data.Naming.Specs,
790 Extending => Extending);
792 elsif Get_Mode = Multi_Language and then
793 (not Data.Externally_Built) and then
797 Language : Language_Index;
799 Src_Data : Source_Data;
800 Alt_Lang : Alternate_Language_Id;
801 Alt_Lang_Data : Alternate_Language_Data;
802 Continuation : Boolean := False;
805 Language := Data.First_Language_Processing;
806 while Language /= No_Language_Index loop
807 Source := Data.First_Source;
808 Source_Loop : while Source /= No_Source loop
809 Src_Data := In_Tree.Sources.Table (Source);
811 exit Source_Loop when Src_Data.Language = Language;
813 Alt_Lang := Src_Data.Alternate_Languages;
816 while Alt_Lang /= No_Alternate_Language loop
818 In_Tree.Alt_Langs.Table (Alt_Lang);
820 when Alt_Lang_Data.Language = Language;
821 Alt_Lang := Alt_Lang_Data.Next;
822 end loop Alternate_Loop;
824 Source := Src_Data.Next_In_Project;
825 end loop Source_Loop;
827 if Source = No_Source then
831 (In_Tree.Languages_Data.Table
832 (Language).Display_Name),
836 Continuation := True;
839 Language := In_Tree.Languages_Data.Table (Language).Next;
845 if Get_Mode = Multi_Language then
847 -- If a list of sources is specified in attribute Interfaces, set
848 -- In_Interfaces only for the sources specified in the list.
850 Check_Interfaces (Project, In_Tree, Data);
853 -- If it is a library project file, check if it is a standalone library
856 Check_Stand_Alone_Library
857 (Project, In_Tree, Data, Current_Dir, Extending);
860 -- Put the list of Mains, if any, in the project data
862 Get_Mains (Project, In_Tree, Data);
864 -- Update the project data in the Projects table
866 In_Tree.Projects.Table (Project) := Data;
868 Free_Ada_Naming_Exceptions;
875 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
876 The_Name : String := Name;
878 Need_Letter : Boolean := True;
879 Last_Underscore : Boolean := False;
880 OK : Boolean := The_Name'Length > 0;
883 function Is_Reserved (Name : Name_Id) return Boolean;
884 function Is_Reserved (S : String) return Boolean;
885 -- Check that the given name is not an Ada 95 reserved word. The reason
886 -- for the Ada 95 here is that we do not want to exclude the case of an
887 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
888 -- name would be rejected anyway by the compiler. That means there is no
889 -- requirement that the project file parser reject this.
895 function Is_Reserved (S : String) return Boolean is
898 Add_Str_To_Name_Buffer (S);
899 return Is_Reserved (Name_Find);
906 function Is_Reserved (Name : Name_Id) return Boolean is
908 if Get_Name_Table_Byte (Name) /= 0
909 and then Name /= Name_Project
910 and then Name /= Name_Extends
911 and then Name /= Name_External
912 and then Name not in Ada_2005_Reserved_Words
916 if Current_Verbosity = High then
917 Write_Str (The_Name);
918 Write_Line (" is an Ada reserved word.");
928 -- Start of processing for Check_Ada_Name
933 Name_Len := The_Name'Length;
934 Name_Buffer (1 .. Name_Len) := The_Name;
936 -- Special cases of children of packages A, G, I and S on VMS
939 and then Name_Len > 3
940 and then Name_Buffer (2 .. 3) = "__"
942 ((Name_Buffer (1) = 'a') or else
943 (Name_Buffer (1) = 'g') or else
944 (Name_Buffer (1) = 'i') or else
945 (Name_Buffer (1) = 's'))
947 Name_Buffer (2) := '.';
948 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
949 Name_Len := Name_Len - 1;
952 Real_Name := Name_Find;
954 if Is_Reserved (Real_Name) then
958 First := The_Name'First;
960 for Index in The_Name'Range loop
963 -- We need a letter (at the beginning, and following a dot),
964 -- but we don't have one.
966 if Is_Letter (The_Name (Index)) then
967 Need_Letter := False;
972 if Current_Verbosity = High then
973 Write_Int (Types.Int (Index));
975 Write_Char (The_Name (Index));
976 Write_Line ("' is not a letter.");
982 elsif Last_Underscore
983 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
985 -- Two underscores are illegal, and a dot cannot follow
990 if Current_Verbosity = High then
991 Write_Int (Types.Int (Index));
993 Write_Char (The_Name (Index));
994 Write_Line ("' is illegal here.");
999 elsif The_Name (Index) = '.' then
1001 -- First, check if the name before the dot is not a reserved word
1002 if Is_Reserved (The_Name (First .. Index - 1)) then
1008 -- We need a letter after a dot
1010 Need_Letter := True;
1012 elsif The_Name (Index) = '_' then
1013 Last_Underscore := True;
1016 -- We need an letter or a digit
1018 Last_Underscore := False;
1020 if not Is_Alphanumeric (The_Name (Index)) then
1023 if Current_Verbosity = High then
1024 Write_Int (Types.Int (Index));
1026 Write_Char (The_Name (Index));
1027 Write_Line ("' is not alphanumeric.");
1035 -- Cannot end with an underscore or a dot
1037 OK := OK and then not Need_Letter and then not Last_Underscore;
1040 if First /= Name'First and then
1041 Is_Reserved (The_Name (First .. The_Name'Last))
1049 -- Signal a problem with No_Name
1055 --------------------------------------
1056 -- Check_Ada_Naming_Scheme_Validity --
1057 --------------------------------------
1059 procedure Check_Ada_Naming_Scheme_Validity
1060 (Project : Project_Id;
1061 In_Tree : Project_Tree_Ref;
1062 Naming : Naming_Data)
1065 -- Only check if we are not using the Default naming scheme
1067 if Naming /= In_Tree.Private_Part.Default_Naming then
1069 Dot_Replacement : constant String :=
1071 (Naming.Dot_Replacement);
1073 Spec_Suffix : constant String :=
1074 Spec_Suffix_Of (In_Tree, "ada", Naming);
1076 Body_Suffix : constant String :=
1077 Body_Suffix_Of (In_Tree, "ada", Naming);
1079 Separate_Suffix : constant String :=
1081 (Naming.Separate_Suffix);
1084 -- Dot_Replacement cannot
1087 -- - start or end with an alphanumeric
1088 -- - be a single '_'
1089 -- - start with an '_' followed by an alphanumeric
1090 -- - contain a '.' except if it is "."
1092 if Dot_Replacement'Length = 0
1093 or else Is_Alphanumeric
1094 (Dot_Replacement (Dot_Replacement'First))
1095 or else Is_Alphanumeric
1096 (Dot_Replacement (Dot_Replacement'Last))
1097 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1099 (Dot_Replacement'Length = 1
1102 (Dot_Replacement (Dot_Replacement'First + 1))))
1103 or else (Dot_Replacement'Length > 1
1105 Index (Source => Dot_Replacement,
1106 Pattern => ".") /= 0)
1110 '"' & Dot_Replacement &
1111 """ is illegal for Dot_Replacement.",
1112 Naming.Dot_Repl_Loc);
1118 if Is_Illegal_Suffix
1119 (Spec_Suffix, Dot_Replacement = ".")
1121 Err_Vars.Error_Msg_File_1 :=
1122 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1125 "{ is illegal for Spec_Suffix",
1126 Naming.Ada_Spec_Suffix_Loc);
1129 if Is_Illegal_Suffix
1130 (Body_Suffix, Dot_Replacement = ".")
1132 Err_Vars.Error_Msg_File_1 :=
1133 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1136 "{ is illegal for Body_Suffix",
1137 Naming.Ada_Body_Suffix_Loc);
1140 if Body_Suffix /= Separate_Suffix then
1141 if Is_Illegal_Suffix
1142 (Separate_Suffix, Dot_Replacement = ".")
1144 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1147 "{ is illegal for Separate_Suffix",
1148 Naming.Sep_Suffix_Loc);
1152 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1153 -- since that would cause a clear ambiguity. Note that we do
1154 -- allow a Spec_Suffix to have the same termination as one of
1155 -- these, which causes a potential ambiguity, but we resolve
1156 -- that my matching the longest possible suffix.
1158 if Spec_Suffix = Body_Suffix then
1163 """) cannot be the same as Spec_Suffix.",
1164 Naming.Ada_Body_Suffix_Loc);
1167 if Body_Suffix /= Separate_Suffix
1168 and then Spec_Suffix = Separate_Suffix
1172 "Separate_Suffix (""" &
1174 """) cannot be the same as Spec_Suffix.",
1175 Naming.Sep_Suffix_Loc);
1179 end Check_Ada_Naming_Scheme_Validity;
1181 -------------------------
1182 -- Check_Configuration --
1183 -------------------------
1185 procedure Check_Configuration
1186 (Project : Project_Id;
1187 In_Tree : Project_Tree_Ref;
1188 Data : in out Project_Data)
1190 Dot_Replacement : File_Name_Type := No_File;
1191 Casing : Casing_Type := All_Lower_Case;
1192 Separate_Suffix : File_Name_Type := No_File;
1194 Lang_Index : Language_Index := No_Language_Index;
1195 -- The index of the language data being checked
1197 Prev_Index : Language_Index := No_Language_Index;
1198 -- The index of the previous language
1200 Current_Language : Name_Id := No_Name;
1201 -- The name of the language
1203 Lang_Data : Language_Data;
1204 -- The data of the language being checked
1206 procedure Get_Language_Index_Of (Language : Name_Id);
1207 -- Get the language index of Language, if Language is one of the
1208 -- languages of the project.
1210 procedure Process_Project_Level_Simple_Attributes;
1211 -- Process the simple attributes at the project level
1213 procedure Process_Project_Level_Array_Attributes;
1214 -- Process the associate array attributes at the project level
1216 procedure Process_Packages;
1217 -- Read the packages of the project
1219 ---------------------------
1220 -- Get_Language_Index_Of --
1221 ---------------------------
1223 procedure Get_Language_Index_Of (Language : Name_Id) is
1224 Real_Language : Name_Id;
1227 Get_Name_String (Language);
1228 To_Lower (Name_Buffer (1 .. Name_Len));
1229 Real_Language := Name_Find;
1231 -- Nothing to do if the language is the same as the current language
1233 if Current_Language /= Real_Language then
1234 Lang_Index := Data.First_Language_Processing;
1235 while Lang_Index /= No_Language_Index loop
1236 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1239 In_Tree.Languages_Data.Table (Lang_Index).Next;
1242 if Lang_Index = No_Language_Index then
1243 Current_Language := No_Name;
1245 Current_Language := Real_Language;
1248 end Get_Language_Index_Of;
1250 ----------------------
1251 -- Process_Packages --
1252 ----------------------
1254 procedure Process_Packages is
1255 Packages : Package_Id;
1256 Element : Package_Element;
1258 procedure Process_Binder (Arrays : Array_Id);
1259 -- Process the associate array attributes of package Binder
1261 procedure Process_Builder (Attributes : Variable_Id);
1262 -- Process the simple attributes of package Builder
1264 procedure Process_Compiler (Arrays : Array_Id);
1265 -- Process the associate array attributes of package Compiler
1267 procedure Process_Naming (Attributes : Variable_Id);
1268 -- Process the simple attributes of package Naming
1270 procedure Process_Naming (Arrays : Array_Id);
1271 -- Process the associate array attributes of package Naming
1273 procedure Process_Linker (Attributes : Variable_Id);
1274 -- Process the simple attributes of package Linker of a
1275 -- configuration project.
1277 --------------------
1278 -- Process_Binder --
1279 --------------------
1281 procedure Process_Binder (Arrays : Array_Id) is
1282 Current_Array_Id : Array_Id;
1283 Current_Array : Array_Data;
1284 Element_Id : Array_Element_Id;
1285 Element : Array_Element;
1288 -- Process the associative array attribute of package Binder
1290 Current_Array_Id := Arrays;
1291 while Current_Array_Id /= No_Array loop
1292 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1294 Element_Id := Current_Array.Value;
1295 while Element_Id /= No_Array_Element loop
1296 Element := In_Tree.Array_Elements.Table (Element_Id);
1298 -- Get the name of the language
1300 Get_Language_Index_Of (Element.Index);
1302 if Lang_Index /= No_Language_Index then
1303 case Current_Array.Name is
1306 -- Attribute Driver (<language>)
1308 In_Tree.Languages_Data.Table
1309 (Lang_Index).Config.Binder_Driver :=
1310 File_Name_Type (Element.Value.Value);
1312 when Name_Required_Switches =>
1314 In_Tree.Languages_Data.Table
1315 (Lang_Index).Config.Binder_Required_Switches,
1316 From_List => Element.Value.Values,
1317 In_Tree => In_Tree);
1321 -- Attribute Prefix (<language>)
1323 In_Tree.Languages_Data.Table
1324 (Lang_Index).Config.Binder_Prefix :=
1325 Element.Value.Value;
1327 when Name_Objects_Path =>
1329 -- Attribute Objects_Path (<language>)
1331 In_Tree.Languages_Data.Table
1332 (Lang_Index).Config.Objects_Path :=
1333 Element.Value.Value;
1335 when Name_Objects_Path_File =>
1337 -- Attribute Objects_Path (<language>)
1339 In_Tree.Languages_Data.Table
1340 (Lang_Index).Config.Objects_Path_File :=
1341 Element.Value.Value;
1348 Element_Id := Element.Next;
1351 Current_Array_Id := Current_Array.Next;
1355 ---------------------
1356 -- Process_Builder --
1357 ---------------------
1359 procedure Process_Builder (Attributes : Variable_Id) is
1360 Attribute_Id : Variable_Id;
1361 Attribute : Variable;
1364 -- Process non associated array attribute from package Builder
1366 Attribute_Id := Attributes;
1367 while Attribute_Id /= No_Variable loop
1369 In_Tree.Variable_Elements.Table (Attribute_Id);
1371 if not Attribute.Value.Default then
1372 if Attribute.Name = Name_Executable_Suffix then
1374 -- Attribute Executable_Suffix: the suffix of the
1377 Data.Config.Executable_Suffix :=
1378 Attribute.Value.Value;
1382 Attribute_Id := Attribute.Next;
1384 end Process_Builder;
1386 ----------------------
1387 -- Process_Compiler --
1388 ----------------------
1390 procedure Process_Compiler (Arrays : Array_Id) is
1391 Current_Array_Id : Array_Id;
1392 Current_Array : Array_Data;
1393 Element_Id : Array_Element_Id;
1394 Element : Array_Element;
1395 List : String_List_Id;
1398 -- Process the associative array attribute of package Compiler
1400 Current_Array_Id := Arrays;
1401 while Current_Array_Id /= No_Array loop
1402 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1404 Element_Id := Current_Array.Value;
1405 while Element_Id /= No_Array_Element loop
1406 Element := In_Tree.Array_Elements.Table (Element_Id);
1408 -- Get the name of the language
1410 Get_Language_Index_Of (Element.Index);
1412 if Lang_Index /= No_Language_Index then
1413 case Current_Array.Name is
1414 when Name_Dependency_Switches =>
1416 -- Attribute Dependency_Switches (<language>)
1418 if In_Tree.Languages_Data.Table
1419 (Lang_Index).Config.Dependency_Kind = None
1421 In_Tree.Languages_Data.Table
1422 (Lang_Index).Config.Dependency_Kind :=
1426 List := Element.Value.Values;
1428 if List /= Nil_String then
1430 In_Tree.Languages_Data.Table
1431 (Lang_Index).Config.Dependency_Option,
1433 In_Tree => In_Tree);
1436 when Name_Dependency_Driver =>
1438 -- Attribute Dependency_Driver (<language>)
1440 if In_Tree.Languages_Data.Table
1441 (Lang_Index).Config.Dependency_Kind = None
1443 In_Tree.Languages_Data.Table
1444 (Lang_Index).Config.Dependency_Kind :=
1448 List := Element.Value.Values;
1450 if List /= Nil_String then
1452 In_Tree.Languages_Data.Table
1453 (Lang_Index).Config.Compute_Dependency,
1455 In_Tree => In_Tree);
1458 when Name_Include_Switches =>
1460 -- Attribute Include_Switches (<language>)
1462 List := Element.Value.Values;
1464 if List = Nil_String then
1468 "include option cannot be null",
1469 Element.Value.Location);
1473 In_Tree.Languages_Data.Table
1474 (Lang_Index).Config.Include_Option,
1476 In_Tree => In_Tree);
1478 when Name_Include_Path =>
1480 -- Attribute Include_Path (<language>)
1482 In_Tree.Languages_Data.Table
1483 (Lang_Index).Config.Include_Path :=
1484 Element.Value.Value;
1486 when Name_Include_Path_File =>
1488 -- Attribute Include_Path_File (<language>)
1490 In_Tree.Languages_Data.Table
1491 (Lang_Index).Config.Include_Path_File :=
1492 Element.Value.Value;
1496 -- Attribute Driver (<language>)
1498 Get_Name_String (Element.Value.Value);
1500 In_Tree.Languages_Data.Table
1501 (Lang_Index).Config.Compiler_Driver :=
1502 File_Name_Type (Element.Value.Value);
1504 when Name_Required_Switches =>
1506 In_Tree.Languages_Data.Table
1507 (Lang_Index).Config.
1508 Compiler_Required_Switches,
1509 From_List => Element.Value.Values,
1510 In_Tree => In_Tree);
1512 when Name_Pic_Option =>
1514 -- Attribute Compiler_Pic_Option (<language>)
1516 List := Element.Value.Values;
1518 if List = Nil_String then
1522 "compiler PIC option cannot be null",
1523 Element.Value.Location);
1527 In_Tree.Languages_Data.Table
1528 (Lang_Index).Config.Compilation_PIC_Option,
1530 In_Tree => In_Tree);
1532 when Name_Mapping_File_Switches =>
1534 -- Attribute Mapping_File_Switches (<language>)
1536 List := Element.Value.Values;
1538 if List = Nil_String then
1542 "mapping file switches cannot be null",
1543 Element.Value.Location);
1547 In_Tree.Languages_Data.Table
1548 (Lang_Index).Config.Mapping_File_Switches,
1550 In_Tree => In_Tree);
1552 when Name_Mapping_Spec_Suffix =>
1554 -- Attribute Mapping_Spec_Suffix (<language>)
1556 In_Tree.Languages_Data.Table
1557 (Lang_Index).Config.Mapping_Spec_Suffix :=
1558 File_Name_Type (Element.Value.Value);
1560 when Name_Mapping_Body_Suffix =>
1562 -- Attribute Mapping_Body_Suffix (<language>)
1564 In_Tree.Languages_Data.Table
1565 (Lang_Index).Config.Mapping_Body_Suffix :=
1566 File_Name_Type (Element.Value.Value);
1568 when Name_Config_File_Switches =>
1570 -- Attribute Config_File_Switches (<language>)
1572 List := Element.Value.Values;
1574 if List = Nil_String then
1578 "config file switches cannot be null",
1579 Element.Value.Location);
1583 In_Tree.Languages_Data.Table
1584 (Lang_Index).Config.Config_File_Switches,
1586 In_Tree => In_Tree);
1588 when Name_Objects_Path =>
1590 -- Attribute Objects_Path (<language>)
1592 In_Tree.Languages_Data.Table
1593 (Lang_Index).Config.Objects_Path :=
1594 Element.Value.Value;
1596 when Name_Objects_Path_File =>
1598 -- Attribute Objects_Path_File (<language>)
1600 In_Tree.Languages_Data.Table
1601 (Lang_Index).Config.Objects_Path_File :=
1602 Element.Value.Value;
1604 when Name_Config_Body_File_Name =>
1606 -- Attribute Config_Body_File_Name (<language>)
1608 In_Tree.Languages_Data.Table
1609 (Lang_Index).Config.Config_Body :=
1610 Element.Value.Value;
1612 when Name_Config_Body_File_Name_Pattern =>
1614 -- Attribute Config_Body_File_Name_Pattern
1617 In_Tree.Languages_Data.Table
1618 (Lang_Index).Config.Config_Body_Pattern :=
1619 Element.Value.Value;
1621 when Name_Config_Spec_File_Name =>
1623 -- Attribute Config_Spec_File_Name (<language>)
1625 In_Tree.Languages_Data.Table
1626 (Lang_Index).Config.Config_Spec :=
1627 Element.Value.Value;
1629 when Name_Config_Spec_File_Name_Pattern =>
1631 -- Attribute Config_Spec_File_Name_Pattern
1634 In_Tree.Languages_Data.Table
1635 (Lang_Index).Config.Config_Spec_Pattern :=
1636 Element.Value.Value;
1638 when Name_Config_File_Unique =>
1640 -- Attribute Config_File_Unique (<language>)
1643 In_Tree.Languages_Data.Table
1644 (Lang_Index).Config.Config_File_Unique :=
1646 (Get_Name_String (Element.Value.Value));
1648 when Constraint_Error =>
1652 "illegal value for Config_File_Unique",
1653 Element.Value.Location);
1661 Element_Id := Element.Next;
1664 Current_Array_Id := Current_Array.Next;
1666 end Process_Compiler;
1668 --------------------
1669 -- Process_Naming --
1670 --------------------
1672 procedure Process_Naming (Attributes : Variable_Id) is
1673 Attribute_Id : Variable_Id;
1674 Attribute : Variable;
1677 -- Process non associated array attribute from package Naming
1679 Attribute_Id := Attributes;
1680 while Attribute_Id /= No_Variable loop
1682 In_Tree.Variable_Elements.Table (Attribute_Id);
1684 if not Attribute.Value.Default then
1685 if Attribute.Name = Name_Separate_Suffix then
1687 -- Attribute Separate_Suffix
1689 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1691 elsif Attribute.Name = Name_Casing then
1697 Value (Get_Name_String (Attribute.Value.Value));
1700 when Constraint_Error =>
1704 "invalid value for Casing",
1705 Attribute.Value.Location);
1708 elsif Attribute.Name = Name_Dot_Replacement then
1710 -- Attribute Dot_Replacement
1712 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1717 Attribute_Id := Attribute.Next;
1721 procedure Process_Naming (Arrays : Array_Id) is
1722 Current_Array_Id : Array_Id;
1723 Current_Array : Array_Data;
1724 Element_Id : Array_Element_Id;
1725 Element : Array_Element;
1727 -- Process the associative array attribute of package Naming
1729 Current_Array_Id := Arrays;
1730 while Current_Array_Id /= No_Array loop
1731 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1733 Element_Id := Current_Array.Value;
1734 while Element_Id /= No_Array_Element loop
1735 Element := In_Tree.Array_Elements.Table (Element_Id);
1737 -- Get the name of the language
1739 Get_Language_Index_Of (Element.Index);
1741 if Lang_Index /= No_Language_Index then
1742 case Current_Array.Name is
1743 when Name_Specification_Suffix | Name_Spec_Suffix =>
1745 -- Attribute Spec_Suffix (<language>)
1747 In_Tree.Languages_Data.Table
1748 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1749 File_Name_Type (Element.Value.Value);
1751 when Name_Implementation_Suffix | Name_Body_Suffix =>
1753 -- Attribute Body_Suffix (<language>)
1755 In_Tree.Languages_Data.Table
1756 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1757 File_Name_Type (Element.Value.Value);
1759 In_Tree.Languages_Data.Table
1760 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1761 File_Name_Type (Element.Value.Value);
1768 Element_Id := Element.Next;
1771 Current_Array_Id := Current_Array.Next;
1775 --------------------
1776 -- Process_Linker --
1777 --------------------
1779 procedure Process_Linker (Attributes : Variable_Id) is
1780 Attribute_Id : Variable_Id;
1781 Attribute : Variable;
1784 -- Process non associated array attribute from package Linker
1786 Attribute_Id := Attributes;
1787 while Attribute_Id /= No_Variable loop
1789 In_Tree.Variable_Elements.Table (Attribute_Id);
1791 if not Attribute.Value.Default then
1792 if Attribute.Name = Name_Driver then
1794 -- Attribute Linker'Driver: the default linker to use
1796 Data.Config.Linker :=
1797 Path_Name_Type (Attribute.Value.Value);
1799 elsif Attribute.Name = Name_Required_Switches then
1801 -- Attribute Required_Switches: the minimum
1802 -- options to use when invoking the linker
1805 Data.Config.Minimum_Linker_Options,
1806 From_List => Attribute.Value.Values,
1807 In_Tree => In_Tree);
1809 elsif Attribute.Name = Name_Map_File_Option then
1810 Data.Config.Map_File_Option := Attribute.Value.Value;
1814 Attribute_Id := Attribute.Next;
1818 -- Start of processing for Process_Packages
1821 Packages := Data.Decl.Packages;
1822 while Packages /= No_Package loop
1823 Element := In_Tree.Packages.Table (Packages);
1825 case Element.Name is
1828 -- Process attributes of package Binder
1830 Process_Binder (Element.Decl.Arrays);
1832 when Name_Builder =>
1834 -- Process attributes of package Builder
1836 Process_Builder (Element.Decl.Attributes);
1838 when Name_Compiler =>
1840 -- Process attributes of package Compiler
1842 Process_Compiler (Element.Decl.Arrays);
1846 -- Process attributes of package Linker
1848 Process_Linker (Element.Decl.Attributes);
1852 -- Process attributes of package Naming
1854 Process_Naming (Element.Decl.Attributes);
1855 Process_Naming (Element.Decl.Arrays);
1861 Packages := Element.Next;
1863 end Process_Packages;
1865 ---------------------------------------------
1866 -- Process_Project_Level_Simple_Attributes --
1867 ---------------------------------------------
1869 procedure Process_Project_Level_Simple_Attributes is
1870 Attribute_Id : Variable_Id;
1871 Attribute : Variable;
1872 List : String_List_Id;
1875 -- Process non associated array attribute at project level
1877 Attribute_Id := Data.Decl.Attributes;
1878 while Attribute_Id /= No_Variable loop
1880 In_Tree.Variable_Elements.Table (Attribute_Id);
1882 if not Attribute.Value.Default then
1883 if Attribute.Name = Name_Library_Builder then
1885 -- Attribute Library_Builder: the application to invoke
1886 -- to build libraries.
1888 Data.Config.Library_Builder :=
1889 Path_Name_Type (Attribute.Value.Value);
1891 elsif Attribute.Name = Name_Archive_Builder then
1893 -- Attribute Archive_Builder: the archive builder
1894 -- (usually "ar") and its minimum options (usually "cr").
1896 List := Attribute.Value.Values;
1898 if List = Nil_String then
1902 "archive builder cannot be null",
1903 Attribute.Value.Location);
1906 Put (Into_List => Data.Config.Archive_Builder,
1908 In_Tree => In_Tree);
1910 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1912 -- Attribute Archive_Builder: the archive builder
1913 -- (usually "ar") and its minimum options (usually "cr").
1915 List := Attribute.Value.Values;
1917 if List /= Nil_String then
1919 (Into_List => Data.Config.Archive_Builder_Append_Option,
1921 In_Tree => In_Tree);
1924 elsif Attribute.Name = Name_Archive_Indexer then
1926 -- Attribute Archive_Indexer: the optional archive
1927 -- indexer (usually "ranlib") with its minimum options
1930 List := Attribute.Value.Values;
1932 if List = Nil_String then
1936 "archive indexer cannot be null",
1937 Attribute.Value.Location);
1940 Put (Into_List => Data.Config.Archive_Indexer,
1942 In_Tree => In_Tree);
1944 elsif Attribute.Name = Name_Library_Partial_Linker then
1946 -- Attribute Library_Partial_Linker: the optional linker
1947 -- driver with its minimum options, to partially link
1950 List := Attribute.Value.Values;
1952 if List = Nil_String then
1956 "partial linker cannot be null",
1957 Attribute.Value.Location);
1960 Put (Into_List => Data.Config.Lib_Partial_Linker,
1962 In_Tree => In_Tree);
1964 elsif Attribute.Name = Name_Library_GCC then
1965 Data.Config.Shared_Lib_Driver :=
1966 File_Name_Type (Attribute.Value.Value);
1968 elsif Attribute.Name = Name_Archive_Suffix then
1969 Data.Config.Archive_Suffix :=
1970 File_Name_Type (Attribute.Value.Value);
1972 elsif Attribute.Name = Name_Linker_Executable_Option then
1974 -- Attribute Linker_Executable_Option: optional options
1975 -- to specify an executable name. Defaults to "-o".
1977 List := Attribute.Value.Values;
1979 if List = Nil_String then
1983 "linker executable option cannot be null",
1984 Attribute.Value.Location);
1987 Put (Into_List => Data.Config.Linker_Executable_Option,
1989 In_Tree => In_Tree);
1991 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
1993 -- Attribute Linker_Lib_Dir_Option: optional options
1994 -- to specify a library search directory. Defaults to
1997 Get_Name_String (Attribute.Value.Value);
1999 if Name_Len = 0 then
2003 "linker library directory option cannot be empty",
2004 Attribute.Value.Location);
2007 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2009 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2011 -- Attribute Linker_Lib_Name_Option: optional options
2012 -- to specify the name of a library to be linked in.
2013 -- Defaults to "-l".
2015 Get_Name_String (Attribute.Value.Value);
2017 if Name_Len = 0 then
2021 "linker library name option cannot be empty",
2022 Attribute.Value.Location);
2025 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2027 elsif Attribute.Name = Name_Run_Path_Option then
2029 -- Attribute Run_Path_Option: optional options to
2030 -- specify a path for libraries.
2032 List := Attribute.Value.Values;
2034 if List /= Nil_String then
2035 Put (Into_List => Data.Config.Run_Path_Option,
2037 In_Tree => In_Tree);
2040 elsif Attribute.Name = Name_Library_Support then
2042 pragma Unsuppress (All_Checks);
2044 Data.Config.Lib_Support :=
2045 Library_Support'Value (Get_Name_String
2046 (Attribute.Value.Value));
2048 when Constraint_Error =>
2052 "invalid value """ &
2053 Get_Name_String (Attribute.Value.Value) &
2054 """ for Library_Support",
2055 Attribute.Value.Location);
2058 elsif Attribute.Name = Name_Shared_Library_Prefix then
2059 Data.Config.Shared_Lib_Prefix :=
2060 File_Name_Type (Attribute.Value.Value);
2062 elsif Attribute.Name = Name_Shared_Library_Suffix then
2063 Data.Config.Shared_Lib_Suffix :=
2064 File_Name_Type (Attribute.Value.Value);
2066 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2068 pragma Unsuppress (All_Checks);
2070 Data.Config.Symbolic_Link_Supported :=
2071 Boolean'Value (Get_Name_String
2072 (Attribute.Value.Value));
2074 when Constraint_Error =>
2079 & Get_Name_String (Attribute.Value.Value)
2080 & """ for Symbolic_Link_Supported",
2081 Attribute.Value.Location);
2085 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2088 pragma Unsuppress (All_Checks);
2090 Data.Config.Lib_Maj_Min_Id_Supported :=
2091 Boolean'Value (Get_Name_String
2092 (Attribute.Value.Value));
2094 when Constraint_Error =>
2098 "invalid value """ &
2099 Get_Name_String (Attribute.Value.Value) &
2100 """ for Library_Major_Minor_Id_Supported",
2101 Attribute.Value.Location);
2104 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2106 pragma Unsuppress (All_Checks);
2108 Data.Config.Auto_Init_Supported :=
2109 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2111 when Constraint_Error =>
2116 & Get_Name_String (Attribute.Value.Value)
2117 & """ for Library_Auto_Init_Supported",
2118 Attribute.Value.Location);
2121 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2122 List := Attribute.Value.Values;
2124 if List /= Nil_String then
2125 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2127 In_Tree => In_Tree);
2130 elsif Attribute.Name = Name_Library_Version_Switches then
2131 List := Attribute.Value.Values;
2133 if List /= Nil_String then
2134 Put (Into_List => Data.Config.Lib_Version_Options,
2136 In_Tree => In_Tree);
2141 Attribute_Id := Attribute.Next;
2143 end Process_Project_Level_Simple_Attributes;
2145 --------------------------------------------
2146 -- Process_Project_Level_Array_Attributes --
2147 --------------------------------------------
2149 procedure Process_Project_Level_Array_Attributes is
2150 Current_Array_Id : Array_Id;
2151 Current_Array : Array_Data;
2152 Element_Id : Array_Element_Id;
2153 Element : Array_Element;
2154 List : String_List_Id;
2157 -- Process the associative array attributes at project level
2159 Current_Array_Id := Data.Decl.Arrays;
2160 while Current_Array_Id /= No_Array loop
2161 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2163 Element_Id := Current_Array.Value;
2164 while Element_Id /= No_Array_Element loop
2165 Element := In_Tree.Array_Elements.Table (Element_Id);
2167 -- Get the name of the language
2169 Get_Language_Index_Of (Element.Index);
2171 if Lang_Index /= No_Language_Index then
2172 case Current_Array.Name is
2173 when Name_Inherit_Source_Path =>
2174 List := Element.Value.Values;
2176 if List /= Nil_String then
2179 In_Tree.Languages_Data.Table (Lang_Index).
2180 Config.Include_Compatible_Languages,
2183 Lower_Case => True);
2186 when Name_Toolchain_Description =>
2188 -- Attribute Toolchain_Description (<language>)
2190 In_Tree.Languages_Data.Table
2191 (Lang_Index).Config.Toolchain_Description :=
2192 Element.Value.Value;
2194 when Name_Toolchain_Version =>
2196 -- Attribute Toolchain_Version (<language>)
2198 In_Tree.Languages_Data.Table
2199 (Lang_Index).Config.Toolchain_Version :=
2200 Element.Value.Value;
2202 when Name_Runtime_Library_Dir =>
2204 -- Attribute Runtime_Library_Dir (<language>)
2206 In_Tree.Languages_Data.Table
2207 (Lang_Index).Config.Runtime_Library_Dir :=
2208 Element.Value.Value;
2210 when Name_Object_Generated =>
2212 pragma Unsuppress (All_Checks);
2218 (Get_Name_String (Element.Value.Value));
2220 In_Tree.Languages_Data.Table
2221 (Lang_Index).Config.Object_Generated := Value;
2223 -- If no object is generated, no object may be
2227 In_Tree.Languages_Data.Table
2228 (Lang_Index).Config.Objects_Linked := False;
2232 when Constraint_Error =>
2237 & Get_Name_String (Element.Value.Value)
2238 & """ for Object_Generated",
2239 Element.Value.Location);
2242 when Name_Objects_Linked =>
2244 pragma Unsuppress (All_Checks);
2250 (Get_Name_String (Element.Value.Value));
2252 -- No change if Object_Generated is False, as this
2253 -- forces Objects_Linked to be False too.
2255 if In_Tree.Languages_Data.Table
2256 (Lang_Index).Config.Object_Generated
2258 In_Tree.Languages_Data.Table
2259 (Lang_Index).Config.Objects_Linked :=
2264 when Constraint_Error =>
2269 & Get_Name_String (Element.Value.Value)
2270 & """ for Objects_Linked",
2271 Element.Value.Location);
2278 Element_Id := Element.Next;
2281 Current_Array_Id := Current_Array.Next;
2283 end Process_Project_Level_Array_Attributes;
2286 Process_Project_Level_Simple_Attributes;
2287 Process_Project_Level_Array_Attributes;
2290 -- For unit based languages, set Casing, Dot_Replacement and
2291 -- Separate_Suffix in Naming_Data.
2293 Lang_Index := Data.First_Language_Processing;
2294 while Lang_Index /= No_Language_Index loop
2295 if In_Tree.Languages_Data.Table
2296 (Lang_Index).Name = Name_Ada
2298 In_Tree.Languages_Data.Table
2299 (Lang_Index).Config.Naming_Data.Casing := Casing;
2300 In_Tree.Languages_Data.Table
2301 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2304 if Separate_Suffix /= No_File then
2305 In_Tree.Languages_Data.Table
2306 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2313 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2316 -- Give empty names to various prefixes/suffixes, if they have not
2317 -- been specified in the configuration.
2319 if Data.Config.Archive_Suffix = No_File then
2320 Data.Config.Archive_Suffix := Empty_File;
2323 if Data.Config.Shared_Lib_Prefix = No_File then
2324 Data.Config.Shared_Lib_Prefix := Empty_File;
2327 if Data.Config.Shared_Lib_Suffix = No_File then
2328 Data.Config.Shared_Lib_Suffix := Empty_File;
2331 Lang_Index := Data.First_Language_Processing;
2332 while Lang_Index /= No_Language_Index loop
2333 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2335 Current_Language := Lang_Data.Display_Name;
2337 -- For all languages, Compiler_Driver needs to be specified
2339 if Lang_Data.Config.Compiler_Driver = No_File then
2340 Error_Msg_Name_1 := Current_Language;
2344 "?no compiler specified for language %%" &
2345 ", ignoring all its sources",
2348 if Lang_Index = Data.First_Language_Processing then
2349 Data.First_Language_Processing :=
2352 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2356 elsif Lang_Data.Name = Name_Ada then
2357 Prev_Index := Lang_Index;
2359 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2360 -- Body_Suffix need to be specified.
2362 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2366 "Dot_Replacement not specified for Ada",
2370 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2374 "Spec_Suffix not specified for Ada",
2378 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2382 "Body_Suffix not specified for Ada",
2387 Prev_Index := Lang_Index;
2389 -- For file based languages, either Spec_Suffix or Body_Suffix
2390 -- need to be specified.
2392 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2393 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2395 Error_Msg_Name_1 := Current_Language;
2399 "no suffixes specified for %%",
2404 Lang_Index := Lang_Data.Next;
2406 end Check_Configuration;
2408 -------------------------------
2409 -- Check_If_Externally_Built --
2410 -------------------------------
2412 procedure Check_If_Externally_Built
2413 (Project : Project_Id;
2414 In_Tree : Project_Tree_Ref;
2415 Data : in out Project_Data)
2417 Externally_Built : constant Variable_Value :=
2419 (Name_Externally_Built,
2420 Data.Decl.Attributes, In_Tree);
2423 if not Externally_Built.Default then
2424 Get_Name_String (Externally_Built.Value);
2425 To_Lower (Name_Buffer (1 .. Name_Len));
2427 if Name_Buffer (1 .. Name_Len) = "true" then
2428 Data.Externally_Built := True;
2430 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2431 Error_Msg (Project, In_Tree,
2432 "Externally_Built may only be true or false",
2433 Externally_Built.Location);
2437 -- A virtual project extending an externally built project is itself
2438 -- externally built.
2440 if Data.Virtual and then Data.Extends /= No_Project then
2441 Data.Externally_Built :=
2442 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2445 if Current_Verbosity = High then
2446 Write_Str ("Project is ");
2448 if not Data.Externally_Built then
2452 Write_Line ("externally built.");
2454 end Check_If_Externally_Built;
2456 ----------------------
2457 -- Check_Interfaces --
2458 ----------------------
2460 procedure Check_Interfaces
2461 (Project : Project_Id;
2462 In_Tree : Project_Tree_Ref;
2463 Data : in out Project_Data)
2465 Interfaces : constant Prj.Variable_Value :=
2467 (Snames.Name_Interfaces,
2468 Data.Decl.Attributes,
2471 List : String_List_Id;
2472 Element : String_Element;
2473 Name : File_Name_Type;
2476 Src_Data : Source_Data;
2478 Project_2 : Project_Id;
2479 Data_2 : Project_Data;
2482 if not Interfaces.Default then
2484 -- Set In_Interfaces to False for all sources. It will be set to True
2485 -- later for the sources in the Interfaces list.
2487 Project_2 := Project;
2490 Source := Data_2.First_Source;
2491 while Source /= No_Source loop
2492 Src_Data := In_Tree.Sources.Table (Source);
2493 Src_Data.In_Interfaces := False;
2494 In_Tree.Sources.Table (Source) := Src_Data;
2495 Source := Src_Data.Next_In_Project;
2498 Project_2 := Data_2.Extends;
2500 exit when Project_2 = No_Project;
2502 Data_2 := In_Tree.Projects.Table (Project_2);
2505 List := Interfaces.Values;
2506 while List /= Nil_String loop
2507 Element := In_Tree.String_Elements.Table (List);
2508 Get_Name_String (Element.Value);
2509 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2512 Project_2 := Project;
2516 Source := Data_2.First_Source;
2517 while Source /= No_Source loop
2518 Src_Data := In_Tree.Sources.Table (Source);
2519 if Src_Data.File = Name then
2520 if not Src_Data.Locally_Removed then
2521 In_Tree.Sources.Table (Source).In_Interfaces := True;
2522 In_Tree.Sources.Table
2523 (Source).Declared_In_Interfaces := True;
2525 if Src_Data.Other_Part /= No_Source then
2526 In_Tree.Sources.Table
2527 (Src_Data.Other_Part).In_Interfaces := True;
2528 In_Tree.Sources.Table
2529 (Src_Data.Other_Part).Declared_In_Interfaces :=
2533 if Current_Verbosity = High then
2534 Write_Str (" interface: ");
2535 Write_Line (Get_Name_String (Src_Data.Path.Name));
2542 Source := Src_Data.Next_In_Project;
2545 Project_2 := Data_2.Extends;
2547 exit Big_Loop when Project_2 = No_Project;
2549 Data_2 := In_Tree.Projects.Table (Project_2);
2552 if Source = No_Source then
2553 Error_Msg_File_1 := File_Name_Type (Element.Value);
2554 Error_Msg_Name_1 := Data.Name;
2559 "{ cannot be an interface of project %% " &
2560 "as it is not one of its sources",
2564 List := Element.Next;
2567 Data.Interfaces_Defined := True;
2569 elsif Data.Extends /= No_Project then
2570 Data.Interfaces_Defined :=
2571 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2573 if Data.Interfaces_Defined then
2574 Source := Data.First_Source;
2575 while Source /= No_Source loop
2576 Src_Data := In_Tree.Sources.Table (Source);
2578 if not Src_Data.Declared_In_Interfaces then
2579 Src_Data.In_Interfaces := False;
2580 In_Tree.Sources.Table (Source) := Src_Data;
2583 Source := Src_Data.Next_In_Project;
2587 end Check_Interfaces;
2589 --------------------------
2590 -- Check_Naming_Schemes --
2591 --------------------------
2593 procedure Check_Naming_Schemes
2594 (Data : in out Project_Data;
2595 Project : Project_Id;
2596 In_Tree : Project_Tree_Ref)
2598 Naming_Id : constant Package_Id :=
2599 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2600 Naming : Package_Element;
2602 procedure Check_Unit_Names (List : Array_Element_Id);
2603 -- Check that a list of unit names contains only valid names
2605 procedure Get_Exceptions (Kind : Source_Kind);
2607 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2609 ----------------------
2610 -- Check_Unit_Names --
2611 ----------------------
2613 procedure Check_Unit_Names (List : Array_Element_Id) is
2614 Current : Array_Element_Id;
2615 Element : Array_Element;
2616 Unit_Name : Name_Id;
2619 -- Loop through elements of the string list
2622 while Current /= No_Array_Element loop
2623 Element := In_Tree.Array_Elements.Table (Current);
2625 -- Put file name in canonical case
2627 if not Osint.File_Names_Case_Sensitive then
2628 Get_Name_String (Element.Value.Value);
2629 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2630 Element.Value.Value := Name_Find;
2633 -- Check that it contains a valid unit name
2635 Get_Name_String (Element.Index);
2636 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2638 if Unit_Name = No_Name then
2639 Err_Vars.Error_Msg_Name_1 := Element.Index;
2642 "%% is not a valid unit name.",
2643 Element.Value.Location);
2646 if Current_Verbosity = High then
2647 Write_Str (" Unit (""");
2648 Write_Str (Get_Name_String (Unit_Name));
2652 Element.Index := Unit_Name;
2653 In_Tree.Array_Elements.Table (Current) := Element;
2656 Current := Element.Next;
2658 end Check_Unit_Names;
2660 --------------------
2661 -- Get_Exceptions --
2662 --------------------
2664 procedure Get_Exceptions (Kind : Source_Kind) is
2665 Exceptions : Array_Element_Id;
2666 Exception_List : Variable_Value;
2667 Element_Id : String_List_Id;
2668 Element : String_Element;
2669 File_Name : File_Name_Type;
2670 Lang_Id : Language_Index;
2672 Lang_Kind : Language_Kind;
2679 (Name_Implementation_Exceptions,
2680 In_Arrays => Naming.Decl.Arrays,
2681 In_Tree => In_Tree);
2686 (Name_Specification_Exceptions,
2687 In_Arrays => Naming.Decl.Arrays,
2688 In_Tree => In_Tree);
2691 Lang_Id := Data.First_Language_Processing;
2692 while Lang_Id /= No_Language_Index loop
2693 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2696 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2698 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2700 Exception_List := Value_Of
2702 In_Array => Exceptions,
2703 In_Tree => In_Tree);
2705 if Exception_List /= Nil_Variable_Value then
2706 Element_Id := Exception_List.Values;
2707 while Element_Id /= Nil_String loop
2708 Element := In_Tree.String_Elements.Table (Element_Id);
2710 if Osint.File_Names_Case_Sensitive then
2711 File_Name := File_Name_Type (Element.Value);
2713 Get_Name_String (Element.Value);
2714 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2715 File_Name := Name_Find;
2718 Source := Data.First_Source;
2719 while Source /= No_Source
2721 In_Tree.Sources.Table (Source).File /= File_Name
2724 In_Tree.Sources.Table (Source).Next_In_Project;
2727 if Source = No_Source then
2736 File_Name => File_Name,
2737 Display_File => File_Name_Type (Element.Value),
2738 Naming_Exception => True,
2739 Lang_Kind => Lang_Kind);
2742 -- Check if the file name is already recorded for
2743 -- another language or another kind.
2746 In_Tree.Sources.Table (Source).Language /= Lang_Id
2751 "the same file cannot be a source " &
2755 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2759 "the same file cannot be a source " &
2764 -- If the file is already recorded for the same
2765 -- language and the same kind, it means that the file
2766 -- name appears several times in the *_Exceptions
2767 -- attribute; so there is nothing to do.
2771 Element_Id := Element.Next;
2776 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2780 -------------------------
2781 -- Get_Unit_Exceptions --
2782 -------------------------
2784 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2785 Exceptions : Array_Element_Id;
2786 Element : Array_Element;
2789 File_Name : File_Name_Type;
2790 Lang_Id : constant Language_Index :=
2791 Data.Unit_Based_Language_Index;
2792 Lang : constant Name_Id :=
2793 Data.Unit_Based_Language_Name;
2796 Source_To_Replace : Source_Id := No_Source;
2798 Other_Project : Project_Id;
2799 Other_Part : Source_Id := No_Source;
2802 if Lang_Id = No_Language_Index or else Lang = No_Name then
2807 Exceptions := Value_Of
2809 In_Arrays => Naming.Decl.Arrays,
2810 In_Tree => In_Tree);
2812 if Exceptions = No_Array_Element then
2815 (Name_Implementation,
2816 In_Arrays => Naming.Decl.Arrays,
2817 In_Tree => In_Tree);
2824 In_Arrays => Naming.Decl.Arrays,
2825 In_Tree => In_Tree);
2827 if Exceptions = No_Array_Element then
2828 Exceptions := Value_Of
2829 (Name_Specification,
2830 In_Arrays => Naming.Decl.Arrays,
2831 In_Tree => In_Tree);
2836 while Exceptions /= No_Array_Element loop
2837 Element := In_Tree.Array_Elements.Table (Exceptions);
2839 if Osint.File_Names_Case_Sensitive then
2840 File_Name := File_Name_Type (Element.Value.Value);
2842 Get_Name_String (Element.Value.Value);
2843 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2844 File_Name := Name_Find;
2847 Get_Name_String (Element.Index);
2848 To_Lower (Name_Buffer (1 .. Name_Len));
2851 Index := Element.Value.Index;
2853 -- For Ada, check if it is a valid unit name
2855 if Lang = Name_Ada then
2856 Get_Name_String (Element.Index);
2857 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2859 if Unit = No_Name then
2860 Err_Vars.Error_Msg_Name_1 := Element.Index;
2863 "%% is not a valid unit name.",
2864 Element.Value.Location);
2868 if Unit /= No_Name then
2870 -- Check if the source already exists
2872 Source := In_Tree.First_Source;
2873 Source_To_Replace := No_Source;
2875 while Source /= No_Source and then
2876 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2877 In_Tree.Sources.Table (Source).Index /= Index)
2879 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2882 if Source /= No_Source then
2883 if In_Tree.Sources.Table (Source).Kind /= Kind then
2884 Other_Part := Source;
2888 In_Tree.Sources.Table (Source).Next_In_Sources;
2890 exit when Source = No_Source or else
2891 (In_Tree.Sources.Table (Source).Unit = Unit
2893 In_Tree.Sources.Table (Source).Index = Index);
2897 if Source /= No_Source then
2898 Other_Project := In_Tree.Sources.Table (Source).Project;
2900 if Is_Extending (Project, Other_Project, In_Tree) then
2902 In_Tree.Sources.Table (Source).Other_Part;
2904 -- Record the source to be removed
2906 Source_To_Replace := Source;
2907 Source := No_Source;
2910 Error_Msg_Name_1 := Unit;
2912 In_Tree.Projects.Table (Other_Project).Name;
2916 "%% is already a source of project %%",
2917 Element.Value.Location);
2922 if Source = No_Source then
2931 File_Name => File_Name,
2932 Display_File => File_Name_Type (Element.Value.Value),
2933 Lang_Kind => Unit_Based,
2934 Other_Part => Other_Part,
2937 Naming_Exception => True,
2938 Source_To_Replace => Source_To_Replace);
2942 Exceptions := Element.Next;
2945 end Get_Unit_Exceptions;
2947 -- Start of processing for Check_Naming_Schemes
2950 if Get_Mode = Ada_Only then
2952 -- If there is a package Naming, we will put in Data.Naming what is
2953 -- in this package Naming.
2955 if Naming_Id /= No_Package then
2956 Naming := In_Tree.Packages.Table (Naming_Id);
2958 if Current_Verbosity = High then
2959 Write_Line ("Checking ""Naming"" for Ada.");
2963 Bodies : constant Array_Element_Id :=
2965 (Name_Body, Naming.Decl.Arrays, In_Tree);
2967 Specs : constant Array_Element_Id :=
2969 (Name_Spec, Naming.Decl.Arrays, In_Tree);
2972 if Bodies /= No_Array_Element then
2974 -- We have elements in the array Body_Part
2976 if Current_Verbosity = High then
2977 Write_Line ("Found Bodies.");
2980 Data.Naming.Bodies := Bodies;
2981 Check_Unit_Names (Bodies);
2984 if Current_Verbosity = High then
2985 Write_Line ("No Bodies.");
2989 if Specs /= No_Array_Element then
2991 -- We have elements in the array Specs
2993 if Current_Verbosity = High then
2994 Write_Line ("Found Specs.");
2997 Data.Naming.Specs := Specs;
2998 Check_Unit_Names (Specs);
3001 if Current_Verbosity = High then
3002 Write_Line ("No Specs.");
3007 -- We are now checking if variables Dot_Replacement, Casing,
3008 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3010 -- For each variable, if it does not exist, we do nothing,
3011 -- because we already have the default.
3013 -- Check Dot_Replacement
3016 Dot_Replacement : constant Variable_Value :=
3018 (Name_Dot_Replacement,
3019 Naming.Decl.Attributes, In_Tree);
3022 pragma Assert (Dot_Replacement.Kind = Single,
3023 "Dot_Replacement is not a single string");
3025 if not Dot_Replacement.Default then
3026 Get_Name_String (Dot_Replacement.Value);
3028 if Name_Len = 0 then
3031 "Dot_Replacement cannot be empty",
3032 Dot_Replacement.Location);
3035 if Osint.File_Names_Case_Sensitive then
3036 Data.Naming.Dot_Replacement :=
3037 File_Name_Type (Dot_Replacement.Value);
3039 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3040 Data.Naming.Dot_Replacement := Name_Find;
3042 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3047 if Current_Verbosity = High then
3048 Write_Str (" Dot_Replacement = """);
3049 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3057 Casing_String : constant Variable_Value :=
3060 Naming.Decl.Attributes,
3064 pragma Assert (Casing_String.Kind = Single,
3065 "Casing is not a single string");
3067 if not Casing_String.Default then
3069 Casing_Image : constant String :=
3070 Get_Name_String (Casing_String.Value);
3073 Casing_Value : constant Casing_Type :=
3074 Value (Casing_Image);
3076 Data.Naming.Casing := Casing_Value;
3080 when Constraint_Error =>
3081 if Casing_Image'Length = 0 then
3084 "Casing cannot be an empty string",
3085 Casing_String.Location);
3088 Name_Len := Casing_Image'Length;
3089 Name_Buffer (1 .. Name_Len) := Casing_Image;
3090 Err_Vars.Error_Msg_Name_1 := Name_Find;
3093 "%% is not a correct Casing",
3094 Casing_String.Location);
3100 if Current_Verbosity = High then
3101 Write_Str (" Casing = ");
3102 Write_Str (Image (Data.Naming.Casing));
3107 -- Check Spec_Suffix
3110 Ada_Spec_Suffix : constant Variable_Value :=
3114 In_Array => Data.Naming.Spec_Suffix,
3115 In_Tree => In_Tree);
3118 if Ada_Spec_Suffix.Kind = Single
3119 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3121 Get_Name_String (Ada_Spec_Suffix.Value);
3122 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3123 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3124 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3131 Default_Ada_Spec_Suffix);
3135 if Current_Verbosity = High then
3136 Write_Str (" Spec_Suffix = """);
3137 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3142 -- Check Body_Suffix
3145 Ada_Body_Suffix : constant Variable_Value :=
3149 In_Array => Data.Naming.Body_Suffix,
3150 In_Tree => In_Tree);
3153 if Ada_Body_Suffix.Kind = Single
3154 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3156 Get_Name_String (Ada_Body_Suffix.Value);
3157 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3158 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3159 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3166 Default_Ada_Body_Suffix);
3170 if Current_Verbosity = High then
3171 Write_Str (" Body_Suffix = """);
3172 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3177 -- Check Separate_Suffix
3180 Ada_Sep_Suffix : constant Variable_Value :=
3182 (Variable_Name => Name_Separate_Suffix,
3183 In_Variables => Naming.Decl.Attributes,
3184 In_Tree => In_Tree);
3187 if Ada_Sep_Suffix.Default then
3188 Data.Naming.Separate_Suffix :=
3189 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3192 Get_Name_String (Ada_Sep_Suffix.Value);
3194 if Name_Len = 0 then
3197 "Separate_Suffix cannot be empty",
3198 Ada_Sep_Suffix.Location);
3201 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3202 Data.Naming.Separate_Suffix := Name_Find;
3203 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3208 if Current_Verbosity = High then
3209 Write_Str (" Separate_Suffix = """);
3210 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3215 -- Check if Data.Naming is valid
3217 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3220 elsif not In_Configuration then
3222 -- Look into package Naming, if there is one
3224 if Naming_Id /= No_Package then
3225 Naming := In_Tree.Packages.Table (Naming_Id);
3227 if Current_Verbosity = High then
3228 Write_Line ("Checking package Naming.");
3231 -- We are now checking if attribute Dot_Replacement, Casing,
3232 -- and/or Separate_Suffix exist.
3234 -- For each attribute, if it does not exist, we do nothing,
3235 -- because we already have the default.
3236 -- Otherwise, for all unit-based languages, we put the declared
3237 -- value in the language config.
3240 Dot_Repl : constant Variable_Value :=
3242 (Name_Dot_Replacement,
3243 Naming.Decl.Attributes, In_Tree);
3244 Dot_Replacement : File_Name_Type := No_File;
3246 Casing_String : constant Variable_Value :=
3249 Naming.Decl.Attributes,
3251 Casing : Casing_Type;
3252 Casing_Defined : Boolean := False;
3254 Sep_Suffix : constant Variable_Value :=
3256 (Variable_Name => Name_Separate_Suffix,
3257 In_Variables => Naming.Decl.Attributes,
3258 In_Tree => In_Tree);
3259 Separate_Suffix : File_Name_Type := No_File;
3261 Lang_Id : Language_Index;
3263 -- Check attribute Dot_Replacement
3265 if not Dot_Repl.Default then
3266 Get_Name_String (Dot_Repl.Value);
3268 if Name_Len = 0 then
3271 "Dot_Replacement cannot be empty",
3275 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3276 Dot_Replacement := Name_Find;
3278 if Current_Verbosity = High then
3279 Write_Str (" Dot_Replacement = """);
3280 Write_Str (Get_Name_String (Dot_Replacement));
3287 -- Check attribute Casing
3289 if not Casing_String.Default then
3291 Casing_Image : constant String :=
3292 Get_Name_String (Casing_String.Value);
3295 Casing_Value : constant Casing_Type :=
3296 Value (Casing_Image);
3298 Casing := Casing_Value;
3299 Casing_Defined := True;
3301 if Current_Verbosity = High then
3302 Write_Str (" Casing = ");
3303 Write_Str (Image (Casing));
3310 when Constraint_Error =>
3311 if Casing_Image'Length = 0 then
3314 "Casing cannot be an empty string",
3315 Casing_String.Location);
3318 Name_Len := Casing_Image'Length;
3319 Name_Buffer (1 .. Name_Len) := Casing_Image;
3320 Err_Vars.Error_Msg_Name_1 := Name_Find;
3323 "%% is not a correct Casing",
3324 Casing_String.Location);
3329 if not Sep_Suffix.Default then
3330 Get_Name_String (Sep_Suffix.Value);
3332 if Name_Len = 0 then
3335 "Separate_Suffix cannot be empty",
3336 Sep_Suffix.Location);
3339 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3340 Separate_Suffix := Name_Find;
3342 if Current_Verbosity = High then
3343 Write_Str (" Separate_Suffix = """);
3344 Write_Str (Get_Name_String (Separate_Suffix));
3351 -- For all unit based languages, if any, set the specified
3352 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3354 if Dot_Replacement /= No_File
3355 or else Casing_Defined
3356 or else Separate_Suffix /= No_File
3358 Lang_Id := Data.First_Language_Processing;
3359 while Lang_Id /= No_Language_Index loop
3360 if In_Tree.Languages_Data.Table
3361 (Lang_Id).Config.Kind = Unit_Based
3363 if Dot_Replacement /= No_File then
3364 In_Tree.Languages_Data.Table
3365 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3369 if Casing_Defined then
3370 In_Tree.Languages_Data.Table
3371 (Lang_Id).Config.Naming_Data.Casing := Casing;
3374 if Separate_Suffix /= No_File then
3375 In_Tree.Languages_Data.Table
3376 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3382 In_Tree.Languages_Data.Table (Lang_Id).Next;
3387 -- Next, get the spec and body suffixes
3390 Suffix : Variable_Value;
3391 Lang_Id : Language_Index;
3395 Lang_Id := Data.First_Language_Processing;
3396 while Lang_Id /= No_Language_Index loop
3397 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3403 Attribute_Or_Array_Name => Name_Spec_Suffix,
3404 In_Package => Naming_Id,
3405 In_Tree => In_Tree);
3407 if Suffix = Nil_Variable_Value then
3410 Attribute_Or_Array_Name => Name_Specification_Suffix,
3411 In_Package => Naming_Id,
3412 In_Tree => In_Tree);
3415 if Suffix /= Nil_Variable_Value then
3416 In_Tree.Languages_Data.Table (Lang_Id).
3417 Config.Naming_Data.Spec_Suffix :=
3418 File_Name_Type (Suffix.Value);
3425 Attribute_Or_Array_Name => Name_Body_Suffix,
3426 In_Package => Naming_Id,
3427 In_Tree => In_Tree);
3429 if Suffix = Nil_Variable_Value then
3432 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3433 In_Package => Naming_Id,
3434 In_Tree => In_Tree);
3437 if Suffix /= Nil_Variable_Value then
3438 In_Tree.Languages_Data.Table (Lang_Id).
3439 Config.Naming_Data.Body_Suffix :=
3440 File_Name_Type (Suffix.Value);
3443 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3447 -- Get the exceptions for file based languages
3449 Get_Exceptions (Spec);
3450 Get_Exceptions (Impl);
3452 -- Get the exceptions for unit based languages
3454 Get_Unit_Exceptions (Spec);
3455 Get_Unit_Exceptions (Impl);
3459 end Check_Naming_Schemes;
3461 ------------------------------
3462 -- Check_Library_Attributes --
3463 ------------------------------
3465 procedure Check_Library_Attributes
3466 (Project : Project_Id;
3467 In_Tree : Project_Tree_Ref;
3468 Current_Dir : String;
3469 Data : in out Project_Data)
3471 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3473 Lib_Dir : constant Prj.Variable_Value :=
3475 (Snames.Name_Library_Dir, Attributes, In_Tree);
3477 Lib_Name : constant Prj.Variable_Value :=
3479 (Snames.Name_Library_Name, Attributes, In_Tree);
3481 Lib_Version : constant Prj.Variable_Value :=
3483 (Snames.Name_Library_Version, Attributes, In_Tree);
3485 Lib_ALI_Dir : constant Prj.Variable_Value :=
3487 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3489 The_Lib_Kind : constant Prj.Variable_Value :=
3491 (Snames.Name_Library_Kind, Attributes, In_Tree);
3493 Imported_Project_List : Project_List := Empty_Project_List;
3495 Continuation : String_Access := No_Continuation_String'Access;
3497 Support_For_Libraries : Library_Support;
3499 Library_Directory_Present : Boolean;
3501 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3502 -- Check if an imported or extended project if also a library project
3508 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3509 Proj_Data : Project_Data;
3514 if Proj /= No_Project then
3515 Proj_Data := In_Tree.Projects.Table (Proj);
3517 if not Proj_Data.Library then
3519 -- The only not library projects that are OK are those that
3520 -- have no sources. However, header files from non-Ada
3521 -- languages are OK, as there is nothing to compile.
3523 Src_Id := Proj_Data.First_Source;
3524 while Src_Id /= No_Source loop
3525 Src := In_Tree.Sources.Table (Src_Id);
3527 exit when Src.Lang_Kind /= File_Based
3528 or else Src.Kind /= Spec;
3530 Src_Id := Src.Next_In_Project;
3533 if Src_Id /= No_Source then
3534 Error_Msg_Name_1 := Data.Name;
3535 Error_Msg_Name_2 := Proj_Data.Name;
3538 if Data.Library_Kind /= Static then
3542 "shared library project %% cannot extend " &
3543 "project %% that is not a library project",
3545 Continuation := Continuation_String'Access;
3548 elsif Data.Library_Kind /= Static then
3552 "shared library project %% cannot import project %% " &
3553 "that is not a shared library project",
3555 Continuation := Continuation_String'Access;
3559 elsif Data.Library_Kind /= Static and then
3560 Proj_Data.Library_Kind = Static
3562 Error_Msg_Name_1 := Data.Name;
3563 Error_Msg_Name_2 := Proj_Data.Name;
3569 "shared library project %% cannot extend static " &
3570 "library project %%",
3577 "shared library project %% cannot import static " &
3578 "library project %%",
3582 Continuation := Continuation_String'Access;
3587 -- Start of processing for Check_Library_Attributes
3590 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3592 -- Special case of extending project
3594 if Data.Extends /= No_Project then
3596 Extended_Data : constant Project_Data :=
3597 In_Tree.Projects.Table (Data.Extends);
3600 -- If the project extended is a library project, we inherit the
3601 -- library name, if it is not redefined; we check that the library
3602 -- directory is specified.
3604 if Extended_Data.Library then
3605 if Data.Qualifier = Standard then
3608 "a standard project cannot extend a library project",
3612 if Lib_Name.Default then
3613 Data.Library_Name := Extended_Data.Library_Name;
3616 if Lib_Dir.Default then
3617 if not Data.Virtual then
3620 "a project extending a library project must " &
3621 "specify an attribute Library_Dir",
3625 -- For a virtual project extending a library project,
3626 -- inherit library directory.
3628 Data.Library_Dir := Extended_Data.Library_Dir;
3629 Library_Directory_Present := True;
3637 pragma Assert (Lib_Name.Kind = Single);
3639 if Lib_Name.Value = Empty_String then
3640 if Current_Verbosity = High
3641 and then Data.Library_Name = No_Name
3643 Write_Line ("No library name");
3647 -- There is no restriction on the syntax of library names
3649 Data.Library_Name := Lib_Name.Value;
3652 if Data.Library_Name /= No_Name then
3653 if Current_Verbosity = High then
3654 Write_Str ("Library name = """);
3655 Write_Str (Get_Name_String (Data.Library_Name));
3659 pragma Assert (Lib_Dir.Kind = Single);
3661 if not Library_Directory_Present then
3662 if Current_Verbosity = High then
3663 Write_Line ("No library directory");
3667 -- Find path name (unless inherited), check that it is a directory
3669 if Data.Library_Dir = No_Path_Information then
3673 File_Name_Type (Lib_Dir.Value),
3674 Data.Directory.Display_Name,
3675 Data.Library_Dir.Name,
3676 Data.Library_Dir.Display_Name,
3677 Create => "library",
3678 Current_Dir => Current_Dir,
3679 Location => Lib_Dir.Location);
3682 if Data.Library_Dir = No_Path_Information then
3684 -- Get the absolute name of the library directory that
3685 -- does not exist, to report an error.
3688 Dir_Name : constant String :=
3689 Get_Name_String (Lib_Dir.Value);
3692 if Is_Absolute_Path (Dir_Name) then
3693 Err_Vars.Error_Msg_File_1 :=
3694 File_Name_Type (Lib_Dir.Value);
3697 Get_Name_String (Data.Directory.Display_Name);
3699 if Name_Buffer (Name_Len) /= Directory_Separator then
3700 Name_Len := Name_Len + 1;
3701 Name_Buffer (Name_Len) := Directory_Separator;
3705 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3707 Name_Len := Name_Len + Dir_Name'Length;
3708 Err_Vars.Error_Msg_File_1 := Name_Find;
3715 "library directory { does not exist",
3719 -- The library directory cannot be the same as the Object
3722 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3725 "library directory cannot be the same " &
3726 "as object directory",
3728 Data.Library_Dir := No_Path_Information;
3732 OK : Boolean := True;
3733 Dirs_Id : String_List_Id;
3734 Dir_Elem : String_Element;
3737 -- The library directory cannot be the same as a source
3738 -- directory of the current project.
3740 Dirs_Id := Data.Source_Dirs;
3741 while Dirs_Id /= Nil_String loop
3742 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3743 Dirs_Id := Dir_Elem.Next;
3746 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3748 Err_Vars.Error_Msg_File_1 :=
3749 File_Name_Type (Dir_Elem.Value);
3752 "library directory cannot be the same " &
3753 "as source directory {",
3762 -- The library directory cannot be the same as a source
3763 -- directory of another project either.
3766 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3767 if Pid /= Project then
3768 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3770 Dir_Loop : while Dirs_Id /= Nil_String loop
3772 In_Tree.String_Elements.Table (Dirs_Id);
3773 Dirs_Id := Dir_Elem.Next;
3775 if Data.Library_Dir.Name =
3776 Path_Name_Type (Dir_Elem.Value)
3778 Err_Vars.Error_Msg_File_1 :=
3779 File_Name_Type (Dir_Elem.Value);
3780 Err_Vars.Error_Msg_Name_1 :=
3781 In_Tree.Projects.Table (Pid).Name;
3785 "library directory cannot be the same " &
3786 "as source directory { of project %%",
3793 end loop Project_Loop;
3797 Data.Library_Dir := No_Path_Information;
3799 elsif Current_Verbosity = High then
3801 -- Display the Library directory in high verbosity
3803 Write_Str ("Library directory =""");
3805 (Get_Name_String (Data.Library_Dir.Display_Name));
3815 Data.Library_Dir /= No_Path_Information
3817 Data.Library_Name /= No_Name;
3819 if Data.Extends = No_Project then
3820 case Data.Qualifier is
3822 if Data.Library then
3825 "a standard project cannot be a library project",
3830 if not Data.Library then
3833 "not a library project",
3843 if Data.Library then
3844 if Get_Mode = Multi_Language then
3845 Support_For_Libraries := Data.Config.Lib_Support;
3848 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3851 if Support_For_Libraries = Prj.None then
3854 "?libraries are not supported on this platform",
3856 Data.Library := False;
3859 if Lib_ALI_Dir.Value = Empty_String then
3860 if Current_Verbosity = High then
3861 Write_Line ("No library ALI directory specified");
3863 Data.Library_ALI_Dir := Data.Library_Dir;
3866 -- Find path name, check that it is a directory
3871 File_Name_Type (Lib_ALI_Dir.Value),
3872 Data.Directory.Display_Name,
3873 Data.Library_ALI_Dir.Name,
3874 Data.Library_ALI_Dir.Display_Name,
3875 Create => "library ALI",
3876 Current_Dir => Current_Dir,
3877 Location => Lib_ALI_Dir.Location);
3879 if Data.Library_ALI_Dir = No_Path_Information then
3881 -- Get the absolute name of the library ALI directory that
3882 -- does not exist, to report an error.
3885 Dir_Name : constant String :=
3886 Get_Name_String (Lib_ALI_Dir.Value);
3889 if Is_Absolute_Path (Dir_Name) then
3890 Err_Vars.Error_Msg_File_1 :=
3891 File_Name_Type (Lib_Dir.Value);
3894 Get_Name_String (Data.Directory.Display_Name);
3896 if Name_Buffer (Name_Len) /= Directory_Separator then
3897 Name_Len := Name_Len + 1;
3898 Name_Buffer (Name_Len) := Directory_Separator;
3902 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3904 Name_Len := Name_Len + Dir_Name'Length;
3905 Err_Vars.Error_Msg_File_1 := Name_Find;
3912 "library 'A'L'I directory { does not exist",
3913 Lib_ALI_Dir.Location);
3917 if Data.Library_ALI_Dir /= Data.Library_Dir then
3919 -- The library ALI directory cannot be the same as the
3920 -- Object directory.
3922 if Data.Library_ALI_Dir = Data.Object_Directory then
3925 "library 'A'L'I directory cannot be the same " &
3926 "as object directory",
3927 Lib_ALI_Dir.Location);
3928 Data.Library_ALI_Dir := No_Path_Information;
3932 OK : Boolean := True;
3933 Dirs_Id : String_List_Id;
3934 Dir_Elem : String_Element;
3937 -- The library ALI directory cannot be the same as
3938 -- a source directory of the current project.
3940 Dirs_Id := Data.Source_Dirs;
3941 while Dirs_Id /= Nil_String loop
3942 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3943 Dirs_Id := Dir_Elem.Next;
3945 if Data.Library_ALI_Dir.Name =
3946 Path_Name_Type (Dir_Elem.Value)
3948 Err_Vars.Error_Msg_File_1 :=
3949 File_Name_Type (Dir_Elem.Value);
3952 "library 'A'L'I directory cannot be " &
3953 "the same as source directory {",
3954 Lib_ALI_Dir.Location);
3962 -- The library ALI directory cannot be the same as
3963 -- a source directory of another project either.
3967 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
3969 if Pid /= Project then
3971 In_Tree.Projects.Table (Pid).Source_Dirs;
3974 while Dirs_Id /= Nil_String loop
3976 In_Tree.String_Elements.Table (Dirs_Id);
3977 Dirs_Id := Dir_Elem.Next;
3979 if Data.Library_ALI_Dir.Name =
3980 Path_Name_Type (Dir_Elem.Value)
3982 Err_Vars.Error_Msg_File_1 :=
3983 File_Name_Type (Dir_Elem.Value);
3984 Err_Vars.Error_Msg_Name_1 :=
3985 In_Tree.Projects.Table (Pid).Name;
3989 "library 'A'L'I directory cannot " &
3990 "be the same as source directory " &
3992 Lib_ALI_Dir.Location);
3994 exit ALI_Project_Loop;
3996 end loop ALI_Dir_Loop;
3998 end loop ALI_Project_Loop;
4002 Data.Library_ALI_Dir := No_Path_Information;
4004 elsif Current_Verbosity = High then
4006 -- Display the Library ALI directory in high
4009 Write_Str ("Library ALI directory =""");
4012 (Data.Library_ALI_Dir.Display_Name));
4020 pragma Assert (Lib_Version.Kind = Single);
4022 if Lib_Version.Value = Empty_String then
4023 if Current_Verbosity = High then
4024 Write_Line ("No library version specified");
4028 Data.Lib_Internal_Name := Lib_Version.Value;
4031 pragma Assert (The_Lib_Kind.Kind = Single);
4033 if The_Lib_Kind.Value = Empty_String then
4034 if Current_Verbosity = High then
4035 Write_Line ("No library kind specified");
4039 Get_Name_String (The_Lib_Kind.Value);
4042 Kind_Name : constant String :=
4043 To_Lower (Name_Buffer (1 .. Name_Len));
4045 OK : Boolean := True;
4048 if Kind_Name = "static" then
4049 Data.Library_Kind := Static;
4051 elsif Kind_Name = "dynamic" then
4052 Data.Library_Kind := Dynamic;
4054 elsif Kind_Name = "relocatable" then
4055 Data.Library_Kind := Relocatable;
4060 "illegal value for Library_Kind",
4061 The_Lib_Kind.Location);
4065 if Current_Verbosity = High and then OK then
4066 Write_Str ("Library kind = ");
4067 Write_Line (Kind_Name);
4070 if Data.Library_Kind /= Static and then
4071 Support_For_Libraries = Prj.Static_Only
4075 "only static libraries are supported " &
4077 The_Lib_Kind.Location);
4078 Data.Library := False;
4083 if Data.Library then
4084 if Current_Verbosity = High then
4085 Write_Line ("This is a library project file");
4088 if Get_Mode = Multi_Language then
4089 Check_Library (Data.Extends, Extends => True);
4091 Imported_Project_List := Data.Imported_Projects;
4092 while Imported_Project_List /= Empty_Project_List loop
4094 (In_Tree.Project_Lists.Table
4095 (Imported_Project_List).Project,
4097 Imported_Project_List :=
4098 In_Tree.Project_Lists.Table
4099 (Imported_Project_List).Next;
4107 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4108 -- Warn if they are declared, as it is a common error to think that
4109 -- library are "linked" with Linker switches.
4111 if Data.Library then
4113 Linker_Package_Id : constant Package_Id :=
4114 Util.Value_Of (Name_Linker, Data.Decl.Packages, In_Tree);
4115 Linker_Package : Package_Element;
4116 Switches : Array_Element_Id := No_Array_Element;
4119 if Linker_Package_Id /= No_Package then
4120 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4124 (Name => Name_Switches,
4125 In_Arrays => Linker_Package.Decl.Arrays,
4126 In_Tree => In_Tree);
4128 if Switches = No_Array_Element then
4131 (Name => Name_Default_Switches,
4132 In_Arrays => Linker_Package.Decl.Arrays,
4133 In_Tree => In_Tree);
4136 if Switches /= No_Array_Element then
4139 "?Linker switches not taken into account in library " &
4147 if Data.Extends /= No_Project then
4148 In_Tree.Projects.Table (Data.Extends).Library := False;
4150 end Check_Library_Attributes;
4152 --------------------------
4153 -- Check_Package_Naming --
4154 --------------------------
4156 procedure Check_Package_Naming
4157 (Project : Project_Id;
4158 In_Tree : Project_Tree_Ref;
4159 Data : in out Project_Data)
4161 Naming_Id : constant Package_Id :=
4162 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4164 Naming : Package_Element;
4167 -- If there is a package Naming, we will put in Data.Naming
4168 -- what is in this package Naming.
4170 if Naming_Id /= No_Package then
4171 Naming := In_Tree.Packages.Table (Naming_Id);
4173 if Current_Verbosity = High then
4174 Write_Line ("Checking ""Naming"".");
4177 -- Check Spec_Suffix
4180 Spec_Suffixs : Array_Element_Id :=
4186 Suffix : Array_Element_Id;
4187 Element : Array_Element;
4188 Suffix2 : Array_Element_Id;
4191 -- If some suffixes have been specified, we make sure that
4192 -- for each language for which a default suffix has been
4193 -- specified, there is a suffix specified, either the one
4194 -- in the project file or if there were none, the default.
4196 if Spec_Suffixs /= No_Array_Element then
4197 Suffix := Data.Naming.Spec_Suffix;
4199 while Suffix /= No_Array_Element loop
4201 In_Tree.Array_Elements.Table (Suffix);
4202 Suffix2 := Spec_Suffixs;
4204 while Suffix2 /= No_Array_Element loop
4205 exit when In_Tree.Array_Elements.Table
4206 (Suffix2).Index = Element.Index;
4207 Suffix2 := In_Tree.Array_Elements.Table
4211 -- There is a registered default suffix, but no
4212 -- suffix specified in the project file.
4213 -- Add the default to the array.
4215 if Suffix2 = No_Array_Element then
4216 Array_Element_Table.Increment_Last
4217 (In_Tree.Array_Elements);
4218 In_Tree.Array_Elements.Table
4219 (Array_Element_Table.Last
4220 (In_Tree.Array_Elements)) :=
4221 (Index => Element.Index,
4222 Src_Index => Element.Src_Index,
4223 Index_Case_Sensitive => False,
4224 Value => Element.Value,
4225 Next => Spec_Suffixs);
4226 Spec_Suffixs := Array_Element_Table.Last
4227 (In_Tree.Array_Elements);
4230 Suffix := Element.Next;
4233 -- Put the resulting array as the specification suffixes
4235 Data.Naming.Spec_Suffix := Spec_Suffixs;
4240 Current : Array_Element_Id;
4241 Element : Array_Element;
4244 Current := Data.Naming.Spec_Suffix;
4245 while Current /= No_Array_Element loop
4246 Element := In_Tree.Array_Elements.Table (Current);
4247 Get_Name_String (Element.Value.Value);
4249 if Name_Len = 0 then
4252 "Spec_Suffix cannot be empty",
4253 Element.Value.Location);
4256 In_Tree.Array_Elements.Table (Current) := Element;
4257 Current := Element.Next;
4261 -- Check Body_Suffix
4264 Impl_Suffixs : Array_Element_Id :=
4270 Suffix : Array_Element_Id;
4271 Element : Array_Element;
4272 Suffix2 : Array_Element_Id;
4275 -- If some suffixes have been specified, we make sure that
4276 -- for each language for which a default suffix has been
4277 -- specified, there is a suffix specified, either the one
4278 -- in the project file or if there were none, the default.
4280 if Impl_Suffixs /= No_Array_Element then
4281 Suffix := Data.Naming.Body_Suffix;
4282 while Suffix /= No_Array_Element loop
4284 In_Tree.Array_Elements.Table (Suffix);
4286 Suffix2 := Impl_Suffixs;
4287 while Suffix2 /= No_Array_Element loop
4288 exit when In_Tree.Array_Elements.Table
4289 (Suffix2).Index = Element.Index;
4290 Suffix2 := In_Tree.Array_Elements.Table
4294 -- There is a registered default suffix, but no suffix was
4295 -- specified in the project file. Add default to the array.
4297 if Suffix2 = No_Array_Element then
4298 Array_Element_Table.Increment_Last
4299 (In_Tree.Array_Elements);
4300 In_Tree.Array_Elements.Table
4301 (Array_Element_Table.Last
4302 (In_Tree.Array_Elements)) :=
4303 (Index => Element.Index,
4304 Src_Index => Element.Src_Index,
4305 Index_Case_Sensitive => False,
4306 Value => Element.Value,
4307 Next => Impl_Suffixs);
4308 Impl_Suffixs := Array_Element_Table.Last
4309 (In_Tree.Array_Elements);
4312 Suffix := Element.Next;
4315 -- Put the resulting array as the implementation suffixes
4317 Data.Naming.Body_Suffix := Impl_Suffixs;
4322 Current : Array_Element_Id;
4323 Element : Array_Element;
4326 Current := Data.Naming.Body_Suffix;
4327 while Current /= No_Array_Element loop
4328 Element := In_Tree.Array_Elements.Table (Current);
4329 Get_Name_String (Element.Value.Value);
4331 if Name_Len = 0 then
4334 "Body_Suffix cannot be empty",
4335 Element.Value.Location);
4338 In_Tree.Array_Elements.Table (Current) := Element;
4339 Current := Element.Next;
4343 -- Get the exceptions, if any
4345 Data.Naming.Specification_Exceptions :=
4347 (Name_Specification_Exceptions,
4348 In_Arrays => Naming.Decl.Arrays,
4349 In_Tree => In_Tree);
4351 Data.Naming.Implementation_Exceptions :=
4353 (Name_Implementation_Exceptions,
4354 In_Arrays => Naming.Decl.Arrays,
4355 In_Tree => In_Tree);
4357 end Check_Package_Naming;
4359 ---------------------------------
4360 -- Check_Programming_Languages --
4361 ---------------------------------
4363 procedure Check_Programming_Languages
4364 (In_Tree : Project_Tree_Ref;
4365 Project : Project_Id;
4366 Data : in out Project_Data)
4368 Languages : Variable_Value := Nil_Variable_Value;
4369 Def_Lang : Variable_Value := Nil_Variable_Value;
4370 Def_Lang_Id : Name_Id;
4373 Data.First_Language_Processing := No_Language_Index;
4375 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4378 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4379 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4380 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4382 if Data.Source_Dirs /= Nil_String then
4384 -- Check if languages are specified in this project
4386 if Languages.Default then
4388 -- Attribute Languages is not specified. So, it defaults to
4389 -- a project of the default language only.
4391 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4392 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4394 -- In Ada_Only mode, the default language is Ada
4396 if Get_Mode = Ada_Only then
4397 In_Tree.Name_Lists.Table (Data.Languages) :=
4398 (Name => Name_Ada, Next => No_Name_List);
4400 -- Attribute Languages is not specified. So, it defaults to
4401 -- a project of language Ada only. No sources of languages
4404 Data.Other_Sources_Present := False;
4407 -- Fail if there is no default language defined
4409 if Def_Lang.Default then
4410 if not Default_Language_Is_Ada then
4414 "no languages defined for this project",
4416 Def_Lang_Id := No_Name;
4418 Def_Lang_Id := Name_Ada;
4422 Get_Name_String (Def_Lang.Value);
4423 To_Lower (Name_Buffer (1 .. Name_Len));
4424 Def_Lang_Id := Name_Find;
4427 if Def_Lang_Id /= No_Name then
4428 In_Tree.Name_Lists.Table (Data.Languages) :=
4429 (Name => Def_Lang_Id, Next => No_Name_List);
4431 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4433 Data.First_Language_Processing :=
4434 Language_Data_Table.Last (In_Tree.Languages_Data);
4435 In_Tree.Languages_Data.Table
4436 (Data.First_Language_Processing) := No_Language_Data;
4437 In_Tree.Languages_Data.Table
4438 (Data.First_Language_Processing).Name := Def_Lang_Id;
4439 Get_Name_String (Def_Lang_Id);
4440 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4441 In_Tree.Languages_Data.Table
4442 (Data.First_Language_Processing).Display_Name := Name_Find;
4444 if Def_Lang_Id = Name_Ada then
4445 In_Tree.Languages_Data.Table
4446 (Data.First_Language_Processing).Config.Kind
4448 In_Tree.Languages_Data.Table
4449 (Data.First_Language_Processing).Config.Dependency_Kind
4451 Data.Unit_Based_Language_Name := Name_Ada;
4452 Data.Unit_Based_Language_Index :=
4453 Data.First_Language_Processing;
4455 In_Tree.Languages_Data.Table
4456 (Data.First_Language_Processing).Config.Kind
4464 Current : String_List_Id := Languages.Values;
4465 Element : String_Element;
4466 Lang_Name : Name_Id;
4467 Index : Language_Index;
4468 Lang_Data : Language_Data;
4469 NL_Id : Name_List_Index := No_Name_List;
4472 -- Assume there are no language declared
4474 Data.Ada_Sources_Present := False;
4475 Data.Other_Sources_Present := False;
4477 -- If there are no languages declared, there are no sources
4479 if Current = Nil_String then
4480 Data.Source_Dirs := Nil_String;
4482 if Data.Qualifier = Standard then
4486 "a standard project cannot have no language declared",
4487 Languages.Location);
4491 -- Look through all the languages specified in attribute
4494 while Current /= Nil_String loop
4496 In_Tree.String_Elements.Table (Current);
4497 Get_Name_String (Element.Value);
4498 To_Lower (Name_Buffer (1 .. Name_Len));
4499 Lang_Name := Name_Find;
4501 NL_Id := Data.Languages;
4502 while NL_Id /= No_Name_List loop
4504 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4505 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4508 if NL_Id = No_Name_List then
4509 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4511 if Data.Languages = No_Name_List then
4513 Name_List_Table.Last (In_Tree.Name_Lists);
4516 NL_Id := Data.Languages;
4517 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4520 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4523 In_Tree.Name_Lists.Table (NL_Id).Next :=
4524 Name_List_Table.Last (In_Tree.Name_Lists);
4527 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4528 In_Tree.Name_Lists.Table (NL_Id) :=
4529 (Lang_Name, No_Name_List);
4531 if Get_Mode = Ada_Only then
4532 -- Check for language Ada
4534 if Lang_Name = Name_Ada then
4535 Data.Ada_Sources_Present := True;
4538 Data.Other_Sources_Present := True;
4542 Language_Data_Table.Increment_Last
4543 (In_Tree.Languages_Data);
4545 Language_Data_Table.Last (In_Tree.Languages_Data);
4546 Lang_Data.Name := Lang_Name;
4547 Lang_Data.Display_Name := Element.Value;
4548 Lang_Data.Next := Data.First_Language_Processing;
4550 if Lang_Name = Name_Ada then
4551 Lang_Data.Config.Kind := Unit_Based;
4552 Lang_Data.Config.Dependency_Kind := ALI_File;
4553 Data.Unit_Based_Language_Name := Name_Ada;
4554 Data.Unit_Based_Language_Index := Index;
4557 Lang_Data.Config.Kind := File_Based;
4558 Lang_Data.Config.Dependency_Kind := None;
4561 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4562 Data.First_Language_Processing := Index;
4566 Current := Element.Next;
4572 end Check_Programming_Languages;
4578 function Check_Project
4580 Root_Project : Project_Id;
4581 In_Tree : Project_Tree_Ref;
4582 Extending : Boolean) return Boolean
4585 if P = Root_Project then
4588 elsif Extending then
4590 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4593 while Data.Extends /= No_Project loop
4594 if P = Data.Extends then
4598 Data := In_Tree.Projects.Table (Data.Extends);
4606 -------------------------------
4607 -- Check_Stand_Alone_Library --
4608 -------------------------------
4610 procedure Check_Stand_Alone_Library
4611 (Project : Project_Id;
4612 In_Tree : Project_Tree_Ref;
4613 Data : in out Project_Data;
4614 Current_Dir : String;
4615 Extending : Boolean)
4617 Lib_Interfaces : constant Prj.Variable_Value :=
4619 (Snames.Name_Library_Interface,
4620 Data.Decl.Attributes,
4623 Lib_Auto_Init : constant Prj.Variable_Value :=
4625 (Snames.Name_Library_Auto_Init,
4626 Data.Decl.Attributes,
4629 Lib_Src_Dir : constant Prj.Variable_Value :=
4631 (Snames.Name_Library_Src_Dir,
4632 Data.Decl.Attributes,
4635 Lib_Symbol_File : constant Prj.Variable_Value :=
4637 (Snames.Name_Library_Symbol_File,
4638 Data.Decl.Attributes,
4641 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4643 (Snames.Name_Library_Symbol_Policy,
4644 Data.Decl.Attributes,
4647 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4649 (Snames.Name_Library_Reference_Symbol_File,
4650 Data.Decl.Attributes,
4653 Auto_Init_Supported : Boolean;
4654 OK : Boolean := True;
4656 Next_Proj : Project_Id;
4659 if Get_Mode = Multi_Language then
4660 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4662 Auto_Init_Supported :=
4663 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4666 pragma Assert (Lib_Interfaces.Kind = List);
4668 -- It is a stand-alone library project file if attribute
4669 -- Library_Interface is defined.
4671 if not Lib_Interfaces.Default then
4672 SAL_Library : declare
4673 Interfaces : String_List_Id := Lib_Interfaces.Values;
4674 Interface_ALIs : String_List_Id := Nil_String;
4676 The_Unit_Id : Unit_Index;
4677 The_Unit_Data : Unit_Data;
4679 procedure Add_ALI_For (Source : File_Name_Type);
4680 -- Add an ALI file name to the list of Interface ALIs
4686 procedure Add_ALI_For (Source : File_Name_Type) is
4688 Get_Name_String (Source);
4691 ALI : constant String :=
4692 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4693 ALI_Name_Id : Name_Id;
4696 Name_Len := ALI'Length;
4697 Name_Buffer (1 .. Name_Len) := ALI;
4698 ALI_Name_Id := Name_Find;
4700 String_Element_Table.Increment_Last
4701 (In_Tree.String_Elements);
4702 In_Tree.String_Elements.Table
4703 (String_Element_Table.Last
4704 (In_Tree.String_Elements)) :=
4705 (Value => ALI_Name_Id,
4707 Display_Value => ALI_Name_Id,
4709 In_Tree.String_Elements.Table
4710 (Interfaces).Location,
4712 Next => Interface_ALIs);
4713 Interface_ALIs := String_Element_Table.Last
4714 (In_Tree.String_Elements);
4718 -- Start of processing for SAL_Library
4721 Data.Standalone_Library := True;
4723 -- Library_Interface cannot be an empty list
4725 if Interfaces = Nil_String then
4728 "Library_Interface cannot be an empty list",
4729 Lib_Interfaces.Location);
4732 -- Process each unit name specified in the attribute
4733 -- Library_Interface.
4735 while Interfaces /= Nil_String loop
4737 (In_Tree.String_Elements.Table (Interfaces).Value);
4738 To_Lower (Name_Buffer (1 .. Name_Len));
4740 if Name_Len = 0 then
4743 "an interface cannot be an empty string",
4744 In_Tree.String_Elements.Table (Interfaces).Location);
4748 Error_Msg_Name_1 := Unit;
4750 if Get_Mode = Ada_Only then
4752 Units_Htable.Get (In_Tree.Units_HT, Unit);
4754 if The_Unit_Id = No_Unit_Index then
4758 In_Tree.String_Elements.Table
4759 (Interfaces).Location);
4762 -- Check that the unit is part of the project
4765 In_Tree.Units.Table (The_Unit_Id);
4767 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4768 and then The_Unit_Data.File_Names
4769 (Body_Part).Path.Name /= Slash
4772 (The_Unit_Data.File_Names (Body_Part).Project,
4773 Project, In_Tree, Extending)
4775 -- There is a body for this unit.
4776 -- If there is no spec, we need to check
4777 -- that it is not a subunit.
4779 if The_Unit_Data.File_Names
4780 (Specification).Name = No_File
4783 Src_Ind : Source_File_Index;
4786 Src_Ind := Sinput.P.Load_Project_File
4788 (The_Unit_Data.File_Names
4789 (Body_Part).Path.Name));
4791 if Sinput.P.Source_File_Is_Subunit
4796 "%% is a subunit; " &
4797 "it cannot be an interface",
4799 String_Elements.Table
4800 (Interfaces).Location);
4805 -- The unit is not a subunit, so we add
4806 -- to the Interface ALIs the ALI file
4807 -- corresponding to the body.
4810 (The_Unit_Data.File_Names (Body_Part).Name);
4815 "%% is not an unit of this project",
4816 In_Tree.String_Elements.Table
4817 (Interfaces).Location);
4820 elsif The_Unit_Data.File_Names
4821 (Specification).Name /= No_File
4822 and then The_Unit_Data.File_Names
4823 (Specification).Path.Name /= Slash
4824 and then Check_Project
4825 (The_Unit_Data.File_Names
4826 (Specification).Project,
4827 Project, In_Tree, Extending)
4830 -- The unit is part of the project, it has
4831 -- a spec, but no body. We add to the Interface
4832 -- ALIs the ALI file corresponding to the spec.
4835 (The_Unit_Data.File_Names (Specification).Name);
4840 "%% is not an unit of this project",
4841 In_Tree.String_Elements.Table
4842 (Interfaces).Location);
4847 -- Multi_Language mode
4849 Next_Proj := Data.Extends;
4850 Source := Data.First_Source;
4853 while Source /= No_Source and then
4854 In_Tree.Sources.Table (Source).Unit /= Unit
4857 In_Tree.Sources.Table (Source).Next_In_Project;
4860 exit when Source /= No_Source or else
4861 Next_Proj = No_Project;
4864 In_Tree.Projects.Table (Next_Proj).First_Source;
4866 In_Tree.Projects.Table (Next_Proj).Extends;
4869 if Source /= No_Source then
4870 if In_Tree.Sources.Table (Source).Kind = Sep then
4871 Source := No_Source;
4873 elsif In_Tree.Sources.Table (Source).Kind = Spec
4875 In_Tree.Sources.Table (Source).Other_Part /=
4878 Source := In_Tree.Sources.Table (Source).Other_Part;
4882 if Source /= No_Source then
4883 if In_Tree.Sources.Table (Source).Project /= Project
4887 In_Tree.Sources.Table (Source).Project,
4890 Source := No_Source;
4894 if Source = No_Source then
4897 "%% is not an unit of this project",
4898 In_Tree.String_Elements.Table
4899 (Interfaces).Location);
4902 if In_Tree.Sources.Table (Source).Kind = Spec and then
4903 In_Tree.Sources.Table (Source).Other_Part /=
4906 Source := In_Tree.Sources.Table (Source).Other_Part;
4909 String_Element_Table.Increment_Last
4910 (In_Tree.String_Elements);
4911 In_Tree.String_Elements.Table
4912 (String_Element_Table.Last
4913 (In_Tree.String_Elements)) :=
4915 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4918 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4920 In_Tree.String_Elements.Table
4921 (Interfaces).Location,
4923 Next => Interface_ALIs);
4924 Interface_ALIs := String_Element_Table.Last
4925 (In_Tree.String_Elements);
4933 In_Tree.String_Elements.Table (Interfaces).Next;
4936 -- Put the list of Interface ALIs in the project data
4938 Data.Lib_Interface_ALIs := Interface_ALIs;
4940 -- Check value of attribute Library_Auto_Init and set
4941 -- Lib_Auto_Init accordingly.
4943 if Lib_Auto_Init.Default then
4945 -- If no attribute Library_Auto_Init is declared, then set auto
4946 -- init only if it is supported.
4948 Data.Lib_Auto_Init := Auto_Init_Supported;
4951 Get_Name_String (Lib_Auto_Init.Value);
4952 To_Lower (Name_Buffer (1 .. Name_Len));
4954 if Name_Buffer (1 .. Name_Len) = "false" then
4955 Data.Lib_Auto_Init := False;
4957 elsif Name_Buffer (1 .. Name_Len) = "true" then
4958 if Auto_Init_Supported then
4959 Data.Lib_Auto_Init := True;
4962 -- Library_Auto_Init cannot be "true" if auto init is not
4967 "library auto init not supported " &
4969 Lib_Auto_Init.Location);
4975 "invalid value for attribute Library_Auto_Init",
4976 Lib_Auto_Init.Location);
4981 -- If attribute Library_Src_Dir is defined and not the empty string,
4982 -- check if the directory exist and is not the object directory or
4983 -- one of the source directories. This is the directory where copies
4984 -- of the interface sources will be copied. Note that this directory
4985 -- may be the library directory.
4987 if Lib_Src_Dir.Value /= Empty_String then
4989 Dir_Id : constant File_Name_Type :=
4990 File_Name_Type (Lib_Src_Dir.Value);
4997 Data.Directory.Display_Name,
4998 Data.Library_Src_Dir.Name,
4999 Data.Library_Src_Dir.Display_Name,
5000 Create => "library source copy",
5001 Current_Dir => Current_Dir,
5002 Location => Lib_Src_Dir.Location);
5004 -- If directory does not exist, report an error
5006 if Data.Library_Src_Dir = No_Path_Information then
5008 -- Get the absolute name of the library directory that does
5009 -- not exist, to report an error.
5012 Dir_Name : constant String :=
5013 Get_Name_String (Dir_Id);
5016 if Is_Absolute_Path (Dir_Name) then
5017 Err_Vars.Error_Msg_File_1 := Dir_Id;
5020 Get_Name_String (Data.Directory.Name);
5022 if Name_Buffer (Name_Len) /=
5025 Name_Len := Name_Len + 1;
5026 Name_Buffer (Name_Len) :=
5027 Directory_Separator;
5032 Name_Len + Dir_Name'Length) :=
5034 Name_Len := Name_Len + Dir_Name'Length;
5035 Err_Vars.Error_Msg_Name_1 := Name_Find;
5040 Error_Msg_File_1 := Dir_Id;
5043 "Directory { does not exist",
5044 Lib_Src_Dir.Location);
5047 -- Report error if it is the same as the object directory
5049 elsif Data.Library_Src_Dir = Data.Object_Directory then
5052 "directory to copy interfaces cannot be " &
5053 "the object directory",
5054 Lib_Src_Dir.Location);
5055 Data.Library_Src_Dir := No_Path_Information;
5059 Src_Dirs : String_List_Id;
5060 Src_Dir : String_Element;
5063 -- Interface copy directory cannot be one of the source
5064 -- directory of the current project.
5066 Src_Dirs := Data.Source_Dirs;
5067 while Src_Dirs /= Nil_String loop
5068 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5070 -- Report error if it is one of the source directories
5072 if Data.Library_Src_Dir.Name =
5073 Path_Name_Type (Src_Dir.Value)
5077 "directory to copy interfaces cannot " &
5078 "be one of the source directories",
5079 Lib_Src_Dir.Location);
5080 Data.Library_Src_Dir := No_Path_Information;
5084 Src_Dirs := Src_Dir.Next;
5087 if Data.Library_Src_Dir /= No_Path_Information then
5089 -- It cannot be a source directory of any other
5092 Project_Loop : for Pid in 1 ..
5093 Project_Table.Last (In_Tree.Projects)
5096 In_Tree.Projects.Table (Pid).Source_Dirs;
5097 Dir_Loop : while Src_Dirs /= Nil_String loop
5099 In_Tree.String_Elements.Table (Src_Dirs);
5101 -- Report error if it is one of the source
5104 if Data.Library_Src_Dir.Name =
5105 Path_Name_Type (Src_Dir.Value)
5108 File_Name_Type (Src_Dir.Value);
5110 In_Tree.Projects.Table (Pid).Name;
5113 "directory to copy interfaces cannot " &
5114 "be the same as source directory { of " &
5116 Lib_Src_Dir.Location);
5117 Data.Library_Src_Dir := No_Path_Information;
5121 Src_Dirs := Src_Dir.Next;
5123 end loop Project_Loop;
5127 -- In high verbosity, if there is a valid Library_Src_Dir,
5128 -- display its path name.
5130 if Data.Library_Src_Dir /= No_Path_Information
5131 and then Current_Verbosity = High
5133 Write_Str ("Directory to copy interfaces =""");
5134 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5141 -- Check the symbol related attributes
5143 -- First, the symbol policy
5145 if not Lib_Symbol_Policy.Default then
5147 Value : constant String :=
5149 (Get_Name_String (Lib_Symbol_Policy.Value));
5152 -- Symbol policy must hove one of a limited number of values
5154 if Value = "autonomous" or else Value = "default" then
5155 Data.Symbol_Data.Symbol_Policy := Autonomous;
5157 elsif Value = "compliant" then
5158 Data.Symbol_Data.Symbol_Policy := Compliant;
5160 elsif Value = "controlled" then
5161 Data.Symbol_Data.Symbol_Policy := Controlled;
5163 elsif Value = "restricted" then
5164 Data.Symbol_Data.Symbol_Policy := Restricted;
5166 elsif Value = "direct" then
5167 Data.Symbol_Data.Symbol_Policy := Direct;
5172 "illegal value for Library_Symbol_Policy",
5173 Lib_Symbol_Policy.Location);
5178 -- If attribute Library_Symbol_File is not specified, symbol policy
5179 -- cannot be Restricted.
5181 if Lib_Symbol_File.Default then
5182 if Data.Symbol_Data.Symbol_Policy = Restricted then
5185 "Library_Symbol_File needs to be defined when " &
5186 "symbol policy is Restricted",
5187 Lib_Symbol_Policy.Location);
5191 -- Library_Symbol_File is defined
5193 Data.Symbol_Data.Symbol_File :=
5194 Path_Name_Type (Lib_Symbol_File.Value);
5196 Get_Name_String (Lib_Symbol_File.Value);
5198 if Name_Len = 0 then
5201 "symbol file name cannot be an empty string",
5202 Lib_Symbol_File.Location);
5205 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5208 for J in 1 .. Name_Len loop
5209 if Name_Buffer (J) = '/'
5210 or else Name_Buffer (J) = Directory_Separator
5219 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5222 "symbol file name { is illegal. " &
5223 "Name cannot include directory info.",
5224 Lib_Symbol_File.Location);
5229 -- If attribute Library_Reference_Symbol_File is not defined,
5230 -- symbol policy cannot be Compliant or Controlled.
5232 if Lib_Ref_Symbol_File.Default then
5233 if Data.Symbol_Data.Symbol_Policy = Compliant
5234 or else Data.Symbol_Data.Symbol_Policy = Controlled
5238 "a reference symbol file need to be defined",
5239 Lib_Symbol_Policy.Location);
5243 -- Library_Reference_Symbol_File is defined, check file exists
5245 Data.Symbol_Data.Reference :=
5246 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5248 Get_Name_String (Lib_Ref_Symbol_File.Value);
5250 if Name_Len = 0 then
5253 "reference symbol file name cannot be an empty string",
5254 Lib_Symbol_File.Location);
5257 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5259 Add_Str_To_Name_Buffer
5260 (Get_Name_String (Data.Directory.Name));
5261 Add_Char_To_Name_Buffer (Directory_Separator);
5262 Add_Str_To_Name_Buffer
5263 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5264 Data.Symbol_Data.Reference := Name_Find;
5267 if not Is_Regular_File
5268 (Get_Name_String (Data.Symbol_Data.Reference))
5271 File_Name_Type (Lib_Ref_Symbol_File.Value);
5273 -- For controlled and direct symbol policies, it is an error
5274 -- if the reference symbol file does not exist. For other
5275 -- symbol policies, this is just a warning
5278 Data.Symbol_Data.Symbol_Policy /= Controlled
5279 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5283 "<library reference symbol file { does not exist",
5284 Lib_Ref_Symbol_File.Location);
5286 -- In addition in the non-controlled case, if symbol policy
5287 -- is Compliant, it is changed to Autonomous, because there
5288 -- is no reference to check against, and we don't want to
5289 -- fail in this case.
5291 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5292 if Data.Symbol_Data.Symbol_Policy = Compliant then
5293 Data.Symbol_Data.Symbol_Policy := Autonomous;
5298 -- If both the reference symbol file and the symbol file are
5299 -- defined, then check that they are not the same file.
5301 if Data.Symbol_Data.Symbol_File /= No_Path then
5302 Get_Name_String (Data.Symbol_Data.Symbol_File);
5304 if Name_Len > 0 then
5306 Symb_Path : constant String :=
5309 (Data.Object_Directory.Name) &
5310 Directory_Separator &
5311 Name_Buffer (1 .. Name_Len),
5312 Directory => Current_Dir,
5314 Opt.Follow_Links_For_Files);
5315 Ref_Path : constant String :=
5318 (Data.Symbol_Data.Reference),
5319 Directory => Current_Dir,
5321 Opt.Follow_Links_For_Files);
5323 if Symb_Path = Ref_Path then
5326 "library reference symbol file and library" &
5327 " symbol file cannot be the same file",
5328 Lib_Ref_Symbol_File.Location);
5336 end Check_Stand_Alone_Library;
5338 ----------------------------
5339 -- Compute_Directory_Last --
5340 ----------------------------
5342 function Compute_Directory_Last (Dir : String) return Natural is
5345 and then (Dir (Dir'Last - 1) = Directory_Separator
5346 or else Dir (Dir'Last - 1) = '/')
5348 return Dir'Last - 1;
5352 end Compute_Directory_Last;
5359 (Project : Project_Id;
5360 In_Tree : Project_Tree_Ref;
5362 Flag_Location : Source_Ptr)
5364 Real_Location : Source_Ptr := Flag_Location;
5365 Error_Buffer : String (1 .. 5_000);
5366 Error_Last : Natural := 0;
5367 Name_Number : Natural := 0;
5368 File_Number : Natural := 0;
5369 First : Positive := Msg'First;
5372 procedure Add (C : Character);
5373 -- Add a character to the buffer
5375 procedure Add (S : String);
5376 -- Add a string to the buffer
5379 -- Add a name to the buffer
5382 -- Add a file name to the buffer
5388 procedure Add (C : Character) is
5390 Error_Last := Error_Last + 1;
5391 Error_Buffer (Error_Last) := C;
5394 procedure Add (S : String) is
5396 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5397 Error_Last := Error_Last + S'Length;
5404 procedure Add_File is
5405 File : File_Name_Type;
5409 File_Number := File_Number + 1;
5413 File := Err_Vars.Error_Msg_File_1;
5415 File := Err_Vars.Error_Msg_File_2;
5417 File := Err_Vars.Error_Msg_File_3;
5422 Get_Name_String (File);
5423 Add (Name_Buffer (1 .. Name_Len));
5431 procedure Add_Name is
5436 Name_Number := Name_Number + 1;
5440 Name := Err_Vars.Error_Msg_Name_1;
5442 Name := Err_Vars.Error_Msg_Name_2;
5444 Name := Err_Vars.Error_Msg_Name_3;
5449 Get_Name_String (Name);
5450 Add (Name_Buffer (1 .. Name_Len));
5454 -- Start of processing for Error_Msg
5457 -- If location of error is unknown, use the location of the project
5459 if Real_Location = No_Location then
5460 Real_Location := In_Tree.Projects.Table (Project).Location;
5463 if Error_Report = null then
5464 Prj.Err.Error_Msg (Msg, Real_Location);
5468 -- Ignore continuation character
5470 if Msg (First) = '\' then
5474 -- Warning character is always the first one in this package
5475 -- this is an undocumented kludge???
5477 if Msg (First) = '?' then
5481 elsif Msg (First) = '<' then
5484 if Err_Vars.Error_Msg_Warn then
5490 while Index <= Msg'Last loop
5491 if Msg (Index) = '{' then
5494 elsif Msg (Index) = '%' then
5495 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5507 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5510 ----------------------
5511 -- Find_Ada_Sources --
5512 ----------------------
5514 procedure Find_Ada_Sources
5515 (Project : Project_Id;
5516 In_Tree : Project_Tree_Ref;
5517 Data : in out Project_Data;
5518 Current_Dir : String)
5520 Source_Dir : String_List_Id := Data.Source_Dirs;
5521 Element : String_Element;
5523 Current_Source : String_List_Id := Nil_String;
5524 Source_Recorded : Boolean := False;
5527 if Current_Verbosity = High then
5528 Write_Line ("Looking for sources:");
5531 -- For each subdirectory
5533 while Source_Dir /= Nil_String loop
5535 Source_Recorded := False;
5536 Element := In_Tree.String_Elements.Table (Source_Dir);
5537 if Element.Value /= No_Name then
5538 Get_Name_String (Element.Display_Value);
5541 Source_Directory : constant String :=
5542 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5543 Dir_Last : constant Natural :=
5544 Compute_Directory_Last (Source_Directory);
5547 if Current_Verbosity = High then
5548 Write_Str ("Source_Dir = ");
5549 Write_Line (Source_Directory);
5552 -- We look at every entry in the source directory
5555 Source_Directory (Source_Directory'First .. Dir_Last));
5558 Read (Dir, Name_Buffer, Name_Len);
5560 if Current_Verbosity = High then
5561 Write_Str (" Checking ");
5562 Write_Line (Name_Buffer (1 .. Name_Len));
5565 exit when Name_Len = 0;
5568 File_Name : constant File_Name_Type := Name_Find;
5570 -- ??? We could probably optimize the following call:
5571 -- we need to resolve links only once for the
5572 -- directory itself, and then do a single call to
5573 -- readlink() for each file. Unfortunately that would
5574 -- require a change in Normalize_Pathname so that it
5575 -- has the option of not resolving links for its
5576 -- Directory parameter, only for Name.
5578 Path : constant String :=
5580 (Name => Name_Buffer (1 .. Name_Len),
5583 (Source_Directory'First .. Dir_Last),
5585 Opt.Follow_Links_For_Files,
5586 Case_Sensitive => True);
5588 Path_Name : Path_Name_Type;
5591 Name_Len := Path'Length;
5592 Name_Buffer (1 .. Name_Len) := Path;
5593 Path_Name := Name_Find;
5595 -- We attempt to register it as a source. However,
5596 -- there is no error if the file does not contain a
5597 -- valid source. But there is an error if we have a
5598 -- duplicate unit name.
5601 (File_Name => File_Name,
5602 Path_Name => Path_Name,
5606 Location => No_Location,
5607 Current_Source => Current_Source,
5608 Source_Recorded => Source_Recorded,
5609 Current_Dir => Current_Dir);
5618 when Directory_Error =>
5622 if Source_Recorded then
5623 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5627 Source_Dir := Element.Next;
5630 if Current_Verbosity = High then
5631 Write_Line ("end Looking for sources.");
5634 end Find_Ada_Sources;
5636 --------------------------------
5637 -- Free_Ada_Naming_Exceptions --
5638 --------------------------------
5640 procedure Free_Ada_Naming_Exceptions is
5642 Ada_Naming_Exception_Table.Set_Last (0);
5643 Ada_Naming_Exceptions.Reset;
5644 Reverse_Ada_Naming_Exceptions.Reset;
5645 end Free_Ada_Naming_Exceptions;
5647 ---------------------
5648 -- Get_Directories --
5649 ---------------------
5651 procedure Get_Directories
5652 (Project : Project_Id;
5653 In_Tree : Project_Tree_Ref;
5654 Current_Dir : String;
5655 Data : in out Project_Data)
5657 Object_Dir : constant Variable_Value :=
5659 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5661 Exec_Dir : constant Variable_Value :=
5663 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5665 Source_Dirs : constant Variable_Value :=
5667 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5669 Excluded_Source_Dirs : constant Variable_Value :=
5671 (Name_Excluded_Source_Dirs,
5672 Data.Decl.Attributes,
5675 Source_Files : constant Variable_Value :=
5677 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5679 Last_Source_Dir : String_List_Id := Nil_String;
5681 procedure Find_Source_Dirs
5682 (From : File_Name_Type;
5683 Location : Source_Ptr;
5684 Removed : Boolean := False);
5685 -- Find one or several source directories, and add (or remove, if
5686 -- Removed is True) them to list of source directories of the project.
5688 ----------------------
5689 -- Find_Source_Dirs --
5690 ----------------------
5692 procedure Find_Source_Dirs
5693 (From : File_Name_Type;
5694 Location : Source_Ptr;
5695 Removed : Boolean := False)
5697 Directory : constant String := Get_Name_String (From);
5698 Element : String_Element;
5700 procedure Recursive_Find_Dirs (Path : Name_Id);
5701 -- Find all the subdirectories (recursively) of Path and add them
5702 -- to the list of source directories of the project.
5704 -------------------------
5705 -- Recursive_Find_Dirs --
5706 -------------------------
5708 procedure Recursive_Find_Dirs (Path : Name_Id) is
5710 Name : String (1 .. 250);
5712 List : String_List_Id;
5713 Prev : String_List_Id;
5714 Element : String_Element;
5715 Found : Boolean := False;
5717 Non_Canonical_Path : Name_Id := No_Name;
5718 Canonical_Path : Name_Id := No_Name;
5720 The_Path : constant String :=
5722 (Get_Name_String (Path),
5723 Directory => Current_Dir,
5724 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5725 Directory_Separator;
5727 The_Path_Last : constant Natural :=
5728 Compute_Directory_Last (The_Path);
5731 Name_Len := The_Path_Last - The_Path'First + 1;
5732 Name_Buffer (1 .. Name_Len) :=
5733 The_Path (The_Path'First .. The_Path_Last);
5734 Non_Canonical_Path := Name_Find;
5736 if Osint.File_Names_Case_Sensitive then
5737 Canonical_Path := Non_Canonical_Path;
5739 Get_Name_String (Non_Canonical_Path);
5740 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5741 Canonical_Path := Name_Find;
5744 -- To avoid processing the same directory several times, check
5745 -- if the directory is already in Recursive_Dirs. If it is, then
5746 -- there is nothing to do, just return. If it is not, put it there
5747 -- and continue recursive processing.
5750 if Recursive_Dirs.Get (Canonical_Path) then
5753 Recursive_Dirs.Set (Canonical_Path, True);
5757 -- Check if directory is already in list
5759 List := Data.Source_Dirs;
5761 while List /= Nil_String loop
5762 Element := In_Tree.String_Elements.Table (List);
5764 if Element.Value /= No_Name then
5765 Found := Element.Value = Canonical_Path;
5770 List := Element.Next;
5773 -- If directory is not already in list, put it there
5775 if (not Removed) and (not Found) then
5776 if Current_Verbosity = High then
5778 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5781 String_Element_Table.Increment_Last
5782 (In_Tree.String_Elements);
5784 (Value => Canonical_Path,
5785 Display_Value => Non_Canonical_Path,
5786 Location => No_Location,
5791 -- Case of first source directory
5793 if Last_Source_Dir = Nil_String then
5794 Data.Source_Dirs := String_Element_Table.Last
5795 (In_Tree.String_Elements);
5797 -- Here we already have source directories
5800 -- Link the previous last to the new one
5802 In_Tree.String_Elements.Table
5803 (Last_Source_Dir).Next :=
5804 String_Element_Table.Last
5805 (In_Tree.String_Elements);
5808 -- And register this source directory as the new last
5810 Last_Source_Dir := String_Element_Table.Last
5811 (In_Tree.String_Elements);
5812 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5815 elsif Removed and Found then
5816 if Prev = Nil_String then
5818 In_Tree.String_Elements.Table (List).Next;
5820 In_Tree.String_Elements.Table (Prev).Next :=
5821 In_Tree.String_Elements.Table (List).Next;
5825 -- Now look for subdirectories. We do that even when this
5826 -- directory is already in the list, because some of its
5827 -- subdirectories may not be in the list yet.
5829 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5832 Read (Dir, Name, Last);
5835 if Name (1 .. Last) /= "."
5836 and then Name (1 .. Last) /= ".."
5838 -- Avoid . and .. directories
5840 if Current_Verbosity = High then
5841 Write_Str (" Checking ");
5842 Write_Line (Name (1 .. Last));
5846 Path_Name : constant String :=
5848 (Name => Name (1 .. Last),
5850 The_Path (The_Path'First .. The_Path_Last),
5851 Resolve_Links => Opt.Follow_Links_For_Dirs,
5852 Case_Sensitive => True);
5855 if Is_Directory (Path_Name) then
5856 -- We have found a new subdirectory, call self
5858 Name_Len := Path_Name'Length;
5859 Name_Buffer (1 .. Name_Len) := Path_Name;
5860 Recursive_Find_Dirs (Name_Find);
5869 when Directory_Error =>
5871 end Recursive_Find_Dirs;
5873 -- Start of processing for Find_Source_Dirs
5876 if Current_Verbosity = High and then not Removed then
5877 Write_Str ("Find_Source_Dirs (""");
5878 Write_Str (Directory);
5882 -- First, check if we are looking for a directory tree, indicated
5883 -- by "/**" at the end.
5885 if Directory'Length >= 3
5886 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5887 and then (Directory (Directory'Last - 2) = '/'
5889 Directory (Directory'Last - 2) = Directory_Separator)
5892 Data.Known_Order_Of_Source_Dirs := False;
5895 Name_Len := Directory'Length - 3;
5897 if Name_Len = 0 then
5899 -- Case of "/**": all directories in file system
5902 Name_Buffer (1) := Directory (Directory'First);
5905 Name_Buffer (1 .. Name_Len) :=
5906 Directory (Directory'First .. Directory'Last - 3);
5909 if Current_Verbosity = High then
5910 Write_Str ("Looking for all subdirectories of """);
5911 Write_Str (Name_Buffer (1 .. Name_Len));
5916 Base_Dir : constant File_Name_Type := Name_Find;
5917 Root_Dir : constant String :=
5919 (Name => Get_Name_String (Base_Dir),
5921 Get_Name_String (Data.Directory.Display_Name),
5922 Resolve_Links => False,
5923 Case_Sensitive => True);
5926 if Root_Dir'Length = 0 then
5927 Err_Vars.Error_Msg_File_1 := Base_Dir;
5929 if Location = No_Location then
5932 "{ is not a valid directory.",
5937 "{ is not a valid directory.",
5942 -- We have an existing directory, we register it and all of
5943 -- its subdirectories.
5945 if Current_Verbosity = High then
5946 Write_Line ("Looking for source directories:");
5949 Name_Len := Root_Dir'Length;
5950 Name_Buffer (1 .. Name_Len) := Root_Dir;
5951 Recursive_Find_Dirs (Name_Find);
5953 if Current_Verbosity = High then
5954 Write_Line ("End of looking for source directories.");
5959 -- We have a single directory
5963 Path_Name : Path_Name_Type;
5964 Display_Path_Name : Path_Name_Type;
5965 List : String_List_Id;
5966 Prev : String_List_Id;
5970 (Project => Project,
5973 Parent => Data.Directory.Display_Name,
5975 Display => Display_Path_Name,
5976 Current_Dir => Current_Dir);
5978 if Path_Name = No_Path then
5979 Err_Vars.Error_Msg_File_1 := From;
5981 if Location = No_Location then
5984 "{ is not a valid directory",
5989 "{ is not a valid directory",
5995 Path : constant String :=
5996 Get_Name_String (Path_Name) &
5997 Directory_Separator;
5998 Last_Path : constant Natural :=
5999 Compute_Directory_Last (Path);
6001 Display_Path : constant String :=
6003 (Display_Path_Name) &
6004 Directory_Separator;
6005 Last_Display_Path : constant Natural :=
6006 Compute_Directory_Last
6008 Display_Path_Id : Name_Id;
6012 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6013 Path_Id := Name_Find;
6015 Add_Str_To_Name_Buffer
6017 (Display_Path'First .. Last_Display_Path));
6018 Display_Path_Id := Name_Find;
6022 -- As it is an existing directory, we add it to the
6023 -- list of directories.
6025 String_Element_Table.Increment_Last
6026 (In_Tree.String_Elements);
6030 Display_Value => Display_Path_Id,
6031 Location => No_Location,
6033 Next => Nil_String);
6035 if Last_Source_Dir = Nil_String then
6037 -- This is the first source directory
6039 Data.Source_Dirs := String_Element_Table.Last
6040 (In_Tree.String_Elements);
6043 -- We already have source directories, link the
6044 -- previous last to the new one.
6046 In_Tree.String_Elements.Table
6047 (Last_Source_Dir).Next :=
6048 String_Element_Table.Last
6049 (In_Tree.String_Elements);
6052 -- And register this source directory as the new last
6054 Last_Source_Dir := String_Element_Table.Last
6055 (In_Tree.String_Elements);
6056 In_Tree.String_Elements.Table
6057 (Last_Source_Dir) := Element;
6060 -- Remove source dir, if present
6062 List := Data.Source_Dirs;
6065 -- Look for source dir in current list
6067 while List /= Nil_String loop
6068 Element := In_Tree.String_Elements.Table (List);
6069 exit when Element.Value = Path_Id;
6071 List := Element.Next;
6074 if List /= Nil_String then
6075 -- Source dir was found, remove it from the list
6077 if Prev = Nil_String then
6079 In_Tree.String_Elements.Table (List).Next;
6082 In_Tree.String_Elements.Table (Prev).Next :=
6083 In_Tree.String_Elements.Table (List).Next;
6091 end Find_Source_Dirs;
6093 -- Start of processing for Get_Directories
6096 if Current_Verbosity = High then
6097 Write_Line ("Starting to look for directories");
6100 -- Check the object directory
6102 pragma Assert (Object_Dir.Kind = Single,
6103 "Object_Dir is not a single string");
6105 -- We set the object directory to its default
6107 Data.Object_Directory := Data.Directory;
6109 if Object_Dir.Value /= Empty_String then
6110 Get_Name_String (Object_Dir.Value);
6112 if Name_Len = 0 then
6115 "Object_Dir cannot be empty",
6116 Object_Dir.Location);
6119 -- We check that the specified object directory does exist
6124 File_Name_Type (Object_Dir.Value),
6125 Data.Directory.Display_Name,
6126 Data.Object_Directory.Name,
6127 Data.Object_Directory.Display_Name,
6129 Location => Object_Dir.Location,
6130 Current_Dir => Current_Dir);
6132 if Data.Object_Directory = No_Path_Information then
6134 -- The object directory does not exist, report an error if the
6135 -- project is not externally built.
6137 if not Data.Externally_Built then
6138 Err_Vars.Error_Msg_File_1 :=
6139 File_Name_Type (Object_Dir.Value);
6142 "the object directory { cannot be found",
6146 -- Do not keep a nil Object_Directory. Set it to the specified
6147 -- (relative or absolute) path. This is for the benefit of
6148 -- tools that recover from errors; for example, these tools
6149 -- could create the non existent directory.
6151 Data.Object_Directory.Display_Name :=
6152 Path_Name_Type (Object_Dir.Value);
6154 if Osint.File_Names_Case_Sensitive then
6155 Data.Object_Directory.Name :=
6156 Path_Name_Type (Object_Dir.Value);
6158 Get_Name_String (Object_Dir.Value);
6159 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6160 Data.Object_Directory.Name := Name_Find;
6165 elsif Subdirs /= null then
6167 Name_Buffer (1) := '.';
6172 Data.Directory.Name,
6173 Data.Object_Directory.Name,
6174 Data.Object_Directory.Display_Name,
6176 Location => Object_Dir.Location,
6177 Current_Dir => Current_Dir);
6180 if Current_Verbosity = High then
6181 if Data.Object_Directory = No_Path_Information then
6182 Write_Line ("No object directory");
6184 Write_Str ("Object directory: """);
6185 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6190 -- Check the exec directory
6192 pragma Assert (Exec_Dir.Kind = Single,
6193 "Exec_Dir is not a single string");
6195 -- We set the object directory to its default
6197 Data.Exec_Directory := Data.Object_Directory;
6199 if Exec_Dir.Value /= Empty_String then
6200 Get_Name_String (Exec_Dir.Value);
6202 if Name_Len = 0 then
6205 "Exec_Dir cannot be empty",
6209 -- We check that the specified exec directory does exist
6214 File_Name_Type (Exec_Dir.Value),
6215 Data.Directory.Name,
6216 Data.Exec_Directory.Name,
6217 Data.Exec_Directory.Display_Name,
6219 Location => Exec_Dir.Location,
6220 Current_Dir => Current_Dir);
6222 if Data.Exec_Directory = No_Path_Information then
6223 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6226 "the exec directory { cannot be found",
6232 if Current_Verbosity = High then
6233 if Data.Exec_Directory = No_Path_Information then
6234 Write_Line ("No exec directory");
6236 Write_Str ("Exec directory: """);
6237 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6242 -- Look for the source directories
6244 if Current_Verbosity = High then
6245 Write_Line ("Starting to look for source directories");
6248 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6250 if (not Source_Files.Default) and then
6251 Source_Files.Values = Nil_String
6253 Data.Source_Dirs := Nil_String;
6255 if Data.Qualifier = Standard then
6259 "a standard project cannot have no sources",
6260 Source_Files.Location);
6263 if Data.Extends = No_Project
6264 and then Data.Object_Directory = Data.Directory
6266 Data.Object_Directory := No_Path_Information;
6269 elsif Source_Dirs.Default then
6271 -- No Source_Dirs specified: the single source directory is the one
6272 -- containing the project file
6274 String_Element_Table.Increment_Last
6275 (In_Tree.String_Elements);
6276 Data.Source_Dirs := String_Element_Table.Last
6277 (In_Tree.String_Elements);
6278 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6279 (Value => Name_Id (Data.Directory.Name),
6280 Display_Value => Name_Id (Data.Directory.Display_Name),
6281 Location => No_Location,
6286 if Current_Verbosity = High then
6287 Write_Line ("Single source directory:");
6289 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6293 elsif Source_Dirs.Values = Nil_String then
6294 if Data.Qualifier = Standard then
6298 "a standard project cannot have no source directories",
6299 Source_Dirs.Location);
6302 -- If Source_Dirs is an empty string list, this means that this
6303 -- project contains no source. For projects that don't extend other
6304 -- projects, this also means that there is no need for an object
6305 -- directory, if not specified.
6307 if Data.Extends = No_Project
6308 and then Data.Object_Directory = Data.Directory
6310 Data.Object_Directory := No_Path_Information;
6313 Data.Source_Dirs := Nil_String;
6317 Source_Dir : String_List_Id;
6318 Element : String_Element;
6321 -- Process the source directories for each element of the list
6323 Source_Dir := Source_Dirs.Values;
6324 while Source_Dir /= Nil_String loop
6326 In_Tree.String_Elements.Table (Source_Dir);
6328 (File_Name_Type (Element.Value), Element.Location);
6329 Source_Dir := Element.Next;
6334 if not Excluded_Source_Dirs.Default
6335 and then Excluded_Source_Dirs.Values /= Nil_String
6338 Source_Dir : String_List_Id;
6339 Element : String_Element;
6342 -- Process the source directories for each element of the list
6344 Source_Dir := Excluded_Source_Dirs.Values;
6345 while Source_Dir /= Nil_String loop
6347 In_Tree.String_Elements.Table (Source_Dir);
6349 (File_Name_Type (Element.Value),
6352 Source_Dir := Element.Next;
6357 if Current_Verbosity = High then
6358 Write_Line ("Putting source directories in canonical cases");
6362 Current : String_List_Id := Data.Source_Dirs;
6363 Element : String_Element;
6366 while Current /= Nil_String loop
6367 Element := In_Tree.String_Elements.Table (Current);
6368 if Element.Value /= No_Name then
6369 if not Osint.File_Names_Case_Sensitive then
6370 Get_Name_String (Element.Value);
6371 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6372 Element.Value := Name_Find;
6375 In_Tree.String_Elements.Table (Current) := Element;
6378 Current := Element.Next;
6382 end Get_Directories;
6389 (Project : Project_Id;
6390 In_Tree : Project_Tree_Ref;
6391 Data : in out Project_Data)
6393 Mains : constant Variable_Value :=
6394 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6397 Data.Mains := Mains.Values;
6399 -- If no Mains were specified, and if we are an extending project,
6400 -- inherit the Mains from the project we are extending.
6402 if Mains.Default then
6403 if not Data.Library and then Data.Extends /= No_Project then
6405 In_Tree.Projects.Table (Data.Extends).Mains;
6408 -- In a library project file, Main cannot be specified
6410 elsif Data.Library then
6413 "a library project file cannot have Main specified",
6418 ---------------------------
6419 -- Get_Sources_From_File --
6420 ---------------------------
6422 procedure Get_Sources_From_File
6424 Location : Source_Ptr;
6425 Project : Project_Id;
6426 In_Tree : Project_Tree_Ref)
6428 File : Prj.Util.Text_File;
6429 Line : String (1 .. 250);
6431 Source_Name : File_Name_Type;
6432 Name_Loc : Name_Location;
6435 if Get_Mode = Ada_Only then
6439 if Current_Verbosity = High then
6440 Write_Str ("Opening """);
6447 Prj.Util.Open (File, Path);
6449 if not Prj.Util.Is_Valid (File) then
6450 Error_Msg (Project, In_Tree, "file does not exist", Location);
6452 -- Read the lines one by one
6454 while not Prj.Util.End_Of_File (File) loop
6455 Prj.Util.Get_Line (File, Line, Last);
6457 -- A non empty, non comment line should contain a file name
6460 and then (Last = 1 or else Line (1 .. 2) /= "--")
6463 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6464 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6465 Source_Name := Name_Find;
6467 -- Check that there is no directory information
6469 for J in 1 .. Last loop
6470 if Line (J) = '/' or else Line (J) = Directory_Separator then
6471 Error_Msg_File_1 := Source_Name;
6475 "file name cannot include directory information ({)",
6481 Name_Loc := Source_Names.Get (Source_Name);
6483 if Name_Loc = No_Name_Location then
6485 (Name => Source_Name,
6486 Location => Location,
6487 Source => No_Source,
6492 Source_Names.Set (Source_Name, Name_Loc);
6496 Prj.Util.Close (File);
6499 end Get_Sources_From_File;
6506 (In_Tree : Project_Tree_Ref;
6507 Canonical_File_Name : File_Name_Type;
6508 Naming : Naming_Data;
6509 Exception_Id : out Ada_Naming_Exception_Id;
6510 Unit_Name : out Name_Id;
6511 Unit_Kind : out Spec_Or_Body;
6512 Needs_Pragma : out Boolean)
6514 Info_Id : Ada_Naming_Exception_Id :=
6515 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6516 VMS_Name : File_Name_Type;
6519 if Info_Id = No_Ada_Naming_Exception then
6520 if Hostparm.OpenVMS then
6521 VMS_Name := Canonical_File_Name;
6522 Get_Name_String (VMS_Name);
6524 if Name_Buffer (Name_Len) = '.' then
6525 Name_Len := Name_Len - 1;
6526 VMS_Name := Name_Find;
6529 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6534 if Info_Id /= No_Ada_Naming_Exception then
6535 Exception_Id := Info_Id;
6536 Unit_Name := No_Name;
6537 Unit_Kind := Specification;
6538 Needs_Pragma := True;
6542 Needs_Pragma := False;
6543 Exception_Id := No_Ada_Naming_Exception;
6545 Get_Name_String (Canonical_File_Name);
6547 -- How about some comments and a name for this declare block ???
6548 -- In fact the whole code below needs more comments ???
6551 File : String := Name_Buffer (1 .. Name_Len);
6552 First : constant Positive := File'First;
6553 Last : Natural := File'Last;
6554 Standard_GNAT : Boolean;
6555 Spec : constant File_Name_Type :=
6556 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6557 Body_Suff : constant File_Name_Type :=
6558 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6561 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6562 and then Body_Suff = Default_Ada_Body_Suffix;
6565 Spec_Suffix : constant String := Get_Name_String (Spec);
6566 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6567 Sep_Suffix : constant String :=
6568 Get_Name_String (Naming.Separate_Suffix);
6570 May_Be_Spec : Boolean;
6571 May_Be_Body : Boolean;
6572 May_Be_Sep : Boolean;
6576 File'Length > Spec_Suffix'Length
6578 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6581 File'Length > Body_Suffix'Length
6583 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6586 File'Length > Sep_Suffix'Length
6588 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6590 -- If two May_Be_ booleans are True, always choose the longer one
6593 if May_Be_Body and then
6594 Spec_Suffix'Length < Body_Suffix'Length
6596 Unit_Kind := Body_Part;
6598 if May_Be_Sep and then
6599 Body_Suffix'Length < Sep_Suffix'Length
6601 Last := Last - Sep_Suffix'Length;
6602 May_Be_Body := False;
6605 Last := Last - Body_Suffix'Length;
6606 May_Be_Sep := False;
6609 elsif May_Be_Sep and then
6610 Spec_Suffix'Length < Sep_Suffix'Length
6612 Unit_Kind := Body_Part;
6613 Last := Last - Sep_Suffix'Length;
6616 Unit_Kind := Specification;
6617 Last := Last - Spec_Suffix'Length;
6620 elsif May_Be_Body then
6621 Unit_Kind := Body_Part;
6623 if May_Be_Sep and then
6624 Body_Suffix'Length < Sep_Suffix'Length
6626 Last := Last - Sep_Suffix'Length;
6627 May_Be_Body := False;
6629 Last := Last - Body_Suffix'Length;
6630 May_Be_Sep := False;
6633 elsif May_Be_Sep then
6634 Unit_Kind := Body_Part;
6635 Last := Last - Sep_Suffix'Length;
6643 -- This is not a source file
6645 Unit_Name := No_Name;
6646 Unit_Kind := Specification;
6648 if Current_Verbosity = High then
6649 Write_Line (" Not a valid file name.");
6654 elsif Current_Verbosity = High then
6656 when Specification =>
6657 Write_Str (" Specification: ");
6658 Write_Line (File (First .. Last + Spec_Suffix'Length));
6662 Write_Str (" Body: ");
6663 Write_Line (File (First .. Last + Body_Suffix'Length));
6666 Write_Str (" Separate: ");
6667 Write_Line (File (First .. Last + Sep_Suffix'Length));
6673 Get_Name_String (Naming.Dot_Replacement);
6675 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6677 if Name_Buffer (1 .. Name_Len) /= "." then
6679 -- If Dot_Replacement is not a single dot, then there should not
6680 -- be any dot in the name.
6682 for Index in First .. Last loop
6683 if File (Index) = '.' then
6684 if Current_Verbosity = High then
6686 (" Not a valid file name (some dot not replaced).");
6689 Unit_Name := No_Name;
6695 -- Replace the substring Dot_Replacement with dots
6698 Index : Positive := First;
6701 while Index <= Last - Name_Len + 1 loop
6703 if File (Index .. Index + Name_Len - 1) =
6704 Name_Buffer (1 .. Name_Len)
6706 File (Index) := '.';
6708 if Name_Len > 1 and then Index < Last then
6709 File (Index + 1 .. Last - Name_Len + 1) :=
6710 File (Index + Name_Len .. Last);
6713 Last := Last - Name_Len + 1;
6721 -- Check if the casing is right
6724 Src : String := File (First .. Last);
6725 Src_Last : Positive := Last;
6728 case Naming.Casing is
6729 when All_Lower_Case =>
6732 Mapping => Lower_Case_Map);
6734 when All_Upper_Case =>
6737 Mapping => Upper_Case_Map);
6739 when Mixed_Case | Unknown =>
6743 if Src /= File (First .. Last) then
6744 if Current_Verbosity = High then
6745 Write_Line (" Not a valid file name (casing).");
6748 Unit_Name := No_Name;
6752 -- We put the name in lower case
6756 Mapping => Lower_Case_Map);
6758 -- In the standard GNAT naming scheme, check for special cases:
6759 -- children or separates of A, G, I or S, and run time sources.
6761 if Standard_GNAT and then Src'Length >= 3 then
6763 S1 : constant Character := Src (Src'First);
6764 S2 : constant Character := Src (Src'First + 1);
6765 S3 : constant Character := Src (Src'First + 2);
6773 -- Children or separates of packages A, G, I or S. These
6774 -- names are x__ ... or x~... (where x is a, g, i, or s).
6775 -- Both versions (x__... and x~...) are allowed in all
6776 -- platforms, because it is not possible to know the
6777 -- platform before processing of the project files.
6779 if S2 = '_' and then S3 = '_' then
6780 Src (Src'First + 1) := '.';
6781 Src_Last := Src_Last - 1;
6782 Src (Src'First + 2 .. Src_Last) :=
6783 Src (Src'First + 3 .. Src_Last + 1);
6786 Src (Src'First + 1) := '.';
6788 -- If it is potentially a run time source, disable
6789 -- filling of the mapping file to avoid warnings.
6792 Set_Mapping_File_Initial_State_To_Empty;
6798 if Current_Verbosity = High then
6800 Write_Line (Src (Src'First .. Src_Last));
6803 -- Now, we check if this name is a valid unit name
6806 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6816 function Hash (Unit : Unit_Info) return Header_Num is
6818 return Header_Num (Unit.Unit mod 2048);
6821 -----------------------
6822 -- Is_Illegal_Suffix --
6823 -----------------------
6825 function Is_Illegal_Suffix
6827 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6830 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6834 -- If dot replacement is a single dot, and first character of suffix is
6837 if Dot_Replacement_Is_A_Single_Dot
6838 and then Suffix (Suffix'First) = '.'
6840 for Index in Suffix'First + 1 .. Suffix'Last loop
6842 -- If there is another dot
6844 if Suffix (Index) = '.' then
6846 -- It is illegal to have a letter following the initial dot
6848 return Is_Letter (Suffix (Suffix'First + 1));
6856 end Is_Illegal_Suffix;
6858 ----------------------
6859 -- Locate_Directory --
6860 ----------------------
6862 procedure Locate_Directory
6863 (Project : Project_Id;
6864 In_Tree : Project_Tree_Ref;
6865 Name : File_Name_Type;
6866 Parent : Path_Name_Type;
6867 Dir : out Path_Name_Type;
6868 Display : out Path_Name_Type;
6869 Create : String := "";
6870 Current_Dir : String;
6871 Location : Source_Ptr := No_Location)
6873 The_Parent : constant String :=
6874 Get_Name_String (Parent) & Directory_Separator;
6876 The_Parent_Last : constant Natural :=
6877 Compute_Directory_Last (The_Parent);
6879 Full_Name : File_Name_Type;
6881 The_Name : File_Name_Type;
6884 Get_Name_String (Name);
6886 -- Add Subdirs.all if it is a directory that may be created and
6887 -- Subdirs is not null;
6889 if Create /= "" and then Subdirs /= null then
6890 if Name_Buffer (Name_Len) /= Directory_Separator then
6891 Add_Char_To_Name_Buffer (Directory_Separator);
6894 Add_Str_To_Name_Buffer (Subdirs.all);
6897 -- Convert '/' to directory separator (for Windows)
6899 for J in 1 .. Name_Len loop
6900 if Name_Buffer (J) = '/' then
6901 Name_Buffer (J) := Directory_Separator;
6905 The_Name := Name_Find;
6907 if Current_Verbosity = High then
6908 Write_Str ("Locate_Directory (""");
6909 Write_Str (Get_Name_String (The_Name));
6910 Write_Str (""", """);
6911 Write_Str (The_Parent);
6918 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6919 Full_Name := The_Name;
6923 Add_Str_To_Name_Buffer
6924 (The_Parent (The_Parent'First .. The_Parent_Last));
6925 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6926 Full_Name := Name_Find;
6930 Full_Path_Name : constant String := Get_Name_String (Full_Name);
6933 if (Setup_Projects or else Subdirs /= null)
6934 and then Create'Length > 0
6935 and then not Is_Directory (Full_Path_Name)
6938 Create_Path (Full_Path_Name);
6940 if not Quiet_Output then
6942 Write_Str (" directory """);
6943 Write_Str (Full_Path_Name);
6944 Write_Line (""" created");
6951 "could not create " & Create &
6952 " directory " & Full_Path_Name,
6957 if Is_Directory (Full_Path_Name) then
6959 Normed : constant String :=
6962 Directory => Current_Dir,
6963 Resolve_Links => False,
6964 Case_Sensitive => True);
6966 Canonical_Path : constant String :=
6969 Directory => Current_Dir,
6971 Opt.Follow_Links_For_Dirs,
6972 Case_Sensitive => False);
6975 Name_Len := Normed'Length;
6976 Name_Buffer (1 .. Name_Len) := Normed;
6977 Display := Name_Find;
6979 Name_Len := Canonical_Path'Length;
6980 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6985 end Locate_Directory;
6987 ---------------------------
6988 -- Find_Excluded_Sources --
6989 ---------------------------
6991 procedure Find_Excluded_Sources
6992 (Project : Project_Id;
6993 In_Tree : Project_Tree_Ref;
6994 Data : Project_Data)
6996 Excluded_Sources : Variable_Value;
6998 Excluded_Source_List_File : Variable_Value;
7000 Current : String_List_Id;
7002 Element : String_Element;
7004 Location : Source_Ptr;
7006 Name : File_Name_Type;
7008 File : Prj.Util.Text_File;
7009 Line : String (1 .. 300);
7012 Locally_Removed : Boolean := False;
7014 Excluded_Source_List_File :=
7016 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7020 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7022 -- If Excluded_Source_Files is not declared, check
7023 -- Locally_Removed_Files.
7025 if Excluded_Sources.Default then
7026 Locally_Removed := True;
7029 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7032 Excluded_Sources_Htable.Reset;
7034 -- If there are excluded sources, put them in the table
7036 if not Excluded_Sources.Default then
7037 if not Excluded_Source_List_File.Default then
7038 if Locally_Removed then
7041 "?both attributes Locally_Removed_Files and " &
7042 "Excluded_Source_List_File are present",
7043 Excluded_Source_List_File.Location);
7047 "?both attributes Excluded_Source_Files and " &
7048 "Excluded_Source_List_File are present",
7049 Excluded_Source_List_File.Location);
7053 Current := Excluded_Sources.Values;
7054 while Current /= Nil_String loop
7055 Element := In_Tree.String_Elements.Table (Current);
7057 if Osint.File_Names_Case_Sensitive then
7058 Name := File_Name_Type (Element.Value);
7060 Get_Name_String (Element.Value);
7061 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7065 -- If the element has no location, then use the location
7066 -- of Excluded_Sources to report possible errors.
7068 if Element.Location = No_Location then
7069 Location := Excluded_Sources.Location;
7071 Location := Element.Location;
7074 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7075 Current := Element.Next;
7078 elsif not Excluded_Source_List_File.Default then
7079 Location := Excluded_Source_List_File.Location;
7082 Source_File_Path_Name : constant String :=
7085 (Excluded_Source_List_File.Value),
7086 Data.Directory.Name);
7089 if Source_File_Path_Name'Length = 0 then
7090 Err_Vars.Error_Msg_File_1 :=
7091 File_Name_Type (Excluded_Source_List_File.Value);
7094 "file with excluded sources { does not exist",
7095 Excluded_Source_List_File.Location);
7100 Prj.Util.Open (File, Source_File_Path_Name);
7102 if not Prj.Util.Is_Valid (File) then
7104 (Project, In_Tree, "file does not exist", Location);
7106 -- Read the lines one by one
7108 while not Prj.Util.End_Of_File (File) loop
7109 Prj.Util.Get_Line (File, Line, Last);
7111 -- A non empty, non comment line should contain a file
7115 and then (Last = 1 or else Line (1 .. 2) /= "--")
7118 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7119 Canonical_Case_File_Name
7120 (Name_Buffer (1 .. Name_Len));
7123 -- Check that there is no directory information
7125 for J in 1 .. Last loop
7127 or else Line (J) = Directory_Separator
7129 Error_Msg_File_1 := Name;
7133 "file name cannot include " &
7134 "directory information ({)",
7140 Excluded_Sources_Htable.Set
7141 (Name, (Name, False, Location));
7145 Prj.Util.Close (File);
7150 end Find_Excluded_Sources;
7152 ---------------------------
7153 -- Find_Explicit_Sources --
7154 ---------------------------
7156 procedure Find_Explicit_Sources
7157 (Current_Dir : String;
7158 Project : Project_Id;
7159 In_Tree : Project_Tree_Ref;
7160 Data : in out Project_Data)
7162 Sources : constant Variable_Value :=
7165 Data.Decl.Attributes,
7167 Source_List_File : constant Variable_Value :=
7169 (Name_Source_List_File,
7170 Data.Decl.Attributes,
7172 Name_Loc : Name_Location;
7175 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7177 (Source_List_File.Kind = Single,
7178 "Source_List_File is not a single string");
7180 -- If the user has specified a Sources attribute
7182 if not Sources.Default then
7183 if not Source_List_File.Default then
7186 "?both attributes source_files and " &
7187 "source_list_file are present",
7188 Source_List_File.Location);
7191 -- Sources is a list of file names
7194 Current : String_List_Id := Sources.Values;
7195 Element : String_Element;
7196 Location : Source_Ptr;
7197 Name : File_Name_Type;
7200 if Get_Mode = Ada_Only then
7201 Data.Ada_Sources_Present := Current /= Nil_String;
7204 if Get_Mode = Multi_Language then
7205 if Current = Nil_String then
7206 Data.First_Language_Processing := No_Language_Index;
7208 -- This project contains no source. For projects that
7209 -- don't extend other projects, this also means that
7210 -- there is no need for an object directory, if not
7213 if Data.Extends = No_Project
7214 and then Data.Object_Directory = Data.Directory
7216 Data.Object_Directory := No_Path_Information;
7221 while Current /= Nil_String loop
7222 Element := In_Tree.String_Elements.Table (Current);
7223 Get_Name_String (Element.Value);
7225 if Osint.File_Names_Case_Sensitive then
7226 Name := File_Name_Type (Element.Value);
7228 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7232 -- If the element has no location, then use the
7233 -- location of Sources to report possible errors.
7235 if Element.Location = No_Location then
7236 Location := Sources.Location;
7238 Location := Element.Location;
7241 -- Check that there is no directory information
7243 for J in 1 .. Name_Len loop
7244 if Name_Buffer (J) = '/'
7245 or else Name_Buffer (J) = Directory_Separator
7247 Error_Msg_File_1 := Name;
7251 "file name cannot include directory " &
7258 -- In Multi_Language mode, check whether the file is
7259 -- already there: the same file name may be in the list; if
7260 -- the source is missing, the error will be on the first
7261 -- mention of the source file name.
7265 Name_Loc := No_Name_Location;
7266 when Multi_Language =>
7267 Name_Loc := Source_Names.Get (Name);
7270 if Name_Loc = No_Name_Location then
7273 Location => Location,
7274 Source => No_Source,
7277 Source_Names.Set (Name, Name_Loc);
7280 Current := Element.Next;
7283 if Get_Mode = Ada_Only then
7284 Get_Path_Names_And_Record_Ada_Sources
7285 (Project, In_Tree, Data, Current_Dir);
7289 -- If we have no Source_Files attribute, check the Source_List_File
7292 elsif not Source_List_File.Default then
7294 -- Source_List_File is the name of the file
7295 -- that contains the source file names
7298 Source_File_Path_Name : constant String :=
7300 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7303 if Source_File_Path_Name'Length = 0 then
7304 Err_Vars.Error_Msg_File_1 :=
7305 File_Name_Type (Source_List_File.Value);
7308 "file with sources { does not exist",
7309 Source_List_File.Location);
7312 Get_Sources_From_File
7313 (Source_File_Path_Name, Source_List_File.Location,
7316 if Get_Mode = Ada_Only then
7317 -- Look in the source directories to find those sources
7319 Get_Path_Names_And_Record_Ada_Sources
7320 (Project, In_Tree, Data, Current_Dir);
7326 -- Neither Source_Files nor Source_List_File has been
7327 -- specified. Find all the files that satisfy the naming
7328 -- scheme in all the source directories.
7330 if Get_Mode = Ada_Only then
7331 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7335 if Get_Mode = Multi_Language then
7337 (Project, In_Tree, Data,
7339 Sources.Default and then Source_List_File.Default);
7341 -- Check if all exceptions have been found.
7342 -- For Ada, it is an error if an exception is not found.
7343 -- For other language, the source is simply removed.
7347 Src_Data : Source_Data;
7350 Source := Data.First_Source;
7351 while Source /= No_Source loop
7352 Src_Data := In_Tree.Sources.Table (Source);
7354 if Src_Data.Naming_Exception
7355 and then Src_Data.Path = No_Path_Information
7357 if Src_Data.Unit /= No_Name then
7358 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7359 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7362 "source file %% for unit %% not found",
7366 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7369 Source := Src_Data.Next_In_Project;
7373 -- Check that all sources in Source_Files or the file
7374 -- Source_List_File has been found.
7377 Name_Loc : Name_Location;
7380 Name_Loc := Source_Names.Get_First;
7381 while Name_Loc /= No_Name_Location loop
7382 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7383 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7387 "file %% not found",
7391 Name_Loc := Source_Names.Get_Next;
7396 if Get_Mode = Ada_Only
7397 and then Data.Extends = No_Project
7399 -- We should have found at least one source, if not report an error
7401 if Data.Ada_Sources = Nil_String then
7403 (Project, "Ada", In_Tree, Source_List_File.Location);
7407 end Find_Explicit_Sources;
7409 -------------------------------------------
7410 -- Get_Path_Names_And_Record_Ada_Sources --
7411 -------------------------------------------
7413 procedure Get_Path_Names_And_Record_Ada_Sources
7414 (Project : Project_Id;
7415 In_Tree : Project_Tree_Ref;
7416 Data : in out Project_Data;
7417 Current_Dir : String)
7419 Source_Dir : String_List_Id;
7420 Element : String_Element;
7421 Path : Path_Name_Type;
7423 Name : File_Name_Type;
7424 Canonical_Name : File_Name_Type;
7425 Name_Str : String (1 .. 1_024);
7426 Last : Natural := 0;
7428 Current_Source : String_List_Id := Nil_String;
7429 First_Error : Boolean := True;
7430 Source_Recorded : Boolean := False;
7433 -- We look in all source directories for the file names in the hash
7434 -- table Source_Names.
7436 Source_Dir := Data.Source_Dirs;
7437 while Source_Dir /= Nil_String loop
7438 Source_Recorded := False;
7439 Element := In_Tree.String_Elements.Table (Source_Dir);
7442 Dir_Path : constant String :=
7443 Get_Name_String (Element.Display_Value);
7445 if Current_Verbosity = High then
7446 Write_Str ("checking directory """);
7447 Write_Str (Dir_Path);
7451 Open (Dir, Dir_Path);
7454 Read (Dir, Name_Str, Last);
7458 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7461 if Osint.File_Names_Case_Sensitive then
7462 Canonical_Name := Name;
7464 Canonical_Case_File_Name (Name_Str (1 .. Last));
7465 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7466 Canonical_Name := Name_Find;
7469 NL := Source_Names.Get (Canonical_Name);
7471 if NL /= No_Name_Location and then not NL.Found then
7473 Source_Names.Set (Canonical_Name, NL);
7474 Name_Len := Dir_Path'Length;
7475 Name_Buffer (1 .. Name_Len) := Dir_Path;
7477 if Name_Buffer (Name_Len) /= Directory_Separator then
7478 Add_Char_To_Name_Buffer (Directory_Separator);
7481 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7484 if Current_Verbosity = High then
7485 Write_Str (" found ");
7486 Write_Line (Get_Name_String (Name));
7489 -- Register the source if it is an Ada compilation unit
7497 Location => NL.Location,
7498 Current_Source => Current_Source,
7499 Source_Recorded => Source_Recorded,
7500 Current_Dir => Current_Dir);
7507 if Source_Recorded then
7508 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7512 Source_Dir := Element.Next;
7515 -- It is an error if a source file name in a source list or
7516 -- in a source list file is not found.
7518 NL := Source_Names.Get_First;
7519 while NL /= No_Name_Location loop
7520 if not NL.Found then
7521 Err_Vars.Error_Msg_File_1 := NL.Name;
7526 "source file { cannot be found",
7528 First_Error := False;
7533 "\source file { cannot be found",
7538 NL := Source_Names.Get_Next;
7540 end Get_Path_Names_And_Record_Ada_Sources;
7542 --------------------------
7543 -- Check_Naming_Schemes --
7544 --------------------------
7546 procedure Check_Naming_Schemes
7547 (In_Tree : Project_Tree_Ref;
7548 Data : in out Project_Data;
7550 File_Name : File_Name_Type;
7551 Alternate_Languages : out Alternate_Language_Id;
7552 Language : out Language_Index;
7553 Language_Name : out Name_Id;
7554 Display_Language_Name : out Name_Id;
7556 Lang_Kind : out Language_Kind;
7557 Kind : out Source_Kind)
7559 Last : Positive := Filename'Last;
7560 Config : Language_Config;
7561 Lang : Name_List_Index := Data.Languages;
7562 Header_File : Boolean := False;
7563 First_Language : Language_Index;
7566 Last_Spec : Natural;
7567 Last_Body : Natural;
7572 Alternate_Languages := No_Alternate_Language;
7574 while Lang /= No_Name_List loop
7575 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7576 Language := Data.First_Language_Processing;
7578 if Current_Verbosity = High then
7580 (" Testing language "
7581 & Get_Name_String (Language_Name)
7582 & " Header_File=" & Header_File'Img);
7585 while Language /= No_Language_Index loop
7586 if In_Tree.Languages_Data.Table (Language).Name =
7589 Display_Language_Name :=
7590 In_Tree.Languages_Data.Table (Language).Display_Name;
7591 Config := In_Tree.Languages_Data.Table (Language).Config;
7592 Lang_Kind := Config.Kind;
7594 if Config.Kind = File_Based then
7596 -- For file based languages, there is no Unit. Just
7597 -- check if the file name has the implementation or,
7598 -- if it is specified, the template suffix of the
7604 and then Config.Naming_Data.Body_Suffix /= No_File
7607 Impl_Suffix : constant String :=
7608 Get_Name_String (Config.Naming_Data.Body_Suffix);
7611 if Filename'Length > Impl_Suffix'Length
7614 (Last - Impl_Suffix'Length + 1 .. Last) =
7619 if Current_Verbosity = High then
7620 Write_Str (" source of language ");
7622 (Get_Name_String (Display_Language_Name));
7630 if Config.Naming_Data.Spec_Suffix /= No_File then
7632 Spec_Suffix : constant String :=
7634 (Config.Naming_Data.Spec_Suffix);
7637 if Filename'Length > Spec_Suffix'Length
7640 (Last - Spec_Suffix'Length + 1 .. Last) =
7645 if Current_Verbosity = High then
7646 Write_Str (" header file of language ");
7648 (Get_Name_String (Display_Language_Name));
7652 Alternate_Language_Table.Increment_Last
7653 (In_Tree.Alt_Langs);
7654 In_Tree.Alt_Langs.Table
7655 (Alternate_Language_Table.Last
7656 (In_Tree.Alt_Langs)) :=
7657 (Language => Language,
7658 Next => Alternate_Languages);
7659 Alternate_Languages :=
7660 Alternate_Language_Table.Last
7661 (In_Tree.Alt_Langs);
7663 Header_File := True;
7664 First_Language := Language;
7670 elsif not Header_File then
7671 -- Unit based language
7673 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7678 -- ??? Are we doing this once per file in the project ?
7679 -- It should be done only once per project.
7681 case Config.Naming_Data.Casing is
7682 when All_Lower_Case =>
7683 for J in Filename'Range loop
7684 if Is_Letter (Filename (J)) then
7685 if not Is_Lower (Filename (J)) then
7692 when All_Upper_Case =>
7693 for J in Filename'Range loop
7694 if Is_Letter (Filename (J)) then
7695 if not Is_Upper (Filename (J)) then
7708 Last_Spec := Natural'Last;
7709 Last_Body := Natural'Last;
7710 Last_Sep := Natural'Last;
7712 if Config.Naming_Data.Separate_Suffix /= No_File
7714 Config.Naming_Data.Separate_Suffix /=
7715 Config.Naming_Data.Body_Suffix
7718 Suffix : constant String :=
7720 (Config.Naming_Data.Separate_Suffix);
7722 if Filename'Length > Suffix'Length
7725 (Last - Suffix'Length + 1 .. Last) =
7728 Last_Sep := Last - Suffix'Length;
7733 if Config.Naming_Data.Body_Suffix /= No_File then
7735 Suffix : constant String :=
7737 (Config.Naming_Data.Body_Suffix);
7739 if Filename'Length > Suffix'Length
7742 (Last - Suffix'Length + 1 .. Last) =
7745 Last_Body := Last - Suffix'Length;
7750 if Config.Naming_Data.Spec_Suffix /= No_File then
7752 Suffix : constant String :=
7754 (Config.Naming_Data.Spec_Suffix);
7756 if Filename'Length > Suffix'Length
7759 (Last - Suffix'Length + 1 .. Last) =
7762 Last_Spec := Last - Suffix'Length;
7768 Last_Min : constant Natural :=
7769 Natural'Min (Natural'Min (Last_Spec,
7774 OK := Last_Min < Last;
7779 if Last_Min = Last_Spec then
7782 elsif Last_Min = Last_Body then
7794 -- Replace dot replacements with dots
7799 J : Positive := Filename'First;
7801 Dot_Replacement : constant String :=
7803 (Config.Naming_Data.
7806 Max : constant Positive :=
7807 Last - Dot_Replacement'Length + 1;
7811 Name_Len := Name_Len + 1;
7813 if J <= Max and then
7815 (J .. J + Dot_Replacement'Length - 1) =
7818 Name_Buffer (Name_Len) := '.';
7819 J := J + Dot_Replacement'Length;
7822 if Filename (J) = '.' then
7827 Name_Buffer (Name_Len) :=
7828 GNAT.Case_Util.To_Lower (Filename (J));
7839 -- The name buffer should contain the name of the
7840 -- the unit, if it is one.
7842 -- Check that this is a valid unit name
7844 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7846 if Unit /= No_Name then
7848 if Current_Verbosity = High then
7850 Write_Str (" spec of ");
7852 Write_Str (" body of ");
7855 Write_Str (Get_Name_String (Unit));
7856 Write_Str (" (language ");
7858 (Get_Name_String (Display_Language_Name));
7862 -- Comments required, declare block should
7866 Unit_Except : constant Unit_Exception :=
7867 Unit_Exceptions.Get (Unit);
7869 procedure Masked_Unit (Spec : Boolean);
7870 -- Indicate that there is an exception for
7871 -- the same unit, so the file is not a
7872 -- source for the unit.
7878 procedure Masked_Unit (Spec : Boolean) is
7880 if Current_Verbosity = High then
7882 Write_Str (Filename);
7883 Write_Str (""" contains the ");
7892 (" of a unit that is found in """);
7897 (Unit_Except.Spec));
7901 (Unit_Except.Impl));
7904 Write_Line (""" (ignored)");
7907 Language := No_Language_Index;
7912 if Unit_Except.Spec /= No_File
7913 and then Unit_Except.Spec /= File_Name
7915 Masked_Unit (Spec => True);
7919 if Unit_Except.Impl /= No_File
7920 and then Unit_Except.Impl /= File_Name
7922 Masked_Unit (Spec => False);
7933 Language := In_Tree.Languages_Data.Table (Language).Next;
7936 Lang := In_Tree.Name_Lists.Table (Lang).Next;
7939 -- Comment needed here ???
7942 Language := First_Language;
7945 Language := No_Language_Index;
7947 if Current_Verbosity = High then
7948 Write_Line (" not a source of any language");
7951 end Check_Naming_Schemes;
7957 procedure Check_File
7958 (Project : Project_Id;
7959 In_Tree : Project_Tree_Ref;
7960 Data : in out Project_Data;
7962 File_Name : File_Name_Type;
7963 Display_File_Name : File_Name_Type;
7964 Source_Directory : String;
7965 For_All_Sources : Boolean)
7967 Display_Path : constant String :=
7970 Directory => Source_Directory,
7971 Resolve_Links => Opt.Follow_Links_For_Files,
7972 Case_Sensitive => True);
7974 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7975 Path_Id : Path_Name_Type;
7976 Display_Path_Id : Path_Name_Type;
7977 Check_Name : Boolean := False;
7978 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
7979 Language : Language_Index;
7981 Other_Part : Source_Id;
7983 Src_Ind : Source_File_Index;
7984 Src_Data : Source_Data;
7986 Source_To_Replace : Source_Id := No_Source;
7987 Language_Name : Name_Id;
7988 Display_Language_Name : Name_Id;
7989 Lang_Kind : Language_Kind;
7990 Kind : Source_Kind := Spec;
7993 Name_Len := Display_Path'Length;
7994 Name_Buffer (1 .. Name_Len) := Display_Path;
7995 Display_Path_Id := Name_Find;
7997 if Osint.File_Names_Case_Sensitive then
7998 Path_Id := Display_Path_Id;
8000 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8001 Path_Id := Name_Find;
8004 if Name_Loc = No_Name_Location then
8005 Check_Name := For_All_Sources;
8008 if Name_Loc.Found then
8010 -- Check if it is OK to have the same file name in several
8011 -- source directories.
8013 if not Data.Known_Order_Of_Source_Dirs then
8014 Error_Msg_File_1 := File_Name;
8017 "{ is found in several source directories",
8022 Name_Loc.Found := True;
8024 Source_Names.Set (File_Name, Name_Loc);
8026 if Name_Loc.Source = No_Source then
8030 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8031 (Path_Id, Display_Path_Id);
8033 Source_Paths_Htable.Set
8034 (In_Tree.Source_Paths_HT,
8038 -- Check if this is a subunit
8040 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8042 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8044 Src_Ind := Sinput.P.Load_Project_File
8045 (Get_Name_String (Path_Id));
8047 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8048 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8056 Other_Part := No_Source;
8058 Check_Naming_Schemes
8059 (In_Tree => In_Tree,
8061 Filename => Get_Name_String (File_Name),
8062 File_Name => File_Name,
8063 Alternate_Languages => Alternate_Languages,
8064 Language => Language,
8065 Language_Name => Language_Name,
8066 Display_Language_Name => Display_Language_Name,
8068 Lang_Kind => Lang_Kind,
8071 if Language = No_Language_Index then
8073 -- A file name in a list must be a source of a language
8075 if Name_Loc.Found then
8076 Error_Msg_File_1 := File_Name;
8080 "language unknown for {",
8085 -- Check if the same file name or unit is used in the prj tree
8087 Source := In_Tree.First_Source;
8089 while Source /= No_Source loop
8090 Src_Data := In_Tree.Sources.Table (Source);
8093 and then Src_Data.Unit = Unit
8095 ((Src_Data.Kind = Spec and then Kind = Impl)
8097 (Src_Data.Kind = Impl and then Kind = Spec))
8099 Other_Part := Source;
8101 elsif (Unit /= No_Name
8102 and then Src_Data.Unit = Unit
8104 (Src_Data.Kind = Kind
8106 (Src_Data.Kind = Sep and then Kind = Impl)
8108 (Src_Data.Kind = Impl and then Kind = Sep)))
8109 or else (Unit = No_Name and then Src_Data.File = File_Name)
8111 -- Duplication of file/unit in same project is only
8112 -- allowed if order of source directories is known.
8114 if Project = Src_Data.Project then
8115 if Data.Known_Order_Of_Source_Dirs then
8118 elsif Unit /= No_Name then
8119 Error_Msg_Name_1 := Unit;
8121 (Project, In_Tree, "duplicate unit %%", No_Location);
8125 Error_Msg_File_1 := File_Name;
8127 (Project, In_Tree, "duplicate source file name {",
8132 -- Do not allow the same unit name in different
8133 -- projects, except if one is extending the other.
8135 -- For a file based language, the same file name
8136 -- replaces a file in a project being extended, but
8137 -- it is allowed to have the same file name in
8138 -- unrelated projects.
8141 (Project, Src_Data.Project, In_Tree)
8143 Source_To_Replace := Source;
8145 elsif Unit /= No_Name then
8146 Error_Msg_Name_1 := Unit;
8149 "unit %% cannot belong to several projects",
8152 Error_Msg_Name_1 := In_Tree.Projects.Table (Project).Name;
8153 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8155 (Project, In_Tree, "\ project %%, %%", No_Location);
8158 In_Tree.Projects.Table (Src_Data.Project).Name;
8159 Error_Msg_Name_2 := Name_Id (Src_Data.Path.Display_Name);
8161 (Project, In_Tree, "\ project %%, %%", No_Location);
8167 Source := Src_Data.Next_In_Sources;
8176 Lang => Language_Name,
8177 Lang_Id => Language,
8178 Lang_Kind => Lang_Kind,
8180 Alternate_Languages => Alternate_Languages,
8181 File_Name => File_Name,
8182 Display_File => Display_File_Name,
8183 Other_Part => Other_Part,
8186 Display_Path => Display_Path_Id,
8187 Source_To_Replace => Source_To_Replace);
8193 ------------------------
8194 -- Search_Directories --
8195 ------------------------
8197 procedure Search_Directories
8198 (Project : Project_Id;
8199 In_Tree : Project_Tree_Ref;
8200 Data : in out Project_Data;
8201 For_All_Sources : Boolean)
8203 Source_Dir : String_List_Id;
8204 Element : String_Element;
8206 Name : String (1 .. 1_000);
8208 File_Name : File_Name_Type;
8209 Display_File_Name : File_Name_Type;
8212 if Current_Verbosity = High then
8213 Write_Line ("Looking for sources:");
8216 -- Loop through subdirectories
8218 Source_Dir := Data.Source_Dirs;
8219 while Source_Dir /= Nil_String loop
8221 Element := In_Tree.String_Elements.Table (Source_Dir);
8222 if Element.Value /= No_Name then
8223 Get_Name_String (Element.Display_Value);
8226 Source_Directory : constant String :=
8227 Name_Buffer (1 .. Name_Len) &
8228 Directory_Separator;
8230 Dir_Last : constant Natural :=
8231 Compute_Directory_Last
8235 if Current_Verbosity = High then
8236 Write_Str ("Source_Dir = ");
8237 Write_Line (Source_Directory);
8240 -- We look to every entry in the source directory
8242 Open (Dir, Source_Directory);
8245 Read (Dir, Name, Last);
8249 -- ??? Duplicate system call here, we just did a
8250 -- a similar one. Maybe Ada.Directories would be more
8254 (Source_Directory & Name (1 .. Last))
8256 if Current_Verbosity = High then
8257 Write_Str (" Checking ");
8258 Write_Line (Name (1 .. Last));
8262 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8263 Display_File_Name := Name_Find;
8265 if Osint.File_Names_Case_Sensitive then
8266 File_Name := Display_File_Name;
8268 Canonical_Case_File_Name
8269 (Name_Buffer (1 .. Name_Len));
8270 File_Name := Name_Find;
8275 Excluded_Sources_Htable.Get (File_Name);
8278 if FF /= No_File_Found then
8279 if not FF.Found then
8281 Excluded_Sources_Htable.Set
8284 if Current_Verbosity = High then
8285 Write_Str (" excluded source """);
8286 Write_Str (Get_Name_String (File_Name));
8293 (Project => Project,
8296 Name => Name (1 .. Last),
8297 File_Name => File_Name,
8298 Display_File_Name => Display_File_Name,
8299 Source_Directory => Source_Directory
8300 (Source_Directory'First .. Dir_Last),
8301 For_All_Sources => For_All_Sources);
8312 when Directory_Error =>
8316 Source_Dir := Element.Next;
8319 if Current_Verbosity = High then
8320 Write_Line ("end Looking for sources.");
8322 end Search_Directories;
8324 ----------------------
8325 -- Look_For_Sources --
8326 ----------------------
8328 procedure Look_For_Sources
8329 (Project : Project_Id;
8330 In_Tree : Project_Tree_Ref;
8331 Data : in out Project_Data;
8332 Current_Dir : String)
8334 procedure Remove_Locally_Removed_Files_From_Units;
8335 -- Mark all locally removed sources as such in the Units table
8337 procedure Process_Sources_In_Multi_Language_Mode;
8338 -- Find all source files when in multi language mode
8340 ---------------------------------------------
8341 -- Remove_Locally_Removed_Files_From_Units --
8342 ---------------------------------------------
8344 procedure Remove_Locally_Removed_Files_From_Units is
8345 Excluded : File_Found;
8348 Extended : Project_Id;
8351 Excluded := Excluded_Sources_Htable.Get_First;
8352 while Excluded /= No_File_Found loop
8356 for Index in Unit_Table.First ..
8357 Unit_Table.Last (In_Tree.Units)
8359 Unit := In_Tree.Units.Table (Index);
8361 for Kind in Spec_Or_Body'Range loop
8362 if Unit.File_Names (Kind).Name = Excluded.File then
8365 -- Check that this is from the current project or
8366 -- that the current project extends.
8368 Extended := Unit.File_Names (Kind).Project;
8370 if Extended = Project
8371 or else Project_Extends (Project, Extended, In_Tree)
8373 Unit.File_Names (Kind).Path.Name := Slash;
8374 Unit.File_Names (Kind).Needs_Pragma := False;
8375 In_Tree.Units.Table (Index) := Unit;
8376 Add_Forbidden_File_Name
8377 (Unit.File_Names (Kind).Name);
8381 "cannot remove a source from " &
8388 end loop For_Each_Unit;
8391 Err_Vars.Error_Msg_File_1 := Excluded.File;
8393 (Project, In_Tree, "unknown file {", Excluded.Location);
8396 Excluded := Excluded_Sources_Htable.Get_Next;
8398 end Remove_Locally_Removed_Files_From_Units;
8400 --------------------------------------------
8401 -- Process_Sources_In_Multi_Language_Mode --
8402 --------------------------------------------
8404 procedure Process_Sources_In_Multi_Language_Mode is
8406 Src_Data : Source_Data;
8407 Name_Loc : Name_Location;
8412 -- First, put all naming exceptions if any, in the Source_Names table
8414 Unit_Exceptions.Reset;
8416 Source := Data.First_Source;
8417 while Source /= No_Source loop
8418 Src_Data := In_Tree.Sources.Table (Source);
8420 -- A file that is excluded cannot also be an exception file name
8422 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8425 Error_Msg_File_1 := Src_Data.File;
8428 "{ cannot be both excluded and an exception file name",
8432 Name_Loc := (Name => Src_Data.File,
8433 Location => No_Location,
8435 Except => Src_Data.Unit /= No_Name,
8438 if Current_Verbosity = High then
8439 Write_Str ("Putting source #");
8440 Write_Str (Source'Img);
8441 Write_Str (", file ");
8442 Write_Str (Get_Name_String (Src_Data.File));
8443 Write_Line (" in Source_Names");
8446 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8448 -- If this is an Ada exception, record it in table Unit_Exceptions
8450 if Src_Data.Unit /= No_Name then
8452 Unit_Except : Unit_Exception :=
8453 Unit_Exceptions.Get (Src_Data.Unit);
8456 Unit_Except.Name := Src_Data.Unit;
8458 if Src_Data.Kind = Spec then
8459 Unit_Except.Spec := Src_Data.File;
8461 Unit_Except.Impl := Src_Data.File;
8464 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8468 Source := Src_Data.Next_In_Project;
8471 Find_Explicit_Sources
8472 (Current_Dir, Project, In_Tree, Data);
8474 -- Mark as such the sources that are declared as excluded
8476 FF := Excluded_Sources_Htable.Get_First;
8477 while FF /= No_File_Found loop
8479 Source := In_Tree.First_Source;
8481 while Source /= No_Source loop
8482 Src_Data := In_Tree.Sources.Table (Source);
8484 if Src_Data.File = FF.File then
8486 -- Check that this is from this project or a project that
8487 -- the current project extends.
8489 if Src_Data.Project = Project or else
8490 Is_Extending (Project, Src_Data.Project, In_Tree)
8492 Src_Data.Locally_Removed := True;
8493 Src_Data.In_Interfaces := False;
8494 In_Tree.Sources.Table (Source) := Src_Data;
8495 Add_Forbidden_File_Name (FF.File);
8501 Source := Src_Data.Next_In_Sources;
8504 if not FF.Found and not OK then
8505 Err_Vars.Error_Msg_File_1 := FF.File;
8506 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8509 FF := Excluded_Sources_Htable.Get_Next;
8512 -- Check that two sources of this project do not have the same object
8515 Check_Object_File_Names : declare
8517 Src_Data : Source_Data;
8518 Source_Name : File_Name_Type;
8520 procedure Check_Object;
8521 -- Check if object file name of the current source is already in
8522 -- hash table Object_File_Names. If it is, report an error. If it
8523 -- is not, put it there with the file name of the current source.
8529 procedure Check_Object is
8531 Source_Name := Object_File_Names.Get (Src_Data.Object);
8533 if Source_Name /= No_File then
8534 Error_Msg_File_1 := Src_Data.File;
8535 Error_Msg_File_2 := Source_Name;
8539 "{ and { have the same object file name",
8543 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8547 -- Start of processing for Check_Object_File_Names
8550 Object_File_Names.Reset;
8551 Src_Id := In_Tree.First_Source;
8552 while Src_Id /= No_Source loop
8553 Src_Data := In_Tree.Sources.Table (Src_Id);
8555 if Src_Data.Compiled and then Src_Data.Object_Exists
8556 and then Project_Extends (Project, Src_Data.Project, In_Tree)
8558 if Src_Data.Unit = No_Name then
8559 if Src_Data.Kind = Impl then
8564 case Src_Data.Kind is
8566 if Src_Data.Other_Part = No_Source then
8574 if Src_Data.Other_Part /= No_Source then
8578 -- Check if it is a subunit
8581 Src_Ind : constant Source_File_Index :=
8582 Sinput.P.Load_Project_File
8584 (Src_Data.Path.Name));
8587 if Sinput.P.Source_File_Is_Subunit
8590 In_Tree.Sources.Table (Src_Id).Kind := Sep;
8600 Src_Id := Src_Data.Next_In_Sources;
8602 end Check_Object_File_Names;
8603 end Process_Sources_In_Multi_Language_Mode;
8605 -- Start of processing for Look_For_Sources
8609 Find_Excluded_Sources (Project, In_Tree, Data);
8613 if Is_A_Language (In_Tree, Data, Name_Ada) then
8614 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8615 Remove_Locally_Removed_Files_From_Units;
8618 when Multi_Language =>
8619 if Data.First_Language_Processing /= No_Language_Index then
8620 Process_Sources_In_Multi_Language_Mode;
8623 end Look_For_Sources;
8629 function Path_Name_Of
8630 (File_Name : File_Name_Type;
8631 Directory : Path_Name_Type) return String
8633 Result : String_Access;
8634 The_Directory : constant String := Get_Name_String (Directory);
8637 Get_Name_String (File_Name);
8640 (File_Name => Name_Buffer (1 .. Name_Len),
8641 Path => The_Directory);
8643 if Result = null then
8646 Canonical_Case_File_Name (Result.all);
8651 -------------------------------
8652 -- Prepare_Ada_Naming_Exceptions --
8653 -------------------------------
8655 procedure Prepare_Ada_Naming_Exceptions
8656 (List : Array_Element_Id;
8657 In_Tree : Project_Tree_Ref;
8658 Kind : Spec_Or_Body)
8660 Current : Array_Element_Id;
8661 Element : Array_Element;
8665 -- Traverse the list
8668 while Current /= No_Array_Element loop
8669 Element := In_Tree.Array_Elements.Table (Current);
8671 if Element.Index /= No_Name then
8674 Unit => Element.Index,
8675 Next => No_Ada_Naming_Exception);
8676 Reverse_Ada_Naming_Exceptions.Set
8677 (Unit, (Element.Value.Value, Element.Value.Index));
8679 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8680 Ada_Naming_Exception_Table.Increment_Last;
8681 Ada_Naming_Exception_Table.Table
8682 (Ada_Naming_Exception_Table.Last) := Unit;
8683 Ada_Naming_Exceptions.Set
8684 (File_Name_Type (Element.Value.Value),
8685 Ada_Naming_Exception_Table.Last);
8688 Current := Element.Next;
8690 end Prepare_Ada_Naming_Exceptions;
8692 ---------------------
8693 -- Project_Extends --
8694 ---------------------
8696 function Project_Extends
8697 (Extending : Project_Id;
8698 Extended : Project_Id;
8699 In_Tree : Project_Tree_Ref) return Boolean
8701 Current : Project_Id := Extending;
8705 if Current = No_Project then
8708 elsif Current = Extended then
8712 Current := In_Tree.Projects.Table (Current).Extends;
8714 end Project_Extends;
8716 -----------------------
8717 -- Record_Ada_Source --
8718 -----------------------
8720 procedure Record_Ada_Source
8721 (File_Name : File_Name_Type;
8722 Path_Name : Path_Name_Type;
8723 Project : Project_Id;
8724 In_Tree : Project_Tree_Ref;
8725 Data : in out Project_Data;
8726 Location : Source_Ptr;
8727 Current_Source : in out String_List_Id;
8728 Source_Recorded : in out Boolean;
8729 Current_Dir : String)
8731 Canonical_File_Name : File_Name_Type;
8732 Canonical_Path_Name : Path_Name_Type;
8734 Exception_Id : Ada_Naming_Exception_Id;
8735 Unit_Name : Name_Id;
8736 Unit_Kind : Spec_Or_Body;
8737 Unit_Ind : Int := 0;
8739 Name_Index : Name_And_Index;
8740 Needs_Pragma : Boolean;
8742 The_Location : Source_Ptr := Location;
8743 Previous_Source : constant String_List_Id := Current_Source;
8744 Except_Name : Name_And_Index := No_Name_And_Index;
8746 Unit_Prj : Unit_Project;
8748 File_Name_Recorded : Boolean := False;
8751 if Osint.File_Names_Case_Sensitive then
8752 Canonical_File_Name := File_Name;
8753 Canonical_Path_Name := Path_Name;
8755 Get_Name_String (File_Name);
8756 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8757 Canonical_File_Name := Name_Find;
8760 Canonical_Path : constant String :=
8762 (Get_Name_String (Path_Name),
8763 Directory => Current_Dir,
8764 Resolve_Links => Opt.Follow_Links_For_Files,
8765 Case_Sensitive => False);
8768 Add_Str_To_Name_Buffer (Canonical_Path);
8769 Canonical_Path_Name := Name_Find;
8773 -- Find out the unit name, the unit kind and if it needs
8774 -- a specific SFN pragma.
8777 (In_Tree => In_Tree,
8778 Canonical_File_Name => Canonical_File_Name,
8779 Naming => Data.Naming,
8780 Exception_Id => Exception_Id,
8781 Unit_Name => Unit_Name,
8782 Unit_Kind => Unit_Kind,
8783 Needs_Pragma => Needs_Pragma);
8785 if Exception_Id = No_Ada_Naming_Exception
8786 and then Unit_Name = No_Name
8788 if Current_Verbosity = High then
8790 Write_Str (Get_Name_String (Canonical_File_Name));
8791 Write_Line (""" is not a valid source file name (ignored).");
8795 -- Check to see if the source has been hidden by an exception,
8796 -- but only if it is not an exception.
8798 if not Needs_Pragma then
8800 Reverse_Ada_Naming_Exceptions.Get
8801 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8803 if Except_Name /= No_Name_And_Index then
8804 if Current_Verbosity = High then
8806 Write_Str (Get_Name_String (Canonical_File_Name));
8807 Write_Str (""" contains a unit that is found in """);
8808 Write_Str (Get_Name_String (Except_Name.Name));
8809 Write_Line (""" (ignored).");
8812 -- The file is not included in the source of the project since
8813 -- it is hidden by the exception. So, nothing else to do.
8820 if Exception_Id /= No_Ada_Naming_Exception then
8821 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8822 Exception_Id := Info.Next;
8823 Info.Next := No_Ada_Naming_Exception;
8824 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8826 Unit_Name := Info.Unit;
8827 Unit_Ind := Name_Index.Index;
8828 Unit_Kind := Info.Kind;
8831 -- Put the file name in the list of sources of the project
8833 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8834 In_Tree.String_Elements.Table
8835 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8836 (Value => Name_Id (Canonical_File_Name),
8837 Display_Value => Name_Id (File_Name),
8838 Location => No_Location,
8843 if Current_Source = Nil_String then
8845 String_Element_Table.Last (In_Tree.String_Elements);
8846 Data.Sources := Data.Ada_Sources;
8848 In_Tree.String_Elements.Table (Current_Source).Next :=
8849 String_Element_Table.Last (In_Tree.String_Elements);
8853 String_Element_Table.Last (In_Tree.String_Elements);
8855 -- Put the unit in unit list
8858 The_Unit : Unit_Index :=
8859 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8861 The_Unit_Data : Unit_Data;
8864 if Current_Verbosity = High then
8865 Write_Str ("Putting ");
8866 Write_Str (Get_Name_String (Unit_Name));
8867 Write_Line (" in the unit list.");
8870 -- The unit is already in the list, but may be it is
8871 -- only the other unit kind (spec or body), or what is
8872 -- in the unit list is a unit of a project we are extending.
8874 if The_Unit /= No_Unit_Index then
8875 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8877 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8880 The_Unit_Data.File_Names
8881 (Unit_Kind).Path.Name = Slash)
8882 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8883 or else Project_Extends
8885 The_Unit_Data.File_Names (Unit_Kind).Project,
8889 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
8891 Remove_Forbidden_File_Name
8892 (The_Unit_Data.File_Names (Unit_Kind).Name);
8895 -- Record the file name in the hash table Files_Htable
8897 Unit_Prj := (Unit => The_Unit, Project => Project);
8900 Canonical_File_Name,
8903 The_Unit_Data.File_Names (Unit_Kind) :=
8904 (Name => Canonical_File_Name,
8906 Display_Name => File_Name,
8907 Path => (Canonical_Path_Name, Path_Name),
8909 Needs_Pragma => Needs_Pragma);
8910 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8911 Source_Recorded := True;
8913 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8914 and then (Data.Known_Order_Of_Source_Dirs
8916 The_Unit_Data.File_Names
8917 (Unit_Kind).Path.Name = Canonical_Path_Name)
8919 if Previous_Source = Nil_String then
8920 Data.Ada_Sources := Nil_String;
8921 Data.Sources := Nil_String;
8923 In_Tree.String_Elements.Table (Previous_Source).Next :=
8925 String_Element_Table.Decrement_Last
8926 (In_Tree.String_Elements);
8929 Current_Source := Previous_Source;
8932 -- It is an error to have two units with the same name
8933 -- and the same kind (spec or body).
8935 if The_Location = No_Location then
8937 In_Tree.Projects.Table (Project).Location;
8940 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8942 (Project, In_Tree, "duplicate unit %%", The_Location);
8944 Err_Vars.Error_Msg_Name_1 :=
8945 In_Tree.Projects.Table
8946 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
8947 Err_Vars.Error_Msg_File_1 :=
8949 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
8952 "\ project file %%, {", The_Location);
8954 Err_Vars.Error_Msg_Name_1 :=
8955 In_Tree.Projects.Table (Project).Name;
8956 Err_Vars.Error_Msg_File_1 :=
8957 File_Name_Type (Canonical_Path_Name);
8960 "\ project file %%, {", The_Location);
8963 -- It is a new unit, create a new record
8966 -- First, check if there is no other unit with this file
8967 -- name in another project. If it is, report error but note
8968 -- we do that only for the first unit in the source file.
8971 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
8973 if not File_Name_Recorded and then
8974 Unit_Prj /= No_Unit_Project
8976 Error_Msg_File_1 := File_Name;
8978 In_Tree.Projects.Table (Unit_Prj.Project).Name;
8981 "{ is already a source of project %%",
8985 Unit_Table.Increment_Last (In_Tree.Units);
8986 The_Unit := Unit_Table.Last (In_Tree.Units);
8988 (In_Tree.Units_HT, Unit_Name, The_Unit);
8989 Unit_Prj := (Unit => The_Unit, Project => Project);
8992 Canonical_File_Name,
8994 The_Unit_Data.Name := Unit_Name;
8995 The_Unit_Data.File_Names (Unit_Kind) :=
8996 (Name => Canonical_File_Name,
8998 Display_Name => File_Name,
8999 Path => (Canonical_Path_Name, Path_Name),
9001 Needs_Pragma => Needs_Pragma);
9002 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9003 Source_Recorded := True;
9008 exit when Exception_Id = No_Ada_Naming_Exception;
9009 File_Name_Recorded := True;
9012 end Record_Ada_Source;
9018 procedure Remove_Source
9020 Replaced_By : Source_Id;
9021 Project : Project_Id;
9022 Data : in out Project_Data;
9023 In_Tree : Project_Tree_Ref)
9025 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9029 if Current_Verbosity = High then
9030 Write_Str ("Removing source #");
9031 Write_Line (Id'Img);
9034 if Replaced_By /= No_Source then
9035 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9036 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9037 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9040 -- Remove the source from the global source list
9042 Source := In_Tree.First_Source;
9045 In_Tree.First_Source := Src_Data.Next_In_Sources;
9048 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9049 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9052 In_Tree.Sources.Table (Source).Next_In_Sources :=
9053 Src_Data.Next_In_Sources;
9056 -- Remove the source from the project list
9058 if Src_Data.Project = Project then
9059 Source := Data.First_Source;
9062 Data.First_Source := Src_Data.Next_In_Project;
9064 if Src_Data.Next_In_Project = No_Source then
9065 Data.Last_Source := No_Source;
9069 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9070 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9073 In_Tree.Sources.Table (Source).Next_In_Project :=
9074 Src_Data.Next_In_Project;
9076 if Src_Data.Next_In_Project = No_Source then
9077 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9082 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9085 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9086 Src_Data.Next_In_Project;
9088 if Src_Data.Next_In_Project = No_Source then
9089 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9094 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9095 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9098 In_Tree.Sources.Table (Source).Next_In_Project :=
9099 Src_Data.Next_In_Project;
9101 if Src_Data.Next_In_Project = No_Source then
9102 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9107 -- Remove source from the language list
9109 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9112 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9113 Src_Data.Next_In_Lang;
9116 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9117 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9120 In_Tree.Sources.Table (Source).Next_In_Lang :=
9121 Src_Data.Next_In_Lang;
9125 -----------------------
9126 -- Report_No_Sources --
9127 -----------------------
9129 procedure Report_No_Sources
9130 (Project : Project_Id;
9132 In_Tree : Project_Tree_Ref;
9133 Location : Source_Ptr;
9134 Continuation : Boolean := False)
9137 case When_No_Sources is
9141 when Warning | Error =>
9143 Msg : constant String :=
9146 " sources in this project";
9149 Error_Msg_Warn := When_No_Sources = Warning;
9151 if Continuation then
9153 (Project, In_Tree, "\" & Msg, Location);
9157 (Project, In_Tree, Msg, Location);
9161 end Report_No_Sources;
9163 ----------------------
9164 -- Show_Source_Dirs --
9165 ----------------------
9167 procedure Show_Source_Dirs
9168 (Data : Project_Data;
9169 In_Tree : Project_Tree_Ref)
9171 Current : String_List_Id;
9172 Element : String_Element;
9175 Write_Line ("Source_Dirs:");
9177 Current := Data.Source_Dirs;
9178 while Current /= Nil_String loop
9179 Element := In_Tree.String_Elements.Table (Current);
9181 Write_Line (Get_Name_String (Element.Value));
9182 Current := Element.Next;
9185 Write_Line ("end Source_Dirs.");
9186 end Show_Source_Dirs;
9188 -------------------------
9189 -- Warn_If_Not_Sources --
9190 -------------------------
9192 -- comments needed in this body ???
9194 procedure Warn_If_Not_Sources
9195 (Project : Project_Id;
9196 In_Tree : Project_Tree_Ref;
9197 Conventions : Array_Element_Id;
9199 Extending : Boolean)
9201 Conv : Array_Element_Id;
9203 The_Unit_Id : Unit_Index;
9204 The_Unit_Data : Unit_Data;
9205 Location : Source_Ptr;
9208 Conv := Conventions;
9209 while Conv /= No_Array_Element loop
9210 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9211 Error_Msg_Name_1 := Unit;
9212 Get_Name_String (Unit);
9213 To_Lower (Name_Buffer (1 .. Name_Len));
9215 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9216 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9218 if The_Unit_Id = No_Unit_Index then
9219 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9222 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9224 In_Tree.Array_Elements.Table (Conv).Value.Value;
9227 if not Check_Project
9228 (The_Unit_Data.File_Names (Specification).Project,
9229 Project, In_Tree, Extending)
9233 "?source of spec of unit %% (%%)" &
9234 " cannot be found in this project",
9239 if not Check_Project
9240 (The_Unit_Data.File_Names (Body_Part).Project,
9241 Project, In_Tree, Extending)
9245 "?source of body of unit %% (%%)" &
9246 " cannot be found in this project",
9252 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9254 end Warn_If_Not_Sources;