1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2007, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT
.Case_Util
; use GNAT
.Case_Util
;
27 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
30 with Err_Vars
; use Err_Vars
;
35 with Osint
; use Osint
;
36 with Output
; use Output
;
37 with Prj
.Env
; use Prj
.Env
;
39 with Prj
.Util
; use Prj
.Util
;
41 with Snames
; use Snames
;
42 with Table
; use Table
;
43 with Targparm
; use Targparm
;
45 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
46 with Ada
.Directories
; use Ada
.Directories
;
47 with Ada
.Strings
; use Ada
.Strings
;
48 with Ada
.Strings
.Fixed
; use Ada
.Strings
.Fixed
;
49 with Ada
.Strings
.Maps
.Constants
; use Ada
.Strings
.Maps
.Constants
;
51 package body Prj
.Nmsc
is
53 No_Continuation_String
: aliased String := "";
54 Continuation_String
: aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali
";
66 -- File suffix for ali files
68 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
69 -- File suffix for object files
71 type Name_Location is record
72 Name : File_Name_Type;
73 Location : Source_Ptr;
74 Source : Source_Id := No_Source;
75 Except : Boolean := False;
76 Found : Boolean := False;
78 -- Information about file names found in string list attribute
79 -- Source_Files or in a source list file, stored in hash table
80 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
82 No_Name_Location : constant Name_Location :=
84 Location => No_Location,
89 package Source_Names is new GNAT.HTable.Simple_HTable
90 (Header_Num => Header_Num,
91 Element => Name_Location,
92 No_Element => No_Name_Location,
93 Key => File_Name_Type,
96 -- Hash table to store file names found in string list attribute
97 -- Source_Files or in a source list file, stored in hash table
98 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
100 -- More documentation needed on what unit exceptions are about ???
102 type Unit_Exception is record
104 Spec : File_Name_Type;
105 Impl : File_Name_Type;
108 No_Unit_Exception : constant Unit_Exception :=
113 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
114 (Header_Num => Header_Num,
115 Element => Unit_Exception,
116 No_Element => No_Unit_Exception,
120 -- Hash table to store the unit exceptions
122 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
123 (Header_Num => Header_Num,
129 -- Hash table to store recursive source directories, to avoid looking
130 -- several times, and to avoid cycles that may be introduced by symbolic
133 type Ada_Naming_Exception_Id is new Nat;
134 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
136 type Unit_Info is record
139 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
141 -- No_Unit : constant Unit_Info :=
142 -- (Specification, No_Name, No_Ada_Naming_Exception);
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
149 Table_Increment => 100,
150 Table_Name => "Prj
.Nmsc
.Ada_Naming_Exception_Table
");
152 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
153 (Header_Num => Header_Num,
154 Element => Ada_Naming_Exception_Id,
155 No_Element => No_Ada_Naming_Exception,
156 Key => File_Name_Type,
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 type File_Found is record
163 File : File_Name_Type := No_File;
164 Found : Boolean := False;
165 Location : Source_Ptr := No_Location;
167 No_File_Found : constant File_Found := (No_File, False, No_Location);
169 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
170 (Header_Num => Header_Num,
171 Element => File_Found,
172 No_Element => No_File_Found,
173 Key => File_Name_Type,
176 -- A hash table to store the excluded files, if any. This is filled by
177 -- Find_Excluded_Sources below
179 procedure Find_Excluded_Sources
180 (In_Tree : Project_Tree_Ref;
181 Data : Project_Data);
182 -- Find the list of files that should not be considered as source files
184 -- Sets the list in the Excluded_Sources_Htable
186 function Hash (Unit : Unit_Info) return Header_Num;
188 type Name_And_Index is record
189 Name : Name_Id := No_Name;
192 No_Name_And_Index : constant Name_And_Index :=
193 (Name => No_Name, Index => 0);
195 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
196 (Header_Num => Header_Num,
197 Element => Name_And_Index,
198 No_Element => No_Name_And_Index,
202 -- A table to check if a unit with an exceptional name will hide
203 -- a source with a file name following the naming convention.
207 Data : in out Project_Data;
208 In_Tree : Project_Tree_Ref;
209 Project : Project_Id;
211 Lang_Id : Language_Index;
213 File_Name : File_Name_Type;
214 Display_File : File_Name_Type;
215 Lang_Kind : Language_Kind;
216 Naming_Exception : Boolean := False;
217 Path : Path_Name_Type := No_Path;
218 Display_Path : Path_Name_Type := No_Path;
219 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
220 Other_Part : Source_Id := No_Source;
221 Unit : Name_Id := No_Name;
223 Source_To_Replace : Source_Id := No_Source);
224 -- Add a new source to the different lists: list of all sources in the
225 -- project tree, list of source of a project and list of sources of a
227 -- If Path is specified, the file is also added to Source_Paths_HT.
228 -- If Source_To_Replace is specified, it points to the source in the
229 -- extended project that the new file is overriding.
231 function ALI_File_Name (Source : String) return String;
232 -- Return the ALI file name corresponding to a source
234 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
235 -- Check that a name is a valid Ada unit name
237 procedure Check_Naming_Schemes
238 (Data : in out Project_Data;
239 Project : Project_Id;
240 In_Tree : Project_Tree_Ref);
241 -- Check the naming scheme part of Data
243 procedure Check_Ada_Naming_Scheme_Validity
244 (Project : Project_Id;
245 In_Tree : Project_Tree_Ref;
246 Naming : Naming_Data);
247 -- Check that the package Naming is correct
249 procedure Check_Configuration
250 (Project : Project_Id;
251 In_Tree : Project_Tree_Ref;
252 Data : in out Project_Data);
253 -- Check the configuration attributes for the project
255 procedure Check_For_Source
256 (File_Name : File_Name_Type;
257 Path_Name : Path_Name_Type;
258 Project : Project_Id;
259 In_Tree : Project_Tree_Ref;
260 Data : in out Project_Data;
261 Location : Source_Ptr;
262 Language : Language_Index;
264 Naming_Exception : Boolean);
265 -- Check if a file, with name File_Name and path Path_Name, in a source
266 -- directory is a source for language Language in project Project of
267 -- project tree In_Tree. ???
269 procedure Check_If_Externally_Built
270 (Project : Project_Id;
271 In_Tree : Project_Tree_Ref;
272 Data : in out Project_Data);
273 -- Check attribute Externally_Built of project Project in project tree
274 -- In_Tree and modify its data Data if it has the value "true".
276 procedure Check_Library_Attributes
277 (Project : Project_Id;
278 In_Tree : Project_Tree_Ref;
279 Current_Dir : String;
280 Data : in out Project_Data);
281 -- Check the library attributes of project Project in project tree In_Tree
282 -- and modify its data Data accordingly.
283 -- Current_Dir should represent the current directory, and is passed for
284 -- efficiency to avoid system calls to recompute it
286 procedure Check_Package_Naming
287 (Project : Project_Id;
288 In_Tree : Project_Tree_Ref;
289 Data : in out Project_Data);
290 -- Check package Naming of project Project in project tree In_Tree and
291 -- modify its data Data accordingly.
293 procedure Check_Programming_Languages
294 (In_Tree : Project_Tree_Ref;
295 Project : Project_Id;
296 Data : in out Project_Data);
297 -- Check attribute Languages for the project with data Data in project
298 -- tree In_Tree and set the components of Data for all the programming
299 -- languages indicated in attribute Languages, if any.
301 function Check_Project
303 Root_Project : Project_Id;
304 In_Tree : Project_Tree_Ref;
305 Extending : Boolean) return Boolean;
306 -- Returns True if P is Root_Project or, if Extending is True, a project
307 -- extended by Root_Project.
309 procedure Check_Stand_Alone_Library
310 (Project : Project_Id;
311 In_Tree : Project_Tree_Ref;
312 Data : in out Project_Data;
313 Current_Dir : String;
314 Extending : Boolean);
315 -- Check if project Project in project tree In_Tree is a Stand-Alone
316 -- Library project, and modify its data Data accordingly if it is one.
317 -- Current_Dir should represent the current directory, and is passed for
318 -- efficiency to avoid system calls to recompute it
320 procedure Get_Path_Names_And_Record_Ada_Sources
321 (Project : Project_Id;
322 In_Tree : Project_Tree_Ref;
323 Data : in out Project_Data;
324 Current_Dir : String);
325 -- Find the path names of the source files in the Source_Names table
326 -- in the source directories and record those that are Ada sources.
328 function Compute_Directory_Last (Dir : String) return Natural;
329 -- Return the index of the last significant character in Dir. This is used
330 -- to avoid duplicates '/' at the end of directory names
333 (Project : Project_Id;
334 In_Tree : Project_Tree_Ref;
336 Flag_Location : Source_Ptr);
337 -- Output an error message. If Error_Report is null, simply call
338 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
341 procedure Find_Ada_Sources
342 (Project : Project_Id;
343 In_Tree : Project_Tree_Ref;
344 Data : in out Project_Data;
345 Current_Dir : String);
346 -- Find all the Ada sources in all of the source directories of a project
347 -- Current_Dir should represent the current directory, and is passed for
348 -- efficiency to avoid system calls to recompute it
350 procedure Find_Sources
351 (Project : Project_Id;
352 In_Tree : Project_Tree_Ref;
353 Data : in out Project_Data;
354 For_Language : Language_Index;
355 Current_Dir : String);
356 -- Find all the sources in all of the source directories of a project for
357 -- a specified language.
359 procedure Search_Directories
360 (Project : Project_Id;
361 In_Tree : Project_Tree_Ref;
362 Data : in out Project_Data;
363 For_All_Sources : Boolean);
364 -- Search the source directories to find the sources.
365 -- If For_All_Sources is True, check each regular file name against
366 -- the naming schemes of the different languages. Otherwise consider
367 -- only the file names in the hash table Source_Names.
370 (Project : Project_Id;
371 In_Tree : Project_Tree_Ref;
372 Data : in out Project_Data;
374 File_Name : File_Name_Type;
375 Display_File_Name : File_Name_Type;
376 Source_Directory : String;
377 For_All_Sources : Boolean);
378 -- Check if file File_Name is a valid source of the project. This is used
379 -- in multi-language mode only.
380 -- When the file matches one of the naming schemes, it is added to
381 -- various htables through Add_Source and to Source_Paths_Htable.
383 -- Name is the name of the candidate file. It hasn't been normalized yet
384 -- and is the direct result of readdir().
386 -- File_Name is the same as Name, but has been normalized.
387 -- Display_File_Name, however, has not been normalized.
389 -- Source_Directory is the directory in which the file
390 -- was found. It hasn't been normalized (nor has had links resolved).
391 -- It should not end with a directory separator, to avoid duplicates
394 -- If For_All_Sources is True, then all possible file names are analyzed
395 -- otherwise only those currently set in the Source_Names htable.
397 procedure Check_Naming_Schemes
398 (In_Tree : Project_Tree_Ref;
399 Data : in out Project_Data;
401 File_Name : File_Name_Type;
402 Alternate_Languages : out Alternate_Language_Id;
403 Language : out Language_Index;
404 Language_Name : out Name_Id;
405 Display_Language_Name : out Name_Id;
407 Lang_Kind : out Language_Kind;
408 Kind : out Source_Kind);
409 -- Check if the file name File_Name conforms to one of the naming
410 -- schemes of the project.
411 -- If the file does not match one of the naming schemes, set Language
412 -- to No_Language_Index.
413 -- Filename is the name of the file being investigated. It has been
414 -- normalized (case-folded). File_Name is the same value.
416 procedure Free_Ada_Naming_Exceptions;
417 -- Free the internal hash tables used for checking naming exceptions
419 procedure Get_Directories
420 (Project : Project_Id;
421 In_Tree : Project_Tree_Ref;
422 Current_Dir : String;
423 Data : in out Project_Data);
424 -- Get the object directory, the exec directory and the source directories
426 -- Current_Dir should represent the current directory, and is passed for
427 -- efficiency to avoid system calls to recompute it
430 (Project : Project_Id;
431 In_Tree : Project_Tree_Ref;
432 Data : in out Project_Data);
433 -- Get the mains of a project from attribute Main, if it exists, and put
434 -- them in the project data.
436 procedure Get_Sources_From_File
438 Location : Source_Ptr;
439 Project : Project_Id;
440 In_Tree : Project_Tree_Ref);
441 -- Get the list of sources from a text file and put them in hash table
444 procedure Find_Explicit_Sources
445 (Lang : Language_Index;
446 Current_Dir : String;
447 Project : Project_Id;
448 In_Tree : Project_Tree_Ref;
449 Data : in out Project_Data);
450 -- Process the Source_Files and Source_List_File attributes, and store
451 -- the list of source files into the Source_Names htable.
452 -- Lang indicates which language is being processed when in Ada_Only
453 -- mode (all languages are processed anyway when in Multi_Language mode)
456 (In_Tree : Project_Tree_Ref;
457 Canonical_File_Name : File_Name_Type;
458 Naming : Naming_Data;
459 Exception_Id : out Ada_Naming_Exception_Id;
460 Unit_Name : out Name_Id;
461 Unit_Kind : out Spec_Or_Body;
462 Needs_Pragma : out Boolean);
463 -- Find out, from a file name, the unit name, the unit kind and if a
464 -- specific SFN pragma is needed. If the file name corresponds to no
465 -- unit, then Unit_Name will be No_Name. If the file is a multi-unit source
466 -- or an exception to the naming scheme, then Exception_Id is set to
467 -- the unit or units that the source contains.
469 function Is_Illegal_Suffix
471 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
472 -- Returns True if the string Suffix cannot be used as
473 -- a spec suffix, a body suffix or a separate suffix.
475 procedure Locate_Directory
476 (Project : Project_Id;
477 In_Tree : Project_Tree_Ref;
478 Name : File_Name_Type;
479 Parent : Path_Name_Type;
480 Dir : out Path_Name_Type;
481 Display : out Path_Name_Type;
482 Create : String := "";
483 Current_Dir : String;
484 Location : Source_Ptr := No_Location);
485 -- Locate a directory. Name is the directory name. Parent is the root
486 -- directory, if Name a relative path name. Dir is set to the canonical
487 -- case path name of the directory, and Display is the directory path name
488 -- for display purposes. If the directory does not exist and Project_Setup
489 -- is True and Create is a non null string, an attempt is made to create
490 -- the directory. If the directory does not exist and Project_Setup is
491 -- 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.
502 -- Current_Dir should represent the current directory, and is passed for
503 -- efficiency to avoid system calls to recompute it
505 function Path_Name_Of
506 (File_Name : File_Name_Type;
507 Directory : Path_Name_Type) return String;
508 -- Returns the path name of a (non project) file.
509 -- Returns an empty string if file cannot be found.
511 procedure Prepare_Ada_Naming_Exceptions
512 (List : Array_Element_Id;
513 In_Tree : Project_Tree_Ref;
514 Kind : Spec_Or_Body);
515 -- Prepare the internal hash tables used for checking naming exceptions
516 -- for Ada. Insert all elements of List in the tables.
518 function Project_Extends
519 (Extending : Project_Id;
520 Extended : Project_Id;
521 In_Tree : Project_Tree_Ref) return Boolean;
522 -- Returns True if Extending is extending Extended either directly or
525 procedure Record_Ada_Source
526 (File_Name : File_Name_Type;
527 Path_Name : Path_Name_Type;
528 Project : Project_Id;
529 In_Tree : Project_Tree_Ref;
530 Data : in out Project_Data;
531 Location : Source_Ptr;
532 Current_Source : in out String_List_Id;
533 Source_Recorded : in out Boolean;
534 Current_Dir : String);
535 -- Put a unit in the list of units of a project, if the file name
536 -- corresponds to a valid unit name.
537 -- Current_Dir should represent the current directory, and is passed for
538 -- efficiency to avoid system calls to recompute it
540 procedure Record_Other_Sources
541 (Project : Project_Id;
542 In_Tree : Project_Tree_Ref;
543 Data : in out Project_Data;
544 Language : Language_Index;
545 Naming_Exceptions : Boolean);
546 -- Record the sources of a language in a project.
547 -- When Naming_Exceptions is True, mark the found sources as such, to
548 -- later remove those that are not named in a list of sources.
550 procedure Remove_Source
552 Replaced_By : Source_Id;
553 Project : Project_Id;
554 Data : in out Project_Data;
555 In_Tree : Project_Tree_Ref);
557 procedure Report_No_Sources
558 (Project : Project_Id;
560 In_Tree : Project_Tree_Ref;
561 Location : Source_Ptr);
562 -- Report an error or a warning depending on the value of When_No_Sources
563 -- when there are no sources for language Lang_Name.
565 procedure Show_Source_Dirs
566 (Data : Project_Data; In_Tree : Project_Tree_Ref);
567 -- List all the source directories of a project
570 (Language : Language_Index;
571 Naming : Naming_Data;
572 In_Tree : Project_Tree_Ref) return File_Name_Type;
573 -- Get the suffix for the source of a language from a package naming.
574 -- If not specified, return the default for the language.
576 procedure Warn_If_Not_Sources
577 (Project : Project_Id;
578 In_Tree : Project_Tree_Ref;
579 Conventions : Array_Element_Id;
581 Extending : Boolean);
582 -- Check that individual naming conventions apply to immediate
583 -- sources of the project; if not, issue a warning.
591 Data : in out Project_Data;
592 In_Tree : Project_Tree_Ref;
593 Project : Project_Id;
595 Lang_Id : Language_Index;
597 File_Name : File_Name_Type;
598 Display_File : File_Name_Type;
599 Lang_Kind : Language_Kind;
600 Naming_Exception : Boolean := False;
601 Path : Path_Name_Type := No_Path;
602 Display_Path : Path_Name_Type := No_Path;
603 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
604 Other_Part : Source_Id := No_Source;
605 Unit : Name_Id := No_Name;
607 Source_To_Replace : Source_Id := No_Source)
609 Source : constant Source_Id := Data.Last_Source;
610 Src_Data : Source_Data := No_Source_Data;
613 -- This is a new source. Create an entry for it in the Sources table.
615 Source_Data_Table.Increment_Last (In_Tree.Sources);
616 Id := Source_Data_Table.Last (In_Tree.Sources);
618 if Current_Verbosity = High then
619 Write_Str ("Adding source #
");
621 Write_Str (", File
: ");
623 if Lang_Kind = Unit_Based then
624 Write_Str (", Unit
: ");
625 Write_Str (Get_Name_String (Unit));
628 Write_Line (Get_Name_String (File_Name));
631 Src_Data.Project := Project;
632 Src_Data.Language_Name := Lang;
633 Src_Data.Language := Lang_Id;
634 Src_Data.Lang_Kind := Lang_Kind;
635 Src_Data.Kind := Kind;
636 Src_Data.Alternate_Languages := Alternate_Languages;
637 Src_Data.Other_Part := Other_Part;
638 Src_Data.Unit := Unit;
639 Src_Data.Index := Index;
640 Src_Data.File := File_Name;
641 Src_Data.Object := Object_Name (File_Name);
642 Src_Data.Display_File := Display_File;
643 Src_Data.Dependency :=
644 In_Tree.Languages_Data.Table (Lang_Id).Config.Dependency_Kind;
645 Src_Data.Dep_Name := Dependency_Name (File_Name, Src_Data.Dependency);
646 Src_Data.Switches := Switches_Name (File_Name);
647 Src_Data.Naming_Exception := Naming_Exception;
649 if Path /= No_Path then
650 Src_Data.Path := Path;
651 Src_Data.Display_Path := Display_Path;
652 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
655 -- Add the source to the global list
657 Src_Data.Next_In_Sources := In_Tree.First_Source;
658 In_Tree.First_Source := Id;
660 -- Add the source to the project list
662 if Source = No_Source then
663 Data.First_Source := Id;
665 In_Tree.Sources.Table (Source).Next_In_Project := Id;
668 Data.Last_Source := Id;
670 -- Add the source to the language list
672 Src_Data.Next_In_Lang :=
673 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
674 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
676 In_Tree.Sources.Table (Id) := Src_Data;
678 if Source_To_Replace /= No_Source then
679 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
687 function ALI_File_Name (Source : String) return String is
689 -- If the source name has an extension, then replace it with
692 for Index in reverse Source'First + 1 .. Source'Last loop
693 if Source (Index) = '.' then
694 return Source (Source'First .. Index - 1) & ALI_Suffix;
698 -- If there is no dot, or if it is the first character, just add the
701 return Source & ALI_Suffix;
709 (Project : Project_Id;
710 In_Tree : Project_Tree_Ref;
711 Report_Error : Put_Line_Access;
712 When_No_Sources : Error_Warning;
713 Current_Dir : String)
715 Data : Project_Data := In_Tree.Projects.Table (Project);
716 Extending : Boolean := False;
719 Nmsc.When_No_Sources := When_No_Sources;
720 Error_Report := Report_Error;
722 Recursive_Dirs.Reset;
724 Check_If_Externally_Built (Project, In_Tree, Data);
726 -- Object, exec and source directories
728 Get_Directories (Project, In_Tree, Current_Dir, Data);
730 -- Get the programming languages
732 Check_Programming_Languages (In_Tree, Project, Data);
734 -- Check configuration in multi language mode
736 if Must_Check_Configuration then
737 Check_Configuration (Project, In_Tree, Data);
740 -- Library attributes
742 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
744 if Current_Verbosity = High then
745 Show_Source_Dirs (Data, In_Tree);
748 Check_Package_Naming (Project, In_Tree, Data);
750 Extending := Data.Extends /= No_Project;
752 Check_Naming_Schemes (Data, Project, In_Tree);
754 if Get_Mode = Ada_Only then
755 Prepare_Ada_Naming_Exceptions
756 (Data.Naming.Bodies, In_Tree, Body_Part);
757 Prepare_Ada_Naming_Exceptions
758 (Data.Naming.Specs, In_Tree, Specification);
763 if Data.Source_Dirs /= Nil_String then
764 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
766 if Get_Mode = Ada_Only then
768 -- Check that all individual naming conventions apply to sources
769 -- of this project file.
772 (Project, In_Tree, Data.Naming.Bodies,
774 Extending => Extending);
776 (Project, In_Tree, Data.Naming.Specs,
778 Extending => Extending);
780 elsif Get_Mode = Multi_Language and then
781 (not Data.Externally_Built) and then
785 Language : Language_Index;
787 Src_Data : Source_Data;
788 Alt_Lang : Alternate_Language_Id;
789 Alt_Lang_Data : Alternate_Language_Data;
792 Language := Data.First_Language_Processing;
793 while Language /= No_Language_Index loop
794 Source := Data.First_Source;
795 Source_Loop : while Source /= No_Source loop
796 Src_Data := In_Tree.Sources.Table (Source);
798 exit Source_Loop when Src_Data.Language = Language;
800 Alt_Lang := Src_Data.Alternate_Languages;
803 while Alt_Lang /= No_Alternate_Language loop
805 In_Tree.Alt_Langs.Table (Alt_Lang);
807 when Alt_Lang_Data.Language = Language;
808 Alt_Lang := Alt_Lang_Data.Next;
809 end loop Alternate_Loop;
811 Source := Src_Data.Next_In_Project;
812 end loop Source_Loop;
814 if Source = No_Source then
818 (In_Tree.Languages_Data.Table
819 (Language).Display_Name),
824 Language := In_Tree.Languages_Data.Table (Language).Next;
830 -- If it is a library project file, check if it is a standalone library
833 Check_Stand_Alone_Library
834 (Project, In_Tree, Data, Current_Dir, Extending);
837 -- Put the list of Mains, if any, in the project data
839 Get_Mains (Project, In_Tree, Data);
841 -- Update the project data in the Projects table
843 In_Tree.Projects.Table (Project) := Data;
845 Free_Ada_Naming_Exceptions;
852 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
853 The_Name : String := Name;
855 Need_Letter : Boolean := True;
856 Last_Underscore : Boolean := False;
857 OK : Boolean := The_Name'Length > 0;
860 function Is_Reserved (Name : Name_Id) return Boolean;
861 function Is_Reserved (S : String) return Boolean;
862 -- Check that the given name is not an Ada 95 reserved word. The reason
863 -- for the Ada 95 here is that we do not want to exclude the case of an
864 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
865 -- name would be rejected anyway by the compiler. That means there is no
866 -- requirement that the project file parser reject this.
872 function Is_Reserved (S : String) return Boolean is
875 Add_Str_To_Name_Buffer (S);
876 return Is_Reserved (Name_Find);
883 function Is_Reserved (Name : Name_Id) return Boolean is
885 if Get_Name_Table_Byte (Name) /= 0
886 and then Name /= Name_Project
887 and then Name /= Name_Extends
888 and then Name /= Name_External
889 and then Name not in Ada_2005_Reserved_Words
893 if Current_Verbosity = High then
894 Write_Str (The_Name);
895 Write_Line (" is an Ada reserved word
.");
905 -- Start of processing for Check_Ada_Name
910 Name_Len := The_Name'Length;
911 Name_Buffer (1 .. Name_Len) := The_Name;
913 -- Special cases of children of packages A, G, I and S on VMS
916 and then Name_Len > 3
917 and then Name_Buffer (2 .. 3) = "__
"
919 ((Name_Buffer (1) = 'a') or else
920 (Name_Buffer (1) = 'g') or else
921 (Name_Buffer (1) = 'i') or else
922 (Name_Buffer (1) = 's'))
924 Name_Buffer (2) := '.';
925 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
926 Name_Len := Name_Len - 1;
929 Real_Name := Name_Find;
931 if Is_Reserved (Real_Name) then
935 First := The_Name'First;
937 for Index in The_Name'Range loop
940 -- We need a letter (at the beginning, and following a dot),
941 -- but we don't have one.
943 if Is_Letter (The_Name (Index)) then
944 Need_Letter := False;
949 if Current_Verbosity = High then
950 Write_Int (Types.Int (Index));
952 Write_Char (The_Name (Index));
953 Write_Line ("' is not a letter
.");
959 elsif Last_Underscore
960 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
962 -- Two underscores are illegal, and a dot cannot follow
967 if Current_Verbosity = High then
968 Write_Int (Types.Int (Index));
970 Write_Char (The_Name (Index));
971 Write_Line ("' is illegal here
.");
976 elsif The_Name (Index) = '.' then
978 -- First, check if the name before the dot is not a reserved word
979 if Is_Reserved (The_Name (First .. Index - 1)) then
985 -- We need a letter after a dot
989 elsif The_Name (Index) = '_' then
990 Last_Underscore := True;
993 -- We need an letter or a digit
995 Last_Underscore := False;
997 if not Is_Alphanumeric (The_Name (Index)) then
1000 if Current_Verbosity = High then
1001 Write_Int (Types.Int (Index));
1003 Write_Char (The_Name (Index));
1004 Write_Line ("' is not alphanumeric
.");
1012 -- Cannot end with an underscore or a dot
1014 OK := OK and then not Need_Letter and then not Last_Underscore;
1017 if First /= Name'First and then
1018 Is_Reserved (The_Name (First .. The_Name'Last))
1026 -- Signal a problem with No_Name
1032 --------------------------------------
1033 -- Check_Ada_Naming_Scheme_Validity --
1034 --------------------------------------
1036 procedure Check_Ada_Naming_Scheme_Validity
1037 (Project : Project_Id;
1038 In_Tree : Project_Tree_Ref;
1039 Naming : Naming_Data)
1042 -- Only check if we are not using the Default naming scheme
1044 if Naming /= In_Tree.Private_Part.Default_Naming then
1046 Dot_Replacement : constant String :=
1048 (Naming.Dot_Replacement);
1050 Spec_Suffix : constant String :=
1051 Spec_Suffix_Of (In_Tree, "ada
", Naming);
1053 Body_Suffix : constant String :=
1054 Body_Suffix_Of (In_Tree, "ada
", Naming);
1056 Separate_Suffix : constant String :=
1058 (Naming.Separate_Suffix);
1061 -- Dot_Replacement cannot
1064 -- - start or end with an alphanumeric
1065 -- - be a single '_'
1066 -- - start with an '_' followed by an alphanumeric
1067 -- - contain a '.' except if it is "."
1069 if Dot_Replacement'Length = 0
1070 or else Is_Alphanumeric
1071 (Dot_Replacement (Dot_Replacement'First))
1072 or else Is_Alphanumeric
1073 (Dot_Replacement (Dot_Replacement'Last))
1074 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1076 (Dot_Replacement'Length = 1
1079 (Dot_Replacement (Dot_Replacement'First + 1))))
1080 or else (Dot_Replacement'Length > 1
1082 Index (Source => Dot_Replacement,
1083 Pattern => ".") /= 0)
1087 '"' & Dot_Replacement &
1088 """ is illegal for Dot_Replacement.",
1089 Naming.Dot_Repl_Loc);
1095 if Is_Illegal_Suffix
1096 (Spec_Suffix, Dot_Replacement = ".")
1098 Err_Vars.Error_Msg_File_1 :=
1099 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1102 "{ is illegal for Spec_Suffix",
1103 Naming.Ada_Spec_Suffix_Loc);
1106 if Is_Illegal_Suffix
1107 (Body_Suffix, Dot_Replacement = ".")
1109 Err_Vars.Error_Msg_File_1 :=
1110 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1113 "{ is illegal for Body_Suffix",
1114 Naming.Ada_Body_Suffix_Loc);
1117 if Body_Suffix /= Separate_Suffix then
1118 if Is_Illegal_Suffix
1119 (Separate_Suffix, Dot_Replacement = ".")
1121 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1124 "{ is illegal for Separate_Suffix",
1125 Naming.Sep_Suffix_Loc);
1129 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1130 -- since that would cause a clear ambiguity. Note that we do
1131 -- allow a Spec_Suffix to have the same termination as one of
1132 -- these, which causes a potential ambiguity, but we resolve
1133 -- that my matching the longest possible suffix.
1135 if Spec_Suffix = Body_Suffix then
1140 """) cannot be the same as Spec_Suffix.",
1141 Naming.Ada_Body_Suffix_Loc);
1144 if Body_Suffix /= Separate_Suffix
1145 and then Spec_Suffix = Separate_Suffix
1149 "Separate_Suffix (""" &
1151 """) cannot be the same as Spec_Suffix.",
1152 Naming.Sep_Suffix_Loc);
1156 end Check_Ada_Naming_Scheme_Validity;
1158 -------------------------
1159 -- Check_Configuration --
1160 -------------------------
1162 procedure Check_Configuration
1163 (Project : Project_Id;
1164 In_Tree : Project_Tree_Ref;
1165 Data : in out Project_Data)
1167 Dot_Replacement : File_Name_Type := No_File;
1168 Casing : Casing_Type := All_Lower_Case;
1169 Separate_Suffix : File_Name_Type := No_File;
1171 Lang_Index : Language_Index := No_Language_Index;
1172 -- The index of the language data being checked
1174 Prev_Index : Language_Index := No_Language_Index;
1175 -- The index of the previous language
1177 Current_Language : Name_Id := No_Name;
1178 -- The name of the language
1180 Lang_Data : Language_Data;
1181 -- The data of the language being checked
1183 procedure Get_Language_Index_Of (Language : Name_Id);
1184 -- Get the language index of Language, if Language is one of the
1185 -- languages of the project.
1187 procedure Process_Project_Level_Simple_Attributes;
1188 -- Process the simple attributes at the project level
1190 procedure Process_Project_Level_Array_Attributes;
1191 -- Process the associate array attributes at the project level
1193 procedure Process_Packages;
1194 -- Read the packages of the project
1196 ---------------------------
1197 -- Get_Language_Index_Of --
1198 ---------------------------
1200 procedure Get_Language_Index_Of (Language : Name_Id) is
1201 Real_Language : Name_Id;
1204 Get_Name_String (Language);
1205 To_Lower (Name_Buffer (1 .. Name_Len));
1206 Real_Language := Name_Find;
1208 -- Nothing to do if the language is the same as the current language
1210 if Current_Language /= Real_Language then
1211 Lang_Index := Data.First_Language_Processing;
1212 while Lang_Index /= No_Language_Index loop
1213 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1216 In_Tree.Languages_Data.Table (Lang_Index).Next;
1219 if Lang_Index = No_Language_Index then
1220 Current_Language := No_Name;
1222 Current_Language := Real_Language;
1225 end Get_Language_Index_Of;
1227 ----------------------
1228 -- Process_Packages --
1229 ----------------------
1231 procedure Process_Packages is
1232 Packages : Package_Id;
1233 Element : Package_Element;
1235 procedure Process_Binder (Arrays : Array_Id);
1236 -- Process the associate array attributes of package Binder
1238 procedure Process_Builder (Attributes : Variable_Id);
1239 -- Process the simple attributes of package Builder
1241 procedure Process_Compiler (Arrays : Array_Id);
1242 -- Process the associate array attributes of package Compiler
1244 procedure Process_Naming (Attributes : Variable_Id);
1245 -- Process the simple attributes of package Naming
1247 procedure Process_Naming (Arrays : Array_Id);
1248 -- Process the associate array attributes of package Naming
1250 procedure Process_Linker (Attributes : Variable_Id);
1251 -- Process the simple attributes of package Linker of a
1252 -- configuration project.
1254 --------------------
1255 -- Process_Binder --
1256 --------------------
1258 procedure Process_Binder (Arrays : Array_Id) is
1259 Current_Array_Id : Array_Id;
1260 Current_Array : Array_Data;
1261 Element_Id : Array_Element_Id;
1262 Element : Array_Element;
1265 -- Process the associative array attribute of package Binder
1267 Current_Array_Id := Arrays;
1268 while Current_Array_Id /= No_Array loop
1269 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1271 Element_Id := Current_Array.Value;
1272 while Element_Id /= No_Array_Element loop
1273 Element := In_Tree.Array_Elements.Table (Element_Id);
1275 -- Get the name of the language
1277 Get_Language_Index_Of (Element.Index);
1279 if Lang_Index /= No_Language_Index then
1280 case Current_Array.Name is
1283 -- Attribute Driver (<language>)
1285 In_Tree.Languages_Data.Table
1286 (Lang_Index).Config.Binder_Driver :=
1287 File_Name_Type (Element.Value.Value);
1289 when Name_Required_Switches =>
1291 In_Tree.Languages_Data.Table
1292 (Lang_Index).Config.Binder_Required_Switches,
1293 From_List => Element.Value.Values,
1294 In_Tree => In_Tree);
1298 -- Attribute Prefix (<language>)
1300 In_Tree.Languages_Data.Table
1301 (Lang_Index).Config.Binder_Prefix :=
1302 Element.Value.Value;
1304 when Name_Objects_Path =>
1306 -- Attribute Objects_Path (<language>)
1308 In_Tree.Languages_Data.Table
1309 (Lang_Index).Config.Objects_Path :=
1310 Element.Value.Value;
1312 when Name_Objects_Path_File =>
1314 -- Attribute Objects_Path (<language>)
1316 In_Tree.Languages_Data.Table
1317 (Lang_Index).Config.Objects_Path_File :=
1318 Element.Value.Value;
1325 Element_Id := Element.Next;
1328 Current_Array_Id := Current_Array.Next;
1332 ---------------------
1333 -- Process_Builder --
1334 ---------------------
1336 procedure Process_Builder (Attributes : Variable_Id) is
1337 Attribute_Id : Variable_Id;
1338 Attribute : Variable;
1341 -- Process non associated array attribute from package Builder
1343 Attribute_Id := Attributes;
1344 while Attribute_Id /= No_Variable loop
1346 In_Tree.Variable_Elements.Table (Attribute_Id);
1348 if not Attribute.Value.Default then
1349 if Attribute.Name = Name_Executable_Suffix then
1351 -- Attribute Executable_Suffix: the suffix of the
1354 Data.Config.Executable_Suffix :=
1355 Attribute.Value.Value;
1359 Attribute_Id := Attribute.Next;
1361 end Process_Builder;
1363 ----------------------
1364 -- Process_Compiler --
1365 ----------------------
1367 procedure Process_Compiler (Arrays : Array_Id) is
1368 Current_Array_Id : Array_Id;
1369 Current_Array : Array_Data;
1370 Element_Id : Array_Element_Id;
1371 Element : Array_Element;
1372 List : String_List_Id;
1375 -- Process the associative array attribute of package Compiler
1377 Current_Array_Id := Arrays;
1378 while Current_Array_Id /= No_Array loop
1379 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1381 Element_Id := Current_Array.Value;
1382 while Element_Id /= No_Array_Element loop
1383 Element := In_Tree.Array_Elements.Table (Element_Id);
1385 -- Get the name of the language
1387 Get_Language_Index_Of (Element.Index);
1389 if Lang_Index /= No_Language_Index then
1390 case Current_Array.Name is
1391 when Name_Dependency_Switches =>
1393 -- Attribute Dependency_Switches (<language>)
1395 if In_Tree.Languages_Data.Table
1396 (Lang_Index).Config.Dependency_Kind = None
1398 In_Tree.Languages_Data.Table
1399 (Lang_Index).Config.Dependency_Kind :=
1403 List := Element.Value.Values;
1405 if List /= Nil_String then
1407 In_Tree.Languages_Data.Table
1408 (Lang_Index).Config.Dependency_Option,
1410 In_Tree => In_Tree);
1413 when Name_Dependency_Driver =>
1415 -- Attribute Dependency_Driver (<language>)
1417 if In_Tree.Languages_Data.Table
1418 (Lang_Index).Config.Dependency_Kind = None
1420 In_Tree.Languages_Data.Table
1421 (Lang_Index).Config.Dependency_Kind :=
1425 List := Element.Value.Values;
1427 if List /= Nil_String then
1429 In_Tree.Languages_Data.Table
1430 (Lang_Index).Config.Compute_Dependency,
1432 In_Tree => In_Tree);
1435 when Name_Include_Switches =>
1437 -- Attribute Include_Switches (<language>)
1439 List := Element.Value.Values;
1441 if List = Nil_String then
1445 "include option cannot be null",
1446 Element.Value.Location);
1450 In_Tree.Languages_Data.Table
1451 (Lang_Index).Config.Include_Option,
1453 In_Tree => In_Tree);
1455 when Name_Include_Path =>
1457 -- Attribute Include_Path (<language>)
1459 In_Tree.Languages_Data.Table
1460 (Lang_Index).Config.Include_Path :=
1461 Element.Value.Value;
1463 when Name_Include_Path_File =>
1465 -- Attribute Include_Path_File (<language>)
1467 In_Tree.Languages_Data.Table
1468 (Lang_Index).Config.Include_Path_File :=
1469 Element.Value.Value;
1473 -- Attribute Driver (<language>)
1475 Get_Name_String (Element.Value.Value);
1477 if Name_Len = 0 then
1481 "compiler driver name cannot be empty",
1482 Element.Value.Location);
1485 In_Tree.Languages_Data.Table
1486 (Lang_Index).Config.Compiler_Driver :=
1487 File_Name_Type (Element.Value.Value);
1489 when Name_Required_Switches =>
1491 In_Tree.Languages_Data.Table
1492 (Lang_Index).Config.
1493 Compiler_Required_Switches,
1494 From_List => Element.Value.Values,
1495 In_Tree => In_Tree);
1497 when Name_Pic_Option =>
1499 -- Attribute Compiler_Pic_Option (<language>)
1501 List := Element.Value.Values;
1503 if List = Nil_String then
1507 "compiler PIC option cannot be null",
1508 Element.Value.Location);
1512 In_Tree.Languages_Data.Table
1513 (Lang_Index).Config.Compilation_PIC_Option,
1515 In_Tree => In_Tree);
1517 when Name_Mapping_File_Switches =>
1519 -- Attribute Mapping_File_Switches (<language>)
1521 List := Element.Value.Values;
1523 if List = Nil_String then
1527 "mapping file switches cannot be null",
1528 Element.Value.Location);
1532 In_Tree.Languages_Data.Table
1533 (Lang_Index).Config.Mapping_File_Switches,
1535 In_Tree => In_Tree);
1537 when Name_Mapping_Spec_Suffix =>
1539 -- Attribute Mapping_Spec_Suffix (<language>)
1541 In_Tree.Languages_Data.Table
1542 (Lang_Index).Config.Mapping_Spec_Suffix :=
1543 File_Name_Type (Element.Value.Value);
1545 when Name_Mapping_Body_Suffix =>
1547 -- Attribute Mapping_Body_Suffix (<language>)
1549 In_Tree.Languages_Data.Table
1550 (Lang_Index).Config.Mapping_Body_Suffix :=
1551 File_Name_Type (Element.Value.Value);
1553 when Name_Config_File_Switches =>
1555 -- Attribute Config_File_Switches (<language>)
1557 List := Element.Value.Values;
1559 if List = Nil_String then
1563 "config file switches cannot be null",
1564 Element.Value.Location);
1568 In_Tree.Languages_Data.Table
1569 (Lang_Index).Config.Config_File_Switches,
1571 In_Tree => In_Tree);
1573 when Name_Objects_Path =>
1575 -- Attribute Objects_Path (<language>)
1577 In_Tree.Languages_Data.Table
1578 (Lang_Index).Config.Objects_Path :=
1579 Element.Value.Value;
1581 when Name_Objects_Path_File =>
1583 -- Attribute Objects_Path_File (<language>)
1585 In_Tree.Languages_Data.Table
1586 (Lang_Index).Config.Objects_Path_File :=
1587 Element.Value.Value;
1589 when Name_Config_Body_File_Name =>
1591 -- Attribute Config_Body_File_Name (<language>)
1593 In_Tree.Languages_Data.Table
1594 (Lang_Index).Config.Config_Body :=
1595 Element.Value.Value;
1597 when Name_Config_Body_File_Name_Pattern =>
1599 -- Attribute Config_Body_File_Name_Pattern
1602 In_Tree.Languages_Data.Table
1603 (Lang_Index).Config.Config_Body_Pattern :=
1604 Element.Value.Value;
1606 when Name_Config_Spec_File_Name =>
1608 -- Attribute Config_Spec_File_Name (<language>)
1610 In_Tree.Languages_Data.Table
1611 (Lang_Index).Config.Config_Spec :=
1612 Element.Value.Value;
1614 when Name_Config_Spec_File_Name_Pattern =>
1616 -- Attribute Config_Spec_File_Name_Pattern
1619 In_Tree.Languages_Data.Table
1620 (Lang_Index).Config.Config_Spec_Pattern :=
1621 Element.Value.Value;
1623 when Name_Config_File_Unique =>
1625 -- Attribute Config_File_Unique (<language>)
1628 In_Tree.Languages_Data.Table
1629 (Lang_Index).Config.Config_File_Unique :=
1631 (Get_Name_String (Element.Value.Value));
1633 when Constraint_Error =>
1637 "illegal value for Config_File_Unique",
1638 Element.Value.Location);
1646 Element_Id := Element.Next;
1649 Current_Array_Id := Current_Array.Next;
1651 end Process_Compiler;
1653 --------------------
1654 -- Process_Naming --
1655 --------------------
1657 procedure Process_Naming (Attributes : Variable_Id) is
1658 Attribute_Id : Variable_Id;
1659 Attribute : Variable;
1662 -- Process non associated array attribute from package Naming
1664 Attribute_Id := Attributes;
1665 while Attribute_Id /= No_Variable loop
1667 In_Tree.Variable_Elements.Table (Attribute_Id);
1669 if not Attribute.Value.Default then
1670 if Attribute.Name = Name_Separate_Suffix then
1672 -- Attribute Separate_Suffix
1674 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1676 elsif Attribute.Name = Name_Casing then
1682 Value (Get_Name_String (Attribute.Value.Value));
1685 when Constraint_Error =>
1689 "invalid value for Casing",
1690 Attribute.Value.Location);
1693 elsif Attribute.Name = Name_Dot_Replacement then
1695 -- Attribute Dot_Replacement
1697 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1702 Attribute_Id := Attribute.Next;
1706 procedure Process_Naming (Arrays : Array_Id) is
1707 Current_Array_Id : Array_Id;
1708 Current_Array : Array_Data;
1709 Element_Id : Array_Element_Id;
1710 Element : Array_Element;
1712 -- Process the associative array attribute of package Naming
1714 Current_Array_Id := Arrays;
1715 while Current_Array_Id /= No_Array loop
1716 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1718 Element_Id := Current_Array.Value;
1719 while Element_Id /= No_Array_Element loop
1720 Element := In_Tree.Array_Elements.Table (Element_Id);
1722 -- Get the name of the language
1724 Get_Language_Index_Of (Element.Index);
1726 if Lang_Index /= No_Language_Index then
1727 case Current_Array.Name is
1728 when Name_Specification_Suffix | Name_Spec_Suffix =>
1730 -- Attribute Spec_Suffix (<language>)
1732 In_Tree.Languages_Data.Table
1733 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1734 File_Name_Type (Element.Value.Value);
1736 when Name_Implementation_Suffix | Name_Body_Suffix =>
1738 -- Attribute Body_Suffix (<language>)
1740 In_Tree.Languages_Data.Table
1741 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1742 File_Name_Type (Element.Value.Value);
1744 In_Tree.Languages_Data.Table
1745 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1746 File_Name_Type (Element.Value.Value);
1753 Element_Id := Element.Next;
1756 Current_Array_Id := Current_Array.Next;
1760 --------------------
1761 -- Process_Linker --
1762 --------------------
1764 procedure Process_Linker (Attributes : Variable_Id) is
1765 Attribute_Id : Variable_Id;
1766 Attribute : Variable;
1769 -- Process non associated array attribute from package Linker
1771 Attribute_Id := Attributes;
1772 while Attribute_Id /= No_Variable loop
1774 In_Tree.Variable_Elements.Table (Attribute_Id);
1776 if not Attribute.Value.Default then
1777 if Attribute.Name = Name_Driver then
1779 -- Attribute Linker'Driver: the default linker to use
1781 Data.Config.Linker :=
1782 Path_Name_Type (Attribute.Value.Value);
1785 Attribute.Name = Name_Required_Switches
1788 -- Attribute Required_Switches: the minimum
1789 -- options to use when invoking the linker
1792 Data.Config.Minimum_Linker_Options,
1793 From_List => Attribute.Value.Values,
1794 In_Tree => In_Tree);
1799 Attribute_Id := Attribute.Next;
1803 -- Start of processing for Process_Packages
1806 Packages := Data.Decl.Packages;
1807 while Packages /= No_Package loop
1808 Element := In_Tree.Packages.Table (Packages);
1810 case Element.Name is
1813 -- Process attributes of package Binder
1815 Process_Binder (Element.Decl.Arrays);
1817 when Name_Builder =>
1819 -- Process attributes of package Builder
1821 Process_Builder (Element.Decl.Attributes);
1823 when Name_Compiler =>
1825 -- Process attributes of package Compiler
1827 Process_Compiler (Element.Decl.Arrays);
1831 -- Process attributes of package Linker
1833 Process_Linker (Element.Decl.Attributes);
1837 -- Process attributes of package Naming
1839 Process_Naming (Element.Decl.Attributes);
1840 Process_Naming (Element.Decl.Arrays);
1846 Packages := Element.Next;
1848 end Process_Packages;
1850 ---------------------------------------------
1851 -- Process_Project_Level_Simple_Attributes --
1852 ---------------------------------------------
1854 procedure Process_Project_Level_Simple_Attributes is
1855 Attribute_Id : Variable_Id;
1856 Attribute : Variable;
1857 List : String_List_Id;
1860 -- Process non associated array attribute at project level
1862 Attribute_Id := Data.Decl.Attributes;
1863 while Attribute_Id /= No_Variable loop
1865 In_Tree.Variable_Elements.Table (Attribute_Id);
1867 if not Attribute.Value.Default then
1868 if Attribute.Name = Name_Library_Builder then
1870 -- Attribute Library_Builder: the application to invoke
1871 -- to build libraries.
1873 Data.Config.Library_Builder :=
1874 Path_Name_Type (Attribute.Value.Value);
1876 elsif Attribute.Name = Name_Archive_Builder then
1878 -- Attribute Archive_Builder: the archive builder
1879 -- (usually "ar") and its minimum options (usually "cr").
1881 List := Attribute.Value.Values;
1883 if List = Nil_String then
1887 "archive builder cannot be null",
1888 Attribute.Value.Location);
1891 Put (Into_List => Data.Config.Archive_Builder,
1893 In_Tree => In_Tree);
1895 elsif Attribute.Name = Name_Archive_Indexer then
1897 -- Attribute Archive_Indexer: the optional archive
1898 -- indexer (usually "ranlib") with its minimum options
1901 List := Attribute.Value.Values;
1903 if List = Nil_String then
1907 "archive indexer cannot be null",
1908 Attribute.Value.Location);
1911 Put (Into_List => Data.Config.Archive_Indexer,
1913 In_Tree => In_Tree);
1915 elsif Attribute.Name = Name_Library_Partial_Linker then
1917 -- Attribute Library_Partial_Linker: the optional linker
1918 -- driver with its minimum options, to partially link
1921 List := Attribute.Value.Values;
1923 if List = Nil_String then
1927 "partial linker cannot be null",
1928 Attribute.Value.Location);
1931 Put (Into_List => Data.Config.Lib_Partial_Linker,
1933 In_Tree => In_Tree);
1935 elsif Attribute.Name = Name_Archive_Suffix then
1936 Data.Config.Archive_Suffix :=
1937 File_Name_Type (Attribute.Value.Value);
1939 elsif Attribute.Name = Name_Linker_Executable_Option then
1941 -- Attribute Linker_Executable_Option: optional options
1942 -- to specify an executable name. Defaults to "-o".
1944 List := Attribute.Value.Values;
1946 if List = Nil_String then
1950 "linker executable option cannot be null",
1951 Attribute.Value.Location);
1954 Put (Into_List => Data.Config.Linker_Executable_Option,
1956 In_Tree => In_Tree);
1958 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
1960 -- Attribute Linker_Lib_Dir_Option: optional options
1961 -- to specify a library search directory. Defaults to
1964 Get_Name_String (Attribute.Value.Value);
1966 if Name_Len = 0 then
1970 "linker library directory option cannot be empty",
1971 Attribute.Value.Location);
1974 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
1976 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
1978 -- Attribute Linker_Lib_Name_Option: optional options
1979 -- to specify the name of a library to be linked in.
1980 -- Defaults to "-l".
1982 Get_Name_String (Attribute.Value.Value);
1984 if Name_Len = 0 then
1988 "linker library name option cannot be empty",
1989 Attribute.Value.Location);
1992 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
1994 elsif Attribute.Name = Name_Run_Path_Option then
1996 -- Attribute Run_Path_Option: optional options to
1997 -- specify a path for libraries.
1999 List := Attribute.Value.Values;
2001 if List /= Nil_String then
2002 Put (Into_List => Data.Config.Run_Path_Option,
2004 In_Tree => In_Tree);
2007 elsif Attribute.Name = Name_Library_Support then
2009 pragma Unsuppress (All_Checks);
2011 Data.Config.Lib_Support :=
2012 Library_Support'Value (Get_Name_String
2013 (Attribute.Value.Value));
2015 when Constraint_Error =>
2019 "invalid value """ &
2020 Get_Name_String (Attribute.Value.Value) &
2021 """ for Library_Support",
2022 Attribute.Value.Location);
2025 elsif Attribute.Name = Name_Shared_Library_Prefix then
2026 Data.Config.Shared_Lib_Prefix :=
2027 File_Name_Type (Attribute.Value.Value);
2029 elsif Attribute.Name = Name_Shared_Library_Suffix then
2030 Data.Config.Shared_Lib_Suffix :=
2031 File_Name_Type (Attribute.Value.Value);
2033 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2035 pragma Unsuppress (All_Checks);
2037 Data.Config.Symbolic_Link_Supported :=
2038 Boolean'Value (Get_Name_String
2039 (Attribute.Value.Value));
2041 when Constraint_Error =>
2045 "invalid value """ &
2046 Get_Name_String (Attribute.Value.Value) &
2047 """ for Symbolic_Link_Supported",
2048 Attribute.Value.Location);
2052 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2055 pragma Unsuppress (All_Checks);
2057 Data.Config.Lib_Maj_Min_Id_Supported :=
2058 Boolean'Value (Get_Name_String
2059 (Attribute.Value.Value));
2061 when Constraint_Error =>
2065 "invalid value """ &
2066 Get_Name_String (Attribute.Value.Value) &
2067 """ for Library_Major_Minor_Id_Supported",
2068 Attribute.Value.Location);
2072 Attribute.Name = Name_Library_Auto_Init_Supported
2075 pragma Unsuppress (All_Checks);
2077 Data.Config.Auto_Init_Supported :=
2078 Boolean'Value (Get_Name_String
2079 (Attribute.Value.Value));
2081 when Constraint_Error =>
2085 "invalid value """ &
2086 Get_Name_String (Attribute.Value.Value) &
2087 """ for Library_Auto_Init_Supported",
2088 Attribute.Value.Location);
2092 Attribute.Name = Name_Shared_Library_Minimum_Switches
2094 List := Attribute.Value.Values;
2096 if List /= Nil_String then
2097 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2099 In_Tree => In_Tree);
2103 Attribute.Name = Name_Library_Version_Switches
2105 List := Attribute.Value.Values;
2107 if List /= Nil_String then
2108 Put (Into_List => Data.Config.Lib_Version_Options,
2110 In_Tree => In_Tree);
2115 Attribute_Id := Attribute.Next;
2117 end Process_Project_Level_Simple_Attributes;
2119 --------------------------------------------
2120 -- Process_Project_Level_Array_Attributes --
2121 --------------------------------------------
2123 procedure Process_Project_Level_Array_Attributes is
2124 Current_Array_Id : Array_Id;
2125 Current_Array : Array_Data;
2126 Element_Id : Array_Element_Id;
2127 Element : Array_Element;
2130 -- Process the associative array attributes at project level
2132 Current_Array_Id := Data.Decl.Arrays;
2133 while Current_Array_Id /= No_Array loop
2134 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2136 Element_Id := Current_Array.Value;
2137 while Element_Id /= No_Array_Element loop
2138 Element := In_Tree.Array_Elements.Table (Element_Id);
2140 -- Get the name of the language
2142 Get_Language_Index_Of (Element.Index);
2144 if Lang_Index /= No_Language_Index then
2145 case Current_Array.Name is
2146 when Name_Toolchain_Description =>
2148 -- Attribute Toolchain_Description (<language>)
2150 In_Tree.Languages_Data.Table
2151 (Lang_Index).Config.Toolchain_Description :=
2152 Element.Value.Value;
2154 when Name_Toolchain_Version =>
2156 -- Attribute Toolchain_Version (<language>)
2158 In_Tree.Languages_Data.Table
2159 (Lang_Index).Config.Toolchain_Version :=
2160 Element.Value.Value;
2162 when Name_Runtime_Library_Dir =>
2164 -- Attribute Runtime_Library_Dir (<language>)
2166 In_Tree.Languages_Data.Table
2167 (Lang_Index).Config.Runtime_Library_Dir :=
2168 Element.Value.Value;
2175 Element_Id := Element.Next;
2178 Current_Array_Id := Current_Array.Next;
2180 end Process_Project_Level_Array_Attributes;
2183 Process_Project_Level_Simple_Attributes;
2184 Process_Project_Level_Array_Attributes;
2187 -- For unit based languages, set Casing, Dot_Replacement and
2188 -- Separate_Suffix in Naming_Data.
2190 Lang_Index := Data.First_Language_Processing;
2191 while Lang_Index /= No_Language_Index loop
2192 if In_Tree.Languages_Data.Table
2193 (Lang_Index).Name = Name_Ada
2195 In_Tree.Languages_Data.Table
2196 (Lang_Index).Config.Naming_Data.Casing := Casing;
2197 In_Tree.Languages_Data.Table
2198 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2201 if Separate_Suffix /= No_File then
2202 In_Tree.Languages_Data.Table
2203 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2210 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2213 -- Give empty names to various prefixes/suffixes, if they have not
2214 -- been specified in the configuration.
2216 if Data.Config.Archive_Suffix = No_File then
2217 Data.Config.Archive_Suffix := Empty_File;
2220 if Data.Config.Shared_Lib_Prefix = No_File then
2221 Data.Config.Shared_Lib_Prefix := Empty_File;
2224 if Data.Config.Shared_Lib_Suffix = No_File then
2225 Data.Config.Shared_Lib_Suffix := Empty_File;
2228 Lang_Index := Data.First_Language_Processing;
2229 while Lang_Index /= No_Language_Index loop
2230 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2232 Current_Language := Lang_Data.Display_Name;
2234 -- For all languages, Compiler_Driver needs to be specified
2236 if Lang_Data.Config.Compiler_Driver = No_File then
2237 Error_Msg_Name_1 := Current_Language;
2241 "?no compiler specified for language %%" &
2242 ", ignoring all its sources",
2245 if Lang_Index = Data.First_Language_Processing then
2246 Data.First_Language_Processing :=
2249 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2253 elsif Lang_Data.Name = Name_Ada then
2254 Prev_Index := Lang_Index;
2256 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2257 -- Body_Suffix need to be specified.
2259 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2263 "Dot_Replacement not specified for Ada",
2267 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2271 "Spec_Suffix not specified for Ada",
2275 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2279 "Body_Suffix not specified for Ada",
2284 Prev_Index := Lang_Index;
2286 -- For file based languages, either Spec_Suffix or Body_Suffix
2287 -- need to be specified.
2289 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2290 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2292 Error_Msg_Name_1 := Current_Language;
2296 "no suffixes specified for %%",
2301 Lang_Index := Lang_Data.Next;
2303 end Check_Configuration;
2305 ----------------------
2306 -- Check_For_Source --
2307 ----------------------
2309 procedure Check_For_Source
2310 (File_Name : File_Name_Type;
2311 Path_Name : Path_Name_Type;
2312 Project : Project_Id;
2313 In_Tree : Project_Tree_Ref;
2314 Data : in out Project_Data;
2315 Location : Source_Ptr;
2316 Language : Language_Index;
2318 Naming_Exception : Boolean)
2320 Name : String := Get_Name_String (File_Name);
2321 Real_Location : Source_Ptr := Location;
2324 Canonical_Case_File_Name (Name);
2326 -- A file is a source of a language if Naming_Exception is True (case
2327 -- of naming exceptions) or if its file name ends with the suffix.
2331 (Name'Length > Suffix'Length
2333 Name (Name'Last - Suffix'Length + 1 .. Name'Last) = Suffix)
2335 if Real_Location = No_Location then
2336 Real_Location := Data.Location;
2340 Path_Id : Path_Name_Type;
2341 C_Path_Id : Path_Name_Type;
2342 -- The path name id (in canonical case)
2344 File_Id : File_Name_Type;
2345 -- The file name id (in canonical case)
2347 Obj_Id : File_Name_Type;
2348 -- The object file name
2350 Obj_Path_Id : Path_Name_Type;
2351 -- The object path name
2353 Dep_Id : File_Name_Type;
2354 -- The dependency file name
2356 Dep_Path_Id : Path_Name_Type;
2357 -- The dependency path name
2359 Dot_Pos : Natural := 0;
2360 -- Position of the last dot in Name
2362 Source : Other_Source;
2363 Source_Id : Other_Source_Id := Data.First_Other_Source;
2366 -- Get the file name id
2368 if Osint.File_Names_Case_Sensitive then
2369 File_Id := File_Name;
2371 Name_Len := Name'Length;
2372 Name_Buffer (1 .. Name_Len) := Name;
2373 File_Id := Name_Find;
2376 -- Get the path name id
2378 Path_Id := Path_Name;
2380 if Osint.File_Names_Case_Sensitive then
2381 C_Path_Id := Path_Name;
2384 C_Path : String := Get_Name_String (Path_Name);
2386 Canonical_Case_File_Name (C_Path);
2387 Name_Len := C_Path'Length;
2388 Name_Buffer (1 .. Name_Len) := C_Path;
2389 C_Path_Id := Name_Find;
2393 -- Find the position of the last dot
2395 for J in reverse Name'Range loop
2396 if Name (J) = '.' then
2402 if Dot_Pos <= Name'First then
2403 Dot_Pos := Name'Last + 1;
2406 -- Compute the object file name
2408 Get_Name_String (File_Id);
2409 Name_Len := Dot_Pos - Name'First;
2411 for J in Object_Suffix'Range loop
2412 Name_Len := Name_Len + 1;
2413 Name_Buffer (Name_Len) := Object_Suffix (J);
2416 Obj_Id := Name_Find;
2418 -- Compute the object path name
2420 Get_Name_String (Data.Display_Object_Dir);
2422 if Name_Buffer (Name_Len) /= Directory_Separator
2423 and then Name_Buffer (Name_Len) /= '/'
2425 Name_Len := Name_Len + 1;
2426 Name_Buffer (Name_Len) := Directory_Separator;
2429 Add_Str_To_Name_Buffer (Get_Name_String (Obj_Id));
2430 Obj_Path_Id := Name_Find;
2432 -- Compute the dependency file name
2434 Get_Name_String (File_Id);
2435 Name_Len := Dot_Pos - Name'First + 1;
2436 Name_Buffer (Name_Len) := '.';
2437 Name_Len := Name_Len + 1;
2438 Name_Buffer (Name_Len) := 'd
';
2439 Dep_Id := Name_Find;
2441 -- Compute the dependency path name
2443 Get_Name_String (Data.Display_Object_Dir);
2445 if Name_Buffer (Name_Len) /= Directory_Separator
2446 and then Name_Buffer (Name_Len) /= '/'
2448 Name_Len := Name_Len + 1;
2449 Name_Buffer (Name_Len) := Directory_Separator;
2452 Add_Str_To_Name_Buffer (Get_Name_String (Dep_Id));
2453 Dep_Path_Id := Name_Find;
2455 -- Check if source is already in the list of source for this
2456 -- project: it may have already been specified as a naming
2457 -- exception for the same language or an other language, or
2458 -- they may be two identical file names in different source
2461 while Source_Id /= No_Other_Source loop
2462 Source := In_Tree.Other_Sources.Table (Source_Id);
2464 if Source.File_Name = File_Id then
2465 -- Two sources of different languages cannot have the same
2468 if Source.Language /= Language then
2469 Error_Msg_File_1 := File_Name;
2472 "{ cannot be a source of several languages",
2476 -- No problem if a file has already been specified as
2477 -- a naming exception of this language.
2479 elsif Source.Path_Name = C_Path_Id then
2481 -- Reset the naming exception flag, if this is not a
2482 -- naming exception.
2484 if not Naming_Exception then
2485 In_Tree.Other_Sources.Table
2486 (Source_Id).Naming_Exception := False;
2491 -- There are several files with the same names, but the
2492 -- order of the source directories is known (no /**):
2493 -- only the first one encountered is kept, the other ones
2496 elsif Data.Known_Order_Of_Source_Dirs then
2499 -- But it is an error if the order of the source directories
2503 Error_Msg_File_1 := File_Name;
2506 "{ is found in several source directories",
2511 -- Two sources with different file names cannot have the same
2512 -- object file name.
2514 elsif Source.Object_Name = Obj_Id then
2515 Error_Msg_File_1 := File_Id;
2516 Error_Msg_File_2 := Source.File_Name;
2517 Error_Msg_File_3 := Obj_Id;
2520 "{ and { have the same object file {",
2525 Source_Id := Source.Next;
2528 if Current_Verbosity = High then
2529 Write_Str (" found ");
2530 Display_Language_Name (Language);
2531 Write_Str (" source """);
2532 Write_Str (Get_Name_String (File_Name));
2534 Write_Str (" object path = ");
2535 Write_Line (Get_Name_String (Obj_Path_Id));
2538 -- Create the Other_Source record
2541 (Language => Language,
2542 File_Name => File_Id,
2543 Path_Name => Path_Id,
2544 Source_TS => File_Stamp (Path_Id),
2545 Object_Name => Obj_Id,
2546 Object_Path => Obj_Path_Id,
2547 Object_TS => File_Stamp (Obj_Path_Id),
2549 Dep_Path => Dep_Path_Id,
2550 Dep_TS => File_Stamp (Dep_Path_Id),
2551 Naming_Exception => Naming_Exception,
2552 Next => No_Other_Source);
2554 -- And add it to the Other_Sources table
2556 Other_Source_Table.Increment_Last (In_Tree.Other_Sources);
2557 In_Tree.Other_Sources.Table
2558 (Other_Source_Table.Last (In_Tree.Other_Sources)) := Source;
2560 -- There are sources of languages other than Ada in this project
2562 Data.Other_Sources_Present := True;
2564 -- And there are sources of this language in this project
2566 Set (Language, True, Data, In_Tree);
2568 -- Add this source to the list of sources of languages other than
2569 -- Ada of the project.
2571 if Data.First_Other_Source = No_Other_Source then
2572 Data.First_Other_Source :=
2573 Other_Source_Table.Last (In_Tree.Other_Sources);
2576 In_Tree.Other_Sources.Table (Data.Last_Other_Source).Next :=
2577 Other_Source_Table.Last (In_Tree.Other_Sources);
2580 Data.Last_Other_Source :=
2581 Other_Source_Table.Last (In_Tree.Other_Sources);
2584 end Check_For_Source;
2586 -------------------------------
2587 -- Check_If_Externally_Built --
2588 -------------------------------
2590 procedure Check_If_Externally_Built
2591 (Project : Project_Id;
2592 In_Tree : Project_Tree_Ref;
2593 Data : in out Project_Data)
2595 Externally_Built : constant Variable_Value :=
2597 (Name_Externally_Built,
2598 Data.Decl.Attributes, In_Tree);
2601 if not Externally_Built.Default then
2602 Get_Name_String (Externally_Built.Value);
2603 To_Lower (Name_Buffer (1 .. Name_Len));
2605 if Name_Buffer (1 .. Name_Len) = "true" then
2606 Data.Externally_Built := True;
2608 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2609 Error_Msg (Project, In_Tree,
2610 "Externally_Built may only be true or false",
2611 Externally_Built.Location);
2615 if Current_Verbosity = High then
2616 Write_Str ("Project is ");
2618 if not Data.Externally_Built then
2622 Write_Line ("externally built.");
2624 end Check_If_Externally_Built;
2626 --------------------------
2627 -- Check_Naming_Schemes --
2628 --------------------------
2630 procedure Check_Naming_Schemes
2631 (Data : in out Project_Data;
2632 Project : Project_Id;
2633 In_Tree : Project_Tree_Ref)
2635 Naming_Id : constant Package_Id :=
2636 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2637 Naming : Package_Element;
2639 procedure Check_Unit_Names (List : Array_Element_Id);
2640 -- Check that a list of unit names contains only valid names
2642 procedure Get_Exceptions (Kind : Source_Kind);
2644 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2646 ----------------------
2647 -- Check_Unit_Names --
2648 ----------------------
2650 procedure Check_Unit_Names (List : Array_Element_Id) is
2651 Current : Array_Element_Id;
2652 Element : Array_Element;
2653 Unit_Name : Name_Id;
2656 -- Loop through elements of the string list
2659 while Current /= No_Array_Element loop
2660 Element := In_Tree.Array_Elements.Table (Current);
2662 -- Put file name in canonical case
2664 if not Osint.File_Names_Case_Sensitive then
2665 Get_Name_String (Element.Value.Value);
2666 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2667 Element.Value.Value := Name_Find;
2670 -- Check that it contains a valid unit name
2672 Get_Name_String (Element.Index);
2673 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2675 if Unit_Name = No_Name then
2676 Err_Vars.Error_Msg_Name_1 := Element.Index;
2679 "%% is not a valid unit name.",
2680 Element.Value.Location);
2683 if Current_Verbosity = High then
2684 Write_Str (" Unit (""");
2685 Write_Str (Get_Name_String (Unit_Name));
2689 Element.Index := Unit_Name;
2690 In_Tree.Array_Elements.Table (Current) := Element;
2693 Current := Element.Next;
2695 end Check_Unit_Names;
2697 --------------------
2698 -- Get_Exceptions --
2699 --------------------
2701 procedure Get_Exceptions (Kind : Source_Kind) is
2702 Exceptions : Array_Element_Id;
2703 Exception_List : Variable_Value;
2704 Element_Id : String_List_Id;
2705 Element : String_Element;
2706 File_Name : File_Name_Type;
2707 Lang_Id : Language_Index;
2709 Lang_Kind : Language_Kind;
2716 (Name_Implementation_Exceptions,
2717 In_Arrays => Naming.Decl.Arrays,
2718 In_Tree => In_Tree);
2723 (Name_Specification_Exceptions,
2724 In_Arrays => Naming.Decl.Arrays,
2725 In_Tree => In_Tree);
2728 Lang_Id := Data.First_Language_Processing;
2729 while Lang_Id /= No_Language_Index loop
2730 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2733 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2735 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2737 Exception_List := Value_Of
2739 In_Array => Exceptions,
2740 In_Tree => In_Tree);
2742 if Exception_List /= Nil_Variable_Value then
2743 Element_Id := Exception_List.Values;
2744 while Element_Id /= Nil_String loop
2745 Element := In_Tree.String_Elements.Table (Element_Id);
2747 if Osint.File_Names_Case_Sensitive then
2748 File_Name := File_Name_Type (Element.Value);
2750 Get_Name_String (Element.Value);
2751 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2752 File_Name := Name_Find;
2755 Source := Data.First_Source;
2756 while Source /= No_Source
2758 In_Tree.Sources.Table (Source).File /= File_Name
2761 In_Tree.Sources.Table (Source).Next_In_Project;
2764 if Source = No_Source then
2773 File_Name => File_Name,
2774 Display_File => File_Name_Type (Element.Value),
2775 Naming_Exception => True,
2776 Lang_Kind => Lang_Kind);
2779 -- Check if the file name is already recorded for
2780 -- another language or another kind.
2783 In_Tree.Sources.Table (Source).Language /= Lang_Id
2788 "the same file cannot be a source " &
2792 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2796 "the same file cannot be a source " &
2801 -- If the file is already recorded for the same
2802 -- language and the same kind, it means that the file
2803 -- name appears several times in the *_Exceptions
2804 -- attribute; so there is nothing to do.
2808 Element_Id := Element.Next;
2813 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2817 -------------------------
2818 -- Get_Unit_Exceptions --
2819 -------------------------
2821 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2822 Exceptions : Array_Element_Id;
2823 Element : Array_Element;
2826 File_Name : File_Name_Type;
2827 Lang_Id : constant Language_Index :=
2828 Data.Unit_Based_Language_Index;
2829 Lang : constant Name_Id :=
2830 Data.Unit_Based_Language_Name;
2833 Source_To_Replace : Source_Id := No_Source;
2835 Other_Project : Project_Id;
2836 Other_Part : Source_Id := No_Source;
2839 if Lang_Id = No_Language_Index or else Lang = No_Name then
2844 Exceptions := Value_Of
2846 In_Arrays => Naming.Decl.Arrays,
2847 In_Tree => In_Tree);
2849 if Exceptions = No_Array_Element then
2852 (Name_Implementation,
2853 In_Arrays => Naming.Decl.Arrays,
2854 In_Tree => In_Tree);
2861 In_Arrays => Naming.Decl.Arrays,
2862 In_Tree => In_Tree);
2864 if Exceptions = No_Array_Element then
2865 Exceptions := Value_Of
2866 (Name_Specification,
2867 In_Arrays => Naming.Decl.Arrays,
2868 In_Tree => In_Tree);
2873 while Exceptions /= No_Array_Element loop
2874 Element := In_Tree.Array_Elements.Table (Exceptions);
2876 if Osint.File_Names_Case_Sensitive then
2877 File_Name := File_Name_Type (Element.Value.Value);
2879 Get_Name_String (Element.Value.Value);
2880 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2881 File_Name := Name_Find;
2884 Get_Name_String (Element.Index);
2885 To_Lower (Name_Buffer (1 .. Name_Len));
2888 Index := Element.Value.Index;
2890 -- For Ada, check if it is a valid unit name
2892 if Lang = Name_Ada then
2893 Get_Name_String (Element.Index);
2894 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2896 if Unit = No_Name then
2897 Err_Vars.Error_Msg_Name_1 := Element.Index;
2900 "%% is not a valid unit name.",
2901 Element.Value.Location);
2905 if Unit /= No_Name then
2907 -- Check if the source already exists
2909 Source := In_Tree.First_Source;
2910 Source_To_Replace := No_Source;
2912 while Source /= No_Source and then
2913 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2914 In_Tree.Sources.Table (Source).Index /= Index)
2916 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2919 if Source /= No_Source then
2920 if In_Tree.Sources.Table (Source).Kind /= Kind then
2921 Other_Part := Source;
2925 In_Tree.Sources.Table (Source).Next_In_Sources;
2927 exit when Source = No_Source or else
2928 (In_Tree.Sources.Table (Source).Unit = Unit
2930 In_Tree.Sources.Table (Source).Index = Index);
2934 if Source /= No_Source then
2935 Other_Project := In_Tree.Sources.Table (Source).Project;
2937 if Is_Extending (Project, Other_Project, In_Tree) then
2939 In_Tree.Sources.Table (Source).Other_Part;
2941 -- Record the source to be removed
2943 Source_To_Replace := Source;
2944 Source := No_Source;
2947 Error_Msg_Name_1 := Unit;
2952 "unit%% cannot belong to two projects " &
2954 Element.Value.Location);
2959 if Source = No_Source then
2968 File_Name => File_Name,
2969 Display_File => File_Name_Type (Element.Value.Value),
2970 Lang_Kind => Unit_Based,
2971 Other_Part => Other_Part,
2974 Naming_Exception => True,
2975 Source_To_Replace => Source_To_Replace);
2979 Exceptions := Element.Next;
2982 end Get_Unit_Exceptions;
2984 -- Start of processing for Check_Naming_Schemes
2987 if Get_Mode = Ada_Only then
2989 -- If there is a package Naming, we will put in Data.Naming what is
2990 -- in this package Naming.
2992 if Naming_Id /= No_Package then
2993 Naming := In_Tree.Packages.Table (Naming_Id);
2995 if Current_Verbosity = High then
2996 Write_Line ("Checking ""Naming"" for Ada.");
3000 Bodies : constant Array_Element_Id :=
3002 (Name_Body, Naming.Decl.Arrays, In_Tree);
3004 Specs : constant Array_Element_Id :=
3006 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3009 if Bodies /= No_Array_Element then
3011 -- We have elements in the array Body_Part
3013 if Current_Verbosity = High then
3014 Write_Line ("Found Bodies.");
3017 Data.Naming.Bodies := Bodies;
3018 Check_Unit_Names (Bodies);
3021 if Current_Verbosity = High then
3022 Write_Line ("No Bodies.");
3026 if Specs /= No_Array_Element then
3028 -- We have elements in the array Specs
3030 if Current_Verbosity = High then
3031 Write_Line ("Found Specs.");
3034 Data.Naming.Specs := Specs;
3035 Check_Unit_Names (Specs);
3038 if Current_Verbosity = High then
3039 Write_Line ("No Specs.");
3044 -- We are now checking if variables Dot_Replacement, Casing,
3045 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3047 -- For each variable, if it does not exist, we do nothing,
3048 -- because we already have the default.
3050 -- Check Dot_Replacement
3053 Dot_Replacement : constant Variable_Value :=
3055 (Name_Dot_Replacement,
3056 Naming.Decl.Attributes, In_Tree);
3059 pragma Assert (Dot_Replacement.Kind = Single,
3060 "Dot_Replacement is not a single string");
3062 if not Dot_Replacement.Default then
3063 Get_Name_String (Dot_Replacement.Value);
3065 if Name_Len = 0 then
3068 "Dot_Replacement cannot be empty",
3069 Dot_Replacement.Location);
3072 if Osint.File_Names_Case_Sensitive then
3073 Data.Naming.Dot_Replacement :=
3074 File_Name_Type (Dot_Replacement.Value);
3076 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3077 Data.Naming.Dot_Replacement := Name_Find;
3079 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3084 if Current_Verbosity = High then
3085 Write_Str (" Dot_Replacement = """);
3086 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3094 Casing_String : constant Variable_Value :=
3097 Naming.Decl.Attributes,
3101 pragma Assert (Casing_String.Kind = Single,
3102 "Casing
is not a single
string");
3104 if not Casing_String.Default then
3106 Casing_Image : constant String :=
3107 Get_Name_String (Casing_String.Value);
3110 Casing_Value : constant Casing_Type :=
3111 Value (Casing_Image);
3113 Data.Naming.Casing := Casing_Value;
3117 when Constraint_Error =>
3118 if Casing_Image'Length = 0 then
3121 "Casing cannot be an empty
string",
3122 Casing_String.Location);
3125 Name_Len := Casing_Image'Length;
3126 Name_Buffer (1 .. Name_Len) := Casing_Image;
3127 Err_Vars.Error_Msg_Name_1 := Name_Find;
3130 "%% is not a correct Casing
",
3131 Casing_String.Location);
3137 if Current_Verbosity = High then
3138 Write_Str (" Casing
= ");
3139 Write_Str (Image (Data.Naming.Casing));
3144 -- Check Spec_Suffix
3147 Ada_Spec_Suffix : constant Variable_Value :=
3151 In_Array => Data.Naming.Spec_Suffix,
3152 In_Tree => In_Tree);
3155 if Ada_Spec_Suffix.Kind = Single
3156 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3158 Get_Name_String (Ada_Spec_Suffix.Value);
3159 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3160 Set_Spec_Suffix (In_Tree, "ada
", Data.Naming, Name_Find);
3161 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3168 Default_Ada_Spec_Suffix);
3172 if Current_Verbosity = High then
3173 Write_Str (" Spec_Suffix
= """);
3174 Write_Str (Spec_Suffix_Of (In_Tree, "ada
", Data.Naming));
3179 -- Check Body_Suffix
3182 Ada_Body_Suffix : constant Variable_Value :=
3186 In_Array => Data.Naming.Body_Suffix,
3187 In_Tree => In_Tree);
3190 if Ada_Body_Suffix.Kind = Single
3191 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3193 Get_Name_String (Ada_Body_Suffix.Value);
3194 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3195 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3196 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3203 Default_Ada_Body_Suffix);
3207 if Current_Verbosity = High then
3208 Write_Str (" Body_Suffix = """);
3209 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3214 -- Check Separate_Suffix
3217 Ada_Sep_Suffix : constant Variable_Value :=
3219 (Variable_Name => Name_Separate_Suffix,
3220 In_Variables => Naming.Decl.Attributes,
3221 In_Tree => In_Tree);
3224 if Ada_Sep_Suffix.Default then
3225 Data.Naming.Separate_Suffix :=
3226 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3229 Get_Name_String (Ada_Sep_Suffix.Value);
3231 if Name_Len = 0 then
3234 "Separate_Suffix cannot be empty
",
3235 Ada_Sep_Suffix.Location);
3238 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3239 Data.Naming.Separate_Suffix := Name_Find;
3240 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3245 if Current_Verbosity = High then
3246 Write_Str (" Separate_Suffix
= """);
3247 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3252 -- Check if Data.Naming is valid
3254 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3257 elsif not In_Configuration then
3259 -- Look into package Naming, if there is one
3261 if Naming_Id /= No_Package then
3262 Naming := In_Tree.Packages.Table (Naming_Id);
3264 if Current_Verbosity = High then
3265 Write_Line ("Checking package Naming.");
3268 -- We are now checking if attribute Dot_Replacement, Casing,
3269 -- and/or Separate_Suffix exist.
3271 -- For each attribute, if it does not exist, we do nothing,
3272 -- because we already have the default.
3273 -- Otherwise, for all unit-based languages, we put the declared
3274 -- value in the language config.
3277 Dot_Repl : constant Variable_Value :=
3279 (Name_Dot_Replacement,
3280 Naming.Decl.Attributes, In_Tree);
3281 Dot_Replacement : File_Name_Type := No_File;
3283 Casing_String : constant Variable_Value :=
3286 Naming.Decl.Attributes,
3288 Casing : Casing_Type;
3289 Casing_Defined : Boolean := False;
3291 Sep_Suffix : constant Variable_Value :=
3293 (Variable_Name => Name_Separate_Suffix,
3294 In_Variables => Naming.Decl.Attributes,
3295 In_Tree => In_Tree);
3296 Separate_Suffix : File_Name_Type := No_File;
3298 Lang_Id : Language_Index;
3300 -- Check attribute Dot_Replacement
3302 if not Dot_Repl.Default then
3303 Get_Name_String (Dot_Repl.Value);
3305 if Name_Len = 0 then
3308 "Dot_Replacement cannot be empty",
3312 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3313 Dot_Replacement := Name_Find;
3315 if Current_Verbosity = High then
3316 Write_Str (" Dot_Replacement = """);
3317 Write_Str (Get_Name_String (Dot_Replacement));
3324 -- Check attribute Casing
3326 if not Casing_String.Default then
3328 Casing_Image : constant String :=
3329 Get_Name_String (Casing_String.Value);
3332 Casing_Value : constant Casing_Type :=
3333 Value (Casing_Image);
3335 Casing := Casing_Value;
3336 Casing_Defined := True;
3338 if Current_Verbosity = High then
3339 Write_Str (" Casing
= ");
3340 Write_Str (Image (Casing));
3347 when Constraint_Error =>
3348 if Casing_Image'Length = 0 then
3351 "Casing cannot be an empty
string",
3352 Casing_String.Location);
3355 Name_Len := Casing_Image'Length;
3356 Name_Buffer (1 .. Name_Len) := Casing_Image;
3357 Err_Vars.Error_Msg_Name_1 := Name_Find;
3360 "%% is not a correct Casing
",
3361 Casing_String.Location);
3366 if not Sep_Suffix.Default then
3367 Get_Name_String (Sep_Suffix.Value);
3369 if Name_Len = 0 then
3372 "Separate_Suffix cannot be empty
",
3373 Sep_Suffix.Location);
3376 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3377 Separate_Suffix := Name_Find;
3379 if Current_Verbosity = High then
3380 Write_Str (" Separate_Suffix
= """);
3381 Write_Str (Get_Name_String (Separate_Suffix));
3388 -- For all unit based languages, if any, set the specified
3389 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3391 if Dot_Replacement /= No_File
3392 or else Casing_Defined
3393 or else Separate_Suffix /= No_File
3395 Lang_Id := Data.First_Language_Processing;
3396 while Lang_Id /= No_Language_Index loop
3397 if In_Tree.Languages_Data.Table
3398 (Lang_Id).Config.Kind = Unit_Based
3400 if Dot_Replacement /= No_File then
3401 In_Tree.Languages_Data.Table
3402 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3406 if Casing_Defined then
3407 In_Tree.Languages_Data.Table
3408 (Lang_Id).Config.Naming_Data.Casing := Casing;
3411 if Separate_Suffix /= No_File then
3412 In_Tree.Languages_Data.Table
3413 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3419 In_Tree.Languages_Data.Table (Lang_Id).Next;
3424 -- Next, get the spec and body suffixes
3427 Suffix : Variable_Value;
3428 Lang_Id : Language_Index;
3432 Lang_Id := Data.First_Language_Processing;
3433 while Lang_Id /= No_Language_Index loop
3434 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3440 Attribute_Or_Array_Name => Name_Spec_Suffix,
3441 In_Package => Naming_Id,
3442 In_Tree => In_Tree);
3444 if Suffix = Nil_Variable_Value then
3447 Attribute_Or_Array_Name => Name_Specification_Suffix,
3448 In_Package => Naming_Id,
3449 In_Tree => In_Tree);
3452 if Suffix /= Nil_Variable_Value then
3453 In_Tree.Languages_Data.Table (Lang_Id).
3454 Config.Naming_Data.Spec_Suffix :=
3455 File_Name_Type (Suffix.Value);
3462 Attribute_Or_Array_Name => Name_Body_Suffix,
3463 In_Package => Naming_Id,
3464 In_Tree => In_Tree);
3466 if Suffix = Nil_Variable_Value then
3469 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3470 In_Package => Naming_Id,
3471 In_Tree => In_Tree);
3474 if Suffix /= Nil_Variable_Value then
3475 In_Tree.Languages_Data.Table (Lang_Id).
3476 Config.Naming_Data.Body_Suffix :=
3477 File_Name_Type (Suffix.Value);
3480 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3484 -- Get the exceptions for file based languages
3486 Get_Exceptions (Spec);
3487 Get_Exceptions (Impl);
3489 -- Get the exceptions for unit based languages
3491 Get_Unit_Exceptions (Spec);
3492 Get_Unit_Exceptions (Impl);
3496 end Check_Naming_Schemes;
3498 ------------------------------
3499 -- Check_Library_Attributes --
3500 ------------------------------
3502 procedure Check_Library_Attributes
3503 (Project : Project_Id;
3504 In_Tree : Project_Tree_Ref;
3505 Current_Dir : String;
3506 Data : in out Project_Data)
3508 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3510 Lib_Dir : constant Prj.Variable_Value :=
3512 (Snames.Name_Library_Dir, Attributes, In_Tree);
3514 Lib_Name : constant Prj.Variable_Value :=
3516 (Snames.Name_Library_Name, Attributes, In_Tree);
3518 Lib_Version : constant Prj.Variable_Value :=
3520 (Snames.Name_Library_Version, Attributes, In_Tree);
3522 Lib_ALI_Dir : constant Prj.Variable_Value :=
3524 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3526 The_Lib_Kind : constant Prj.Variable_Value :=
3528 (Snames.Name_Library_Kind, Attributes, In_Tree);
3530 Imported_Project_List : Project_List := Empty_Project_List;
3532 Continuation : String_Access := No_Continuation_String'Access;
3534 Support_For_Libraries : Library_Support;
3536 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3537 -- Check if an imported or extended project if also a library project
3543 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3544 Proj_Data : Project_Data;
3547 if Proj /= No_Project then
3548 Proj_Data := In_Tree.Projects.Table (Proj);
3550 if not Proj_Data.Library then
3551 -- The only not library projects that are OK are those that
3554 if Proj_Data.Source_Dirs /= Nil_String then
3556 Error_Msg_Name_1 := Data.Name;
3557 Error_Msg_Name_2 := Proj_Data.Name;
3563 "library project %% cannot extend project %% " &
3564 "that is not a library project",
3571 "library project %% cannot import project %% " &
3572 "that is not a library project",
3576 Continuation := Continuation_String'Access;
3579 elsif Data.Library_Kind /= Static and then
3580 Proj_Data.Library_Kind = Static
3582 Error_Msg_Name_1 := Data.Name;
3583 Error_Msg_Name_2 := Proj_Data.Name;
3589 "shared library project %% cannot extend static " &
3590 "library project %%",
3597 "shared library project %% cannot import static " &
3598 "library project %%",
3602 Continuation := Continuation_String'Access;
3607 -- Start of processing for Check_Library_Attributes
3610 -- Special case of extending project
3612 if Data.Extends /= No_Project then
3614 Extended_Data : constant Project_Data :=
3615 In_Tree.Projects.Table (Data.Extends);
3618 -- If the project extended is a library project, we inherit the
3619 -- library name, if it is not redefined; we check that the library
3620 -- directory is specified.
3622 if Extended_Data.Library then
3623 if Lib_Name.Default then
3624 Data.Library_Name := Extended_Data.Library_Name;
3627 if Lib_Dir.Default then
3628 if not Data.Virtual then
3631 "a project extending a library project must " &
3632 "specify an attribute Library_Dir",
3640 pragma Assert (Lib_Name.Kind = Single);
3642 if Lib_Name.Value = Empty_String then
3643 if Current_Verbosity = High
3644 and then Data.Library_Name = No_Name
3646 Write_Line ("No library name");
3650 -- There is no restriction on the syntax of library names
3652 Data.Library_Name := Lib_Name.Value;
3655 if Data.Library_Name /= No_Name then
3656 if Current_Verbosity = High then
3657 Write_Str ("Library name = """);
3658 Write_Str (Get_Name_String (Data.Library_Name));
3662 pragma Assert (Lib_Dir.Kind = Single);
3664 if Lib_Dir.Value = Empty_String then
3665 if Current_Verbosity = High then
3666 Write_Line ("No library directory");
3670 -- Find path name, check that it is a directory
3675 File_Name_Type (Lib_Dir.Value),
3676 Data.Display_Directory,
3678 Data.Display_Library_Dir,
3679 Create => "library",
3680 Current_Dir => Current_Dir,
3681 Location => Lib_Dir.Location);
3683 if Data.Library_Dir = No_Path then
3685 -- Get the absolute name of the library directory that
3686 -- does not exist, to report an error.
3689 Dir_Name : constant String :=
3690 Get_Name_String (Lib_Dir.Value);
3693 if Is_Absolute_Path (Dir_Name) then
3694 Err_Vars.Error_Msg_File_1 :=
3695 File_Name_Type (Lib_Dir.Value);
3698 Get_Name_String (Data.Display_Directory);
3700 if Name_Buffer (Name_Len) /= Directory_Separator then
3701 Name_Len := Name_Len + 1;
3702 Name_Buffer (Name_Len) := Directory_Separator;
3706 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3708 Name_Len := Name_Len + Dir_Name'Length;
3709 Err_Vars.Error_Msg_File_1 := Name_Find;
3716 "library directory { does not exist",
3720 -- The library directory cannot be the same as the Object
3723 elsif Data.Library_Dir = Data.Object_Directory then
3726 "library directory cannot be the same " &
3727 "as object directory",
3729 Data.Library_Dir := No_Path;
3730 Data.Display_Library_Dir := No_Path;
3734 OK : Boolean := True;
3735 Dirs_Id : String_List_Id;
3736 Dir_Elem : String_Element;
3739 -- The library directory cannot be the same as a source
3740 -- directory of the current project.
3742 Dirs_Id := Data.Source_Dirs;
3743 while Dirs_Id /= Nil_String loop
3744 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3745 Dirs_Id := Dir_Elem.Next;
3747 if Data.Library_Dir = Path_Name_Type (Dir_Elem.Value) then
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 =
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;
3798 Data.Display_Library_Dir := No_Path;
3800 elsif Current_Verbosity = High then
3802 -- Display the Library directory in high verbosity
3804 Write_Str ("Library directory =""");
3805 Write_Str (Get_Name_String (Data.Display_Library_Dir));
3815 Data.Library_Dir /= No_Path
3817 Data.Library_Name /= No_Name;
3819 if Data.Library then
3820 if Get_Mode = Multi_Language then
3821 Support_For_Libraries := Data.Config.Lib_Support;
3824 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3827 if Support_For_Libraries = Prj.None then
3830 "?libraries are not supported on this platform",
3832 Data.Library := False;
3835 if Lib_ALI_Dir.Value = Empty_String then
3836 if Current_Verbosity = High then
3837 Write_Line ("No library ALI directory specified");
3839 Data.Library_ALI_Dir := Data.Library_Dir;
3840 Data.Display_Library_ALI_Dir := Data.Display_Library_Dir;
3843 -- Find path name, check that it is a directory
3848 File_Name_Type (Lib_ALI_Dir.Value),
3849 Data.Display_Directory,
3850 Data.Library_ALI_Dir,
3851 Data.Display_Library_ALI_Dir,
3852 Create => "library ALI",
3853 Current_Dir => Current_Dir,
3854 Location => Lib_ALI_Dir.Location);
3856 if Data.Library_ALI_Dir = No_Path then
3858 -- Get the absolute name of the library ALI directory that
3859 -- does not exist, to report an error.
3862 Dir_Name : constant String :=
3863 Get_Name_String (Lib_ALI_Dir.Value);
3866 if Is_Absolute_Path (Dir_Name) then
3867 Err_Vars.Error_Msg_File_1 :=
3868 File_Name_Type (Lib_Dir.Value);
3871 Get_Name_String (Data.Display_Directory);
3873 if Name_Buffer (Name_Len) /= Directory_Separator then
3874 Name_Len := Name_Len + 1;
3875 Name_Buffer (Name_Len) := Directory_Separator;
3879 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3881 Name_Len := Name_Len + Dir_Name'Length;
3882 Err_Vars.Error_Msg_File_1 := Name_Find;
3889 "library 'A
'L'I directory { does not exist",
3890 Lib_ALI_Dir.Location);
3894 if Data.Library_ALI_Dir /= Data.Library_Dir then
3896 -- The library ALI directory cannot be the same as the
3897 -- Object directory.
3899 if Data.Library_ALI_Dir = Data.Object_Directory then
3902 "library 'A
'L'I directory cannot be the same " &
3903 "as object directory",
3904 Lib_ALI_Dir.Location);
3905 Data.Library_ALI_Dir := No_Path;
3906 Data.Display_Library_ALI_Dir := No_Path;
3910 OK : Boolean := True;
3911 Dirs_Id : String_List_Id;
3912 Dir_Elem : String_Element;
3915 -- The library ALI directory cannot be the same as
3916 -- a source directory of the current project.
3918 Dirs_Id := Data.Source_Dirs;
3919 while Dirs_Id /= Nil_String loop
3920 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3921 Dirs_Id := Dir_Elem.Next;
3923 if Data.Library_ALI_Dir =
3924 Path_Name_Type (Dir_Elem.Value)
3926 Err_Vars.Error_Msg_File_1 :=
3927 File_Name_Type (Dir_Elem.Value);
3930 "library 'A
'L'I directory cannot be " &
3931 "the same as source directory {",
3932 Lib_ALI_Dir.Location);
3940 -- The library ALI directory cannot be the same as
3941 -- a source directory of another project either.
3945 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
3947 if Pid /= Project then
3949 In_Tree.Projects.Table (Pid).Source_Dirs;
3952 while Dirs_Id /= Nil_String loop
3954 In_Tree.String_Elements.Table (Dirs_Id);
3955 Dirs_Id := Dir_Elem.Next;
3957 if Data.Library_ALI_Dir =
3958 Path_Name_Type (Dir_Elem.Value)
3960 Err_Vars.Error_Msg_File_1 :=
3961 File_Name_Type (Dir_Elem.Value);
3962 Err_Vars.Error_Msg_Name_1 :=
3963 In_Tree.Projects.Table (Pid).Name;
3967 "library 'A
'L'I directory cannot " &
3968 "be the same as source directory " &
3970 Lib_ALI_Dir.Location);
3972 exit ALI_Project_Loop;
3974 end loop ALI_Dir_Loop;
3976 end loop ALI_Project_Loop;
3980 Data.Library_ALI_Dir := No_Path;
3981 Data.Display_Library_ALI_Dir := No_Path;
3983 elsif Current_Verbosity = High then
3985 -- Display the Library ALI directory in high
3988 Write_Str ("Library ALI directory =""");
3990 (Get_Name_String (Data.Display_Library_ALI_Dir));
3998 pragma Assert (Lib_Version.Kind = Single);
4000 if Lib_Version.Value = Empty_String then
4001 if Current_Verbosity = High then
4002 Write_Line ("No library version specified");
4006 Data.Lib_Internal_Name := Lib_Version.Value;
4009 pragma Assert (The_Lib_Kind.Kind = Single);
4011 if The_Lib_Kind.Value = Empty_String then
4012 if Current_Verbosity = High then
4013 Write_Line ("No library kind specified");
4017 Get_Name_String (The_Lib_Kind.Value);
4020 Kind_Name : constant String :=
4021 To_Lower (Name_Buffer (1 .. Name_Len));
4023 OK : Boolean := True;
4026 if Kind_Name = "static" then
4027 Data.Library_Kind := Static;
4029 elsif Kind_Name = "dynamic" then
4030 Data.Library_Kind := Dynamic;
4032 elsif Kind_Name = "relocatable" then
4033 Data.Library_Kind := Relocatable;
4038 "illegal value for Library_Kind",
4039 The_Lib_Kind.Location);
4043 if Current_Verbosity = High and then OK then
4044 Write_Str ("Library kind = ");
4045 Write_Line (Kind_Name);
4048 if Data.Library_Kind /= Static and then
4049 Support_For_Libraries = Prj.Static_Only
4053 "only static libraries are supported " &
4055 The_Lib_Kind.Location);
4056 Data.Library := False;
4061 if Data.Library then
4062 if Current_Verbosity = High then
4063 Write_Line ("This is a library project file");
4066 if Get_Mode = Multi_Language then
4067 Check_Library (Data.Extends, Extends => True);
4069 Imported_Project_List := Data.Imported_Projects;
4070 while Imported_Project_List /= Empty_Project_List loop
4072 (In_Tree.Project_Lists.Table
4073 (Imported_Project_List).Project,
4075 Imported_Project_List :=
4076 In_Tree.Project_Lists.Table
4077 (Imported_Project_List).Next;
4085 if Data.Extends /= No_Project then
4086 In_Tree.Projects.Table (Data.Extends).Library := False;
4088 end Check_Library_Attributes;
4090 --------------------------
4091 -- Check_Package_Naming --
4092 --------------------------
4094 procedure Check_Package_Naming
4095 (Project : Project_Id;
4096 In_Tree : Project_Tree_Ref;
4097 Data : in out Project_Data)
4099 Naming_Id : constant Package_Id :=
4100 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4102 Naming : Package_Element;
4105 -- If there is a package Naming, we will put in Data.Naming
4106 -- what is in this package Naming.
4108 if Naming_Id /= No_Package then
4109 Naming := In_Tree.Packages.Table (Naming_Id);
4111 if Current_Verbosity = High then
4112 Write_Line ("Checking ""Naming"".");
4115 -- Check Spec_Suffix
4118 Spec_Suffixs : Array_Element_Id :=
4124 Suffix : Array_Element_Id;
4125 Element : Array_Element;
4126 Suffix2 : Array_Element_Id;
4129 -- If some suffixs have been specified, we make sure that
4130 -- for each language for which a default suffix has been
4131 -- specified, there is a suffix specified, either the one
4132 -- in the project file or if there were none, the default.
4134 if Spec_Suffixs /= No_Array_Element then
4135 Suffix := Data.Naming.Spec_Suffix;
4137 while Suffix /= No_Array_Element loop
4139 In_Tree.Array_Elements.Table (Suffix);
4140 Suffix2 := Spec_Suffixs;
4142 while Suffix2 /= No_Array_Element loop
4143 exit when In_Tree.Array_Elements.Table
4144 (Suffix2).Index = Element.Index;
4145 Suffix2 := In_Tree.Array_Elements.Table
4149 -- There is a registered default suffix, but no
4150 -- suffix specified in the project file.
4151 -- Add the default to the array.
4153 if Suffix2 = No_Array_Element then
4154 Array_Element_Table.Increment_Last
4155 (In_Tree.Array_Elements);
4156 In_Tree.Array_Elements.Table
4157 (Array_Element_Table.Last
4158 (In_Tree.Array_Elements)) :=
4159 (Index => Element.Index,
4160 Src_Index => Element.Src_Index,
4161 Index_Case_Sensitive => False,
4162 Value => Element.Value,
4163 Next => Spec_Suffixs);
4164 Spec_Suffixs := Array_Element_Table.Last
4165 (In_Tree.Array_Elements);
4168 Suffix := Element.Next;
4171 -- Put the resulting array as the specification suffixs
4173 Data.Naming.Spec_Suffix := Spec_Suffixs;
4178 Current : Array_Element_Id;
4179 Element : Array_Element;
4182 Current := Data.Naming.Spec_Suffix;
4183 while Current /= No_Array_Element loop
4184 Element := In_Tree.Array_Elements.Table (Current);
4185 Get_Name_String (Element.Value.Value);
4187 if Name_Len = 0 then
4190 "Spec_Suffix cannot be empty",
4191 Element.Value.Location);
4194 In_Tree.Array_Elements.Table (Current) := Element;
4195 Current := Element.Next;
4199 -- Check Body_Suffix
4202 Impl_Suffixs : Array_Element_Id :=
4208 Suffix : Array_Element_Id;
4209 Element : Array_Element;
4210 Suffix2 : Array_Element_Id;
4213 -- If some suffixes have been specified, we make sure that
4214 -- for each language for which a default suffix has been
4215 -- specified, there is a suffix specified, either the one
4216 -- in the project file or if there were none, the default.
4218 if Impl_Suffixs /= No_Array_Element then
4219 Suffix := Data.Naming.Body_Suffix;
4220 while Suffix /= No_Array_Element loop
4222 In_Tree.Array_Elements.Table (Suffix);
4224 Suffix2 := Impl_Suffixs;
4225 while Suffix2 /= No_Array_Element loop
4226 exit when In_Tree.Array_Elements.Table
4227 (Suffix2).Index = Element.Index;
4228 Suffix2 := In_Tree.Array_Elements.Table
4232 -- There is a registered default suffix, but no suffix was
4233 -- specified in the project file. Add default to the array.
4235 if Suffix2 = No_Array_Element then
4236 Array_Element_Table.Increment_Last
4237 (In_Tree.Array_Elements);
4238 In_Tree.Array_Elements.Table
4239 (Array_Element_Table.Last
4240 (In_Tree.Array_Elements)) :=
4241 (Index => Element.Index,
4242 Src_Index => Element.Src_Index,
4243 Index_Case_Sensitive => False,
4244 Value => Element.Value,
4245 Next => Impl_Suffixs);
4246 Impl_Suffixs := Array_Element_Table.Last
4247 (In_Tree.Array_Elements);
4250 Suffix := Element.Next;
4253 -- Put the resulting array as the implementation suffixs
4255 Data.Naming.Body_Suffix := Impl_Suffixs;
4260 Current : Array_Element_Id;
4261 Element : Array_Element;
4264 Current := Data.Naming.Body_Suffix;
4265 while Current /= No_Array_Element loop
4266 Element := In_Tree.Array_Elements.Table (Current);
4267 Get_Name_String (Element.Value.Value);
4269 if Name_Len = 0 then
4272 "Body_Suffix cannot be empty",
4273 Element.Value.Location);
4276 In_Tree.Array_Elements.Table (Current) := Element;
4277 Current := Element.Next;
4281 -- Get the exceptions, if any
4283 Data.Naming.Specification_Exceptions :=
4285 (Name_Specification_Exceptions,
4286 In_Arrays => Naming.Decl.Arrays,
4287 In_Tree => In_Tree);
4289 Data.Naming.Implementation_Exceptions :=
4291 (Name_Implementation_Exceptions,
4292 In_Arrays => Naming.Decl.Arrays,
4293 In_Tree => In_Tree);
4295 end Check_Package_Naming;
4297 ---------------------------------
4298 -- Check_Programming_Languages --
4299 ---------------------------------
4301 procedure Check_Programming_Languages
4302 (In_Tree : Project_Tree_Ref;
4303 Project : Project_Id;
4304 Data : in out Project_Data)
4306 Languages : Variable_Value := Nil_Variable_Value;
4307 Def_Lang : Variable_Value := Nil_Variable_Value;
4308 Def_Lang_Id : Name_Id;
4311 Data.First_Language_Processing := No_Language_Index;
4313 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4316 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4317 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4318 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4320 if Data.Source_Dirs /= Nil_String then
4322 -- Check if languages are specified in this project
4324 if Languages.Default then
4326 -- Attribute Languages is not specified. So, it defaults to
4327 -- a project of the default language only.
4329 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4330 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4332 -- In Ada_Only mode, the default language is Ada
4334 if Get_Mode = Ada_Only then
4335 In_Tree.Name_Lists.Table (Data.Languages) :=
4336 (Name => Name_Ada, Next => No_Name_List);
4338 -- Attribute Languages is not specified. So, it defaults to
4339 -- a project of language Ada only.
4341 Data.Langs (Ada_Language_Index) := True;
4343 -- No sources of languages other than Ada
4345 Data.Other_Sources_Present := False;
4348 -- If the configuration file does not define a language either
4350 if Def_Lang.Default then
4351 if not Default_Language_Is_Ada then
4355 "no languages defined for this project",
4357 Def_Lang_Id := No_Name;
4359 Def_Lang_Id := Name_Ada;
4363 -- ??? Are we supporting a single default language in the
4364 -- configuration file ?
4365 Get_Name_String (Def_Lang.Value);
4366 To_Lower (Name_Buffer (1 .. Name_Len));
4367 Def_Lang_Id := Name_Find;
4370 if Def_Lang_Id /= No_Name then
4371 In_Tree.Name_Lists.Table (Data.Languages) :=
4372 (Name => Def_Lang_Id, Next => No_Name_List);
4374 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4376 Data.First_Language_Processing :=
4377 Language_Data_Table.Last (In_Tree.Languages_Data);
4378 In_Tree.Languages_Data.Table
4379 (Data.First_Language_Processing) := No_Language_Data;
4380 In_Tree.Languages_Data.Table
4381 (Data.First_Language_Processing).Name := Def_Lang_Id;
4382 Get_Name_String (Def_Lang_Id);
4383 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4384 In_Tree.Languages_Data.Table
4385 (Data.First_Language_Processing).Display_Name := Name_Find;
4387 if Def_Lang_Id = Name_Ada then
4388 In_Tree.Languages_Data.Table
4389 (Data.First_Language_Processing).Config.Kind
4391 In_Tree.Languages_Data.Table
4392 (Data.First_Language_Processing).Config.Dependency_Kind
4394 Data.Unit_Based_Language_Name := Name_Ada;
4395 Data.Unit_Based_Language_Index :=
4396 Data.First_Language_Processing;
4398 In_Tree.Languages_Data.Table
4399 (Data.First_Language_Processing).Config.Kind
4407 Current : String_List_Id := Languages.Values;
4408 Element : String_Element;
4409 Lang_Name : Name_Id;
4410 Index : Language_Index;
4411 Lang_Data : Language_Data;
4412 NL_Id : Name_List_Index := No_Name_List;
4415 if Get_Mode = Ada_Only then
4417 -- Assume that there is no language specified yet
4419 Data.Other_Sources_Present := False;
4420 Data.Ada_Sources_Present := False;
4423 -- If there are no languages declared, there are no sources
4425 if Current = Nil_String then
4426 Data.Source_Dirs := Nil_String;
4429 -- Look through all the languages specified in attribute
4432 while Current /= Nil_String loop
4434 In_Tree.String_Elements.Table (Current);
4435 Get_Name_String (Element.Value);
4436 To_Lower (Name_Buffer (1 .. Name_Len));
4437 Lang_Name := Name_Find;
4439 NL_Id := Data.Languages;
4440 while NL_Id /= No_Name_List loop
4442 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4443 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4446 if NL_Id = No_Name_List then
4447 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4449 if Data.Languages = No_Name_List then
4451 Name_List_Table.Last (In_Tree.Name_Lists);
4454 NL_Id := Data.Languages;
4455 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4458 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4461 In_Tree.Name_Lists.Table (NL_Id).Next :=
4462 Name_List_Table.Last (In_Tree.Name_Lists);
4465 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4466 In_Tree.Name_Lists.Table (NL_Id) :=
4467 (Lang_Name, No_Name_List);
4469 if Get_Mode = Ada_Only then
4470 Index := Language_Indexes.Get (Lang_Name);
4472 if Index = No_Language_Index then
4473 Add_Language_Name (Lang_Name);
4474 Index := Last_Language_Index;
4477 Set (Index, True, Data, In_Tree);
4478 Set (Language_Processing =>
4479 Default_Language_Processing_Data,
4480 For_Language => Index,
4482 In_Tree => In_Tree);
4484 if Index = Ada_Language_Index then
4485 Data.Ada_Sources_Present := True;
4488 Data.Other_Sources_Present := True;
4492 Language_Data_Table.Increment_Last
4493 (In_Tree.Languages_Data);
4495 Language_Data_Table.Last (In_Tree.Languages_Data);
4496 Lang_Data.Name := Lang_Name;
4497 Lang_Data.Display_Name := Element.Value;
4498 Lang_Data.Next := Data.First_Language_Processing;
4500 if Lang_Name = Name_Ada then
4501 Lang_Data.Config.Kind := Unit_Based;
4502 Lang_Data.Config.Dependency_Kind := ALI_File;
4503 Data.Unit_Based_Language_Name := Name_Ada;
4504 Data.Unit_Based_Language_Index := Index;
4507 Lang_Data.Config.Kind := File_Based;
4508 Lang_Data.Config.Dependency_Kind := None;
4511 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4512 Data.First_Language_Processing := Index;
4516 Current := Element.Next;
4522 end Check_Programming_Languages;
4528 function Check_Project
4530 Root_Project : Project_Id;
4531 In_Tree : Project_Tree_Ref;
4532 Extending : Boolean) return Boolean
4535 if P = Root_Project then
4538 elsif Extending then
4540 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4543 while Data.Extends /= No_Project loop
4544 if P = Data.Extends then
4548 Data := In_Tree.Projects.Table (Data.Extends);
4556 -------------------------------
4557 -- Check_Stand_Alone_Library --
4558 -------------------------------
4560 procedure Check_Stand_Alone_Library
4561 (Project : Project_Id;
4562 In_Tree : Project_Tree_Ref;
4563 Data : in out Project_Data;
4564 Current_Dir : String;
4565 Extending : Boolean)
4567 Lib_Interfaces : constant Prj.Variable_Value :=
4569 (Snames.Name_Library_Interface,
4570 Data.Decl.Attributes,
4573 Lib_Auto_Init : constant Prj.Variable_Value :=
4575 (Snames.Name_Library_Auto_Init,
4576 Data.Decl.Attributes,
4579 Lib_Src_Dir : constant Prj.Variable_Value :=
4581 (Snames.Name_Library_Src_Dir,
4582 Data.Decl.Attributes,
4585 Lib_Symbol_File : constant Prj.Variable_Value :=
4587 (Snames.Name_Library_Symbol_File,
4588 Data.Decl.Attributes,
4591 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4593 (Snames.Name_Library_Symbol_Policy,
4594 Data.Decl.Attributes,
4597 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4599 (Snames.Name_Library_Reference_Symbol_File,
4600 Data.Decl.Attributes,
4603 Auto_Init_Supported : Boolean;
4604 OK : Boolean := True;
4606 Next_Proj : Project_Id;
4609 if Get_Mode = Multi_Language then
4610 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4612 Auto_Init_Supported :=
4613 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4616 pragma Assert (Lib_Interfaces.Kind = List);
4618 -- It is a stand-alone library project file if attribute
4619 -- Library_Interface is defined.
4621 if not Lib_Interfaces.Default then
4622 SAL_Library : declare
4623 Interfaces : String_List_Id := Lib_Interfaces.Values;
4624 Interface_ALIs : String_List_Id := Nil_String;
4626 The_Unit_Id : Unit_Index;
4627 The_Unit_Data : Unit_Data;
4629 procedure Add_ALI_For (Source : File_Name_Type);
4630 -- Add an ALI file name to the list of Interface ALIs
4636 procedure Add_ALI_For (Source : File_Name_Type) is
4638 Get_Name_String (Source);
4641 ALI : constant String :=
4642 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4643 ALI_Name_Id : Name_Id;
4646 Name_Len := ALI'Length;
4647 Name_Buffer (1 .. Name_Len) := ALI;
4648 ALI_Name_Id := Name_Find;
4650 String_Element_Table.Increment_Last
4651 (In_Tree.String_Elements);
4652 In_Tree.String_Elements.Table
4653 (String_Element_Table.Last
4654 (In_Tree.String_Elements)) :=
4655 (Value => ALI_Name_Id,
4657 Display_Value => ALI_Name_Id,
4659 In_Tree.String_Elements.Table
4660 (Interfaces).Location,
4662 Next => Interface_ALIs);
4663 Interface_ALIs := String_Element_Table.Last
4664 (In_Tree.String_Elements);
4668 -- Start of processing for SAL_Library
4671 Data.Standalone_Library := True;
4673 -- Library_Interface cannot be an empty list
4675 if Interfaces = Nil_String then
4678 "Library_Interface cannot be an empty list",
4679 Lib_Interfaces.Location);
4682 -- Process each unit name specified in the attribute
4683 -- Library_Interface.
4685 while Interfaces /= Nil_String loop
4687 (In_Tree.String_Elements.Table (Interfaces).Value);
4688 To_Lower (Name_Buffer (1 .. Name_Len));
4690 if Name_Len = 0 then
4693 "an interface cannot be an empty string",
4694 In_Tree.String_Elements.Table (Interfaces).Location);
4698 Error_Msg_Name_1 := Unit;
4700 if Get_Mode = Ada_Only then
4702 Units_Htable.Get (In_Tree.Units_HT, Unit);
4704 if The_Unit_Id = No_Unit_Index then
4708 In_Tree.String_Elements.Table
4709 (Interfaces).Location);
4712 -- Check that the unit is part of the project
4715 In_Tree.Units.Table (The_Unit_Id);
4717 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4718 and then The_Unit_Data.File_Names (Body_Part).Path /=
4722 (The_Unit_Data.File_Names (Body_Part).Project,
4723 Project, In_Tree, Extending)
4725 -- There is a body for this unit.
4726 -- If there is no spec, we need to check
4727 -- that it is not a subunit.
4729 if The_Unit_Data.File_Names
4730 (Specification).Name = No_File
4733 Src_Ind : Source_File_Index;
4736 Src_Ind := Sinput.P.Load_Project_File
4738 (The_Unit_Data.File_Names
4741 if Sinput.P.Source_File_Is_Subunit
4746 "%% is a subunit; " &
4747 "it cannot be an interface",
4749 String_Elements.Table
4750 (Interfaces).Location);
4755 -- The unit is not a subunit, so we add
4756 -- to the Interface ALIs the ALI file
4757 -- corresponding to the body.
4760 (The_Unit_Data.File_Names (Body_Part).Name);
4765 "%% is not an unit of this project",
4766 In_Tree.String_Elements.Table
4767 (Interfaces).Location);
4770 elsif The_Unit_Data.File_Names
4771 (Specification).Name /= No_File
4772 and then The_Unit_Data.File_Names
4773 (Specification).Path /= Slash
4774 and then Check_Project
4775 (The_Unit_Data.File_Names
4776 (Specification).Project,
4777 Project, In_Tree, Extending)
4780 -- The unit is part of the project, it has
4781 -- a spec, but no body. We add to the Interface
4782 -- ALIs the ALI file corresponding to the spec.
4785 (The_Unit_Data.File_Names (Specification).Name);
4790 "%% is not an unit of this project",
4791 In_Tree.String_Elements.Table
4792 (Interfaces).Location);
4797 -- Multi_Language mode
4799 Next_Proj := Data.Extends;
4800 Source := Data.First_Source;
4803 while Source /= No_Source and then
4804 In_Tree.Sources.Table (Source).Unit /= Unit
4807 In_Tree.Sources.Table (Source).Next_In_Project;
4810 exit when Source /= No_Source or else
4811 Next_Proj = No_Project;
4814 In_Tree.Projects.Table (Next_Proj).First_Source;
4816 In_Tree.Projects.Table (Next_Proj).Extends;
4819 if Source /= No_Source then
4820 if In_Tree.Sources.Table (Source).Kind = Sep then
4821 Source := No_Source;
4823 elsif In_Tree.Sources.Table (Source).Kind = Spec
4825 In_Tree.Sources.Table (Source).Other_Part /=
4828 Source := In_Tree.Sources.Table (Source).Other_Part;
4832 if Source /= No_Source then
4833 if In_Tree.Sources.Table (Source).Project /= Project
4837 In_Tree.Sources.Table (Source).Project,
4840 Source := No_Source;
4844 if Source = No_Source then
4847 "%% is not an unit of this project",
4848 In_Tree.String_Elements.Table
4849 (Interfaces).Location);
4852 if In_Tree.Sources.Table (Source).Kind = Spec and then
4853 In_Tree.Sources.Table (Source).Other_Part /=
4857 In_Tree.Sources.Table (Source).Other_Part;
4860 String_Element_Table.Increment_Last
4861 (In_Tree.String_Elements);
4862 In_Tree.String_Elements.Table
4863 (String_Element_Table.Last
4864 (In_Tree.String_Elements)) :=
4866 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4869 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4871 In_Tree.String_Elements.Table
4872 (Interfaces).Location,
4874 Next => Interface_ALIs);
4875 Interface_ALIs := String_Element_Table.Last
4876 (In_Tree.String_Elements);
4884 In_Tree.String_Elements.Table (Interfaces).Next;
4887 -- Put the list of Interface ALIs in the project data
4889 Data.Lib_Interface_ALIs := Interface_ALIs;
4891 -- Check value of attribute Library_Auto_Init and set
4892 -- Lib_Auto_Init accordingly.
4894 if Lib_Auto_Init.Default then
4896 -- If no attribute Library_Auto_Init is declared, then set auto
4897 -- init only if it is supported.
4899 Data.Lib_Auto_Init := Auto_Init_Supported;
4902 Get_Name_String (Lib_Auto_Init.Value);
4903 To_Lower (Name_Buffer (1 .. Name_Len));
4905 if Name_Buffer (1 .. Name_Len) = "false" then
4906 Data.Lib_Auto_Init := False;
4908 elsif Name_Buffer (1 .. Name_Len) = "true" then
4909 if Auto_Init_Supported then
4910 Data.Lib_Auto_Init := True;
4913 -- Library_Auto_Init cannot be "true" if auto init is not
4918 "library auto init not supported " &
4920 Lib_Auto_Init.Location);
4926 "invalid value for attribute Library_Auto_Init",
4927 Lib_Auto_Init.Location);
4932 -- If attribute Library_Src_Dir is defined and not the empty string,
4933 -- check if the directory exist and is not the object directory or
4934 -- one of the source directories. This is the directory where copies
4935 -- of the interface sources will be copied. Note that this directory
4936 -- may be the library directory.
4938 if Lib_Src_Dir.Value /= Empty_String then
4940 Dir_Id : constant File_Name_Type :=
4941 File_Name_Type (Lib_Src_Dir.Value);
4948 Data.Display_Directory,
4949 Data.Library_Src_Dir,
4950 Data.Display_Library_Src_Dir,
4951 Create => "library source copy",
4952 Current_Dir => Current_Dir,
4953 Location => Lib_Src_Dir.Location);
4955 -- If directory does not exist, report an error
4957 if Data.Library_Src_Dir = No_Path then
4959 -- Get the absolute name of the library directory that does
4960 -- not exist, to report an error.
4963 Dir_Name : constant String :=
4964 Get_Name_String (Dir_Id);
4967 if Is_Absolute_Path (Dir_Name) then
4968 Err_Vars.Error_Msg_File_1 := Dir_Id;
4971 Get_Name_String (Data.Directory);
4973 if Name_Buffer (Name_Len) /=
4976 Name_Len := Name_Len + 1;
4977 Name_Buffer (Name_Len) :=
4978 Directory_Separator;
4983 Name_Len + Dir_Name'Length) :=
4985 Name_Len := Name_Len + Dir_Name'Length;
4986 Err_Vars.Error_Msg_Name_1 := Name_Find;
4991 Error_Msg_File_1 := Dir_Id;
4994 "Directory { does not exist",
4995 Lib_Src_Dir.Location);
4998 -- Report error if it is the same as the object directory
5000 elsif Data.Library_Src_Dir = Data.Object_Directory then
5003 "directory to copy interfaces cannot be " &
5004 "the object directory",
5005 Lib_Src_Dir.Location);
5006 Data.Library_Src_Dir := No_Path;
5010 Src_Dirs : String_List_Id;
5011 Src_Dir : String_Element;
5014 -- Interface copy directory cannot be one of the source
5015 -- directory of the current project.
5017 Src_Dirs := Data.Source_Dirs;
5018 while Src_Dirs /= Nil_String loop
5019 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5021 -- Report error if it is one of the source directories
5023 if Data.Library_Src_Dir =
5024 Path_Name_Type (Src_Dir.Value)
5028 "directory to copy interfaces cannot " &
5029 "be one of the source directories",
5030 Lib_Src_Dir.Location);
5031 Data.Library_Src_Dir := No_Path;
5035 Src_Dirs := Src_Dir.Next;
5038 if Data.Library_Src_Dir /= No_Path then
5040 -- It cannot be a source directory of any other
5043 Project_Loop : for Pid in 1 ..
5044 Project_Table.Last (In_Tree.Projects)
5047 In_Tree.Projects.Table (Pid).Source_Dirs;
5048 Dir_Loop : while Src_Dirs /= Nil_String loop
5050 In_Tree.String_Elements.Table (Src_Dirs);
5052 -- Report error if it is one of the source
5055 if Data.Library_Src_Dir =
5056 Path_Name_Type (Src_Dir.Value)
5059 File_Name_Type (Src_Dir.Value);
5061 In_Tree.Projects.Table (Pid).Name;
5064 "directory to copy interfaces cannot " &
5065 "be the same as source directory { of " &
5067 Lib_Src_Dir.Location);
5068 Data.Library_Src_Dir := No_Path;
5072 Src_Dirs := Src_Dir.Next;
5074 end loop Project_Loop;
5078 -- In high verbosity, if there is a valid Library_Src_Dir,
5079 -- display its path name.
5081 if Data.Library_Src_Dir /= No_Path
5082 and then Current_Verbosity = High
5084 Write_Str ("Directory to copy interfaces =""");
5085 Write_Str (Get_Name_String (Data.Library_Src_Dir));
5092 -- Check the symbol related attributes
5094 -- First, the symbol policy
5096 if not Lib_Symbol_Policy.Default then
5098 Value : constant String :=
5100 (Get_Name_String (Lib_Symbol_Policy.Value));
5103 -- Symbol policy must hove one of a limited number of values
5105 if Value = "autonomous" or else Value = "default" then
5106 Data.Symbol_Data.Symbol_Policy := Autonomous;
5108 elsif Value = "compliant" then
5109 Data.Symbol_Data.Symbol_Policy := Compliant;
5111 elsif Value = "controlled" then
5112 Data.Symbol_Data.Symbol_Policy := Controlled;
5114 elsif Value = "restricted" then
5115 Data.Symbol_Data.Symbol_Policy := Restricted;
5117 elsif Value = "direct" then
5118 Data.Symbol_Data.Symbol_Policy := Direct;
5123 "illegal value for Library_Symbol_Policy",
5124 Lib_Symbol_Policy.Location);
5129 -- If attribute Library_Symbol_File is not specified, symbol policy
5130 -- cannot be Restricted.
5132 if Lib_Symbol_File.Default then
5133 if Data.Symbol_Data.Symbol_Policy = Restricted then
5136 "Library_Symbol_File needs to be defined when " &
5137 "symbol policy is Restricted",
5138 Lib_Symbol_Policy.Location);
5142 -- Library_Symbol_File is defined
5144 Data.Symbol_Data.Symbol_File :=
5145 Path_Name_Type (Lib_Symbol_File.Value);
5147 Get_Name_String (Lib_Symbol_File.Value);
5149 if Name_Len = 0 then
5152 "symbol file name cannot be an empty string",
5153 Lib_Symbol_File.Location);
5156 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5159 for J in 1 .. Name_Len loop
5160 if Name_Buffer (J) = '/'
5161 or else Name_Buffer (J) = Directory_Separator
5170 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5173 "symbol file name { is illegal. " &
5174 "Name canot include directory info.",
5175 Lib_Symbol_File.Location);
5180 -- If attribute Library_Reference_Symbol_File is not defined,
5181 -- symbol policy cannot be Compilant or Controlled.
5183 if Lib_Ref_Symbol_File.Default then
5184 if Data.Symbol_Data.Symbol_Policy = Compliant
5185 or else Data.Symbol_Data.Symbol_Policy = Controlled
5189 "a reference symbol file need to be defined",
5190 Lib_Symbol_Policy.Location);
5194 -- Library_Reference_Symbol_File is defined, check file exists
5196 Data.Symbol_Data.Reference :=
5197 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5199 Get_Name_String (Lib_Ref_Symbol_File.Value);
5201 if Name_Len = 0 then
5204 "reference symbol file name cannot be an empty string",
5205 Lib_Symbol_File.Location);
5208 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5210 Add_Str_To_Name_Buffer (Get_Name_String (Data.Directory));
5211 Add_Char_To_Name_Buffer (Directory_Separator);
5212 Add_Str_To_Name_Buffer
5213 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5214 Data.Symbol_Data.Reference := Name_Find;
5217 if not Is_Regular_File
5218 (Get_Name_String (Data.Symbol_Data.Reference))
5221 File_Name_Type (Lib_Ref_Symbol_File.Value);
5223 -- For controlled and direct symbol policies, it is an error
5224 -- if the reference symbol file does not exist. For other
5225 -- symbol policies, this is just a warning
5228 Data.Symbol_Data.Symbol_Policy /= Controlled
5229 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5233 "<library reference symbol file { does not exist",
5234 Lib_Ref_Symbol_File.Location);
5236 -- In addition in the non-controlled case, if symbol policy
5237 -- is Compliant, it is changed to Autonomous, because there
5238 -- is no reference to check against, and we don't want to
5239 -- fail in this case.
5241 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5242 if Data.Symbol_Data.Symbol_Policy = Compliant then
5243 Data.Symbol_Data.Symbol_Policy := Autonomous;
5248 -- If both the reference symbol file and the symbol file are
5249 -- defined, then check that they are not the same file.
5251 if Data.Symbol_Data.Symbol_File /= No_Path then
5252 Get_Name_String (Data.Symbol_Data.Symbol_File);
5254 if Name_Len > 0 then
5256 Symb_Path : constant String :=
5259 (Data.Object_Directory) &
5260 Directory_Separator &
5261 Name_Buffer (1 .. Name_Len),
5262 Directory => Current_Dir,
5264 Opt.Follow_Links_For_Files);
5265 Ref_Path : constant String :=
5268 (Data.Symbol_Data.Reference),
5269 Directory => Current_Dir,
5271 Opt.Follow_Links_For_Files);
5273 if Symb_Path = Ref_Path then
5276 "library reference symbol file and library" &
5277 " symbol file cannot be the same file",
5278 Lib_Ref_Symbol_File.Location);
5286 end Check_Stand_Alone_Library;
5288 ----------------------------
5289 -- Compute_Directory_Last --
5290 ----------------------------
5292 function Compute_Directory_Last (Dir : String) return Natural is
5295 and then (Dir (Dir'Last - 1) = Directory_Separator
5296 or else Dir (Dir'Last - 1) = '/')
5298 return Dir'Last - 1;
5302 end Compute_Directory_Last;
5309 (Project : Project_Id;
5310 In_Tree : Project_Tree_Ref;
5312 Flag_Location : Source_Ptr)
5314 Real_Location : Source_Ptr := Flag_Location;
5315 Error_Buffer : String (1 .. 5_000);
5316 Error_Last : Natural := 0;
5317 Name_Number : Natural := 0;
5318 File_Number : Natural := 0;
5319 First : Positive := Msg'First;
5322 procedure Add (C : Character);
5323 -- Add a character to the buffer
5325 procedure Add (S : String);
5326 -- Add a string to the buffer
5329 -- Add a name to the buffer
5332 -- Add a file name to the buffer
5338 procedure Add (C : Character) is
5340 Error_Last := Error_Last + 1;
5341 Error_Buffer (Error_Last) := C;
5344 procedure Add (S : String) is
5346 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5347 Error_Last := Error_Last + S'Length;
5354 procedure Add_File is
5355 File : File_Name_Type;
5359 File_Number := File_Number + 1;
5363 File := Err_Vars.Error_Msg_File_1;
5365 File := Err_Vars.Error_Msg_File_2;
5367 File := Err_Vars.Error_Msg_File_3;
5372 Get_Name_String (File);
5373 Add (Name_Buffer (1 .. Name_Len));
5381 procedure Add_Name is
5386 Name_Number := Name_Number + 1;
5390 Name := Err_Vars.Error_Msg_Name_1;
5392 Name := Err_Vars.Error_Msg_Name_2;
5394 Name := Err_Vars.Error_Msg_Name_3;
5399 Get_Name_String (Name);
5400 Add (Name_Buffer (1 .. Name_Len));
5404 -- Start of processing for Error_Msg
5407 -- If location of error is unknown, use the location of the project
5409 if Real_Location = No_Location then
5410 Real_Location := In_Tree.Projects.Table (Project).Location;
5413 if Error_Report = null then
5414 Prj.Err.Error_Msg (Msg, Real_Location);
5418 -- Ignore continuation character
5420 if Msg (First) = '\
' then
5423 -- Warning character is always the first one in this package
5424 -- this is an undocumented kludge???
5426 elsif Msg (First) = '?
' then
5430 elsif Msg (First) = '<' then
5433 if Err_Vars.Error_Msg_Warn then
5439 while Index <= Msg'Last loop
5440 if Msg (Index) = '{' then
5443 elsif Msg (Index) = '%' then
5444 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5456 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5459 ----------------------
5460 -- Find_Ada_Sources --
5461 ----------------------
5463 procedure Find_Ada_Sources
5464 (Project : Project_Id;
5465 In_Tree : Project_Tree_Ref;
5466 Data : in out Project_Data;
5467 Current_Dir : String)
5469 Source_Dir : String_List_Id := Data.Source_Dirs;
5470 Element : String_Element;
5472 Current_Source : String_List_Id := Nil_String;
5473 Source_Recorded : Boolean := False;
5476 if Current_Verbosity = High then
5477 Write_Line ("Looking for sources:");
5480 -- For each subdirectory
5482 while Source_Dir /= Nil_String loop
5484 Source_Recorded := False;
5485 Element := In_Tree.String_Elements.Table (Source_Dir);
5486 if Element.Value /= No_Name then
5487 Get_Name_String (Element.Display_Value);
5490 Source_Directory : constant String :=
5491 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5492 Dir_Last : constant Natural :=
5493 Compute_Directory_Last (Source_Directory);
5496 if Current_Verbosity = High then
5497 Write_Str ("Source_Dir = ");
5498 Write_Line (Source_Directory);
5501 -- We look at every entry in the source directory
5504 Source_Directory (Source_Directory'First .. Dir_Last));
5507 Read (Dir, Name_Buffer, Name_Len);
5509 if Current_Verbosity = High then
5510 Write_Str (" Checking ");
5511 Write_Line (Name_Buffer (1 .. Name_Len));
5514 exit when Name_Len = 0;
5517 File_Name : constant File_Name_Type := Name_Find;
5519 -- ??? We could probably optimize the following call:
5520 -- we need to resolve links only once for the
5521 -- directory itself, and then do a single call to
5522 -- readlink() for each file. Unfortunately that would
5523 -- require a change in Normalize_Pathname so that it
5524 -- has the option of not resolving links for its
5525 -- Directory parameter, only for Name.
5527 Path : constant String :=
5529 (Name => Name_Buffer (1 .. Name_Len),
5532 (Source_Directory'First .. Dir_Last),
5534 Opt.Follow_Links_For_Files,
5535 Case_Sensitive => True);
5537 Path_Name : Path_Name_Type;
5540 Name_Len := Path'Length;
5541 Name_Buffer (1 .. Name_Len) := Path;
5542 Path_Name := Name_Find;
5544 -- We attempt to register it as a source. However,
5545 -- there is no error if the file does not contain a
5546 -- valid source. But there is an error if we have a
5547 -- duplicate unit name.
5550 (File_Name => File_Name,
5551 Path_Name => Path_Name,
5555 Location => No_Location,
5556 Current_Source => Current_Source,
5557 Source_Recorded => Source_Recorded,
5558 Current_Dir => Current_Dir);
5567 when Directory_Error =>
5571 if Source_Recorded then
5572 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5576 Source_Dir := Element.Next;
5579 if Current_Verbosity = High then
5580 Write_Line ("end Looking for sources.");
5583 end Find_Ada_Sources;
5589 procedure Find_Sources
5590 (Project : Project_Id;
5591 In_Tree : Project_Tree_Ref;
5592 Data : in out Project_Data;
5593 For_Language : Language_Index;
5594 Current_Dir : String)
5596 Source_Dir : String_List_Id;
5597 Element : String_Element;
5599 Current_Source : String_List_Id := Nil_String;
5600 Source_Recorded : Boolean := False;
5603 if Current_Verbosity = High then
5604 Write_Line ("Looking for sources:");
5607 -- Loop through subdirectories
5609 Source_Dir := Data.Source_Dirs;
5610 while Source_Dir /= Nil_String loop
5612 Source_Recorded := False;
5613 Element := In_Tree.String_Elements.Table (Source_Dir);
5615 if Element.Value /= No_Name then
5616 Get_Name_String (Element.Display_Value);
5619 Source_Directory : constant String :=
5620 Name_Buffer (1 .. Name_Len) &
5621 Directory_Separator;
5623 Dir_Last : constant Natural :=
5624 Compute_Directory_Last (Source_Directory);
5627 if Current_Verbosity = High then
5628 Write_Str ("Source_Dir = ");
5629 Write_Line (Source_Directory);
5632 -- We look to every entry in the source directory
5634 Open (Dir, Source_Directory
5635 (Source_Directory'First .. Dir_Last));
5638 Read (Dir, Name_Buffer, Name_Len);
5640 if Current_Verbosity = High then
5641 Write_Str (" Checking ");
5642 Write_Line (Name_Buffer (1 .. Name_Len));
5645 exit when Name_Len = 0;
5648 File_Name : constant File_Name_Type := Name_Find;
5649 Path : constant String :=
5651 (Name => Name_Buffer (1 .. Name_Len),
5652 Directory => Source_Directory
5653 (Source_Directory'First .. Dir_Last),
5654 Resolve_Links => Opt.Follow_Links_For_Files,
5655 Case_Sensitive => True);
5656 Path_Name : Path_Name_Type;
5659 Name_Len := Path'Length;
5660 Name_Buffer (1 .. Name_Len) := Path;
5661 Path_Name := Name_Find;
5663 if For_Language = Ada_Language_Index then
5665 -- We attempt to register it as a source. However,
5666 -- there is no error if the file does not contain
5667 -- a valid source. But there is an error if we have
5668 -- a duplicate unit name.
5671 (File_Name => File_Name,
5672 Path_Name => Path_Name,
5676 Location => No_Location,
5677 Current_Source => Current_Source,
5678 Source_Recorded => Source_Recorded,
5679 Current_Dir => Current_Dir);
5683 (File_Name => File_Name,
5684 Path_Name => Path_Name,
5688 Location => No_Location,
5689 Language => For_Language,
5691 Body_Suffix_Of (For_Language, Data, In_Tree),
5692 Naming_Exception => False);
5702 when Directory_Error =>
5706 if Source_Recorded then
5707 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5711 Source_Dir := Element.Next;
5714 if Current_Verbosity = High then
5715 Write_Line ("end Looking for sources.");
5718 if For_Language = Ada_Language_Index then
5720 -- If we have looked for sources and found none, then it is an error,
5721 -- except if it is an extending project. If a non extending project
5722 -- is not supposed to contain any source files, then never call
5725 if Current_Source /= Nil_String then
5726 Data.Ada_Sources_Present := True;
5728 elsif Data.Extends = No_Project then
5729 Report_No_Sources (Project, "Ada", In_Tree, Data.Location);
5734 --------------------------------
5735 -- Free_Ada_Naming_Exceptions --
5736 --------------------------------
5738 procedure Free_Ada_Naming_Exceptions is
5740 Ada_Naming_Exception_Table.Set_Last (0);
5741 Ada_Naming_Exceptions.Reset;
5742 Reverse_Ada_Naming_Exceptions.Reset;
5743 end Free_Ada_Naming_Exceptions;
5745 ---------------------
5746 -- Get_Directories --
5747 ---------------------
5749 procedure Get_Directories
5750 (Project : Project_Id;
5751 In_Tree : Project_Tree_Ref;
5752 Current_Dir : String;
5753 Data : in out Project_Data)
5755 Object_Dir : constant Variable_Value :=
5757 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5759 Exec_Dir : constant Variable_Value :=
5761 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5763 Source_Dirs : constant Variable_Value :=
5765 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5767 Excluded_Source_Dirs : constant Variable_Value :=
5769 (Name_Excluded_Source_Dirs,
5770 Data.Decl.Attributes,
5773 Source_Files : constant Variable_Value :=
5775 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5777 Last_Source_Dir : String_List_Id := Nil_String;
5779 procedure Find_Source_Dirs
5780 (From : File_Name_Type;
5781 Location : Source_Ptr;
5782 Removed : Boolean := False);
5783 -- Find one or several source directories, and add (or remove, if
5784 -- Removed is True) them to list of source directories of the project.
5786 ----------------------
5787 -- Find_Source_Dirs --
5788 ----------------------
5790 procedure Find_Source_Dirs
5791 (From : File_Name_Type;
5792 Location : Source_Ptr;
5793 Removed : Boolean := False)
5795 Directory : constant String := Get_Name_String (From);
5796 Element : String_Element;
5798 procedure Recursive_Find_Dirs (Path : Name_Id);
5799 -- Find all the subdirectories (recursively) of Path and add them
5800 -- to the list of source directories of the project.
5802 -------------------------
5803 -- Recursive_Find_Dirs --
5804 -------------------------
5806 procedure Recursive_Find_Dirs (Path : Name_Id) is
5808 Name : String (1 .. 250);
5810 List : String_List_Id;
5811 Prev : String_List_Id;
5812 Element : String_Element;
5813 Found : Boolean := False;
5815 Non_Canonical_Path : Name_Id := No_Name;
5816 Canonical_Path : Name_Id := No_Name;
5818 The_Path : constant String :=
5820 (Get_Name_String (Path),
5821 Directory => Current_Dir,
5822 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5823 Directory_Separator;
5825 The_Path_Last : constant Natural :=
5826 Compute_Directory_Last (The_Path);
5829 Name_Len := The_Path_Last - The_Path'First + 1;
5830 Name_Buffer (1 .. Name_Len) :=
5831 The_Path (The_Path'First .. The_Path_Last);
5832 Non_Canonical_Path := Name_Find;
5834 if Osint.File_Names_Case_Sensitive then
5835 Canonical_Path := Non_Canonical_Path;
5837 Get_Name_String (Non_Canonical_Path);
5838 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5839 Canonical_Path := Name_Find;
5842 -- To avoid processing the same directory several times, check
5843 -- if the directory is already in Recursive_Dirs. If it is, then
5844 -- there is nothing to do, just return. If it is not, put it there
5845 -- and continue recursive processing.
5848 if Recursive_Dirs.Get (Canonical_Path) then
5851 Recursive_Dirs.Set (Canonical_Path, True);
5855 -- Check if directory is already in list
5857 List := Data.Source_Dirs;
5859 while List /= Nil_String loop
5860 Element := In_Tree.String_Elements.Table (List);
5862 if Element.Value /= No_Name then
5863 Found := Element.Value = Canonical_Path;
5868 List := Element.Next;
5871 -- If directory is not already in list, put it there
5873 if (not Removed) and (not Found) then
5874 if Current_Verbosity = High then
5876 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5879 String_Element_Table.Increment_Last
5880 (In_Tree.String_Elements);
5882 (Value => Canonical_Path,
5883 Display_Value => Non_Canonical_Path,
5884 Location => No_Location,
5889 -- Case of first source directory
5891 if Last_Source_Dir = Nil_String then
5892 Data.Source_Dirs := String_Element_Table.Last
5893 (In_Tree.String_Elements);
5895 -- Here we already have source directories
5898 -- Link the previous last to the new one
5900 In_Tree.String_Elements.Table
5901 (Last_Source_Dir).Next :=
5902 String_Element_Table.Last
5903 (In_Tree.String_Elements);
5906 -- And register this source directory as the new last
5908 Last_Source_Dir := String_Element_Table.Last
5909 (In_Tree.String_Elements);
5910 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5913 elsif Removed and Found then
5914 if Prev = Nil_String then
5916 In_Tree.String_Elements.Table (List).Next;
5918 In_Tree.String_Elements.Table (Prev).Next :=
5919 In_Tree.String_Elements.Table (List).Next;
5923 -- Now look for subdirectories. We do that even when this
5924 -- directory is already in the list, because some of its
5925 -- subdirectories may not be in the list yet.
5927 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5930 Read (Dir, Name, Last);
5933 if Name (1 .. Last) /= "."
5934 and then Name (1 .. Last) /= ".."
5936 -- Avoid . and .. directories
5938 if Current_Verbosity = High then
5939 Write_Str (" Checking ");
5940 Write_Line (Name (1 .. Last));
5944 Path_Name : constant String :=
5946 (Name => Name (1 .. Last),
5948 The_Path (The_Path'First .. The_Path_Last),
5949 Resolve_Links => Opt.Follow_Links_For_Dirs,
5950 Case_Sensitive => True);
5953 if Is_Directory (Path_Name) then
5954 -- We have found a new subdirectory, call self
5956 Name_Len := Path_Name'Length;
5957 Name_Buffer (1 .. Name_Len) := Path_Name;
5958 Recursive_Find_Dirs (Name_Find);
5967 when Directory_Error =>
5969 end Recursive_Find_Dirs;
5971 -- Start of processing for Find_Source_Dirs
5974 if Current_Verbosity = High and then not Removed then
5975 Write_Str ("Find_Source_Dirs (""");
5976 Write_Str (Directory);
5980 -- First, check if we are looking for a directory tree, indicated
5981 -- by "/**" at the end.
5983 if Directory'Length >= 3
5984 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5985 and then (Directory (Directory'Last - 2) = '/'
5987 Directory (Directory'Last - 2) = Directory_Separator)
5990 Data.Known_Order_Of_Source_Dirs := False;
5993 Name_Len := Directory'Length - 3;
5995 if Name_Len = 0 then
5997 -- Case of "/**": all directories in file system
6000 Name_Buffer (1) := Directory (Directory'First);
6003 Name_Buffer (1 .. Name_Len) :=
6004 Directory (Directory'First .. Directory'Last - 3);
6007 if Current_Verbosity = High then
6008 Write_Str ("Looking for all subdirectories of """);
6009 Write_Str (Name_Buffer (1 .. Name_Len));
6014 Base_Dir : constant File_Name_Type := Name_Find;
6015 Root_Dir : constant String :=
6017 (Name => Get_Name_String (Base_Dir),
6019 Get_Name_String (Data.Display_Directory),
6020 Resolve_Links => False,
6021 Case_Sensitive => True);
6024 if Root_Dir'Length = 0 then
6025 Err_Vars.Error_Msg_File_1 := Base_Dir;
6027 if Location = No_Location then
6030 "{ is not a valid directory.",
6035 "{ is not a valid directory.",
6040 -- We have an existing directory, we register it and all of
6041 -- its subdirectories.
6043 if Current_Verbosity = High then
6044 Write_Line ("Looking for source directories:");
6047 Name_Len := Root_Dir'Length;
6048 Name_Buffer (1 .. Name_Len) := Root_Dir;
6049 Recursive_Find_Dirs (Name_Find);
6051 if Current_Verbosity = High then
6052 Write_Line ("End of looking for source directories.");
6057 -- We have a single directory
6061 Path_Name : Path_Name_Type;
6062 Display_Path_Name : Path_Name_Type;
6063 List : String_List_Id;
6064 Prev : String_List_Id;
6068 (Project => Project,
6071 Parent => Data.Display_Directory,
6073 Display => Display_Path_Name,
6074 Current_Dir => Current_Dir);
6076 if Path_Name = No_Path then
6077 Err_Vars.Error_Msg_File_1 := From;
6079 if Location = No_Location then
6082 "{ is not a valid directory",
6087 "{ is not a valid directory",
6093 Path : constant String :=
6094 Get_Name_String (Path_Name) &
6095 Directory_Separator;
6096 Last_Path : constant Natural :=
6097 Compute_Directory_Last (Path);
6099 Display_Path : constant String :=
6101 (Display_Path_Name) &
6102 Directory_Separator;
6103 Last_Display_Path : constant Natural :=
6104 Compute_Directory_Last
6106 Display_Path_Id : Name_Id;
6110 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6111 Path_Id := Name_Find;
6113 Add_Str_To_Name_Buffer
6115 (Display_Path'First .. Last_Display_Path));
6116 Display_Path_Id := Name_Find;
6120 -- As it is an existing directory, we add it to the
6121 -- list of directories.
6123 String_Element_Table.Increment_Last
6124 (In_Tree.String_Elements);
6128 Display_Value => Display_Path_Id,
6129 Location => No_Location,
6131 Next => Nil_String);
6133 if Last_Source_Dir = Nil_String then
6135 -- This is the first source directory
6137 Data.Source_Dirs := String_Element_Table.Last
6138 (In_Tree.String_Elements);
6141 -- We already have source directories, link the
6142 -- previous last to the new one.
6144 In_Tree.String_Elements.Table
6145 (Last_Source_Dir).Next :=
6146 String_Element_Table.Last
6147 (In_Tree.String_Elements);
6150 -- And register this source directory as the new last
6152 Last_Source_Dir := String_Element_Table.Last
6153 (In_Tree.String_Elements);
6154 In_Tree.String_Elements.Table
6155 (Last_Source_Dir) := Element;
6158 -- Remove source dir, if present
6160 List := Data.Source_Dirs;
6163 -- Look for source dir in current list
6165 while List /= Nil_String loop
6166 Element := In_Tree.String_Elements.Table (List);
6167 exit when Element.Value = Path_Id;
6169 List := Element.Next;
6172 if List /= Nil_String then
6173 -- Source dir was found, remove it from the list
6175 if Prev = Nil_String then
6177 In_Tree.String_Elements.Table (List).Next;
6180 In_Tree.String_Elements.Table (Prev).Next :=
6181 In_Tree.String_Elements.Table (List).Next;
6189 end Find_Source_Dirs;
6191 -- Start of processing for Get_Directories
6194 if Current_Verbosity = High then
6195 Write_Line ("Starting to look for directories");
6198 -- Check the object directory
6200 pragma Assert (Object_Dir.Kind = Single,
6201 "Object_Dir is not a single string");
6203 -- We set the object directory to its default
6205 Data.Object_Directory := Data.Directory;
6206 Data.Display_Object_Dir := Data.Display_Directory;
6208 if Object_Dir.Value /= Empty_String then
6209 Get_Name_String (Object_Dir.Value);
6211 if Name_Len = 0 then
6214 "Object_Dir cannot be empty",
6215 Object_Dir.Location);
6218 -- We check that the specified object directory does exist
6223 File_Name_Type (Object_Dir.Value),
6224 Data.Display_Directory,
6225 Data.Object_Directory,
6226 Data.Display_Object_Dir,
6228 Location => Object_Dir.Location,
6229 Current_Dir => Current_Dir);
6231 if Data.Object_Directory = No_Path then
6233 -- The object directory does not exist, report an error if the
6234 -- project is not externally built.
6236 if not Data.Externally_Built then
6237 Err_Vars.Error_Msg_File_1 :=
6238 File_Name_Type (Object_Dir.Value);
6241 "the object directory { cannot be found",
6245 -- Do not keep a nil Object_Directory. Set it to the specified
6246 -- (relative or absolute) path. This is for the benefit of
6247 -- tools that recover from errors; for example, these tools
6248 -- could create the non existent directory.
6250 Data.Display_Object_Dir := Path_Name_Type (Object_Dir.Value);
6252 if Osint.File_Names_Case_Sensitive then
6253 Data.Object_Directory := Path_Name_Type (Object_Dir.Value);
6255 Get_Name_String (Object_Dir.Value);
6256 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6257 Data.Object_Directory := Name_Find;
6263 if Current_Verbosity = High then
6264 if Data.Object_Directory = No_Path then
6265 Write_Line ("No object directory");
6267 Write_Str ("Object directory: """);
6268 Write_Str (Get_Name_String (Data.Display_Object_Dir));
6273 -- Check the exec directory
6275 pragma Assert (Exec_Dir.Kind = Single,
6276 "Exec_Dir is not a single string");
6278 -- We set the object directory to its default
6280 Data.Exec_Directory := Data.Object_Directory;
6281 Data.Display_Exec_Dir := Data.Display_Object_Dir;
6283 if Exec_Dir.Value /= Empty_String then
6284 Get_Name_String (Exec_Dir.Value);
6286 if Name_Len = 0 then
6289 "Exec_Dir cannot be empty",
6293 -- We check that the specified object directory does exist
6298 File_Name_Type (Exec_Dir.Value),
6299 Data.Display_Directory,
6300 Data.Exec_Directory,
6301 Data.Display_Exec_Dir,
6303 Location => Exec_Dir.Location,
6304 Current_Dir => Current_Dir);
6306 if Data.Exec_Directory = No_Path then
6307 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6310 "the exec directory { cannot be found",
6316 if Current_Verbosity = High then
6317 if Data.Exec_Directory = No_Path then
6318 Write_Line ("No exec directory");
6320 Write_Str ("Exec directory: """);
6321 Write_Str (Get_Name_String (Data.Display_Exec_Dir));
6326 -- Look for the source directories
6328 if Current_Verbosity = High then
6329 Write_Line ("Starting to look for source directories");
6332 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6334 if (not Source_Files.Default) and then
6335 Source_Files.Values = Nil_String
6337 Data.Source_Dirs := Nil_String;
6339 if Data.Extends = No_Project
6340 and then Data.Object_Directory = Data.Directory
6342 Data.Object_Directory := No_Path;
6345 elsif Source_Dirs.Default then
6347 -- No Source_Dirs specified: the single source directory is the one
6348 -- containing the project file
6350 String_Element_Table.Increment_Last
6351 (In_Tree.String_Elements);
6352 Data.Source_Dirs := String_Element_Table.Last
6353 (In_Tree.String_Elements);
6354 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6355 (Value => Name_Id (Data.Directory),
6356 Display_Value => Name_Id (Data.Display_Directory),
6357 Location => No_Location,
6362 if Current_Verbosity = High then
6363 Write_Line ("Single source directory:");
6365 Write_Str (Get_Name_String (Data.Display_Directory));
6369 elsif Source_Dirs.Values = Nil_String then
6371 -- If Source_Dirs is an empty string list, this means that this
6372 -- project contains no source. For projects that don't extend other
6373 -- projects, this also means that there is no need for an object
6374 -- directory, if not specified.
6376 if Data.Extends = No_Project
6377 and then Data.Object_Directory = Data.Directory
6379 Data.Object_Directory := No_Path;
6382 Data.Source_Dirs := Nil_String;
6386 Source_Dir : String_List_Id;
6387 Element : String_Element;
6390 -- Process the source directories for each element of the list
6392 Source_Dir := Source_Dirs.Values;
6393 while Source_Dir /= Nil_String loop
6395 In_Tree.String_Elements.Table (Source_Dir);
6397 (File_Name_Type (Element.Value), Element.Location);
6398 Source_Dir := Element.Next;
6403 if not Excluded_Source_Dirs.Default
6404 and then Excluded_Source_Dirs.Values /= Nil_String
6407 Source_Dir : String_List_Id;
6408 Element : String_Element;
6411 -- Process the source directories for each element of the list
6413 Source_Dir := Excluded_Source_Dirs.Values;
6414 while Source_Dir /= Nil_String loop
6416 In_Tree.String_Elements.Table (Source_Dir);
6418 (File_Name_Type (Element.Value),
6421 Source_Dir := Element.Next;
6426 if Current_Verbosity = High then
6427 Write_Line ("Putting source directories in canonical cases");
6431 Current : String_List_Id := Data.Source_Dirs;
6432 Element : String_Element;
6435 while Current /= Nil_String loop
6436 Element := In_Tree.String_Elements.Table (Current);
6437 if Element.Value /= No_Name then
6438 if not Osint.File_Names_Case_Sensitive then
6439 Get_Name_String (Element.Value);
6440 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6441 Element.Value := Name_Find;
6444 In_Tree.String_Elements.Table (Current) := Element;
6447 Current := Element.Next;
6451 end Get_Directories;
6458 (Project : Project_Id;
6459 In_Tree : Project_Tree_Ref;
6460 Data : in out Project_Data)
6462 Mains : constant Variable_Value :=
6463 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6466 Data.Mains := Mains.Values;
6468 -- If no Mains were specified, and if we are an extending project,
6469 -- inherit the Mains from the project we are extending.
6471 if Mains.Default then
6472 if Data.Extends /= No_Project then
6474 In_Tree.Projects.Table (Data.Extends).Mains;
6477 -- In a library project file, Main cannot be specified
6479 elsif Data.Library then
6482 "a library project file cannot have Main specified",
6487 ---------------------------
6488 -- Get_Sources_From_File --
6489 ---------------------------
6491 procedure Get_Sources_From_File
6493 Location : Source_Ptr;
6494 Project : Project_Id;
6495 In_Tree : Project_Tree_Ref)
6497 File : Prj.Util.Text_File;
6498 Line : String (1 .. 250);
6500 Source_Name : File_Name_Type;
6501 Name_Loc : Name_Location;
6504 if Get_Mode = Ada_Only then
6508 if Current_Verbosity = High then
6509 Write_Str ("Opening """);
6516 Prj.Util.Open (File, Path);
6518 if not Prj.Util.Is_Valid (File) then
6519 Error_Msg (Project, In_Tree, "file does not exist", Location);
6521 -- Read the lines one by one
6523 while not Prj.Util.End_Of_File (File) loop
6524 Prj.Util.Get_Line (File, Line, Last);
6526 -- A non empty, non comment line should contain a file name
6529 and then (Last = 1 or else Line (1 .. 2) /= "--")
6532 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6533 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6534 Source_Name := Name_Find;
6536 -- Check that there is no directory information
6538 for J in 1 .. Last loop
6539 if Line (J) = '/' or else Line (J) = Directory_Separator then
6540 Error_Msg_File_1 := Source_Name;
6544 "file name cannot include directory information ({)",
6550 Name_Loc := Source_Names.Get (Source_Name);
6552 if Name_Loc = No_Name_Location then
6554 (Name => Source_Name,
6555 Location => Location,
6556 Source => No_Source,
6561 Source_Names.Set (Source_Name, Name_Loc);
6565 Prj.Util.Close (File);
6568 end Get_Sources_From_File;
6575 (In_Tree : Project_Tree_Ref;
6576 Canonical_File_Name : File_Name_Type;
6577 Naming : Naming_Data;
6578 Exception_Id : out Ada_Naming_Exception_Id;
6579 Unit_Name : out Name_Id;
6580 Unit_Kind : out Spec_Or_Body;
6581 Needs_Pragma : out Boolean)
6583 Info_Id : Ada_Naming_Exception_Id :=
6584 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6585 VMS_Name : File_Name_Type;
6588 if Info_Id = No_Ada_Naming_Exception then
6589 if Hostparm.OpenVMS then
6590 VMS_Name := Canonical_File_Name;
6591 Get_Name_String (VMS_Name);
6593 if Name_Buffer (Name_Len) = '.' then
6594 Name_Len := Name_Len - 1;
6595 VMS_Name := Name_Find;
6598 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6603 if Info_Id /= No_Ada_Naming_Exception then
6604 Exception_Id := Info_Id;
6605 Unit_Name := No_Name;
6606 Unit_Kind := Specification;
6607 Needs_Pragma := True;
6611 Needs_Pragma := False;
6612 Exception_Id := No_Ada_Naming_Exception;
6614 Get_Name_String (Canonical_File_Name);
6616 -- How about some comments and a name for this declare block ???
6617 -- In fact the whole code below needs more comments ???
6620 File : String := Name_Buffer (1 .. Name_Len);
6621 First : constant Positive := File'First;
6622 Last : Natural := File'Last;
6623 Standard_GNAT : Boolean;
6624 Spec : constant File_Name_Type :=
6625 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6626 Body_Suff : constant File_Name_Type :=
6627 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6630 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6631 and then Body_Suff = Default_Ada_Body_Suffix;
6634 Spec_Suffix : constant String := Get_Name_String (Spec);
6635 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6636 Sep_Suffix : constant String :=
6637 Get_Name_String (Naming.Separate_Suffix);
6639 May_Be_Spec : Boolean;
6640 May_Be_Body : Boolean;
6641 May_Be_Sep : Boolean;
6645 File'Length > Spec_Suffix'Length
6647 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6650 File'Length > Body_Suffix'Length
6652 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6655 File'Length > Sep_Suffix'Length
6657 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6659 -- If two May_Be_ booleans are True, always choose the longer one
6662 if May_Be_Body and then
6663 Spec_Suffix'Length < Body_Suffix'Length
6665 Unit_Kind := Body_Part;
6667 if May_Be_Sep and then
6668 Body_Suffix'Length < Sep_Suffix'Length
6670 Last := Last - Sep_Suffix'Length;
6671 May_Be_Body := False;
6674 Last := Last - Body_Suffix'Length;
6675 May_Be_Sep := False;
6678 elsif May_Be_Sep and then
6679 Spec_Suffix'Length < Sep_Suffix'Length
6681 Unit_Kind := Body_Part;
6682 Last := Last - Sep_Suffix'Length;
6685 Unit_Kind := Specification;
6686 Last := Last - Spec_Suffix'Length;
6689 elsif May_Be_Body then
6690 Unit_Kind := Body_Part;
6692 if May_Be_Sep and then
6693 Body_Suffix'Length < Sep_Suffix'Length
6695 Last := Last - Sep_Suffix'Length;
6696 May_Be_Body := False;
6698 Last := Last - Body_Suffix'Length;
6699 May_Be_Sep := False;
6702 elsif May_Be_Sep then
6703 Unit_Kind := Body_Part;
6704 Last := Last - Sep_Suffix'Length;
6712 -- This is not a source file
6714 Unit_Name := No_Name;
6715 Unit_Kind := Specification;
6717 if Current_Verbosity = High then
6718 Write_Line (" Not a valid file name.");
6723 elsif Current_Verbosity = High then
6725 when Specification =>
6726 Write_Str (" Specification: ");
6727 Write_Line (File (First .. Last + Spec_Suffix'Length));
6731 Write_Str (" Body: ");
6732 Write_Line (File (First .. Last + Body_Suffix'Length));
6735 Write_Str (" Separate: ");
6736 Write_Line (File (First .. Last + Sep_Suffix'Length));
6742 Get_Name_String (Naming.Dot_Replacement);
6744 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6746 if Name_Buffer (1 .. Name_Len) /= "." then
6748 -- If Dot_Replacement is not a single dot, then there should not
6749 -- be any dot in the name.
6751 for Index in First .. Last loop
6752 if File (Index) = '.' then
6753 if Current_Verbosity = High then
6755 (" Not a valid file name (some dot not replaced).");
6758 Unit_Name := No_Name;
6764 -- Replace the substring Dot_Replacement with dots
6767 Index : Positive := First;
6770 while Index <= Last - Name_Len + 1 loop
6772 if File (Index .. Index + Name_Len - 1) =
6773 Name_Buffer (1 .. Name_Len)
6775 File (Index) := '.';
6777 if Name_Len > 1 and then Index < Last then
6778 File (Index + 1 .. Last - Name_Len + 1) :=
6779 File (Index + Name_Len .. Last);
6782 Last := Last - Name_Len + 1;
6790 -- Check if the casing is right
6793 Src : String := File (First .. Last);
6794 Src_Last : Positive := Last;
6797 case Naming.Casing is
6798 when All_Lower_Case =>
6801 Mapping => Lower_Case_Map);
6803 when All_Upper_Case =>
6806 Mapping => Upper_Case_Map);
6808 when Mixed_Case | Unknown =>
6812 if Src /= File (First .. Last) then
6813 if Current_Verbosity = High then
6814 Write_Line (" Not a valid file name (casing).");
6817 Unit_Name := No_Name;
6821 -- We put the name in lower case
6825 Mapping => Lower_Case_Map);
6827 -- In the standard GNAT naming scheme, check for special cases:
6828 -- children or separates of A, G, I or S, and run time sources.
6830 if Standard_GNAT and then Src'Length >= 3 then
6832 S1 : constant Character := Src (Src'First);
6833 S2 : constant Character := Src (Src'First + 1);
6834 S3 : constant Character := Src (Src'First + 2);
6842 -- Children or separates of packages A, G, I or S. These
6843 -- names are x__ ... or x~... (where x is a, g, i, or s).
6844 -- Both versions (x__... and x~...) are allowed in all
6845 -- platforms, because it is not possible to know the
6846 -- platform before processing of the project files.
6848 if S2 = '_
' and then S3 = '_
' then
6849 Src (Src'First + 1) := '.';
6850 Src_Last := Src_Last - 1;
6851 Src (Src'First + 2 .. Src_Last) :=
6852 Src (Src'First + 3 .. Src_Last + 1);
6855 Src (Src'First + 1) := '.';
6857 -- If it is potentially a run time source, disable
6858 -- filling of the mapping file to avoid warnings.
6861 Set_Mapping_File_Initial_State_To_Empty;
6867 if Current_Verbosity = High then
6869 Write_Line (Src (Src'First .. Src_Last));
6872 -- Now, we check if this name is a valid unit name
6875 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6885 function Hash (Unit : Unit_Info) return Header_Num is
6887 return Header_Num (Unit.Unit mod 2048);
6890 -----------------------
6891 -- Is_Illegal_Suffix --
6892 -----------------------
6894 function Is_Illegal_Suffix
6896 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6899 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6903 -- If dot replacement is a single dot, and first character of suffix is
6906 if Dot_Replacement_Is_A_Single_Dot
6907 and then Suffix (Suffix'First) = '.'
6909 for Index in Suffix'First + 1 .. Suffix'Last loop
6911 -- If there is another dot
6913 if Suffix (Index) = '.' then
6915 -- It is illegal to have a letter following the initial dot
6917 return Is_Letter (Suffix (Suffix'First + 1));
6925 end Is_Illegal_Suffix;
6927 ----------------------
6928 -- Locate_Directory --
6929 ----------------------
6931 procedure Locate_Directory
6932 (Project : Project_Id;
6933 In_Tree : Project_Tree_Ref;
6934 Name : File_Name_Type;
6935 Parent : Path_Name_Type;
6936 Dir : out Path_Name_Type;
6937 Display : out Path_Name_Type;
6938 Create : String := "";
6939 Current_Dir : String;
6940 Location : Source_Ptr := No_Location)
6942 The_Name : String := Get_Name_String (Name);
6944 The_Parent : constant String :=
6945 Get_Name_String (Parent) & Directory_Separator;
6947 The_Parent_Last : constant Natural :=
6948 Compute_Directory_Last (The_Parent);
6950 Full_Name : File_Name_Type;
6953 -- Convert '/' to directory separator (for Windows)
6955 for J in The_Name'Range loop
6956 if The_Name (J) = '/' then
6957 The_Name (J) := Directory_Separator;
6961 if Current_Verbosity = High then
6962 Write_Str ("Locate_Directory (""");
6963 Write_Str (The_Name);
6964 Write_Str (""", """);
6965 Write_Str (The_Parent);
6972 if Is_Absolute_Path (The_Name) then
6977 Add_Str_To_Name_Buffer
6978 (The_Parent (The_Parent'First .. The_Parent_Last));
6979 Add_Str_To_Name_Buffer (The_Name);
6980 Full_Name := Name_Find;
6984 Full_Path_Name : constant String := Get_Name_String (Full_Name);
6987 if Setup_Projects and then Create'Length > 0
6988 and then not Is_Directory (Full_Path_Name)
6991 Create_Path (Full_Path_Name);
6993 if not Quiet_Output then
6995 Write_Str (" directory """);
6996 Write_Str (Full_Path_Name);
6997 Write_Line (""" created");
7004 "could not create " & Create &
7005 " directory " & Full_Path_Name,
7010 if Is_Directory (Full_Path_Name) then
7012 Normed : constant String :=
7015 Directory => Current_Dir,
7016 Resolve_Links => False,
7017 Case_Sensitive => True);
7019 Canonical_Path : constant String :=
7022 Directory => Current_Dir,
7024 Opt.Follow_Links_For_Dirs,
7025 Case_Sensitive => False);
7028 Name_Len := Normed'Length;
7029 Name_Buffer (1 .. Name_Len) := Normed;
7030 Display := Name_Find;
7032 Name_Len := Canonical_Path'Length;
7033 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7038 end Locate_Directory;
7040 ---------------------------
7041 -- Find_Excluded_Sources --
7042 ---------------------------
7044 procedure Find_Excluded_Sources
7045 (In_Tree : Project_Tree_Ref;
7046 Data : Project_Data)
7048 Excluded_Sources : Variable_Value;
7049 Current : String_List_Id;
7050 Element : String_Element;
7051 Location : Source_Ptr;
7052 Name : File_Name_Type;
7054 -- If Excluded_Source_Files is not declared, check
7055 -- Locally_Removed_Files.
7059 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7061 if Excluded_Sources.Default then
7064 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7067 Excluded_Sources_Htable.Reset;
7069 -- If there are excluded sources, put them in the table
7071 if not Excluded_Sources.Default then
7072 Current := Excluded_Sources.Values;
7073 while Current /= Nil_String loop
7074 Element := In_Tree.String_Elements.Table (Current);
7076 if Osint.File_Names_Case_Sensitive then
7077 Name := File_Name_Type (Element.Value);
7079 Get_Name_String (Element.Value);
7080 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7084 -- If the element has no location, then use the location
7085 -- of Excluded_Sources to report possible errors.
7087 if Element.Location = No_Location then
7088 Location := Excluded_Sources.Location;
7090 Location := Element.Location;
7093 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7094 Current := Element.Next;
7097 end Find_Excluded_Sources;
7099 ---------------------------
7100 -- Find_Explicit_Sources --
7101 ---------------------------
7103 procedure Find_Explicit_Sources
7104 (Lang : Language_Index;
7105 Current_Dir : String;
7106 Project : Project_Id;
7107 In_Tree : Project_Tree_Ref;
7108 Data : in out Project_Data)
7110 Sources : constant Variable_Value :=
7113 Data.Decl.Attributes,
7115 Source_List_File : constant Variable_Value :=
7117 (Name_Source_List_File,
7118 Data.Decl.Attributes,
7120 Name_Loc : Name_Location;
7123 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7125 (Source_List_File.Kind = Single,
7126 "Source_List_File is not a single string");
7128 -- If the user has specified a Sources attribute
7130 if not Sources.Default then
7131 if not Source_List_File.Default then
7134 "?both variables source_files and " &
7135 "source_list_file are present",
7136 Source_List_File.Location);
7139 -- Sources is a list of file names
7142 Current : String_List_Id := Sources.Values;
7143 Element : String_Element;
7144 Location : Source_Ptr;
7145 Name : File_Name_Type;
7148 if Get_Mode = Ada_Only then
7149 Data.Ada_Sources_Present := Current /= Nil_String;
7152 -- If we are processing other languages in the case of gprmake,
7153 -- we should not reset the list of sources, which was already
7154 -- initialized for the Ada files.
7156 if Get_Mode /= Ada_Only or else Lang /= Ada_Language_Index then
7157 if Current = Nil_String then
7160 Data.Source_Dirs := Nil_String;
7161 when Multi_Language =>
7162 Data.First_Language_Processing := No_Language_Index;
7165 -- This project contains no source. For projects that
7166 -- don't extend other projects, this also means that
7167 -- there is no need for an object directory, if not
7170 if Data.Extends = No_Project
7171 and then Data.Object_Directory = Data.Directory
7173 Data.Object_Directory := No_Path;
7178 while Current /= Nil_String loop
7179 Element := In_Tree.String_Elements.Table (Current);
7180 Get_Name_String (Element.Value);
7182 if Osint.File_Names_Case_Sensitive then
7183 Name := File_Name_Type (Element.Value);
7185 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7189 -- If the element has no location, then use the
7190 -- location of Sources to report possible errors.
7192 if Element.Location = No_Location then
7193 Location := Sources.Location;
7195 Location := Element.Location;
7198 -- Check that there is no directory information
7200 for J in 1 .. Name_Len loop
7201 if Name_Buffer (J) = '/'
7202 or else Name_Buffer (J) = Directory_Separator
7204 Error_Msg_File_1 := Name;
7208 "file name cannot include directory " &
7215 -- In Multi_Language mode, check whether the file is
7216 -- already there (??? Is this really needed, and why ?)
7220 Name_Loc := No_Name_Location;
7221 when Multi_Language =>
7222 Name_Loc := Source_Names.Get (Name);
7225 if Name_Loc = No_Name_Location then
7228 Location => Location,
7229 Source => No_Source,
7232 Source_Names.Set (Name, Name_Loc);
7235 Current := Element.Next;
7238 if Get_Mode = Ada_Only then
7239 if Lang = Ada_Language_Index then
7240 Get_Path_Names_And_Record_Ada_Sources
7241 (Project, In_Tree, Data, Current_Dir);
7243 Record_Other_Sources
7244 (Project => Project,
7248 Naming_Exceptions => False);
7253 -- If we have no Source_Files attribute, check the Source_List_File
7256 elsif not Source_List_File.Default then
7258 -- Source_List_File is the name of the file
7259 -- that contains the source file names
7262 Source_File_Path_Name : constant String :=
7264 (File_Name_Type (Source_List_File.Value), Data.Directory);
7267 if Source_File_Path_Name'Length = 0 then
7268 Err_Vars.Error_Msg_File_1 :=
7269 File_Name_Type (Source_List_File.Value);
7272 "file with sources { does not exist",
7273 Source_List_File.Location);
7276 Get_Sources_From_File
7277 (Source_File_Path_Name, Source_List_File.Location,
7280 if Get_Mode = Ada_Only then
7281 -- Look in the source directories to find those sources
7283 if Lang = Ada_Language_Index then
7284 Get_Path_Names_And_Record_Ada_Sources
7285 (Project, In_Tree, Data, Current_Dir);
7288 Record_Other_Sources
7289 (Project => Project,
7293 Naming_Exceptions => False);
7300 -- Neither Source_Files nor Source_List_File has been
7301 -- specified. Find all the files that satisfy the naming
7302 -- scheme in all the source directories.
7306 if Lang = Ada_Language_Index then
7307 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7309 -- Find all the files that satisfy the naming scheme in
7310 -- all the source directories. All the naming exceptions
7311 -- that effectively exist are also part of the source
7312 -- of this language.
7314 Find_Sources (Project, In_Tree, Data, Lang, Current_Dir);
7317 when Multi_Language =>
7322 if Get_Mode = Multi_Language then
7324 (Project, In_Tree, Data,
7326 Sources.Default and then Source_List_File.Default);
7329 if Get_Mode = Ada_Only
7330 and then Lang = Ada_Language_Index
7331 and then Data.Extends = No_Project
7333 -- We should have found at least one source. If not, report an error.
7335 if Data.Ada_Sources = Nil_String then
7337 (Project, "Ada", In_Tree, Source_List_File.Location);
7341 end Find_Explicit_Sources;
7343 -------------------------------------------
7344 -- Get_Path_Names_And_Record_Ada_Sources --
7345 -------------------------------------------
7347 procedure Get_Path_Names_And_Record_Ada_Sources
7348 (Project : Project_Id;
7349 In_Tree : Project_Tree_Ref;
7350 Data : in out Project_Data;
7351 Current_Dir : String)
7353 Source_Dir : String_List_Id := Data.Source_Dirs;
7354 Element : String_Element;
7355 Path : Path_Name_Type;
7357 Name : File_Name_Type;
7358 Canonical_Name : File_Name_Type;
7359 Name_Str : String (1 .. 1_024);
7360 Last : Natural := 0;
7362 Current_Source : String_List_Id := Nil_String;
7363 First_Error : Boolean := True;
7364 Source_Recorded : Boolean := False;
7367 -- We look in all source directories for the file names in the
7368 -- hash table Source_Names
7370 while Source_Dir /= Nil_String loop
7371 Source_Recorded := False;
7372 Element := In_Tree.String_Elements.Table (Source_Dir);
7375 Dir_Path : constant String :=
7376 Get_Name_String (Element.Display_Value);
7378 if Current_Verbosity = High then
7379 Write_Str ("checking directory """);
7380 Write_Str (Dir_Path);
7384 Open (Dir, Dir_Path);
7387 Read (Dir, Name_Str, Last);
7391 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7394 if Osint.File_Names_Case_Sensitive then
7395 Canonical_Name := Name;
7397 Canonical_Case_File_Name (Name_Str (1 .. Last));
7398 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7399 Canonical_Name := Name_Find;
7402 NL := Source_Names.Get (Canonical_Name);
7404 if NL /= No_Name_Location and then not NL.Found then
7406 Source_Names.Set (Canonical_Name, NL);
7407 Name_Len := Dir_Path'Length;
7408 Name_Buffer (1 .. Name_Len) := Dir_Path;
7410 if Name_Buffer (Name_Len) /= Directory_Separator then
7411 Add_Char_To_Name_Buffer (Directory_Separator);
7414 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7417 if Current_Verbosity = High then
7418 Write_Str (" found ");
7419 Write_Line (Get_Name_String (Name));
7422 -- Register the source if it is an Ada compilation unit
7430 Location => NL.Location,
7431 Current_Source => Current_Source,
7432 Source_Recorded => Source_Recorded,
7433 Current_Dir => Current_Dir);
7440 if Source_Recorded then
7441 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7445 Source_Dir := Element.Next;
7448 -- It is an error if a source file name in a source list or
7449 -- in a source list file is not found.
7451 NL := Source_Names.Get_First;
7452 while NL /= No_Name_Location loop
7453 if not NL.Found then
7454 Err_Vars.Error_Msg_File_1 := NL.Name;
7459 "source file { cannot be found",
7461 First_Error := False;
7466 "\source file { cannot be found",
7471 NL := Source_Names.Get_Next;
7473 end Get_Path_Names_And_Record_Ada_Sources;
7475 --------------------------
7476 -- Check_Naming_Schemes --
7477 --------------------------
7479 procedure Check_Naming_Schemes
7480 (In_Tree : Project_Tree_Ref;
7481 Data : in out Project_Data;
7483 File_Name : File_Name_Type;
7484 Alternate_Languages : out Alternate_Language_Id;
7485 Language : out Language_Index;
7486 Language_Name : out Name_Id;
7487 Display_Language_Name : out Name_Id;
7489 Lang_Kind : out Language_Kind;
7490 Kind : out Source_Kind)
7492 Last : Positive := Filename'Last;
7493 Config : Language_Config;
7494 Lang : Name_List_Index := Data.Languages;
7495 Header_File : Boolean := False;
7496 First_Language : Language_Index;
7501 Alternate_Languages := No_Alternate_Language;
7503 while Lang /= No_Name_List loop
7504 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7505 Language := Data.First_Language_Processing;
7507 if Current_Verbosity = High then
7509 (" Testing language "
7510 & Get_Name_String (Language_Name)
7511 & " Header_File=" & Header_File'Img);
7514 while Language /= No_Language_Index loop
7515 if In_Tree.Languages_Data.Table (Language).Name =
7518 Display_Language_Name :=
7519 In_Tree.Languages_Data.Table (Language).Display_Name;
7520 Config := In_Tree.Languages_Data.Table (Language).Config;
7521 Lang_Kind := Config.Kind;
7523 if Config.Kind = File_Based then
7525 -- For file based languages, there is no Unit. Just
7526 -- check if the file name has the implementation or,
7527 -- if it is specified, the template suffix of the
7533 and then Config.Naming_Data.Body_Suffix /= No_File
7536 Impl_Suffix : constant String :=
7537 Get_Name_String (Config.Naming_Data.Body_Suffix);
7540 if Filename'Length > Impl_Suffix'Length
7543 (Last - Impl_Suffix'Length + 1 .. Last) =
7548 if Current_Verbosity = High then
7549 Write_Str (" source of language ");
7551 (Get_Name_String (Display_Language_Name));
7559 if Config.Naming_Data.Spec_Suffix /= No_File then
7561 Spec_Suffix : constant String :=
7563 (Config.Naming_Data.Spec_Suffix);
7566 if Filename'Length > Spec_Suffix'Length
7569 (Last - Spec_Suffix'Length + 1 .. Last) =
7574 if Current_Verbosity = High then
7575 Write_Str (" header file of language ");
7577 (Get_Name_String (Display_Language_Name));
7581 Alternate_Language_Table.Increment_Last
7582 (In_Tree.Alt_Langs);
7583 In_Tree.Alt_Langs.Table
7584 (Alternate_Language_Table.Last
7585 (In_Tree.Alt_Langs)) :=
7586 (Language => Language,
7587 Next => Alternate_Languages);
7588 Alternate_Languages :=
7589 Alternate_Language_Table.Last
7590 (In_Tree.Alt_Langs);
7592 Header_File := True;
7593 First_Language := Language;
7599 elsif not Header_File then
7600 -- Unit based language
7602 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7607 -- ??? Are we doing this once per file in the project ?
7608 -- It should be done only once per project.
7610 case Config.Naming_Data.Casing is
7611 when All_Lower_Case =>
7612 for J in Filename'Range loop
7613 if Is_Letter (Filename (J)) then
7614 if not Is_Lower (Filename (J)) then
7621 when All_Upper_Case =>
7622 for J in Filename'Range loop
7623 if Is_Letter (Filename (J)) then
7624 if not Is_Upper (Filename (J)) then
7639 if Config.Naming_Data.Separate_Suffix /= No_File
7641 Config.Naming_Data.Separate_Suffix /=
7642 Config.Naming_Data.Body_Suffix
7645 Suffix : constant String :=
7647 (Config.Naming_Data.Separate_Suffix);
7649 if Filename'Length > Suffix'Length
7652 (Last - Suffix'Length + 1 .. Last) =
7656 Last := Last - Suffix'Length;
7663 and then Config.Naming_Data.Body_Suffix /= No_File
7666 Suffix : constant String :=
7668 (Config.Naming_Data.Body_Suffix);
7670 if Filename'Length > Suffix'Length
7673 (Last - Suffix'Length + 1 .. Last) =
7677 Last := Last - Suffix'Length;
7684 and then Config.Naming_Data.Spec_Suffix /= No_File
7687 Suffix : constant String :=
7689 (Config.Naming_Data.Spec_Suffix);
7691 if Filename'Length > Suffix'Length
7694 (Last - Suffix'Length + 1 .. Last) =
7698 Last := Last - Suffix'Length;
7707 -- Replace dot replacements with dots
7712 J : Positive := Filename'First;
7714 Dot_Replacement : constant String :=
7716 (Config.Naming_Data.
7719 Max : constant Positive :=
7720 Last - Dot_Replacement'Length + 1;
7724 Name_Len := Name_Len + 1;
7726 if J <= Max and then
7728 (J .. J + Dot_Replacement'Length - 1) =
7731 Name_Buffer (Name_Len) := '.';
7732 J := J + Dot_Replacement'Length;
7735 if Filename (J) = '.' then
7740 Name_Buffer (Name_Len) :=
7741 GNAT.Case_Util.To_Lower (Filename (J));
7752 -- The name buffer should contain the name of the
7753 -- the unit, if it is one.
7755 -- Check that this is a valid unit name
7757 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7759 if Unit /= No_Name then
7761 if Current_Verbosity = High then
7763 Write_Str (" spec of ");
7765 Write_Str (" body of ");
7768 Write_Str (Get_Name_String (Unit));
7769 Write_Str (" (language ");
7771 (Get_Name_String (Display_Language_Name));
7775 -- Comments required, declare block should
7779 Unit_Except : constant Unit_Exception :=
7780 Unit_Exceptions.Get (Unit);
7782 procedure Masked_Unit (Spec : Boolean);
7783 -- Indicate that there is an exception for
7784 -- the same unit, so the file is not a
7785 -- source for the unit.
7791 procedure Masked_Unit (Spec : Boolean) is
7793 if Current_Verbosity = High then
7795 Write_Str (Filename);
7796 Write_Str (""" contains the ");
7805 (" of a unit that is found in """);
7810 (Unit_Except.Spec));
7814 (Unit_Except.Impl));
7817 Write_Line (""" (ignored)");
7820 Language := No_Language_Index;
7825 if Unit_Except.Spec /= No_File
7826 and then Unit_Except.Spec /= File_Name
7828 Masked_Unit (Spec => True);
7832 if Unit_Except.Impl /= No_File
7833 and then Unit_Except.Impl /= File_Name
7835 Masked_Unit (Spec => False);
7846 Language := In_Tree.Languages_Data.Table (Language).Next;
7849 Lang := In_Tree.Name_Lists.Table (Lang).Next;
7852 -- Comment needed here ???
7855 Language := First_Language;
7858 Language := No_Language_Index;
7860 if Current_Verbosity = High then
7861 Write_Line (" not a source of any language");
7864 end Check_Naming_Schemes;
7870 procedure Check_File
7871 (Project : Project_Id;
7872 In_Tree : Project_Tree_Ref;
7873 Data : in out Project_Data;
7875 File_Name : File_Name_Type;
7876 Display_File_Name : File_Name_Type;
7877 Source_Directory : String;
7878 For_All_Sources : Boolean)
7880 Display_Path : constant String :=
7883 Directory => Source_Directory,
7884 Resolve_Links => Opt.Follow_Links_For_Files,
7885 Case_Sensitive => True);
7887 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7888 Path_Id : Path_Name_Type;
7889 Display_Path_Id : Path_Name_Type;
7890 Check_Name : Boolean := False;
7891 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
7892 Language : Language_Index;
7895 Src_Ind : Source_File_Index;
7896 Src_Data : Source_Data;
7898 Source_To_Replace : Source_Id := No_Source;
7899 Language_Name : Name_Id;
7900 Display_Language_Name : Name_Id;
7901 Lang_Kind : Language_Kind;
7902 Kind : Source_Kind := Spec;
7905 Name_Len := Display_Path'Length;
7906 Name_Buffer (1 .. Name_Len) := Display_Path;
7907 Display_Path_Id := Name_Find;
7909 if Osint.File_Names_Case_Sensitive then
7910 Path_Id := Display_Path_Id;
7912 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7913 Path_Id := Name_Find;
7916 if Name_Loc = No_Name_Location then
7917 Check_Name := For_All_Sources;
7920 if Name_Loc.Found then
7922 -- Check if it is OK to have the same file name in several
7923 -- source directories.
7925 if not Data.Known_Order_Of_Source_Dirs then
7926 Error_Msg_File_1 := File_Name;
7929 "{ is found in several source directories",
7934 Name_Loc.Found := True;
7936 if Name_Loc.Source = No_Source then
7940 In_Tree.Sources.Table (Name_Loc.Source).Path := Path_Id;
7941 In_Tree.Sources.Table
7942 (Name_Loc.Source).Display_Path := Display_Path_Id;
7944 Source_Paths_Htable.Set
7945 (In_Tree.Source_Paths_HT,
7949 -- Check if this is a subunit
7951 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
7953 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
7955 Src_Ind := Sinput.P.Load_Project_File
7956 (Get_Name_String (Path_Id));
7958 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7959 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
7967 Check_Naming_Schemes
7968 (In_Tree => In_Tree,
7970 Filename => Get_Name_String (File_Name),
7971 File_Name => File_Name,
7972 Alternate_Languages => Alternate_Languages,
7973 Language => Language,
7974 Language_Name => Language_Name,
7975 Display_Language_Name => Display_Language_Name,
7977 Lang_Kind => Lang_Kind,
7980 if Language = No_Language_Index then
7981 if Name_Loc.Found then
7982 -- A file name in a list must be a source of a language.
7983 Error_Msg_File_1 := File_Name;
7987 "language unknown for {",
7992 -- Check if the same file name or unit is used in the prj tree
7994 Source := In_Tree.First_Source;
7996 while Source /= No_Source loop
7997 Src_Data := In_Tree.Sources.Table (Source);
8000 and then Src_Data.Unit = Unit
8001 and then Src_Data.Kind = Kind)
8002 or else (Unit = No_Name
8003 and then Src_Data.File = File_Name)
8005 -- Duplication of file/unit in same project is only
8006 -- allowed if order of source directories is known.
8008 if Project = Src_Data.Project then
8009 if Data.Known_Order_Of_Source_Dirs then
8012 elsif Unit /= No_Name then
8013 Error_Msg_Name_1 := Unit;
8016 "duplicate unit %%",
8021 Error_Msg_File_1 := File_Name;
8024 "duplicate source file " &
8030 -- Do not allow the same unit name in different
8031 -- projects, except if one is extending the other.
8033 -- For a file based language, the same file name
8034 -- replaces a file in a project being extended, but
8035 -- it is allowed to have the same file name in
8036 -- unrelated projects.
8039 (Project, Src_Data.Project, In_Tree)
8041 Source_To_Replace := Source;
8043 elsif Unit /= No_Name then
8044 Error_Msg_Name_1 := Unit;
8047 "unit %% cannot belong to " &
8054 Source := Src_Data.Next_In_Sources;
8063 Lang => Language_Name,
8064 Lang_Id => Language,
8065 Lang_Kind => Lang_Kind,
8067 Alternate_Languages => Alternate_Languages,
8068 File_Name => File_Name,
8069 Display_File => Display_File_Name,
8072 Display_Path => Display_Path_Id,
8073 Source_To_Replace => Source_To_Replace);
8079 ------------------------
8080 -- Search_Directories --
8081 ------------------------
8083 procedure Search_Directories
8084 (Project : Project_Id;
8085 In_Tree : Project_Tree_Ref;
8086 Data : in out Project_Data;
8087 For_All_Sources : Boolean)
8089 Source_Dir : String_List_Id;
8090 Element : String_Element;
8092 Name : String (1 .. 1_000);
8094 File_Name : File_Name_Type;
8095 Display_File_Name : File_Name_Type;
8098 if Current_Verbosity = High then
8099 Write_Line ("Looking for sources:");
8102 -- Loop through subdirectories
8104 Source_Dir := Data.Source_Dirs;
8105 while Source_Dir /= Nil_String loop
8107 Element := In_Tree.String_Elements.Table (Source_Dir);
8108 if Element.Value /= No_Name then
8109 Get_Name_String (Element.Display_Value);
8112 Source_Directory : constant String :=
8113 Name_Buffer (1 .. Name_Len) &
8114 Directory_Separator;
8115 Dir_Last : constant Natural :=
8116 Compute_Directory_Last
8120 if Current_Verbosity = High then
8121 Write_Str ("Source_Dir = ");
8122 Write_Line (Source_Directory);
8125 -- We look to every entry in the source directory
8127 Open (Dir, Source_Directory);
8130 Read (Dir, Name, Last);
8134 -- ??? Duplicate system call here, we just did a
8135 -- a similar one. Maybe Ada.Directories would be more
8138 (Source_Directory & Name (1 .. Last))
8140 if Current_Verbosity = High then
8141 Write_Str (" Checking ");
8142 Write_Line (Name (1 .. Last));
8146 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8147 Display_File_Name := Name_Find;
8149 if Osint.File_Names_Case_Sensitive then
8150 File_Name := Display_File_Name;
8152 Canonical_Case_File_Name
8153 (Name_Buffer (1 .. Name_Len));
8154 File_Name := Name_Find;
8159 Excluded_Sources_Htable.Get (File_Name);
8162 if FF /= No_File_Found then
8163 if not FF.Found then
8165 Excluded_Sources_Htable.Set
8168 if Current_Verbosity = High then
8169 Write_Str (" excluded source """);
8170 Write_Str (Get_Name_String (File_Name));
8177 (Project => Project,
8180 Name => Name (1 .. Last),
8181 File_Name => File_Name,
8182 Display_File_Name => Display_File_Name,
8183 Source_Directory => Source_Directory
8184 (Source_Directory'First .. Dir_Last),
8185 For_All_Sources => For_All_Sources);
8196 when Directory_Error =>
8199 Source_Dir := Element.Next;
8202 if Current_Verbosity = High then
8203 Write_Line ("end Looking for sources.");
8205 end Search_Directories;
8207 ----------------------
8208 -- Look_For_Sources --
8209 ----------------------
8211 procedure Look_For_Sources
8212 (Project : Project_Id;
8213 In_Tree : Project_Tree_Ref;
8214 Data : in out Project_Data;
8215 Current_Dir : String)
8217 procedure Remove_Locally_Removed_Files_From_Units;
8218 -- Mark all locally removed sources as such in the Units table
8220 procedure Process_Other_Sources_In_Ada_Only_Mode;
8221 -- Find sources for language other than Ada when in Ada_Only mode
8223 procedure Process_Sources_In_Multi_Language_Mode;
8224 -- Find all source files when in multi language mode
8226 ---------------------------------------------
8227 -- Remove_Locally_Removed_Files_From_Units --
8228 ---------------------------------------------
8230 procedure Remove_Locally_Removed_Files_From_Units is
8231 Excluded : File_Found := Excluded_Sources_Htable.Get_First;
8234 Extended : Project_Id;
8236 while Excluded /= No_File_Found loop
8240 for Index in Unit_Table.First ..
8241 Unit_Table.Last (In_Tree.Units)
8243 Unit := In_Tree.Units.Table (Index);
8245 for Kind in Spec_Or_Body'Range loop
8246 if Unit.File_Names (Kind).Name = Excluded.File then
8249 -- Check that this is from the current project or
8250 -- that the current project extends.
8252 Extended := Unit.File_Names (Kind).Project;
8254 if Extended = Project
8255 or else Project_Extends (Project, Extended, In_Tree)
8257 Unit.File_Names (Kind).Path := Slash;
8258 Unit.File_Names (Kind).Needs_Pragma := False;
8259 In_Tree.Units.Table (Index) := Unit;
8260 Add_Forbidden_File_Name
8261 (Unit.File_Names (Kind).Name);
8265 "cannot remove a source from " &
8272 end loop For_Each_Unit;
8275 Err_Vars.Error_Msg_File_1 := Excluded.File;
8277 (Project, In_Tree, "unknown file {", Excluded.Location);
8280 Excluded := Excluded_Sources_Htable.Get_Next;
8282 end Remove_Locally_Removed_Files_From_Units;
8284 --------------------------------------------
8285 -- Process_Other_Sources_In_Ada_Only_Mode --
8286 --------------------------------------------
8288 procedure Process_Other_Sources_In_Ada_Only_Mode is
8290 -- Set Source_Present to False. It will be set back to True
8291 -- whenever a source is found.
8293 Data.Other_Sources_Present := False;
8294 for Lang in Ada_Language_Index + 1 .. Last_Language_Index loop
8296 -- For each language (other than Ada) in the project file
8298 if Is_Present (Lang, Data, In_Tree) then
8300 -- Reset the indication that there are sources of this
8301 -- language. It will be set back to True whenever we find
8302 -- a source of the language.
8304 Set (Lang, False, Data, In_Tree);
8306 -- First, get the source suffix for the language
8308 Set (Suffix => Suffix_For (Lang, Data.Naming, In_Tree),
8309 For_Language => Lang,
8311 In_Tree => In_Tree);
8313 -- Then, deal with the naming exceptions, if any
8318 Naming_Exceptions : constant Variable_Value :=
8320 (Index => Language_Names.Table (Lang),
8322 In_Array => Data.Naming.Implementation_Exceptions,
8323 In_Tree => In_Tree);
8324 Element_Id : String_List_Id;
8325 Element : String_Element;
8326 File_Id : File_Name_Type;
8327 Source_Found : Boolean := False;
8330 -- If there are naming exceptions, look through them one
8333 if Naming_Exceptions /= Nil_Variable_Value then
8334 Element_Id := Naming_Exceptions.Values;
8336 while Element_Id /= Nil_String loop
8337 Element := In_Tree.String_Elements.Table (Element_Id);
8339 if Osint.File_Names_Case_Sensitive then
8340 File_Id := File_Name_Type (Element.Value);
8342 Get_Name_String (Element.Value);
8343 Canonical_Case_File_Name
8344 (Name_Buffer (1 .. Name_Len));
8345 File_Id := Name_Find;
8348 -- Put each naming exception in the Source_Names
8349 -- hash table, but if there are repetition, don't
8350 -- bother after the first instance.
8352 if Source_Names.Get (File_Id) = No_Name_Location then
8353 Source_Found := True;
8357 Location => Element.Location,
8358 Source => No_Source,
8363 Element_Id := Element.Next;
8366 -- If there is at least one naming exception, record
8367 -- those that are found in the source directories.
8369 if Source_Found then
8370 Record_Other_Sources
8371 (Project => Project,
8375 Naming_Exceptions => True);
8381 -- Now, check if a list of sources is declared either through
8382 -- a string list (attribute Source_Files) or a text file
8383 -- (attribute Source_List_File). If a source list is declared,
8384 -- we will consider only those naming exceptions that are
8388 Find_Explicit_Sources
8389 (Lang, Current_Dir, Project, In_Tree, Data);
8392 end Process_Other_Sources_In_Ada_Only_Mode;
8394 --------------------------------------------
8395 -- Process_Sources_In_Multi_Language_Mode --
8396 --------------------------------------------
8398 procedure Process_Sources_In_Multi_Language_Mode is
8399 Source : Source_Id := Data.First_Source;
8400 Src_Data : Source_Data;
8401 Name_Loc : Name_Location;
8405 -- First, put all the naming exceptions, if any, in the Source_Names
8408 Unit_Exceptions.Reset;
8410 while Source /= No_Source loop
8411 Src_Data := In_Tree.Sources.Table (Source);
8413 -- A file that is excluded cannot also be an exception file name
8415 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8418 Error_Msg_File_1 := Src_Data.File;
8422 "{ cannot be both excluded and an exception file name",
8426 Name_Loc := (Name => Src_Data.File,
8427 Location => No_Location,
8429 Except => Src_Data.Unit /= No_Name,
8432 if Current_Verbosity = High then
8433 Write_Str ("Putting source #");
8434 Write_Str (Source'Img);
8435 Write_Str (", file ");
8436 Write_Str (Get_Name_String (Src_Data.File));
8437 Write_Line (" in Source_Names");
8440 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8442 -- If this is an Ada exception, record it in table Unit_Exceptions
8444 if Src_Data.Unit /= No_Name then
8446 Unit_Except : Unit_Exception :=
8447 Unit_Exceptions.Get (Src_Data.Unit);
8450 Unit_Except.Name := Src_Data.Unit;
8452 if Src_Data.Kind = Spec then
8453 Unit_Except.Spec := Src_Data.File;
8455 Unit_Except.Impl := Src_Data.File;
8458 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8462 Source := Src_Data.Next_In_Project;
8465 Find_Explicit_Sources
8466 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
8468 FF := Excluded_Sources_Htable.Get_First;
8470 while FF /= No_File_Found loop
8472 Source := In_Tree.First_Source;
8474 while Source /= No_Source loop
8475 Src_Data := In_Tree.Sources.Table (Source);
8477 if Src_Data.File = FF.File then
8479 -- Check that this is from this project or a
8480 -- project that the current project extends.
8482 if Src_Data.Project = Project or else
8483 Is_Extending (Project, Src_Data.Project, In_Tree)
8485 Src_Data.Locally_Removed := True;
8486 In_Tree.Sources.Table (Source) := Src_Data;
8487 Add_Forbidden_File_Name (FF.File);
8493 Source := Src_Data.Next_In_Sources;
8496 if not FF.Found and not OK then
8497 Err_Vars.Error_Msg_File_1 := FF.File;
8498 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8501 FF := Excluded_Sources_Htable.Get_Next;
8503 end Process_Sources_In_Multi_Language_Mode;
8505 -- Start of processing for Look_For_Sources
8509 Find_Excluded_Sources (In_Tree, Data);
8513 if Is_A_Language (In_Tree, Data, Name_Ada) then
8514 Find_Explicit_Sources
8515 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
8516 Remove_Locally_Removed_Files_From_Units;
8519 if Data.Other_Sources_Present then
8520 Process_Other_Sources_In_Ada_Only_Mode;
8523 when Multi_Language =>
8524 if Data.First_Language_Processing /= No_Language_Index then
8525 Process_Sources_In_Multi_Language_Mode;
8528 end Look_For_Sources;
8534 function Path_Name_Of
8535 (File_Name : File_Name_Type;
8536 Directory : Path_Name_Type) return String
8538 Result : String_Access;
8540 The_Directory : constant String := Get_Name_String (Directory);
8543 Get_Name_String (File_Name);
8544 Result := Locate_Regular_File
8545 (File_Name => Name_Buffer (1 .. Name_Len),
8546 Path => The_Directory);
8548 if Result = null then
8551 Canonical_Case_File_Name (Result.all);
8556 -------------------------------
8557 -- Prepare_Ada_Naming_Exceptions --
8558 -------------------------------
8560 procedure Prepare_Ada_Naming_Exceptions
8561 (List : Array_Element_Id;
8562 In_Tree : Project_Tree_Ref;
8563 Kind : Spec_Or_Body)
8565 Current : Array_Element_Id;
8566 Element : Array_Element;
8570 -- Traverse the list
8573 while Current /= No_Array_Element loop
8574 Element := In_Tree.Array_Elements.Table (Current);
8576 if Element.Index /= No_Name then
8579 Unit => Element.Index,
8580 Next => No_Ada_Naming_Exception);
8581 Reverse_Ada_Naming_Exceptions.Set
8582 (Unit, (Element.Value.Value, Element.Value.Index));
8584 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8585 Ada_Naming_Exception_Table.Increment_Last;
8586 Ada_Naming_Exception_Table.Table
8587 (Ada_Naming_Exception_Table.Last) := Unit;
8588 Ada_Naming_Exceptions.Set
8589 (File_Name_Type (Element.Value.Value),
8590 Ada_Naming_Exception_Table.Last);
8593 Current := Element.Next;
8595 end Prepare_Ada_Naming_Exceptions;
8597 ---------------------
8598 -- Project_Extends --
8599 ---------------------
8601 function Project_Extends
8602 (Extending : Project_Id;
8603 Extended : Project_Id;
8604 In_Tree : Project_Tree_Ref) return Boolean
8606 Current : Project_Id := Extending;
8609 if Current = No_Project then
8612 elsif Current = Extended then
8616 Current := In_Tree.Projects.Table (Current).Extends;
8618 end Project_Extends;
8620 -----------------------
8621 -- Record_Ada_Source --
8622 -----------------------
8624 procedure Record_Ada_Source
8625 (File_Name : File_Name_Type;
8626 Path_Name : Path_Name_Type;
8627 Project : Project_Id;
8628 In_Tree : Project_Tree_Ref;
8629 Data : in out Project_Data;
8630 Location : Source_Ptr;
8631 Current_Source : in out String_List_Id;
8632 Source_Recorded : in out Boolean;
8633 Current_Dir : String)
8635 Canonical_File_Name : File_Name_Type;
8636 Canonical_Path_Name : Path_Name_Type;
8638 Exception_Id : Ada_Naming_Exception_Id;
8639 Unit_Name : Name_Id;
8640 Unit_Kind : Spec_Or_Body;
8641 Unit_Ind : Int := 0;
8643 Name_Index : Name_And_Index;
8644 Needs_Pragma : Boolean;
8646 The_Location : Source_Ptr := Location;
8647 Previous_Source : constant String_List_Id := Current_Source;
8648 Except_Name : Name_And_Index := No_Name_And_Index;
8650 Unit_Prj : Unit_Project;
8652 File_Name_Recorded : Boolean := False;
8655 if Osint.File_Names_Case_Sensitive then
8656 Canonical_File_Name := File_Name;
8657 Canonical_Path_Name := Path_Name;
8659 Get_Name_String (File_Name);
8660 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8661 Canonical_File_Name := Name_Find;
8664 Canonical_Path : constant String :=
8666 (Get_Name_String (Path_Name),
8667 Directory => Current_Dir,
8668 Resolve_Links => Opt.Follow_Links_For_Files,
8669 Case_Sensitive => False);
8672 Add_Str_To_Name_Buffer (Canonical_Path);
8673 Canonical_Path_Name := Name_Find;
8677 -- Find out the unit name, the unit kind and if it needs
8678 -- a specific SFN pragma.
8681 (In_Tree => In_Tree,
8682 Canonical_File_Name => Canonical_File_Name,
8683 Naming => Data.Naming,
8684 Exception_Id => Exception_Id,
8685 Unit_Name => Unit_Name,
8686 Unit_Kind => Unit_Kind,
8687 Needs_Pragma => Needs_Pragma);
8689 if Exception_Id = No_Ada_Naming_Exception and then
8692 if Current_Verbosity = High then
8694 Write_Str (Get_Name_String (Canonical_File_Name));
8695 Write_Line (""" is not a valid source file name (ignored).");
8699 -- Check to see if the source has been hidden by an exception,
8700 -- but only if it is not an exception.
8702 if not Needs_Pragma then
8704 Reverse_Ada_Naming_Exceptions.Get
8705 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8707 if Except_Name /= No_Name_And_Index then
8708 if Current_Verbosity = High then
8710 Write_Str (Get_Name_String (Canonical_File_Name));
8711 Write_Str (""" contains a unit that is found in """);
8712 Write_Str (Get_Name_String (Except_Name.Name));
8713 Write_Line (""" (ignored).");
8716 -- The file is not included in the source of the project since
8717 -- it is hidden by the exception. So, nothing else to do.
8724 if Exception_Id /= No_Ada_Naming_Exception then
8725 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8726 Exception_Id := Info.Next;
8727 Info.Next := No_Ada_Naming_Exception;
8728 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8730 Unit_Name := Info.Unit;
8731 Unit_Ind := Name_Index.Index;
8732 Unit_Kind := Info.Kind;
8735 -- Put the file name in the list of sources of the project
8737 String_Element_Table.Increment_Last
8738 (In_Tree.String_Elements);
8739 In_Tree.String_Elements.Table
8740 (String_Element_Table.Last
8741 (In_Tree.String_Elements)) :=
8742 (Value => Name_Id (Canonical_File_Name),
8743 Display_Value => Name_Id (File_Name),
8744 Location => No_Location,
8749 if Current_Source = Nil_String then
8750 Data.Ada_Sources := String_Element_Table.Last
8751 (In_Tree.String_Elements);
8752 Data.Sources := Data.Ada_Sources;
8754 In_Tree.String_Elements.Table
8755 (Current_Source).Next :=
8756 String_Element_Table.Last
8757 (In_Tree.String_Elements);
8760 Current_Source := String_Element_Table.Last
8761 (In_Tree.String_Elements);
8763 -- Put the unit in unit list
8766 The_Unit : Unit_Index :=
8767 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8769 The_Unit_Data : Unit_Data;
8772 if Current_Verbosity = High then
8773 Write_Str ("Putting ");
8774 Write_Str (Get_Name_String (Unit_Name));
8775 Write_Line (" in the unit list.");
8778 -- The unit is already in the list, but may be it is
8779 -- only the other unit kind (spec or body), or what is
8780 -- in the unit list is a unit of a project we are extending.
8782 if The_Unit /= No_Unit_Index then
8783 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8785 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8788 The_Unit_Data.File_Names (Unit_Kind).Path = Slash)
8789 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8790 or else Project_Extends
8792 The_Unit_Data.File_Names (Unit_Kind).Project,
8795 if The_Unit_Data.File_Names (Unit_Kind).Path = Slash then
8796 Remove_Forbidden_File_Name
8797 (The_Unit_Data.File_Names (Unit_Kind).Name);
8800 -- Record the file name in the hash table Files_Htable
8802 Unit_Prj := (Unit => The_Unit, Project => Project);
8805 Canonical_File_Name,
8808 The_Unit_Data.File_Names (Unit_Kind) :=
8809 (Name => Canonical_File_Name,
8811 Display_Name => File_Name,
8812 Path => Canonical_Path_Name,
8813 Display_Path => Path_Name,
8815 Needs_Pragma => Needs_Pragma);
8816 In_Tree.Units.Table (The_Unit) :=
8818 Source_Recorded := True;
8820 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8821 and then (Data.Known_Order_Of_Source_Dirs or else
8822 The_Unit_Data.File_Names (Unit_Kind).Path =
8823 Canonical_Path_Name)
8825 if Previous_Source = Nil_String then
8826 Data.Ada_Sources := Nil_String;
8827 Data.Sources := Nil_String;
8829 In_Tree.String_Elements.Table
8830 (Previous_Source).Next := Nil_String;
8831 String_Element_Table.Decrement_Last
8832 (In_Tree.String_Elements);
8835 Current_Source := Previous_Source;
8838 -- It is an error to have two units with the same name
8839 -- and the same kind (spec or body).
8841 if The_Location = No_Location then
8843 In_Tree.Projects.Table
8847 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8849 (Project, In_Tree, "duplicate source %%", The_Location);
8851 Err_Vars.Error_Msg_Name_1 :=
8852 In_Tree.Projects.Table
8853 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
8854 Err_Vars.Error_Msg_File_1 :=
8856 (The_Unit_Data.File_Names (Unit_Kind).Path);
8859 "\ project file %%, {", The_Location);
8861 Err_Vars.Error_Msg_Name_1 :=
8862 In_Tree.Projects.Table (Project).Name;
8863 Err_Vars.Error_Msg_File_1 :=
8864 File_Name_Type (Canonical_Path_Name);
8867 "\ project file %%, {", The_Location);
8870 -- It is a new unit, create a new record
8873 -- First, check if there is no other unit with this file
8874 -- name in another project. If it is, report an error.
8875 -- Of course, we do that only for the first unit in the
8878 Unit_Prj := Files_Htable.Get
8879 (In_Tree.Files_HT, Canonical_File_Name);
8881 if not File_Name_Recorded and then
8882 Unit_Prj /= No_Unit_Project
8884 Error_Msg_File_1 := File_Name;
8886 In_Tree.Projects.Table
8887 (Unit_Prj.Project).Name;
8890 "{ is already a source of project %%",
8894 Unit_Table.Increment_Last (In_Tree.Units);
8895 The_Unit := Unit_Table.Last (In_Tree.Units);
8897 (In_Tree.Units_HT, Unit_Name, The_Unit);
8898 Unit_Prj := (Unit => The_Unit, Project => Project);
8901 Canonical_File_Name,
8903 The_Unit_Data.Name := Unit_Name;
8904 The_Unit_Data.File_Names (Unit_Kind) :=
8905 (Name => Canonical_File_Name,
8907 Display_Name => File_Name,
8908 Path => Canonical_Path_Name,
8909 Display_Path => Path_Name,
8911 Needs_Pragma => Needs_Pragma);
8912 In_Tree.Units.Table (The_Unit) :=
8914 Source_Recorded := True;
8919 exit when Exception_Id = No_Ada_Naming_Exception;
8920 File_Name_Recorded := True;
8923 end Record_Ada_Source;
8925 --------------------------
8926 -- Record_Other_Sources --
8927 --------------------------
8929 procedure Record_Other_Sources
8930 (Project : Project_Id;
8931 In_Tree : Project_Tree_Ref;
8932 Data : in out Project_Data;
8933 Language : Language_Index;
8934 Naming_Exceptions : Boolean)
8936 Source_Dir : String_List_Id;
8937 Element : String_Element;
8938 Path : Path_Name_Type;
8940 Canonical_Name : File_Name_Type;
8941 Name_Str : String (1 .. 1_024);
8942 Last : Natural := 0;
8944 First_Error : Boolean := True;
8945 Suffix : constant String :=
8946 Body_Suffix_Of (Language, Data, In_Tree);
8949 Source_Dir := Data.Source_Dirs;
8950 while Source_Dir /= Nil_String loop
8951 Element := In_Tree.String_Elements.Table (Source_Dir);
8954 Dir_Path : constant String :=
8955 Get_Name_String (Element.Display_Value);
8957 if Current_Verbosity = High then
8958 Write_Str ("checking directory """);
8959 Write_Str (Dir_Path);
8960 Write_Str (""" for ");
8962 if Naming_Exceptions then
8963 Write_Str ("naming exceptions");
8966 Write_Str ("sources");
8969 Write_Str (" of Language ");
8970 Display_Language_Name (Language);
8973 Open (Dir, Dir_Path);
8976 Read (Dir, Name_Str, Last);
8980 (Dir_Path & Directory_Separator & Name_Str (1 .. Last))
8983 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
8984 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8985 Canonical_Name := Name_Find;
8986 NL := Source_Names.Get (Canonical_Name);
8988 if NL /= No_Name_Location then
8990 if not Data.Known_Order_Of_Source_Dirs then
8991 Error_Msg_File_1 := Canonical_Name;
8994 "{ is found in several source directories",
9000 Source_Names.Set (Canonical_Name, NL);
9001 Name_Len := Dir_Path'Length;
9002 Name_Buffer (1 .. Name_Len) := Dir_Path;
9003 Add_Char_To_Name_Buffer (Directory_Separator);
9004 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
9008 (File_Name => Canonical_Name,
9013 Location => NL.Location,
9014 Language => Language,
9016 Naming_Exception => Naming_Exceptions);
9025 Source_Dir := Element.Next;
9028 if not Naming_Exceptions then
9029 NL := Source_Names.Get_First;
9031 -- It is an error if a source file name in a source list or
9032 -- in a source list file is not found.
9034 while NL /= No_Name_Location loop
9035 if not NL.Found then
9036 Err_Vars.Error_Msg_File_1 := NL.Name;
9041 "source file { cannot be found",
9043 First_Error := False;
9048 "\source file { cannot be found",
9053 NL := Source_Names.Get_Next;
9056 -- Any naming exception of this language that is not in a list
9057 -- of sources must be removed.
9060 Source_Id : Other_Source_Id := Data.First_Other_Source;
9061 Prev_Id : Other_Source_Id := No_Other_Source;
9062 Source : Other_Source;
9065 while Source_Id /= No_Other_Source loop
9066 Source := In_Tree.Other_Sources.Table (Source_Id);
9068 if Source.Language = Language
9069 and then Source.Naming_Exception
9071 if Current_Verbosity = High then
9072 Write_Str ("Naming exception """);
9073 Write_Str (Get_Name_String (Source.File_Name));
9074 Write_Str (""" is not in the list of sources,");
9075 Write_Line (" so it is removed.");
9078 if Prev_Id = No_Other_Source then
9079 Data.First_Other_Source := Source.Next;
9082 In_Tree.Other_Sources.Table
9083 (Prev_Id).Next := Source.Next;
9086 Source_Id := Source.Next;
9088 if Source_Id = No_Other_Source then
9089 Data.Last_Other_Source := Prev_Id;
9093 Prev_Id := Source_Id;
9094 Source_Id := Source.Next;
9099 end Record_Other_Sources;
9105 procedure Remove_Source
9107 Replaced_By : Source_Id;
9108 Project : Project_Id;
9109 Data : in out Project_Data;
9110 In_Tree : Project_Tree_Ref)
9112 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9117 if Current_Verbosity = High then
9118 Write_Str ("Removing source #");
9119 Write_Line (Id'Img);
9122 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9124 -- Remove the source from the global source list
9126 Source := In_Tree.First_Source;
9129 In_Tree.First_Source := Src_Data.Next_In_Sources;
9132 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9133 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9136 In_Tree.Sources.Table (Source).Next_In_Sources :=
9137 Src_Data.Next_In_Sources;
9140 -- Remove the source from the project list
9142 if Src_Data.Project = Project then
9143 Source := Data.First_Source;
9146 Data.First_Source := Src_Data.Next_In_Project;
9148 if Src_Data.Next_In_Project = No_Source then
9149 Data.Last_Source := No_Source;
9153 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9154 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9157 In_Tree.Sources.Table (Source).Next_In_Project :=
9158 Src_Data.Next_In_Project;
9160 if Src_Data.Next_In_Project = No_Source then
9161 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9166 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9169 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9170 Src_Data.Next_In_Project;
9172 if Src_Data.Next_In_Project = No_Source then
9173 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9178 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9179 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9182 In_Tree.Sources.Table (Source).Next_In_Project :=
9183 Src_Data.Next_In_Project;
9185 if Src_Data.Next_In_Project = No_Source then
9186 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9191 -- Remove source from the language list
9193 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9196 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9197 Src_Data.Next_In_Lang;
9200 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9201 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9204 In_Tree.Sources.Table (Source).Next_In_Lang :=
9205 Src_Data.Next_In_Lang;
9209 -----------------------
9210 -- Report_No_Sources --
9211 -----------------------
9213 procedure Report_No_Sources
9214 (Project : Project_Id;
9216 In_Tree : Project_Tree_Ref;
9217 Location : Source_Ptr)
9220 case When_No_Sources is
9224 when Warning | Error =>
9225 Error_Msg_Warn := When_No_Sources = Warning;
9228 "<there are no " & Lang_Name & " sources in this project",
9231 end Report_No_Sources;
9233 ----------------------
9234 -- Show_Source_Dirs --
9235 ----------------------
9237 procedure Show_Source_Dirs
9238 (Data : Project_Data;
9239 In_Tree : Project_Tree_Ref)
9241 Current : String_List_Id;
9242 Element : String_Element;
9245 Write_Line ("Source_Dirs:");
9247 Current := Data.Source_Dirs;
9248 while Current /= Nil_String loop
9249 Element := In_Tree.String_Elements.Table (Current);
9251 Write_Line (Get_Name_String (Element.Value));
9252 Current := Element.Next;
9255 Write_Line ("end Source_Dirs.");
9256 end Show_Source_Dirs;
9263 (Language : Language_Index;
9264 Naming : Naming_Data;
9265 In_Tree : Project_Tree_Ref) return File_Name_Type
9267 Suffix : constant Variable_Value :=
9269 (Index => Language_Names.Table (Language),
9271 In_Array => Naming.Body_Suffix,
9272 In_Tree => In_Tree);
9274 -- If no suffix for this language in package Naming, use the default
9276 if Suffix = Nil_Variable_Value then
9280 when Ada_Language_Index =>
9281 Add_Str_To_Name_Buffer (".adb");
9283 when C_Language_Index =>
9284 Add_Str_To_Name_Buffer (".c");
9286 when C_Plus_Plus_Language_Index =>
9287 Add_Str_To_Name_Buffer (".cpp");
9293 -- Otherwise use the one specified
9296 Get_Name_String (Suffix.Value);
9299 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9303 -------------------------
9304 -- Warn_If_Not_Sources --
9305 -------------------------
9307 -- comments needed in this body ???
9309 procedure Warn_If_Not_Sources
9310 (Project : Project_Id;
9311 In_Tree : Project_Tree_Ref;
9312 Conventions : Array_Element_Id;
9314 Extending : Boolean)
9316 Conv : Array_Element_Id := Conventions;
9318 The_Unit_Id : Unit_Index;
9319 The_Unit_Data : Unit_Data;
9320 Location : Source_Ptr;
9323 while Conv /= No_Array_Element loop
9324 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9325 Error_Msg_Name_1 := Unit;
9326 Get_Name_String (Unit);
9327 To_Lower (Name_Buffer (1 .. Name_Len));
9329 The_Unit_Id := Units_Htable.Get
9330 (In_Tree.Units_HT, Unit);
9331 Location := In_Tree.Array_Elements.Table
9332 (Conv).Value.Location;
9334 if The_Unit_Id = No_Unit_Index then
9341 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9343 In_Tree.Array_Elements.Table (Conv).Value.Value;
9346 if not Check_Project
9347 (The_Unit_Data.File_Names (Specification).Project,
9348 Project, In_Tree, Extending)
9352 "?source of spec of unit %% (%%)" &
9353 " cannot be found in this project",
9358 if not Check_Project
9359 (The_Unit_Data.File_Names (Body_Part).Project,
9360 Project, In_Tree, Extending)
9364 "?source of body of unit %% (%%)" &
9365 " cannot be found in this project",
9371 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9373 end Warn_If_Not_Sources;