1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
30 with Err_Vars; use Err_Vars;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
39 with Prj.Util; use Prj.Util;
41 with Snames; use Snames;
42 with Table; use Table;
43 with Targparm; use Targparm;
45 with Ada.Characters.Handling; use Ada.Characters.Handling;
46 with Ada.Directories; use Ada.Directories;
47 with Ada.Strings; use Ada.Strings;
48 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
49 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
51 package body Prj.Nmsc is
53 No_Continuation_String : aliased String := "";
54 Continuation_String : aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
68 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;
143 -- Why is the following commented out ???
144 -- No_Unit : constant Unit_Info :=
145 -- (Specification, No_Name, No_Ada_Naming_Exception);
147 package Ada_Naming_Exception_Table is new Table.Table
148 (Table_Component_Type => Unit_Info,
149 Table_Index_Type => Ada_Naming_Exception_Id,
150 Table_Low_Bound => 1,
152 Table_Increment => 100,
153 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
155 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
156 (Header_Num => Header_Num,
157 Element => Ada_Naming_Exception_Id,
158 No_Element => No_Ada_Naming_Exception,
159 Key => File_Name_Type,
162 -- A hash table to store naming exceptions for Ada. For each file name
163 -- there is one or several unit in table Ada_Naming_Exception_Table.
165 package Object_File_Names is new GNAT.HTable.Simple_HTable
166 (Header_Num => Header_Num,
167 Element => File_Name_Type,
168 No_Element => No_File,
169 Key => File_Name_Type,
172 -- A hash table to store the object file names for a project, to check that
173 -- two different sources have different object file names.
175 type File_Found is record
176 File : File_Name_Type := No_File;
177 Found : Boolean := False;
178 Location : Source_Ptr := No_Location;
180 No_File_Found : constant File_Found := (No_File, False, No_Location);
181 -- Comments needed ???
183 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
184 (Header_Num => Header_Num,
185 Element => File_Found,
186 No_Element => No_File_Found,
187 Key => File_Name_Type,
190 -- A hash table to store the excluded files, if any. This is filled by
191 -- Find_Excluded_Sources below.
193 procedure Find_Excluded_Sources
194 (Project : Project_Id;
195 In_Tree : Project_Tree_Ref;
196 Data : Project_Data);
197 -- Find the list of files that should not be considered as source files
198 -- for this project. Sets the list in the Excluded_Sources_Htable.
200 function Hash (Unit : Unit_Info) return Header_Num;
202 type Name_And_Index is record
203 Name : Name_Id := No_Name;
206 No_Name_And_Index : constant Name_And_Index :=
207 (Name => No_Name, Index => 0);
209 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
210 (Header_Num => Header_Num,
211 Element => Name_And_Index,
212 No_Element => No_Name_And_Index,
216 -- A table to check if a unit with an exceptional name will hide a source
217 -- with a file name following the naming convention.
221 Data : in out Project_Data;
222 In_Tree : Project_Tree_Ref;
223 Project : Project_Id;
225 Lang_Id : Language_Index;
227 File_Name : File_Name_Type;
228 Display_File : File_Name_Type;
229 Lang_Kind : Language_Kind;
230 Naming_Exception : Boolean := False;
231 Path : Path_Name_Type := No_Path;
232 Display_Path : Path_Name_Type := No_Path;
233 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
234 Other_Part : Source_Id := No_Source;
235 Unit : Name_Id := No_Name;
237 Source_To_Replace : Source_Id := No_Source);
238 -- Add a new source to the different lists: list of all sources in the
239 -- project tree, list of source of a project and list of sources of a
242 -- If Path is specified, the file is also added to Source_Paths_HT.
243 -- If Source_To_Replace is specified, it points to the source in the
244 -- extended project that the new file is overriding.
246 function ALI_File_Name (Source : String) return String;
247 -- Return the ALI file name corresponding to a source
249 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
250 -- Check that a name is a valid Ada unit name
252 procedure Check_Naming_Schemes
253 (Data : in out Project_Data;
254 Project : Project_Id;
255 In_Tree : Project_Tree_Ref);
256 -- Check the naming scheme part of Data
258 procedure Check_Ada_Naming_Scheme_Validity
259 (Project : Project_Id;
260 In_Tree : Project_Tree_Ref;
261 Naming : Naming_Data);
262 -- Check that the package Naming is correct
264 procedure Check_Configuration
265 (Project : Project_Id;
266 In_Tree : Project_Tree_Ref;
267 Data : in out Project_Data);
268 -- Check the configuration attributes for the project
270 procedure Check_For_Source
271 (File_Name : File_Name_Type;
272 Path_Name : Path_Name_Type;
273 Project : Project_Id;
274 In_Tree : Project_Tree_Ref;
275 Data : in out Project_Data;
276 Location : Source_Ptr;
277 Language : Language_Index;
279 Naming_Exception : Boolean);
280 -- Check if a file, with name File_Name and path Path_Name, in a source
281 -- directory is a source for language Language in project Project of
282 -- project tree In_Tree. ???
284 procedure Check_If_Externally_Built
285 (Project : Project_Id;
286 In_Tree : Project_Tree_Ref;
287 Data : in out Project_Data);
288 -- Check attribute Externally_Built of project Project in project tree
289 -- In_Tree and modify its data Data if it has the value "true".
291 procedure Check_Interfaces
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Data : in out Project_Data);
295 -- If a list of sources is specified in attribute Interfaces, set
296 -- In_Interfaces only for the sources specified in the list.
298 procedure Check_Library_Attributes
299 (Project : Project_Id;
300 In_Tree : Project_Tree_Ref;
301 Current_Dir : String;
302 Data : in out Project_Data);
303 -- Check the library attributes of project Project in project tree In_Tree
304 -- and modify its data Data accordingly.
305 -- Current_Dir should represent the current directory, and is passed for
306 -- efficiency to avoid system calls to recompute it.
308 procedure Check_Package_Naming
309 (Project : Project_Id;
310 In_Tree : Project_Tree_Ref;
311 Data : in out Project_Data);
312 -- Check package Naming of project Project in project tree In_Tree and
313 -- modify its data Data accordingly.
315 procedure Check_Programming_Languages
316 (In_Tree : Project_Tree_Ref;
317 Project : Project_Id;
318 Data : in out Project_Data);
319 -- Check attribute Languages for the project with data Data in project
320 -- tree In_Tree and set the components of Data for all the programming
321 -- languages indicated in attribute Languages, if any.
323 function Check_Project
325 Root_Project : Project_Id;
326 In_Tree : Project_Tree_Ref;
327 Extending : Boolean) return Boolean;
328 -- Returns True if P is Root_Project or, if Extending is True, a project
329 -- extended by Root_Project.
331 procedure Check_Stand_Alone_Library
332 (Project : Project_Id;
333 In_Tree : Project_Tree_Ref;
334 Data : in out Project_Data;
335 Current_Dir : String;
336 Extending : Boolean);
337 -- Check if project Project in project tree In_Tree is a Stand-Alone
338 -- Library project, and modify its data Data accordingly if it is one.
339 -- Current_Dir should represent the current directory, and is passed for
340 -- efficiency to avoid system calls to recompute it.
342 procedure Get_Path_Names_And_Record_Ada_Sources
343 (Project : Project_Id;
344 In_Tree : Project_Tree_Ref;
345 Data : in out Project_Data;
346 Current_Dir : String);
347 -- Find the path names of the source files in the Source_Names table
348 -- in the source directories and record those that are Ada sources.
350 function Compute_Directory_Last (Dir : String) return Natural;
351 -- Return the index of the last significant character in Dir. This is used
352 -- to avoid duplicate '/' (slash) characters at the end of directory names.
355 (Project : Project_Id;
356 In_Tree : Project_Tree_Ref;
358 Flag_Location : Source_Ptr);
359 -- Output an error message. If Error_Report is null, simply call
360 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
363 procedure Find_Ada_Sources
364 (Project : Project_Id;
365 In_Tree : Project_Tree_Ref;
366 Data : in out Project_Data;
367 Current_Dir : String);
368 -- Find all the Ada sources in all of the source directories of a project
369 -- Current_Dir should represent the current directory, and is passed for
370 -- efficiency to avoid system calls to recompute it.
372 procedure Find_Sources
373 (Project : Project_Id;
374 In_Tree : Project_Tree_Ref;
375 Data : in out Project_Data;
376 For_Language : Language_Index;
377 Current_Dir : String);
378 -- Find all the sources in all of the source directories of a project for
379 -- a specified language.
381 procedure Search_Directories
382 (Project : Project_Id;
383 In_Tree : Project_Tree_Ref;
384 Data : in out Project_Data;
385 For_All_Sources : Boolean);
386 -- Search the source directories to find the sources.
387 -- If For_All_Sources is True, check each regular file name against the
388 -- naming schemes of the different languages. Otherwise consider only the
389 -- file names in the hash table Source_Names.
392 (Project : Project_Id;
393 In_Tree : Project_Tree_Ref;
394 Data : in out Project_Data;
396 File_Name : File_Name_Type;
397 Display_File_Name : File_Name_Type;
398 Source_Directory : String;
399 For_All_Sources : Boolean);
400 -- Check if file File_Name is a valid source of the project. This is used
401 -- in multi-language mode only.
402 -- When the file matches one of the naming schemes, it is added to
403 -- various htables through Add_Source and to Source_Paths_Htable.
405 -- Name is the name of the candidate file. It hasn't been normalized yet
406 -- and is the direct result of readdir().
408 -- File_Name is the same as Name, but has been normalized.
409 -- Display_File_Name, however, has not been normalized.
411 -- Source_Directory is the directory in which the file
412 -- was found. It hasn't been normalized (nor has had links resolved).
413 -- It should not end with a directory separator, to avoid duplicates
416 -- If For_All_Sources is True, then all possible file names are analyzed
417 -- otherwise only those currently set in the Source_Names htable.
419 procedure Check_Naming_Schemes
420 (In_Tree : Project_Tree_Ref;
421 Data : in out Project_Data;
423 File_Name : File_Name_Type;
424 Alternate_Languages : out Alternate_Language_Id;
425 Language : out Language_Index;
426 Language_Name : out Name_Id;
427 Display_Language_Name : out Name_Id;
429 Lang_Kind : out Language_Kind;
430 Kind : out Source_Kind);
431 -- Check if the file name File_Name conforms to one of the naming
432 -- schemes of the project.
434 -- If the file does not match one of the naming schemes, set Language
435 -- to No_Language_Index.
437 -- Filename is the name of the file being investigated. It has been
438 -- normalized (case-folded). File_Name is the same value.
440 procedure Free_Ada_Naming_Exceptions;
441 -- Free the internal hash tables used for checking naming exceptions
443 procedure Get_Directories
444 (Project : Project_Id;
445 In_Tree : Project_Tree_Ref;
446 Current_Dir : String;
447 Data : in out Project_Data);
448 -- Get the object directory, the exec directory and the source directories
451 -- Current_Dir should represent the current directory, and is passed for
452 -- efficiency to avoid system calls to recompute it.
455 (Project : Project_Id;
456 In_Tree : Project_Tree_Ref;
457 Data : in out Project_Data);
458 -- Get the mains of a project from attribute Main, if it exists, and put
459 -- them in the project data.
461 procedure Get_Sources_From_File
463 Location : Source_Ptr;
464 Project : Project_Id;
465 In_Tree : Project_Tree_Ref);
466 -- Get the list of sources from a text file and put them in hash table
469 procedure Find_Explicit_Sources
470 (Lang : Language_Index;
471 Current_Dir : String;
472 Project : Project_Id;
473 In_Tree : Project_Tree_Ref;
474 Data : in out Project_Data);
475 -- Process the Source_Files and Source_List_File attributes, and store
476 -- the list of source files into the Source_Names htable.
478 -- Lang indicates which language is being processed when in Ada_Only mode
479 -- (all languages are processed anyway when in Multi_Language mode).
482 (In_Tree : Project_Tree_Ref;
483 Canonical_File_Name : File_Name_Type;
484 Naming : Naming_Data;
485 Exception_Id : out Ada_Naming_Exception_Id;
486 Unit_Name : out Name_Id;
487 Unit_Kind : out Spec_Or_Body;
488 Needs_Pragma : out Boolean);
489 -- Find out, from a file name, the unit name, the unit kind and if a
490 -- specific SFN pragma is needed. If the file name corresponds to no unit,
491 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
492 -- exception to the naming scheme, then Exception_Id is set to the unit or
493 -- units that the source contains.
495 function Is_Illegal_Suffix
497 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
498 -- Returns True if the string Suffix cannot be used as a spec suffix, a
499 -- body suffix or a separate suffix.
501 procedure Locate_Directory
502 (Project : Project_Id;
503 In_Tree : Project_Tree_Ref;
504 Name : File_Name_Type;
505 Parent : Path_Name_Type;
506 Dir : out Path_Name_Type;
507 Display : out Path_Name_Type;
508 Create : String := "";
509 Current_Dir : String;
510 Location : Source_Ptr := No_Location);
511 -- Locate a directory. Name is the directory name. Parent is the root
512 -- directory, if Name a relative path name. Dir is set to the canonical
513 -- case path name of the directory, and Display is the directory path name
514 -- for display purposes. If the directory does not exist and Project_Setup
515 -- is True and Create is a non null string, an attempt is made to create
516 -- the directory. If the directory does not exist and Project_Setup is
517 -- false, then Dir and Display are set to No_Name.
519 -- Current_Dir should represent the current directory, and is passed for
520 -- efficiency to avoid system calls to recompute it.
522 procedure Look_For_Sources
523 (Project : Project_Id;
524 In_Tree : Project_Tree_Ref;
525 Data : in out Project_Data;
526 Current_Dir : String);
527 -- Find all the sources of project Project in project tree In_Tree and
528 -- update its Data accordingly.
530 -- Current_Dir should represent the current directory, and is passed for
531 -- efficiency to avoid system calls to recompute it.
533 function Path_Name_Of
534 (File_Name : File_Name_Type;
535 Directory : Path_Name_Type) return String;
536 -- Returns the path name of a (non project) file. Returns an empty string
537 -- if file cannot be found.
539 procedure Prepare_Ada_Naming_Exceptions
540 (List : Array_Element_Id;
541 In_Tree : Project_Tree_Ref;
542 Kind : Spec_Or_Body);
543 -- Prepare the internal hash tables used for checking naming exceptions
544 -- for Ada. Insert all elements of List in the tables.
546 function Project_Extends
547 (Extending : Project_Id;
548 Extended : Project_Id;
549 In_Tree : Project_Tree_Ref) return Boolean;
550 -- Returns True if Extending is extending Extended either directly or
553 procedure Record_Ada_Source
554 (File_Name : File_Name_Type;
555 Path_Name : Path_Name_Type;
556 Project : Project_Id;
557 In_Tree : Project_Tree_Ref;
558 Data : in out Project_Data;
559 Location : Source_Ptr;
560 Current_Source : in out String_List_Id;
561 Source_Recorded : in out Boolean;
562 Current_Dir : String);
563 -- Put a unit in the list of units of a project, if the file name
564 -- corresponds to a valid unit name.
566 -- Current_Dir should represent the current directory, and is passed for
567 -- efficiency to avoid system calls to recompute it.
569 procedure Record_Other_Sources
570 (Project : Project_Id;
571 In_Tree : Project_Tree_Ref;
572 Data : in out Project_Data;
573 Language : Language_Index;
574 Naming_Exceptions : Boolean);
575 -- Record the sources of a language in a project. When Naming_Exceptions is
576 -- True, mark the found sources as such, to later remove those that are not
577 -- named in a list of sources.
579 procedure Remove_Source
581 Replaced_By : Source_Id;
582 Project : Project_Id;
583 Data : in out Project_Data;
584 In_Tree : Project_Tree_Ref);
587 procedure Report_No_Sources
588 (Project : Project_Id;
590 In_Tree : Project_Tree_Ref;
591 Location : Source_Ptr;
592 Continuation : Boolean := False);
593 -- Report an error or a warning depending on the value of When_No_Sources
594 -- when there are no sources for language Lang_Name.
596 procedure Show_Source_Dirs
597 (Data : Project_Data; In_Tree : Project_Tree_Ref);
598 -- List all the source directories of a project
601 (Language : Language_Index;
602 Naming : Naming_Data;
603 In_Tree : Project_Tree_Ref) return File_Name_Type;
604 -- Get the suffix for the source of a language from a package naming. If
605 -- not specified, return the default for the language.
607 procedure Warn_If_Not_Sources
608 (Project : Project_Id;
609 In_Tree : Project_Tree_Ref;
610 Conventions : Array_Element_Id;
612 Extending : Boolean);
613 -- Check that individual naming conventions apply to immediate sources of
614 -- the project. If not, issue a warning.
622 Data : in out Project_Data;
623 In_Tree : Project_Tree_Ref;
624 Project : Project_Id;
626 Lang_Id : Language_Index;
628 File_Name : File_Name_Type;
629 Display_File : File_Name_Type;
630 Lang_Kind : Language_Kind;
631 Naming_Exception : Boolean := False;
632 Path : Path_Name_Type := No_Path;
633 Display_Path : Path_Name_Type := No_Path;
634 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
635 Other_Part : Source_Id := No_Source;
636 Unit : Name_Id := No_Name;
638 Source_To_Replace : Source_Id := No_Source)
640 Source : constant Source_Id := Data.Last_Source;
641 Src_Data : Source_Data := No_Source_Data;
642 Config : constant Language_Config :=
643 In_Tree.Languages_Data.Table (Lang_Id).Config;
646 -- This is a new source so create an entry for it in the Sources table
648 Source_Data_Table.Increment_Last (In_Tree.Sources);
649 Id := Source_Data_Table.Last (In_Tree.Sources);
651 if Current_Verbosity = High then
652 Write_Str ("Adding source #");
654 Write_Str (", File : ");
655 Write_Str (Get_Name_String (File_Name));
657 if Lang_Kind = Unit_Based then
658 Write_Str (", Unit : ");
659 Write_Str (Get_Name_String (Unit));
665 Src_Data.Project := Project;
666 Src_Data.Language_Name := Lang;
667 Src_Data.Language := Lang_Id;
668 Src_Data.Lang_Kind := Lang_Kind;
669 Src_Data.Compiled := In_Tree.Languages_Data.Table
670 (Lang_Id).Config.Compiler_Driver /=
672 Src_Data.Kind := Kind;
673 Src_Data.Alternate_Languages := Alternate_Languages;
674 Src_Data.Other_Part := Other_Part;
676 Src_Data.Object_Exists := Config.Object_Generated;
677 Src_Data.Object_Linked := Config.Objects_Linked;
679 if Other_Part /= No_Source then
680 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
683 Src_Data.Unit := Unit;
684 Src_Data.Index := Index;
685 Src_Data.File := File_Name;
686 Src_Data.Display_File := Display_File;
687 Src_Data.Dependency := In_Tree.Languages_Data.Table
688 (Lang_Id).Config.Dependency_Kind;
689 Src_Data.Naming_Exception := Naming_Exception;
691 if Src_Data.Compiled and then Src_Data.Object_Exists then
692 Src_Data.Object := Object_Name (File_Name);
694 Dependency_Name (File_Name, Src_Data.Dependency);
695 Src_Data.Switches := Switches_Name (File_Name);
698 if Path /= No_Path then
699 Src_Data.Path := Path;
700 Src_Data.Display_Path := Display_Path;
701 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
704 -- Add the source to the global list
706 Src_Data.Next_In_Sources := In_Tree.First_Source;
707 In_Tree.First_Source := Id;
709 -- Add the source to the project list
711 if Source = No_Source then
712 Data.First_Source := Id;
714 In_Tree.Sources.Table (Source).Next_In_Project := Id;
717 Data.Last_Source := Id;
719 -- Add the source to the language list
721 Src_Data.Next_In_Lang :=
722 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
723 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
725 In_Tree.Sources.Table (Id) := Src_Data;
727 if Source_To_Replace /= No_Source then
728 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
736 function ALI_File_Name (Source : String) return String is
738 -- If the source name has an extension, then replace it with
741 for Index in reverse Source'First + 1 .. Source'Last loop
742 if Source (Index) = '.' then
743 return Source (Source'First .. Index - 1) & ALI_Suffix;
747 -- If there is no dot, or if it is the first character, just add the
750 return Source & ALI_Suffix;
758 (Project : Project_Id;
759 In_Tree : Project_Tree_Ref;
760 Report_Error : Put_Line_Access;
761 When_No_Sources : Error_Warning;
762 Current_Dir : String)
764 Data : Project_Data := In_Tree.Projects.Table (Project);
765 Extending : Boolean := False;
768 Nmsc.When_No_Sources := When_No_Sources;
769 Error_Report := Report_Error;
771 Recursive_Dirs.Reset;
773 Check_If_Externally_Built (Project, In_Tree, Data);
775 -- Object, exec and source directories
777 Get_Directories (Project, In_Tree, Current_Dir, Data);
779 -- Get the programming languages
781 Check_Programming_Languages (In_Tree, Project, Data);
783 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
786 "an abstract project need to have no language, no sources or no " &
787 "source directories",
791 -- Check configuration in multi language mode
793 if Must_Check_Configuration then
794 Check_Configuration (Project, In_Tree, Data);
797 -- Library attributes
799 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
801 if Current_Verbosity = High then
802 Show_Source_Dirs (Data, In_Tree);
805 Check_Package_Naming (Project, In_Tree, Data);
807 Extending := Data.Extends /= No_Project;
809 Check_Naming_Schemes (Data, Project, In_Tree);
811 if Get_Mode = Ada_Only then
812 Prepare_Ada_Naming_Exceptions
813 (Data.Naming.Bodies, In_Tree, Body_Part);
814 Prepare_Ada_Naming_Exceptions
815 (Data.Naming.Specs, In_Tree, Specification);
820 if Data.Source_Dirs /= Nil_String then
821 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
823 if Get_Mode = Ada_Only then
825 -- Check that all individual naming conventions apply to sources
826 -- of this project file.
829 (Project, In_Tree, Data.Naming.Bodies,
831 Extending => Extending);
833 (Project, In_Tree, Data.Naming.Specs,
835 Extending => Extending);
837 elsif Get_Mode = Multi_Language and then
838 (not Data.Externally_Built) and then
842 Language : Language_Index;
844 Src_Data : Source_Data;
845 Alt_Lang : Alternate_Language_Id;
846 Alt_Lang_Data : Alternate_Language_Data;
847 Continuation : Boolean := False;
850 Language := Data.First_Language_Processing;
851 while Language /= No_Language_Index loop
852 Source := Data.First_Source;
853 Source_Loop : while Source /= No_Source loop
854 Src_Data := In_Tree.Sources.Table (Source);
856 exit Source_Loop when Src_Data.Language = Language;
858 Alt_Lang := Src_Data.Alternate_Languages;
861 while Alt_Lang /= No_Alternate_Language loop
863 In_Tree.Alt_Langs.Table (Alt_Lang);
865 when Alt_Lang_Data.Language = Language;
866 Alt_Lang := Alt_Lang_Data.Next;
867 end loop Alternate_Loop;
869 Source := Src_Data.Next_In_Project;
870 end loop Source_Loop;
872 if Source = No_Source then
876 (In_Tree.Languages_Data.Table
877 (Language).Display_Name),
881 Continuation := True;
884 Language := In_Tree.Languages_Data.Table (Language).Next;
890 if Get_Mode = Multi_Language then
892 -- If a list of sources is specified in attribute Interfaces, set
893 -- In_Interfaces only for the sources specified in the list.
895 Check_Interfaces (Project, In_Tree, Data);
898 -- If it is a library project file, check if it is a standalone library
901 Check_Stand_Alone_Library
902 (Project, In_Tree, Data, Current_Dir, Extending);
905 -- Put the list of Mains, if any, in the project data
907 Get_Mains (Project, In_Tree, Data);
909 -- Update the project data in the Projects table
911 In_Tree.Projects.Table (Project) := Data;
913 Free_Ada_Naming_Exceptions;
920 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
921 The_Name : String := Name;
923 Need_Letter : Boolean := True;
924 Last_Underscore : Boolean := False;
925 OK : Boolean := The_Name'Length > 0;
928 function Is_Reserved (Name : Name_Id) return Boolean;
929 function Is_Reserved (S : String) return Boolean;
930 -- Check that the given name is not an Ada 95 reserved word. The reason
931 -- for the Ada 95 here is that we do not want to exclude the case of an
932 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
933 -- name would be rejected anyway by the compiler. That means there is no
934 -- requirement that the project file parser reject this.
940 function Is_Reserved (S : String) return Boolean is
943 Add_Str_To_Name_Buffer (S);
944 return Is_Reserved (Name_Find);
951 function Is_Reserved (Name : Name_Id) return Boolean is
953 if Get_Name_Table_Byte (Name) /= 0
954 and then Name /= Name_Project
955 and then Name /= Name_Extends
956 and then Name /= Name_External
957 and then Name not in Ada_2005_Reserved_Words
961 if Current_Verbosity = High then
962 Write_Str (The_Name);
963 Write_Line (" is an Ada reserved word.");
973 -- Start of processing for Check_Ada_Name
978 Name_Len := The_Name'Length;
979 Name_Buffer (1 .. Name_Len) := The_Name;
981 -- Special cases of children of packages A, G, I and S on VMS
984 and then Name_Len > 3
985 and then Name_Buffer (2 .. 3) = "__"
987 ((Name_Buffer (1) = 'a') or else
988 (Name_Buffer (1) = 'g') or else
989 (Name_Buffer (1) = 'i') or else
990 (Name_Buffer (1) = 's'))
992 Name_Buffer (2) := '.';
993 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
994 Name_Len := Name_Len - 1;
997 Real_Name := Name_Find;
999 if Is_Reserved (Real_Name) then
1003 First := The_Name'First;
1005 for Index in The_Name'Range loop
1008 -- We need a letter (at the beginning, and following a dot),
1009 -- but we don't have one.
1011 if Is_Letter (The_Name (Index)) then
1012 Need_Letter := False;
1017 if Current_Verbosity = High then
1018 Write_Int (Types.Int (Index));
1020 Write_Char (The_Name (Index));
1021 Write_Line ("' is not a letter.");
1027 elsif Last_Underscore
1028 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1030 -- Two underscores are illegal, and a dot cannot follow
1035 if Current_Verbosity = High then
1036 Write_Int (Types.Int (Index));
1038 Write_Char (The_Name (Index));
1039 Write_Line ("' is illegal here.");
1044 elsif The_Name (Index) = '.' then
1046 -- First, check if the name before the dot is not a reserved word
1047 if Is_Reserved (The_Name (First .. Index - 1)) then
1053 -- We need a letter after a dot
1055 Need_Letter := True;
1057 elsif The_Name (Index) = '_' then
1058 Last_Underscore := True;
1061 -- We need an letter or a digit
1063 Last_Underscore := False;
1065 if not Is_Alphanumeric (The_Name (Index)) then
1068 if Current_Verbosity = High then
1069 Write_Int (Types.Int (Index));
1071 Write_Char (The_Name (Index));
1072 Write_Line ("' is not alphanumeric.");
1080 -- Cannot end with an underscore or a dot
1082 OK := OK and then not Need_Letter and then not Last_Underscore;
1085 if First /= Name'First and then
1086 Is_Reserved (The_Name (First .. The_Name'Last))
1094 -- Signal a problem with No_Name
1100 --------------------------------------
1101 -- Check_Ada_Naming_Scheme_Validity --
1102 --------------------------------------
1104 procedure Check_Ada_Naming_Scheme_Validity
1105 (Project : Project_Id;
1106 In_Tree : Project_Tree_Ref;
1107 Naming : Naming_Data)
1110 -- Only check if we are not using the Default naming scheme
1112 if Naming /= In_Tree.Private_Part.Default_Naming then
1114 Dot_Replacement : constant String :=
1116 (Naming.Dot_Replacement);
1118 Spec_Suffix : constant String :=
1119 Spec_Suffix_Of (In_Tree, "ada", Naming);
1121 Body_Suffix : constant String :=
1122 Body_Suffix_Of (In_Tree, "ada", Naming);
1124 Separate_Suffix : constant String :=
1126 (Naming.Separate_Suffix);
1129 -- Dot_Replacement cannot
1132 -- - start or end with an alphanumeric
1133 -- - be a single '_'
1134 -- - start with an '_' followed by an alphanumeric
1135 -- - contain a '.' except if it is "."
1137 if Dot_Replacement'Length = 0
1138 or else Is_Alphanumeric
1139 (Dot_Replacement (Dot_Replacement'First))
1140 or else Is_Alphanumeric
1141 (Dot_Replacement (Dot_Replacement'Last))
1142 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1144 (Dot_Replacement'Length = 1
1147 (Dot_Replacement (Dot_Replacement'First + 1))))
1148 or else (Dot_Replacement'Length > 1
1150 Index (Source => Dot_Replacement,
1151 Pattern => ".") /= 0)
1155 '"' & Dot_Replacement &
1156 """ is illegal for Dot_Replacement.",
1157 Naming.Dot_Repl_Loc);
1163 if Is_Illegal_Suffix
1164 (Spec_Suffix, Dot_Replacement = ".")
1166 Err_Vars.Error_Msg_File_1 :=
1167 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1170 "{ is illegal for Spec_Suffix",
1171 Naming.Ada_Spec_Suffix_Loc);
1174 if Is_Illegal_Suffix
1175 (Body_Suffix, Dot_Replacement = ".")
1177 Err_Vars.Error_Msg_File_1 :=
1178 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1181 "{ is illegal for Body_Suffix",
1182 Naming.Ada_Body_Suffix_Loc);
1185 if Body_Suffix /= Separate_Suffix then
1186 if Is_Illegal_Suffix
1187 (Separate_Suffix, Dot_Replacement = ".")
1189 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1192 "{ is illegal for Separate_Suffix",
1193 Naming.Sep_Suffix_Loc);
1197 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1198 -- since that would cause a clear ambiguity. Note that we do
1199 -- allow a Spec_Suffix to have the same termination as one of
1200 -- these, which causes a potential ambiguity, but we resolve
1201 -- that my matching the longest possible suffix.
1203 if Spec_Suffix = Body_Suffix then
1208 """) cannot be the same as Spec_Suffix.",
1209 Naming.Ada_Body_Suffix_Loc);
1212 if Body_Suffix /= Separate_Suffix
1213 and then Spec_Suffix = Separate_Suffix
1217 "Separate_Suffix (""" &
1219 """) cannot be the same as Spec_Suffix.",
1220 Naming.Sep_Suffix_Loc);
1224 end Check_Ada_Naming_Scheme_Validity;
1226 -------------------------
1227 -- Check_Configuration --
1228 -------------------------
1230 procedure Check_Configuration
1231 (Project : Project_Id;
1232 In_Tree : Project_Tree_Ref;
1233 Data : in out Project_Data)
1235 Dot_Replacement : File_Name_Type := No_File;
1236 Casing : Casing_Type := All_Lower_Case;
1237 Separate_Suffix : File_Name_Type := No_File;
1239 Lang_Index : Language_Index := No_Language_Index;
1240 -- The index of the language data being checked
1242 Prev_Index : Language_Index := No_Language_Index;
1243 -- The index of the previous language
1245 Current_Language : Name_Id := No_Name;
1246 -- The name of the language
1248 Lang_Data : Language_Data;
1249 -- The data of the language being checked
1251 procedure Get_Language_Index_Of (Language : Name_Id);
1252 -- Get the language index of Language, if Language is one of the
1253 -- languages of the project.
1255 procedure Process_Project_Level_Simple_Attributes;
1256 -- Process the simple attributes at the project level
1258 procedure Process_Project_Level_Array_Attributes;
1259 -- Process the associate array attributes at the project level
1261 procedure Process_Packages;
1262 -- Read the packages of the project
1264 ---------------------------
1265 -- Get_Language_Index_Of --
1266 ---------------------------
1268 procedure Get_Language_Index_Of (Language : Name_Id) is
1269 Real_Language : Name_Id;
1272 Get_Name_String (Language);
1273 To_Lower (Name_Buffer (1 .. Name_Len));
1274 Real_Language := Name_Find;
1276 -- Nothing to do if the language is the same as the current language
1278 if Current_Language /= Real_Language then
1279 Lang_Index := Data.First_Language_Processing;
1280 while Lang_Index /= No_Language_Index loop
1281 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1284 In_Tree.Languages_Data.Table (Lang_Index).Next;
1287 if Lang_Index = No_Language_Index then
1288 Current_Language := No_Name;
1290 Current_Language := Real_Language;
1293 end Get_Language_Index_Of;
1295 ----------------------
1296 -- Process_Packages --
1297 ----------------------
1299 procedure Process_Packages is
1300 Packages : Package_Id;
1301 Element : Package_Element;
1303 procedure Process_Binder (Arrays : Array_Id);
1304 -- Process the associate array attributes of package Binder
1306 procedure Process_Builder (Attributes : Variable_Id);
1307 -- Process the simple attributes of package Builder
1309 procedure Process_Compiler (Arrays : Array_Id);
1310 -- Process the associate array attributes of package Compiler
1312 procedure Process_Naming (Attributes : Variable_Id);
1313 -- Process the simple attributes of package Naming
1315 procedure Process_Naming (Arrays : Array_Id);
1316 -- Process the associate array attributes of package Naming
1318 procedure Process_Linker (Attributes : Variable_Id);
1319 -- Process the simple attributes of package Linker of a
1320 -- configuration project.
1322 --------------------
1323 -- Process_Binder --
1324 --------------------
1326 procedure Process_Binder (Arrays : Array_Id) is
1327 Current_Array_Id : Array_Id;
1328 Current_Array : Array_Data;
1329 Element_Id : Array_Element_Id;
1330 Element : Array_Element;
1333 -- Process the associative array attribute of package Binder
1335 Current_Array_Id := Arrays;
1336 while Current_Array_Id /= No_Array loop
1337 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1339 Element_Id := Current_Array.Value;
1340 while Element_Id /= No_Array_Element loop
1341 Element := In_Tree.Array_Elements.Table (Element_Id);
1343 -- Get the name of the language
1345 Get_Language_Index_Of (Element.Index);
1347 if Lang_Index /= No_Language_Index then
1348 case Current_Array.Name is
1351 -- Attribute Driver (<language>)
1353 In_Tree.Languages_Data.Table
1354 (Lang_Index).Config.Binder_Driver :=
1355 File_Name_Type (Element.Value.Value);
1357 when Name_Required_Switches =>
1359 In_Tree.Languages_Data.Table
1360 (Lang_Index).Config.Binder_Required_Switches,
1361 From_List => Element.Value.Values,
1362 In_Tree => In_Tree);
1366 -- Attribute Prefix (<language>)
1368 In_Tree.Languages_Data.Table
1369 (Lang_Index).Config.Binder_Prefix :=
1370 Element.Value.Value;
1372 when Name_Objects_Path =>
1374 -- Attribute Objects_Path (<language>)
1376 In_Tree.Languages_Data.Table
1377 (Lang_Index).Config.Objects_Path :=
1378 Element.Value.Value;
1380 when Name_Objects_Path_File =>
1382 -- Attribute Objects_Path (<language>)
1384 In_Tree.Languages_Data.Table
1385 (Lang_Index).Config.Objects_Path_File :=
1386 Element.Value.Value;
1393 Element_Id := Element.Next;
1396 Current_Array_Id := Current_Array.Next;
1400 ---------------------
1401 -- Process_Builder --
1402 ---------------------
1404 procedure Process_Builder (Attributes : Variable_Id) is
1405 Attribute_Id : Variable_Id;
1406 Attribute : Variable;
1409 -- Process non associated array attribute from package Builder
1411 Attribute_Id := Attributes;
1412 while Attribute_Id /= No_Variable loop
1414 In_Tree.Variable_Elements.Table (Attribute_Id);
1416 if not Attribute.Value.Default then
1417 if Attribute.Name = Name_Executable_Suffix then
1419 -- Attribute Executable_Suffix: the suffix of the
1422 Data.Config.Executable_Suffix :=
1423 Attribute.Value.Value;
1427 Attribute_Id := Attribute.Next;
1429 end Process_Builder;
1431 ----------------------
1432 -- Process_Compiler --
1433 ----------------------
1435 procedure Process_Compiler (Arrays : Array_Id) is
1436 Current_Array_Id : Array_Id;
1437 Current_Array : Array_Data;
1438 Element_Id : Array_Element_Id;
1439 Element : Array_Element;
1440 List : String_List_Id;
1443 -- Process the associative array attribute of package Compiler
1445 Current_Array_Id := Arrays;
1446 while Current_Array_Id /= No_Array loop
1447 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1449 Element_Id := Current_Array.Value;
1450 while Element_Id /= No_Array_Element loop
1451 Element := In_Tree.Array_Elements.Table (Element_Id);
1453 -- Get the name of the language
1455 Get_Language_Index_Of (Element.Index);
1457 if Lang_Index /= No_Language_Index then
1458 case Current_Array.Name is
1459 when Name_Dependency_Switches =>
1461 -- Attribute Dependency_Switches (<language>)
1463 if In_Tree.Languages_Data.Table
1464 (Lang_Index).Config.Dependency_Kind = None
1466 In_Tree.Languages_Data.Table
1467 (Lang_Index).Config.Dependency_Kind :=
1471 List := Element.Value.Values;
1473 if List /= Nil_String then
1475 In_Tree.Languages_Data.Table
1476 (Lang_Index).Config.Dependency_Option,
1478 In_Tree => In_Tree);
1481 when Name_Dependency_Driver =>
1483 -- Attribute Dependency_Driver (<language>)
1485 if In_Tree.Languages_Data.Table
1486 (Lang_Index).Config.Dependency_Kind = None
1488 In_Tree.Languages_Data.Table
1489 (Lang_Index).Config.Dependency_Kind :=
1493 List := Element.Value.Values;
1495 if List /= Nil_String then
1497 In_Tree.Languages_Data.Table
1498 (Lang_Index).Config.Compute_Dependency,
1500 In_Tree => In_Tree);
1503 when Name_Include_Switches =>
1505 -- Attribute Include_Switches (<language>)
1507 List := Element.Value.Values;
1509 if List = Nil_String then
1513 "include option cannot be null",
1514 Element.Value.Location);
1518 In_Tree.Languages_Data.Table
1519 (Lang_Index).Config.Include_Option,
1521 In_Tree => In_Tree);
1523 when Name_Include_Path =>
1525 -- Attribute Include_Path (<language>)
1527 In_Tree.Languages_Data.Table
1528 (Lang_Index).Config.Include_Path :=
1529 Element.Value.Value;
1531 when Name_Include_Path_File =>
1533 -- Attribute Include_Path_File (<language>)
1535 In_Tree.Languages_Data.Table
1536 (Lang_Index).Config.Include_Path_File :=
1537 Element.Value.Value;
1541 -- Attribute Driver (<language>)
1543 Get_Name_String (Element.Value.Value);
1545 In_Tree.Languages_Data.Table
1546 (Lang_Index).Config.Compiler_Driver :=
1547 File_Name_Type (Element.Value.Value);
1549 when Name_Required_Switches =>
1551 In_Tree.Languages_Data.Table
1552 (Lang_Index).Config.
1553 Compiler_Required_Switches,
1554 From_List => Element.Value.Values,
1555 In_Tree => In_Tree);
1557 when Name_Pic_Option =>
1559 -- Attribute Compiler_Pic_Option (<language>)
1561 List := Element.Value.Values;
1563 if List = Nil_String then
1567 "compiler PIC option cannot be null",
1568 Element.Value.Location);
1572 In_Tree.Languages_Data.Table
1573 (Lang_Index).Config.Compilation_PIC_Option,
1575 In_Tree => In_Tree);
1577 when Name_Mapping_File_Switches =>
1579 -- Attribute Mapping_File_Switches (<language>)
1581 List := Element.Value.Values;
1583 if List = Nil_String then
1587 "mapping file switches cannot be null",
1588 Element.Value.Location);
1592 In_Tree.Languages_Data.Table
1593 (Lang_Index).Config.Mapping_File_Switches,
1595 In_Tree => In_Tree);
1597 when Name_Mapping_Spec_Suffix =>
1599 -- Attribute Mapping_Spec_Suffix (<language>)
1601 In_Tree.Languages_Data.Table
1602 (Lang_Index).Config.Mapping_Spec_Suffix :=
1603 File_Name_Type (Element.Value.Value);
1605 when Name_Mapping_Body_Suffix =>
1607 -- Attribute Mapping_Body_Suffix (<language>)
1609 In_Tree.Languages_Data.Table
1610 (Lang_Index).Config.Mapping_Body_Suffix :=
1611 File_Name_Type (Element.Value.Value);
1613 when Name_Config_File_Switches =>
1615 -- Attribute Config_File_Switches (<language>)
1617 List := Element.Value.Values;
1619 if List = Nil_String then
1623 "config file switches cannot be null",
1624 Element.Value.Location);
1628 In_Tree.Languages_Data.Table
1629 (Lang_Index).Config.Config_File_Switches,
1631 In_Tree => In_Tree);
1633 when Name_Objects_Path =>
1635 -- Attribute Objects_Path (<language>)
1637 In_Tree.Languages_Data.Table
1638 (Lang_Index).Config.Objects_Path :=
1639 Element.Value.Value;
1641 when Name_Objects_Path_File =>
1643 -- Attribute Objects_Path_File (<language>)
1645 In_Tree.Languages_Data.Table
1646 (Lang_Index).Config.Objects_Path_File :=
1647 Element.Value.Value;
1649 when Name_Config_Body_File_Name =>
1651 -- Attribute Config_Body_File_Name (<language>)
1653 In_Tree.Languages_Data.Table
1654 (Lang_Index).Config.Config_Body :=
1655 Element.Value.Value;
1657 when Name_Config_Body_File_Name_Pattern =>
1659 -- Attribute Config_Body_File_Name_Pattern
1662 In_Tree.Languages_Data.Table
1663 (Lang_Index).Config.Config_Body_Pattern :=
1664 Element.Value.Value;
1666 when Name_Config_Spec_File_Name =>
1668 -- Attribute Config_Spec_File_Name (<language>)
1670 In_Tree.Languages_Data.Table
1671 (Lang_Index).Config.Config_Spec :=
1672 Element.Value.Value;
1674 when Name_Config_Spec_File_Name_Pattern =>
1676 -- Attribute Config_Spec_File_Name_Pattern
1679 In_Tree.Languages_Data.Table
1680 (Lang_Index).Config.Config_Spec_Pattern :=
1681 Element.Value.Value;
1683 when Name_Config_File_Unique =>
1685 -- Attribute Config_File_Unique (<language>)
1688 In_Tree.Languages_Data.Table
1689 (Lang_Index).Config.Config_File_Unique :=
1691 (Get_Name_String (Element.Value.Value));
1693 when Constraint_Error =>
1697 "illegal value for Config_File_Unique",
1698 Element.Value.Location);
1706 Element_Id := Element.Next;
1709 Current_Array_Id := Current_Array.Next;
1711 end Process_Compiler;
1713 --------------------
1714 -- Process_Naming --
1715 --------------------
1717 procedure Process_Naming (Attributes : Variable_Id) is
1718 Attribute_Id : Variable_Id;
1719 Attribute : Variable;
1722 -- Process non associated array attribute from package Naming
1724 Attribute_Id := Attributes;
1725 while Attribute_Id /= No_Variable loop
1727 In_Tree.Variable_Elements.Table (Attribute_Id);
1729 if not Attribute.Value.Default then
1730 if Attribute.Name = Name_Separate_Suffix then
1732 -- Attribute Separate_Suffix
1734 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1736 elsif Attribute.Name = Name_Casing then
1742 Value (Get_Name_String (Attribute.Value.Value));
1745 when Constraint_Error =>
1749 "invalid value for Casing",
1750 Attribute.Value.Location);
1753 elsif Attribute.Name = Name_Dot_Replacement then
1755 -- Attribute Dot_Replacement
1757 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1762 Attribute_Id := Attribute.Next;
1766 procedure Process_Naming (Arrays : Array_Id) is
1767 Current_Array_Id : Array_Id;
1768 Current_Array : Array_Data;
1769 Element_Id : Array_Element_Id;
1770 Element : Array_Element;
1772 -- Process the associative array attribute of package Naming
1774 Current_Array_Id := Arrays;
1775 while Current_Array_Id /= No_Array loop
1776 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1778 Element_Id := Current_Array.Value;
1779 while Element_Id /= No_Array_Element loop
1780 Element := In_Tree.Array_Elements.Table (Element_Id);
1782 -- Get the name of the language
1784 Get_Language_Index_Of (Element.Index);
1786 if Lang_Index /= No_Language_Index then
1787 case Current_Array.Name is
1788 when Name_Specification_Suffix | Name_Spec_Suffix =>
1790 -- Attribute Spec_Suffix (<language>)
1792 In_Tree.Languages_Data.Table
1793 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1794 File_Name_Type (Element.Value.Value);
1796 when Name_Implementation_Suffix | Name_Body_Suffix =>
1798 -- Attribute Body_Suffix (<language>)
1800 In_Tree.Languages_Data.Table
1801 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1802 File_Name_Type (Element.Value.Value);
1804 In_Tree.Languages_Data.Table
1805 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1806 File_Name_Type (Element.Value.Value);
1813 Element_Id := Element.Next;
1816 Current_Array_Id := Current_Array.Next;
1820 --------------------
1821 -- Process_Linker --
1822 --------------------
1824 procedure Process_Linker (Attributes : Variable_Id) is
1825 Attribute_Id : Variable_Id;
1826 Attribute : Variable;
1829 -- Process non associated array attribute from package Linker
1831 Attribute_Id := Attributes;
1832 while Attribute_Id /= No_Variable loop
1834 In_Tree.Variable_Elements.Table (Attribute_Id);
1836 if not Attribute.Value.Default then
1837 if Attribute.Name = Name_Driver then
1839 -- Attribute Linker'Driver: the default linker to use
1841 Data.Config.Linker :=
1842 Path_Name_Type (Attribute.Value.Value);
1844 elsif Attribute.Name = Name_Required_Switches then
1846 -- Attribute Required_Switches: the minimum
1847 -- options to use when invoking the linker
1850 Data.Config.Minimum_Linker_Options,
1851 From_List => Attribute.Value.Values,
1852 In_Tree => In_Tree);
1854 elsif Attribute.Name = Name_Map_File_Option then
1855 Data.Config.Map_File_Option := Attribute.Value.Value;
1859 Attribute_Id := Attribute.Next;
1863 -- Start of processing for Process_Packages
1866 Packages := Data.Decl.Packages;
1867 while Packages /= No_Package loop
1868 Element := In_Tree.Packages.Table (Packages);
1870 case Element.Name is
1873 -- Process attributes of package Binder
1875 Process_Binder (Element.Decl.Arrays);
1877 when Name_Builder =>
1879 -- Process attributes of package Builder
1881 Process_Builder (Element.Decl.Attributes);
1883 when Name_Compiler =>
1885 -- Process attributes of package Compiler
1887 Process_Compiler (Element.Decl.Arrays);
1891 -- Process attributes of package Linker
1893 Process_Linker (Element.Decl.Attributes);
1897 -- Process attributes of package Naming
1899 Process_Naming (Element.Decl.Attributes);
1900 Process_Naming (Element.Decl.Arrays);
1906 Packages := Element.Next;
1908 end Process_Packages;
1910 ---------------------------------------------
1911 -- Process_Project_Level_Simple_Attributes --
1912 ---------------------------------------------
1914 procedure Process_Project_Level_Simple_Attributes is
1915 Attribute_Id : Variable_Id;
1916 Attribute : Variable;
1917 List : String_List_Id;
1920 -- Process non associated array attribute at project level
1922 Attribute_Id := Data.Decl.Attributes;
1923 while Attribute_Id /= No_Variable loop
1925 In_Tree.Variable_Elements.Table (Attribute_Id);
1927 if not Attribute.Value.Default then
1928 if Attribute.Name = Name_Library_Builder then
1930 -- Attribute Library_Builder: the application to invoke
1931 -- to build libraries.
1933 Data.Config.Library_Builder :=
1934 Path_Name_Type (Attribute.Value.Value);
1936 elsif Attribute.Name = Name_Archive_Builder then
1938 -- Attribute Archive_Builder: the archive builder
1939 -- (usually "ar") and its minimum options (usually "cr").
1941 List := Attribute.Value.Values;
1943 if List = Nil_String then
1947 "archive builder cannot be null",
1948 Attribute.Value.Location);
1951 Put (Into_List => Data.Config.Archive_Builder,
1953 In_Tree => In_Tree);
1955 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1957 -- Attribute Archive_Builder: the archive builder
1958 -- (usually "ar") and its minimum options (usually "cr").
1960 List := Attribute.Value.Values;
1962 if List /= Nil_String then
1964 (Into_List => Data.Config.Archive_Builder_Append_Option,
1966 In_Tree => In_Tree);
1969 elsif Attribute.Name = Name_Archive_Indexer then
1971 -- Attribute Archive_Indexer: the optional archive
1972 -- indexer (usually "ranlib") with its minimum options
1975 List := Attribute.Value.Values;
1977 if List = Nil_String then
1981 "archive indexer cannot be null",
1982 Attribute.Value.Location);
1985 Put (Into_List => Data.Config.Archive_Indexer,
1987 In_Tree => In_Tree);
1989 elsif Attribute.Name = Name_Library_Partial_Linker then
1991 -- Attribute Library_Partial_Linker: the optional linker
1992 -- driver with its minimum options, to partially link
1995 List := Attribute.Value.Values;
1997 if List = Nil_String then
2001 "partial linker cannot be null",
2002 Attribute.Value.Location);
2005 Put (Into_List => Data.Config.Lib_Partial_Linker,
2007 In_Tree => In_Tree);
2009 elsif Attribute.Name = Name_Library_GCC then
2010 Data.Config.Shared_Lib_Driver :=
2011 File_Name_Type (Attribute.Value.Value);
2013 elsif Attribute.Name = Name_Archive_Suffix then
2014 Data.Config.Archive_Suffix :=
2015 File_Name_Type (Attribute.Value.Value);
2017 elsif Attribute.Name = Name_Linker_Executable_Option then
2019 -- Attribute Linker_Executable_Option: optional options
2020 -- to specify an executable name. Defaults to "-o".
2022 List := Attribute.Value.Values;
2024 if List = Nil_String then
2028 "linker executable option cannot be null",
2029 Attribute.Value.Location);
2032 Put (Into_List => Data.Config.Linker_Executable_Option,
2034 In_Tree => In_Tree);
2036 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2038 -- Attribute Linker_Lib_Dir_Option: optional options
2039 -- to specify a library search directory. Defaults to
2042 Get_Name_String (Attribute.Value.Value);
2044 if Name_Len = 0 then
2048 "linker library directory option cannot be empty",
2049 Attribute.Value.Location);
2052 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2054 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2056 -- Attribute Linker_Lib_Name_Option: optional options
2057 -- to specify the name of a library to be linked in.
2058 -- Defaults to "-l".
2060 Get_Name_String (Attribute.Value.Value);
2062 if Name_Len = 0 then
2066 "linker library name option cannot be empty",
2067 Attribute.Value.Location);
2070 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2072 elsif Attribute.Name = Name_Run_Path_Option then
2074 -- Attribute Run_Path_Option: optional options to
2075 -- specify a path for libraries.
2077 List := Attribute.Value.Values;
2079 if List /= Nil_String then
2080 Put (Into_List => Data.Config.Run_Path_Option,
2082 In_Tree => In_Tree);
2085 elsif Attribute.Name = Name_Library_Support then
2087 pragma Unsuppress (All_Checks);
2089 Data.Config.Lib_Support :=
2090 Library_Support'Value (Get_Name_String
2091 (Attribute.Value.Value));
2093 when Constraint_Error =>
2097 "invalid value """ &
2098 Get_Name_String (Attribute.Value.Value) &
2099 """ for Library_Support",
2100 Attribute.Value.Location);
2103 elsif Attribute.Name = Name_Shared_Library_Prefix then
2104 Data.Config.Shared_Lib_Prefix :=
2105 File_Name_Type (Attribute.Value.Value);
2107 elsif Attribute.Name = Name_Shared_Library_Suffix then
2108 Data.Config.Shared_Lib_Suffix :=
2109 File_Name_Type (Attribute.Value.Value);
2111 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2113 pragma Unsuppress (All_Checks);
2115 Data.Config.Symbolic_Link_Supported :=
2116 Boolean'Value (Get_Name_String
2117 (Attribute.Value.Value));
2119 when Constraint_Error =>
2124 & Get_Name_String (Attribute.Value.Value)
2125 & """ for Symbolic_Link_Supported",
2126 Attribute.Value.Location);
2130 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2133 pragma Unsuppress (All_Checks);
2135 Data.Config.Lib_Maj_Min_Id_Supported :=
2136 Boolean'Value (Get_Name_String
2137 (Attribute.Value.Value));
2139 when Constraint_Error =>
2143 "invalid value """ &
2144 Get_Name_String (Attribute.Value.Value) &
2145 """ for Library_Major_Minor_Id_Supported",
2146 Attribute.Value.Location);
2149 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2151 pragma Unsuppress (All_Checks);
2153 Data.Config.Auto_Init_Supported :=
2154 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2156 when Constraint_Error =>
2161 & Get_Name_String (Attribute.Value.Value)
2162 & """ for Library_Auto_Init_Supported",
2163 Attribute.Value.Location);
2166 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2167 List := Attribute.Value.Values;
2169 if List /= Nil_String then
2170 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2172 In_Tree => In_Tree);
2175 elsif Attribute.Name = Name_Library_Version_Switches then
2176 List := Attribute.Value.Values;
2178 if List /= Nil_String then
2179 Put (Into_List => Data.Config.Lib_Version_Options,
2181 In_Tree => In_Tree);
2186 Attribute_Id := Attribute.Next;
2188 end Process_Project_Level_Simple_Attributes;
2190 --------------------------------------------
2191 -- Process_Project_Level_Array_Attributes --
2192 --------------------------------------------
2194 procedure Process_Project_Level_Array_Attributes is
2195 Current_Array_Id : Array_Id;
2196 Current_Array : Array_Data;
2197 Element_Id : Array_Element_Id;
2198 Element : Array_Element;
2199 List : String_List_Id;
2202 -- Process the associative array attributes at project level
2204 Current_Array_Id := Data.Decl.Arrays;
2205 while Current_Array_Id /= No_Array loop
2206 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2208 Element_Id := Current_Array.Value;
2209 while Element_Id /= No_Array_Element loop
2210 Element := In_Tree.Array_Elements.Table (Element_Id);
2212 -- Get the name of the language
2214 Get_Language_Index_Of (Element.Index);
2216 if Lang_Index /= No_Language_Index then
2217 case Current_Array.Name is
2218 when Name_Inherit_Source_Path =>
2219 List := Element.Value.Values;
2221 if List /= Nil_String then
2224 In_Tree.Languages_Data.Table (Lang_Index).
2225 Config.Include_Compatible_Languages,
2228 Lower_Case => True);
2231 when Name_Toolchain_Description =>
2233 -- Attribute Toolchain_Description (<language>)
2235 In_Tree.Languages_Data.Table
2236 (Lang_Index).Config.Toolchain_Description :=
2237 Element.Value.Value;
2239 when Name_Toolchain_Version =>
2241 -- Attribute Toolchain_Version (<language>)
2243 In_Tree.Languages_Data.Table
2244 (Lang_Index).Config.Toolchain_Version :=
2245 Element.Value.Value;
2247 when Name_Runtime_Library_Dir =>
2249 -- Attribute Runtime_Library_Dir (<language>)
2251 In_Tree.Languages_Data.Table
2252 (Lang_Index).Config.Runtime_Library_Dir :=
2253 Element.Value.Value;
2255 when Name_Object_Generated =>
2257 pragma Unsuppress (All_Checks);
2263 (Get_Name_String (Element.Value.Value));
2265 In_Tree.Languages_Data.Table
2266 (Lang_Index).Config.Object_Generated := Value;
2268 -- If no object is generated, no object may be
2272 In_Tree.Languages_Data.Table
2273 (Lang_Index).Config.Objects_Linked := False;
2277 when Constraint_Error =>
2282 & Get_Name_String (Element.Value.Value)
2283 & """ for Object_Generated",
2284 Element.Value.Location);
2287 when Name_Objects_Linked =>
2289 pragma Unsuppress (All_Checks);
2295 (Get_Name_String (Element.Value.Value));
2297 -- No change if Object_Generated is False, as this
2298 -- forces Objects_Linked to be False too.
2300 if In_Tree.Languages_Data.Table
2301 (Lang_Index).Config.Object_Generated
2303 In_Tree.Languages_Data.Table
2304 (Lang_Index).Config.Objects_Linked :=
2309 when Constraint_Error =>
2314 & Get_Name_String (Element.Value.Value)
2315 & """ for Objects_Linked",
2316 Element.Value.Location);
2323 Element_Id := Element.Next;
2326 Current_Array_Id := Current_Array.Next;
2328 end Process_Project_Level_Array_Attributes;
2331 Process_Project_Level_Simple_Attributes;
2332 Process_Project_Level_Array_Attributes;
2335 -- For unit based languages, set Casing, Dot_Replacement and
2336 -- Separate_Suffix in Naming_Data.
2338 Lang_Index := Data.First_Language_Processing;
2339 while Lang_Index /= No_Language_Index loop
2340 if In_Tree.Languages_Data.Table
2341 (Lang_Index).Name = Name_Ada
2343 In_Tree.Languages_Data.Table
2344 (Lang_Index).Config.Naming_Data.Casing := Casing;
2345 In_Tree.Languages_Data.Table
2346 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2349 if Separate_Suffix /= No_File then
2350 In_Tree.Languages_Data.Table
2351 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2358 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2361 -- Give empty names to various prefixes/suffixes, if they have not
2362 -- been specified in the configuration.
2364 if Data.Config.Archive_Suffix = No_File then
2365 Data.Config.Archive_Suffix := Empty_File;
2368 if Data.Config.Shared_Lib_Prefix = No_File then
2369 Data.Config.Shared_Lib_Prefix := Empty_File;
2372 if Data.Config.Shared_Lib_Suffix = No_File then
2373 Data.Config.Shared_Lib_Suffix := Empty_File;
2376 Lang_Index := Data.First_Language_Processing;
2377 while Lang_Index /= No_Language_Index loop
2378 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2380 Current_Language := Lang_Data.Display_Name;
2382 -- For all languages, Compiler_Driver needs to be specified
2384 if Lang_Data.Config.Compiler_Driver = No_File then
2385 Error_Msg_Name_1 := Current_Language;
2389 "?no compiler specified for language %%" &
2390 ", ignoring all its sources",
2393 if Lang_Index = Data.First_Language_Processing then
2394 Data.First_Language_Processing :=
2397 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2401 elsif Lang_Data.Name = Name_Ada then
2402 Prev_Index := Lang_Index;
2404 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2405 -- Body_Suffix need to be specified.
2407 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2411 "Dot_Replacement not specified for Ada",
2415 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2419 "Spec_Suffix not specified for Ada",
2423 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2427 "Body_Suffix not specified for Ada",
2432 Prev_Index := Lang_Index;
2434 -- For file based languages, either Spec_Suffix or Body_Suffix
2435 -- need to be specified.
2437 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2438 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2440 Error_Msg_Name_1 := Current_Language;
2444 "no suffixes specified for %%",
2449 Lang_Index := Lang_Data.Next;
2451 end Check_Configuration;
2453 ----------------------
2454 -- Check_For_Source --
2455 ----------------------
2457 procedure Check_For_Source
2458 (File_Name : File_Name_Type;
2459 Path_Name : Path_Name_Type;
2460 Project : Project_Id;
2461 In_Tree : Project_Tree_Ref;
2462 Data : in out Project_Data;
2463 Location : Source_Ptr;
2464 Language : Language_Index;
2466 Naming_Exception : Boolean)
2468 Name : String := Get_Name_String (File_Name);
2469 Real_Location : Source_Ptr := Location;
2472 Canonical_Case_File_Name (Name);
2474 -- A file is a source of a language if Naming_Exception is True (case
2475 -- of naming exceptions) or if its file name ends with the suffix.
2479 (Name'Length > Suffix'Length
2481 Name (Name'Last - Suffix'Length + 1 .. Name'Last) = Suffix)
2483 if Real_Location = No_Location then
2484 Real_Location := Data.Location;
2488 Path_Id : Path_Name_Type;
2489 C_Path_Id : Path_Name_Type;
2490 -- The path name id (in canonical case)
2492 File_Id : File_Name_Type;
2493 -- The file name id (in canonical case)
2495 Obj_Id : File_Name_Type;
2496 -- The object file name
2498 Obj_Path_Id : Path_Name_Type;
2499 -- The object path name
2501 Dep_Id : File_Name_Type;
2502 -- The dependency file name
2504 Dep_Path_Id : Path_Name_Type;
2505 -- The dependency path name
2507 Dot_Pos : Natural := 0;
2508 -- Position of the last dot in Name
2510 Source : Other_Source;
2511 Source_Id : Other_Source_Id := Data.First_Other_Source;
2514 -- Get the file name id
2516 if Osint.File_Names_Case_Sensitive then
2517 File_Id := File_Name;
2519 Name_Len := Name'Length;
2520 Name_Buffer (1 .. Name_Len) := Name;
2521 File_Id := Name_Find;
2524 -- Get the path name id
2526 Path_Id := Path_Name;
2528 if Osint.File_Names_Case_Sensitive then
2529 C_Path_Id := Path_Name;
2532 C_Path : String := Get_Name_String (Path_Name);
2534 Canonical_Case_File_Name (C_Path);
2535 Name_Len := C_Path'Length;
2536 Name_Buffer (1 .. Name_Len) := C_Path;
2537 C_Path_Id := Name_Find;
2541 -- Find the position of the last dot
2543 for J in reverse Name'Range loop
2544 if Name (J) = '.' then
2550 if Dot_Pos <= Name'First then
2551 Dot_Pos := Name'Last + 1;
2554 -- Compute the object file name
2556 Get_Name_String (File_Id);
2557 Name_Len := Dot_Pos - Name'First;
2559 for J in Object_Suffix'Range loop
2560 Name_Len := Name_Len + 1;
2561 Name_Buffer (Name_Len) := Object_Suffix (J);
2564 Obj_Id := Name_Find;
2566 -- Compute the object path name
2568 Get_Name_String (Data.Display_Object_Dir);
2570 if Name_Buffer (Name_Len) /= Directory_Separator
2571 and then Name_Buffer (Name_Len) /= '/'
2573 Name_Len := Name_Len + 1;
2574 Name_Buffer (Name_Len) := Directory_Separator;
2577 Add_Str_To_Name_Buffer (Get_Name_String (Obj_Id));
2578 Obj_Path_Id := Name_Find;
2580 -- Compute the dependency file name
2582 Get_Name_String (File_Id);
2583 Name_Len := Dot_Pos - Name'First + 1;
2584 Name_Buffer (Name_Len) := '.';
2585 Name_Len := Name_Len + 1;
2586 Name_Buffer (Name_Len) := 'd';
2587 Dep_Id := Name_Find;
2589 -- Compute the dependency path name
2591 Get_Name_String (Data.Display_Object_Dir);
2593 if Name_Buffer (Name_Len) /= Directory_Separator
2594 and then Name_Buffer (Name_Len) /= '/'
2596 Name_Len := Name_Len + 1;
2597 Name_Buffer (Name_Len) := Directory_Separator;
2600 Add_Str_To_Name_Buffer (Get_Name_String (Dep_Id));
2601 Dep_Path_Id := Name_Find;
2603 -- Check if source is already in the list of source for this
2604 -- project: it may have already been specified as a naming
2605 -- exception for the same language or an other language, or
2606 -- they may be two identical file names in different source
2609 while Source_Id /= No_Other_Source loop
2610 Source := In_Tree.Other_Sources.Table (Source_Id);
2612 if Source.File_Name = File_Id then
2613 -- Two sources of different languages cannot have the same
2616 if Source.Language /= Language then
2617 Error_Msg_File_1 := File_Name;
2620 "{ cannot be a source of several languages",
2624 -- No problem if a file has already been specified as
2625 -- a naming exception of this language.
2627 elsif Source.Path_Name = C_Path_Id then
2629 -- Reset the naming exception flag, if this is not a
2630 -- naming exception.
2632 if not Naming_Exception then
2633 In_Tree.Other_Sources.Table
2634 (Source_Id).Naming_Exception := False;
2639 -- There are several files with the same names, but the
2640 -- order of the source directories is known (no /**):
2641 -- only the first one encountered is kept, the other ones
2644 elsif Data.Known_Order_Of_Source_Dirs then
2647 -- But it is an error if the order of the source directories
2651 Error_Msg_File_1 := File_Name;
2654 "{ is found in several source directories",
2659 -- Two sources with different file names cannot have the same
2660 -- object file name.
2662 elsif Source.Object_Name = Obj_Id then
2663 Error_Msg_File_1 := File_Id;
2664 Error_Msg_File_2 := Source.File_Name;
2665 Error_Msg_File_3 := Obj_Id;
2668 "{ and { have the same object file {",
2673 Source_Id := Source.Next;
2676 if Current_Verbosity = High then
2677 Write_Str (" found ");
2678 Display_Language_Name (Language);
2679 Write_Str (" source """);
2680 Write_Str (Get_Name_String (File_Name));
2682 Write_Str (" object path = ");
2683 Write_Line (Get_Name_String (Obj_Path_Id));
2686 -- Create the Other_Source record
2689 (Language => Language,
2690 File_Name => File_Id,
2691 Path_Name => Path_Id,
2692 Source_TS => File_Stamp (Path_Id),
2693 Object_Name => Obj_Id,
2694 Object_Path => Obj_Path_Id,
2695 Object_TS => File_Stamp (Obj_Path_Id),
2697 Dep_Path => Dep_Path_Id,
2698 Dep_TS => File_Stamp (Dep_Path_Id),
2699 Naming_Exception => Naming_Exception,
2700 Next => No_Other_Source);
2702 -- And add it to the Other_Sources table
2704 Other_Source_Table.Increment_Last (In_Tree.Other_Sources);
2705 In_Tree.Other_Sources.Table
2706 (Other_Source_Table.Last (In_Tree.Other_Sources)) := Source;
2708 -- There are sources of languages other than Ada in this project
2710 Data.Other_Sources_Present := True;
2712 -- And there are sources of this language in this project
2714 Set (Language, True, Data, In_Tree);
2716 -- Add this source to the list of sources of languages other than
2717 -- Ada of the project.
2719 if Data.First_Other_Source = No_Other_Source then
2720 Data.First_Other_Source :=
2721 Other_Source_Table.Last (In_Tree.Other_Sources);
2724 In_Tree.Other_Sources.Table (Data.Last_Other_Source).Next :=
2725 Other_Source_Table.Last (In_Tree.Other_Sources);
2728 Data.Last_Other_Source :=
2729 Other_Source_Table.Last (In_Tree.Other_Sources);
2732 end Check_For_Source;
2734 -------------------------------
2735 -- Check_If_Externally_Built --
2736 -------------------------------
2738 procedure Check_If_Externally_Built
2739 (Project : Project_Id;
2740 In_Tree : Project_Tree_Ref;
2741 Data : in out Project_Data)
2743 Externally_Built : constant Variable_Value :=
2745 (Name_Externally_Built,
2746 Data.Decl.Attributes, In_Tree);
2749 if not Externally_Built.Default then
2750 Get_Name_String (Externally_Built.Value);
2751 To_Lower (Name_Buffer (1 .. Name_Len));
2753 if Name_Buffer (1 .. Name_Len) = "true" then
2754 Data.Externally_Built := True;
2756 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2757 Error_Msg (Project, In_Tree,
2758 "Externally_Built may only be true or false",
2759 Externally_Built.Location);
2763 -- A virtual project extending an externally built project is itself
2764 -- externally built.
2766 if Data.Virtual and then Data.Extends /= No_Project then
2767 Data.Externally_Built :=
2768 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2771 if Current_Verbosity = High then
2772 Write_Str ("Project is ");
2774 if not Data.Externally_Built then
2778 Write_Line ("externally built.");
2780 end Check_If_Externally_Built;
2782 ----------------------
2783 -- Check_Interfaces --
2784 ----------------------
2786 procedure Check_Interfaces
2787 (Project : Project_Id;
2788 In_Tree : Project_Tree_Ref;
2789 Data : in out Project_Data)
2791 Interfaces : constant Prj.Variable_Value :=
2793 (Snames.Name_Interfaces,
2794 Data.Decl.Attributes,
2797 List : String_List_Id;
2798 Element : String_Element;
2799 Name : File_Name_Type;
2802 Src_Data : Source_Data;
2804 Project_2 : Project_Id;
2805 Data_2 : Project_Data;
2808 if not Interfaces.Default then
2810 -- Set In_Interfaces to False for all sources. It will be set to True
2811 -- later for the sources in the Interfaces list.
2813 Project_2 := Project;
2816 Source := Data_2.First_Source;
2817 while Source /= No_Source loop
2818 Src_Data := In_Tree.Sources.Table (Source);
2819 Src_Data.In_Interfaces := False;
2820 In_Tree.Sources.Table (Source) := Src_Data;
2821 Source := Src_Data.Next_In_Project;
2824 Project_2 := Data_2.Extends;
2826 exit when Project_2 = No_Project;
2828 Data_2 := In_Tree.Projects.Table (Project_2);
2831 List := Interfaces.Values;
2832 while List /= Nil_String loop
2833 Element := In_Tree.String_Elements.Table (List);
2834 Get_Name_String (Element.Value);
2835 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2838 Project_2 := Project;
2842 Source := Data_2.First_Source;
2843 while Source /= No_Source loop
2844 Src_Data := In_Tree.Sources.Table (Source);
2845 if Src_Data.File = Name then
2846 if not Src_Data.Locally_Removed then
2847 In_Tree.Sources.Table (Source).In_Interfaces := True;
2848 In_Tree.Sources.Table
2849 (Source).Declared_In_Interfaces := True;
2851 if Src_Data.Other_Part /= No_Source then
2852 In_Tree.Sources.Table
2853 (Src_Data.Other_Part).In_Interfaces := True;
2854 In_Tree.Sources.Table
2855 (Src_Data.Other_Part).Declared_In_Interfaces :=
2859 if Current_Verbosity = High then
2860 Write_Str (" interface: ");
2861 Write_Line (Get_Name_String (Src_Data.Path));
2868 Source := Src_Data.Next_In_Project;
2871 Project_2 := Data_2.Extends;
2873 exit Big_Loop when Project_2 = No_Project;
2875 Data_2 := In_Tree.Projects.Table (Project_2);
2878 if Source = No_Source then
2879 Error_Msg_File_1 := File_Name_Type (Element.Value);
2880 Error_Msg_Name_1 := Data.Name;
2885 "{ cannot be an interface of project %% " &
2886 "as it is not one of its sources",
2890 List := Element.Next;
2893 Data.Interfaces_Defined := True;
2895 elsif Data.Extends /= No_Project then
2896 Data.Interfaces_Defined :=
2897 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2899 if Data.Interfaces_Defined then
2900 Source := Data.First_Source;
2901 while Source /= No_Source loop
2902 Src_Data := In_Tree.Sources.Table (Source);
2904 if not Src_Data.Declared_In_Interfaces then
2905 Src_Data.In_Interfaces := False;
2906 In_Tree.Sources.Table (Source) := Src_Data;
2909 Source := Src_Data.Next_In_Project;
2913 end Check_Interfaces;
2915 --------------------------
2916 -- Check_Naming_Schemes --
2917 --------------------------
2919 procedure Check_Naming_Schemes
2920 (Data : in out Project_Data;
2921 Project : Project_Id;
2922 In_Tree : Project_Tree_Ref)
2924 Naming_Id : constant Package_Id :=
2925 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2926 Naming : Package_Element;
2928 procedure Check_Unit_Names (List : Array_Element_Id);
2929 -- Check that a list of unit names contains only valid names
2931 procedure Get_Exceptions (Kind : Source_Kind);
2933 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2935 ----------------------
2936 -- Check_Unit_Names --
2937 ----------------------
2939 procedure Check_Unit_Names (List : Array_Element_Id) is
2940 Current : Array_Element_Id;
2941 Element : Array_Element;
2942 Unit_Name : Name_Id;
2945 -- Loop through elements of the string list
2948 while Current /= No_Array_Element loop
2949 Element := In_Tree.Array_Elements.Table (Current);
2951 -- Put file name in canonical case
2953 if not Osint.File_Names_Case_Sensitive then
2954 Get_Name_String (Element.Value.Value);
2955 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2956 Element.Value.Value := Name_Find;
2959 -- Check that it contains a valid unit name
2961 Get_Name_String (Element.Index);
2962 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2964 if Unit_Name = No_Name then
2965 Err_Vars.Error_Msg_Name_1 := Element.Index;
2968 "%% is not a valid unit name.",
2969 Element.Value.Location);
2972 if Current_Verbosity = High then
2973 Write_Str (" Unit (""");
2974 Write_Str (Get_Name_String (Unit_Name));
2978 Element.Index := Unit_Name;
2979 In_Tree.Array_Elements.Table (Current) := Element;
2982 Current := Element.Next;
2984 end Check_Unit_Names;
2986 --------------------
2987 -- Get_Exceptions --
2988 --------------------
2990 procedure Get_Exceptions (Kind : Source_Kind) is
2991 Exceptions : Array_Element_Id;
2992 Exception_List : Variable_Value;
2993 Element_Id : String_List_Id;
2994 Element : String_Element;
2995 File_Name : File_Name_Type;
2996 Lang_Id : Language_Index;
2998 Lang_Kind : Language_Kind;
3005 (Name_Implementation_Exceptions,
3006 In_Arrays => Naming.Decl.Arrays,
3007 In_Tree => In_Tree);
3012 (Name_Specification_Exceptions,
3013 In_Arrays => Naming.Decl.Arrays,
3014 In_Tree => In_Tree);
3017 Lang_Id := Data.First_Language_Processing;
3018 while Lang_Id /= No_Language_Index loop
3019 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
3022 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3024 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
3026 Exception_List := Value_Of
3028 In_Array => Exceptions,
3029 In_Tree => In_Tree);
3031 if Exception_List /= Nil_Variable_Value then
3032 Element_Id := Exception_List.Values;
3033 while Element_Id /= Nil_String loop
3034 Element := In_Tree.String_Elements.Table (Element_Id);
3036 if Osint.File_Names_Case_Sensitive then
3037 File_Name := File_Name_Type (Element.Value);
3039 Get_Name_String (Element.Value);
3040 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3041 File_Name := Name_Find;
3044 Source := Data.First_Source;
3045 while Source /= No_Source
3047 In_Tree.Sources.Table (Source).File /= File_Name
3050 In_Tree.Sources.Table (Source).Next_In_Project;
3053 if Source = No_Source then
3062 File_Name => File_Name,
3063 Display_File => File_Name_Type (Element.Value),
3064 Naming_Exception => True,
3065 Lang_Kind => Lang_Kind);
3068 -- Check if the file name is already recorded for
3069 -- another language or another kind.
3072 In_Tree.Sources.Table (Source).Language /= Lang_Id
3077 "the same file cannot be a source " &
3081 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
3085 "the same file cannot be a source " &
3090 -- If the file is already recorded for the same
3091 -- language and the same kind, it means that the file
3092 -- name appears several times in the *_Exceptions
3093 -- attribute; so there is nothing to do.
3097 Element_Id := Element.Next;
3102 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3106 -------------------------
3107 -- Get_Unit_Exceptions --
3108 -------------------------
3110 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
3111 Exceptions : Array_Element_Id;
3112 Element : Array_Element;
3115 File_Name : File_Name_Type;
3116 Lang_Id : constant Language_Index :=
3117 Data.Unit_Based_Language_Index;
3118 Lang : constant Name_Id :=
3119 Data.Unit_Based_Language_Name;
3122 Source_To_Replace : Source_Id := No_Source;
3124 Other_Project : Project_Id;
3125 Other_Part : Source_Id := No_Source;
3128 if Lang_Id = No_Language_Index or else Lang = No_Name then
3133 Exceptions := Value_Of
3135 In_Arrays => Naming.Decl.Arrays,
3136 In_Tree => In_Tree);
3138 if Exceptions = No_Array_Element then
3141 (Name_Implementation,
3142 In_Arrays => Naming.Decl.Arrays,
3143 In_Tree => In_Tree);
3150 In_Arrays => Naming.Decl.Arrays,
3151 In_Tree => In_Tree);
3153 if Exceptions = No_Array_Element then
3154 Exceptions := Value_Of
3155 (Name_Specification,
3156 In_Arrays => Naming.Decl.Arrays,
3157 In_Tree => In_Tree);
3162 while Exceptions /= No_Array_Element loop
3163 Element := In_Tree.Array_Elements.Table (Exceptions);
3165 if Osint.File_Names_Case_Sensitive then
3166 File_Name := File_Name_Type (Element.Value.Value);
3168 Get_Name_String (Element.Value.Value);
3169 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3170 File_Name := Name_Find;
3173 Get_Name_String (Element.Index);
3174 To_Lower (Name_Buffer (1 .. Name_Len));
3177 Index := Element.Value.Index;
3179 -- For Ada, check if it is a valid unit name
3181 if Lang = Name_Ada then
3182 Get_Name_String (Element.Index);
3183 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3185 if Unit = No_Name then
3186 Err_Vars.Error_Msg_Name_1 := Element.Index;
3189 "%% is not a valid unit name.",
3190 Element.Value.Location);
3194 if Unit /= No_Name then
3196 -- Check if the source already exists
3198 Source := In_Tree.First_Source;
3199 Source_To_Replace := No_Source;
3201 while Source /= No_Source and then
3202 (In_Tree.Sources.Table (Source).Unit /= Unit or else
3203 In_Tree.Sources.Table (Source).Index /= Index)
3205 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
3208 if Source /= No_Source then
3209 if In_Tree.Sources.Table (Source).Kind /= Kind then
3210 Other_Part := Source;
3214 In_Tree.Sources.Table (Source).Next_In_Sources;
3216 exit when Source = No_Source or else
3217 (In_Tree.Sources.Table (Source).Unit = Unit
3219 In_Tree.Sources.Table (Source).Index = Index);
3223 if Source /= No_Source then
3224 Other_Project := In_Tree.Sources.Table (Source).Project;
3226 if Is_Extending (Project, Other_Project, In_Tree) then
3228 In_Tree.Sources.Table (Source).Other_Part;
3230 -- Record the source to be removed
3232 Source_To_Replace := Source;
3233 Source := No_Source;
3236 Error_Msg_Name_1 := Unit;
3238 In_Tree.Projects.Table (Other_Project).Name;
3242 "%% is already a source of project %%",
3243 Element.Value.Location);
3248 if Source = No_Source then
3257 File_Name => File_Name,
3258 Display_File => File_Name_Type (Element.Value.Value),
3259 Lang_Kind => Unit_Based,
3260 Other_Part => Other_Part,
3263 Naming_Exception => True,
3264 Source_To_Replace => Source_To_Replace);
3268 Exceptions := Element.Next;
3271 end Get_Unit_Exceptions;
3273 -- Start of processing for Check_Naming_Schemes
3276 if Get_Mode = Ada_Only then
3278 -- If there is a package Naming, we will put in Data.Naming what is
3279 -- in this package Naming.
3281 if Naming_Id /= No_Package then
3282 Naming := In_Tree.Packages.Table (Naming_Id);
3284 if Current_Verbosity = High then
3285 Write_Line ("Checking ""Naming"" for Ada.");
3289 Bodies : constant Array_Element_Id :=
3291 (Name_Body, Naming.Decl.Arrays, In_Tree);
3293 Specs : constant Array_Element_Id :=
3295 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3298 if Bodies /= No_Array_Element then
3300 -- We have elements in the array Body_Part
3302 if Current_Verbosity = High then
3303 Write_Line ("Found Bodies.");
3306 Data.Naming.Bodies := Bodies;
3307 Check_Unit_Names (Bodies);
3310 if Current_Verbosity = High then
3311 Write_Line ("No Bodies.");
3315 if Specs /= No_Array_Element then
3317 -- We have elements in the array Specs
3319 if Current_Verbosity = High then
3320 Write_Line ("Found Specs.");
3323 Data.Naming.Specs := Specs;
3324 Check_Unit_Names (Specs);
3327 if Current_Verbosity = High then
3328 Write_Line ("No Specs.");
3333 -- We are now checking if variables Dot_Replacement, Casing,
3334 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3336 -- For each variable, if it does not exist, we do nothing,
3337 -- because we already have the default.
3339 -- Check Dot_Replacement
3342 Dot_Replacement : constant Variable_Value :=
3344 (Name_Dot_Replacement,
3345 Naming.Decl.Attributes, In_Tree);
3348 pragma Assert (Dot_Replacement.Kind = Single,
3349 "Dot_Replacement is not a single string");
3351 if not Dot_Replacement.Default then
3352 Get_Name_String (Dot_Replacement.Value);
3354 if Name_Len = 0 then
3357 "Dot_Replacement cannot be empty",
3358 Dot_Replacement.Location);
3361 if Osint.File_Names_Case_Sensitive then
3362 Data.Naming.Dot_Replacement :=
3363 File_Name_Type (Dot_Replacement.Value);
3365 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3366 Data.Naming.Dot_Replacement := Name_Find;
3368 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3373 if Current_Verbosity = High then
3374 Write_Str (" Dot_Replacement = """);
3375 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3383 Casing_String : constant Variable_Value :=
3386 Naming.Decl.Attributes,
3390 pragma Assert (Casing_String.Kind = Single,
3391 "Casing is not a single string");
3393 if not Casing_String.Default then
3395 Casing_Image : constant String :=
3396 Get_Name_String (Casing_String.Value);
3399 Casing_Value : constant Casing_Type :=
3400 Value (Casing_Image);
3402 Data.Naming.Casing := Casing_Value;
3406 when Constraint_Error =>
3407 if Casing_Image'Length = 0 then
3410 "Casing cannot be an empty string",
3411 Casing_String.Location);
3414 Name_Len := Casing_Image'Length;
3415 Name_Buffer (1 .. Name_Len) := Casing_Image;
3416 Err_Vars.Error_Msg_Name_1 := Name_Find;
3419 "%% is not a correct Casing",
3420 Casing_String.Location);
3426 if Current_Verbosity = High then
3427 Write_Str (" Casing = ");
3428 Write_Str (Image (Data.Naming.Casing));
3433 -- Check Spec_Suffix
3436 Ada_Spec_Suffix : constant Variable_Value :=
3440 In_Array => Data.Naming.Spec_Suffix,
3441 In_Tree => In_Tree);
3444 if Ada_Spec_Suffix.Kind = Single
3445 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3447 Get_Name_String (Ada_Spec_Suffix.Value);
3448 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3449 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3450 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3457 Default_Ada_Spec_Suffix);
3461 if Current_Verbosity = High then
3462 Write_Str (" Spec_Suffix = """);
3463 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3468 -- Check Body_Suffix
3471 Ada_Body_Suffix : constant Variable_Value :=
3475 In_Array => Data.Naming.Body_Suffix,
3476 In_Tree => In_Tree);
3479 if Ada_Body_Suffix.Kind = Single
3480 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3482 Get_Name_String (Ada_Body_Suffix.Value);
3483 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3484 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3485 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3492 Default_Ada_Body_Suffix);
3496 if Current_Verbosity = High then
3497 Write_Str (" Body_Suffix = """);
3498 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3503 -- Check Separate_Suffix
3506 Ada_Sep_Suffix : constant Variable_Value :=
3508 (Variable_Name => Name_Separate_Suffix,
3509 In_Variables => Naming.Decl.Attributes,
3510 In_Tree => In_Tree);
3513 if Ada_Sep_Suffix.Default then
3514 Data.Naming.Separate_Suffix :=
3515 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3518 Get_Name_String (Ada_Sep_Suffix.Value);
3520 if Name_Len = 0 then
3523 "Separate_Suffix cannot be empty",
3524 Ada_Sep_Suffix.Location);
3527 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3528 Data.Naming.Separate_Suffix := Name_Find;
3529 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3534 if Current_Verbosity = High then
3535 Write_Str (" Separate_Suffix = """);
3536 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3541 -- Check if Data.Naming is valid
3543 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3546 elsif not In_Configuration then
3548 -- Look into package Naming, if there is one
3550 if Naming_Id /= No_Package then
3551 Naming := In_Tree.Packages.Table (Naming_Id);
3553 if Current_Verbosity = High then
3554 Write_Line ("Checking package Naming.");
3557 -- We are now checking if attribute Dot_Replacement, Casing,
3558 -- and/or Separate_Suffix exist.
3560 -- For each attribute, if it does not exist, we do nothing,
3561 -- because we already have the default.
3562 -- Otherwise, for all unit-based languages, we put the declared
3563 -- value in the language config.
3566 Dot_Repl : constant Variable_Value :=
3568 (Name_Dot_Replacement,
3569 Naming.Decl.Attributes, In_Tree);
3570 Dot_Replacement : File_Name_Type := No_File;
3572 Casing_String : constant Variable_Value :=
3575 Naming.Decl.Attributes,
3577 Casing : Casing_Type;
3578 Casing_Defined : Boolean := False;
3580 Sep_Suffix : constant Variable_Value :=
3582 (Variable_Name => Name_Separate_Suffix,
3583 In_Variables => Naming.Decl.Attributes,
3584 In_Tree => In_Tree);
3585 Separate_Suffix : File_Name_Type := No_File;
3587 Lang_Id : Language_Index;
3589 -- Check attribute Dot_Replacement
3591 if not Dot_Repl.Default then
3592 Get_Name_String (Dot_Repl.Value);
3594 if Name_Len = 0 then
3597 "Dot_Replacement cannot be empty",
3601 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3602 Dot_Replacement := Name_Find;
3604 if Current_Verbosity = High then
3605 Write_Str (" Dot_Replacement = """);
3606 Write_Str (Get_Name_String (Dot_Replacement));
3613 -- Check attribute Casing
3615 if not Casing_String.Default then
3617 Casing_Image : constant String :=
3618 Get_Name_String (Casing_String.Value);
3621 Casing_Value : constant Casing_Type :=
3622 Value (Casing_Image);
3624 Casing := Casing_Value;
3625 Casing_Defined := True;
3627 if Current_Verbosity = High then
3628 Write_Str (" Casing = ");
3629 Write_Str (Image (Casing));
3636 when Constraint_Error =>
3637 if Casing_Image'Length = 0 then
3640 "Casing cannot be an empty string",
3641 Casing_String.Location);
3644 Name_Len := Casing_Image'Length;
3645 Name_Buffer (1 .. Name_Len) := Casing_Image;
3646 Err_Vars.Error_Msg_Name_1 := Name_Find;
3649 "%% is not a correct Casing",
3650 Casing_String.Location);
3655 if not Sep_Suffix.Default then
3656 Get_Name_String (Sep_Suffix.Value);
3658 if Name_Len = 0 then
3661 "Separate_Suffix cannot be empty",
3662 Sep_Suffix.Location);
3665 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3666 Separate_Suffix := Name_Find;
3668 if Current_Verbosity = High then
3669 Write_Str (" Separate_Suffix = """);
3670 Write_Str (Get_Name_String (Separate_Suffix));
3677 -- For all unit based languages, if any, set the specified
3678 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3680 if Dot_Replacement /= No_File
3681 or else Casing_Defined
3682 or else Separate_Suffix /= No_File
3684 Lang_Id := Data.First_Language_Processing;
3685 while Lang_Id /= No_Language_Index loop
3686 if In_Tree.Languages_Data.Table
3687 (Lang_Id).Config.Kind = Unit_Based
3689 if Dot_Replacement /= No_File then
3690 In_Tree.Languages_Data.Table
3691 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3695 if Casing_Defined then
3696 In_Tree.Languages_Data.Table
3697 (Lang_Id).Config.Naming_Data.Casing := Casing;
3700 if Separate_Suffix /= No_File then
3701 In_Tree.Languages_Data.Table
3702 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3708 In_Tree.Languages_Data.Table (Lang_Id).Next;
3713 -- Next, get the spec and body suffixes
3716 Suffix : Variable_Value;
3717 Lang_Id : Language_Index;
3721 Lang_Id := Data.First_Language_Processing;
3722 while Lang_Id /= No_Language_Index loop
3723 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3729 Attribute_Or_Array_Name => Name_Spec_Suffix,
3730 In_Package => Naming_Id,
3731 In_Tree => In_Tree);
3733 if Suffix = Nil_Variable_Value then
3736 Attribute_Or_Array_Name => Name_Specification_Suffix,
3737 In_Package => Naming_Id,
3738 In_Tree => In_Tree);
3741 if Suffix /= Nil_Variable_Value then
3742 In_Tree.Languages_Data.Table (Lang_Id).
3743 Config.Naming_Data.Spec_Suffix :=
3744 File_Name_Type (Suffix.Value);
3751 Attribute_Or_Array_Name => Name_Body_Suffix,
3752 In_Package => Naming_Id,
3753 In_Tree => In_Tree);
3755 if Suffix = Nil_Variable_Value then
3758 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3759 In_Package => Naming_Id,
3760 In_Tree => In_Tree);
3763 if Suffix /= Nil_Variable_Value then
3764 In_Tree.Languages_Data.Table (Lang_Id).
3765 Config.Naming_Data.Body_Suffix :=
3766 File_Name_Type (Suffix.Value);
3769 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3773 -- Get the exceptions for file based languages
3775 Get_Exceptions (Spec);
3776 Get_Exceptions (Impl);
3778 -- Get the exceptions for unit based languages
3780 Get_Unit_Exceptions (Spec);
3781 Get_Unit_Exceptions (Impl);
3785 end Check_Naming_Schemes;
3787 ------------------------------
3788 -- Check_Library_Attributes --
3789 ------------------------------
3791 procedure Check_Library_Attributes
3792 (Project : Project_Id;
3793 In_Tree : Project_Tree_Ref;
3794 Current_Dir : String;
3795 Data : in out Project_Data)
3797 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3799 Lib_Dir : constant Prj.Variable_Value :=
3801 (Snames.Name_Library_Dir, Attributes, In_Tree);
3803 Lib_Name : constant Prj.Variable_Value :=
3805 (Snames.Name_Library_Name, Attributes, In_Tree);
3807 Lib_Version : constant Prj.Variable_Value :=
3809 (Snames.Name_Library_Version, Attributes, In_Tree);
3811 Lib_ALI_Dir : constant Prj.Variable_Value :=
3813 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3815 The_Lib_Kind : constant Prj.Variable_Value :=
3817 (Snames.Name_Library_Kind, Attributes, In_Tree);
3819 Imported_Project_List : Project_List := Empty_Project_List;
3821 Continuation : String_Access := No_Continuation_String'Access;
3823 Support_For_Libraries : Library_Support;
3825 Library_Directory_Present : Boolean;
3827 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3828 -- Check if an imported or extended project if also a library project
3834 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3835 Proj_Data : Project_Data;
3840 if Proj /= No_Project then
3841 Proj_Data := In_Tree.Projects.Table (Proj);
3843 if not Proj_Data.Library then
3845 -- The only not library projects that are OK are those that
3846 -- have no sources. However, header files from non-Ada
3847 -- languages are OK, as there is nothing to compile.
3849 Src_Id := Proj_Data.First_Source;
3850 while Src_Id /= No_Source loop
3851 Src := In_Tree.Sources.Table (Src_Id);
3853 exit when Src.Lang_Kind /= File_Based
3854 or else Src.Kind /= Spec;
3856 Src_Id := Src.Next_In_Project;
3859 if Src_Id /= No_Source then
3860 Error_Msg_Name_1 := Data.Name;
3861 Error_Msg_Name_2 := Proj_Data.Name;
3864 if Data.Library_Kind /= Static then
3868 "shared library project %% cannot extend " &
3869 "project %% that is not a library project",
3871 Continuation := Continuation_String'Access;
3874 elsif Data.Library_Kind /= Static then
3878 "shared library project %% cannot import project %% " &
3879 "that is not a shared library project",
3881 Continuation := Continuation_String'Access;
3885 elsif Data.Library_Kind /= Static and then
3886 Proj_Data.Library_Kind = Static
3888 Error_Msg_Name_1 := Data.Name;
3889 Error_Msg_Name_2 := Proj_Data.Name;
3895 "shared library project %% cannot extend static " &
3896 "library project %%",
3903 "shared library project %% cannot import static " &
3904 "library project %%",
3908 Continuation := Continuation_String'Access;
3913 -- Start of processing for Check_Library_Attributes
3916 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3918 -- Special case of extending project
3920 if Data.Extends /= No_Project then
3922 Extended_Data : constant Project_Data :=
3923 In_Tree.Projects.Table (Data.Extends);
3926 -- If the project extended is a library project, we inherit the
3927 -- library name, if it is not redefined; we check that the library
3928 -- directory is specified.
3930 if Extended_Data.Library then
3931 if Data.Qualifier = Standard then
3934 "a standard project cannot extend a library project",
3938 if Lib_Name.Default then
3939 Data.Library_Name := Extended_Data.Library_Name;
3942 if Lib_Dir.Default then
3943 if not Data.Virtual then
3946 "a project extending a library project must " &
3947 "specify an attribute Library_Dir",
3951 -- For a virtual project extending a library project,
3952 -- inherit library directory.
3954 Data.Library_Dir := Extended_Data.Library_Dir;
3955 Data.Display_Library_Dir :=
3956 Extended_Data.Display_Library_Dir;
3957 Library_Directory_Present := True;
3965 pragma Assert (Lib_Name.Kind = Single);
3967 if Lib_Name.Value = Empty_String then
3968 if Current_Verbosity = High
3969 and then Data.Library_Name = No_Name
3971 Write_Line ("No library name");
3975 -- There is no restriction on the syntax of library names
3977 Data.Library_Name := Lib_Name.Value;
3980 if Data.Library_Name /= No_Name then
3981 if Current_Verbosity = High then
3982 Write_Str ("Library name = """);
3983 Write_Str (Get_Name_String (Data.Library_Name));
3987 pragma Assert (Lib_Dir.Kind = Single);
3989 if not Library_Directory_Present then
3990 if Current_Verbosity = High then
3991 Write_Line ("No library directory");
3995 -- Find path name (unless inherited), check that it is a directory
3997 if Data.Library_Dir = No_Path then
4001 File_Name_Type (Lib_Dir.Value),
4002 Data.Display_Directory,
4004 Data.Display_Library_Dir,
4005 Create => "library",
4006 Current_Dir => Current_Dir,
4007 Location => Lib_Dir.Location);
4010 if Data.Library_Dir = No_Path then
4012 -- Get the absolute name of the library directory that
4013 -- does not exist, to report an error.
4016 Dir_Name : constant String :=
4017 Get_Name_String (Lib_Dir.Value);
4020 if Is_Absolute_Path (Dir_Name) then
4021 Err_Vars.Error_Msg_File_1 :=
4022 File_Name_Type (Lib_Dir.Value);
4025 Get_Name_String (Data.Display_Directory);
4027 if Name_Buffer (Name_Len) /= Directory_Separator then
4028 Name_Len := Name_Len + 1;
4029 Name_Buffer (Name_Len) := Directory_Separator;
4033 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
4035 Name_Len := Name_Len + Dir_Name'Length;
4036 Err_Vars.Error_Msg_File_1 := Name_Find;
4043 "library directory { does not exist",
4047 -- The library directory cannot be the same as the Object
4050 elsif Data.Library_Dir = Data.Object_Directory then
4053 "library directory cannot be the same " &
4054 "as object directory",
4056 Data.Library_Dir := No_Path;
4057 Data.Display_Library_Dir := No_Path;
4061 OK : Boolean := True;
4062 Dirs_Id : String_List_Id;
4063 Dir_Elem : String_Element;
4066 -- The library directory cannot be the same as a source
4067 -- directory of the current project.
4069 Dirs_Id := Data.Source_Dirs;
4070 while Dirs_Id /= Nil_String loop
4071 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4072 Dirs_Id := Dir_Elem.Next;
4074 if Data.Library_Dir = Path_Name_Type (Dir_Elem.Value) then
4075 Err_Vars.Error_Msg_File_1 :=
4076 File_Name_Type (Dir_Elem.Value);
4079 "library directory cannot be the same " &
4080 "as source directory {",
4089 -- The library directory cannot be the same as a source
4090 -- directory of another project either.
4093 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
4094 if Pid /= Project then
4095 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
4097 Dir_Loop : while Dirs_Id /= Nil_String loop
4099 In_Tree.String_Elements.Table (Dirs_Id);
4100 Dirs_Id := Dir_Elem.Next;
4102 if Data.Library_Dir =
4103 Path_Name_Type (Dir_Elem.Value)
4105 Err_Vars.Error_Msg_File_1 :=
4106 File_Name_Type (Dir_Elem.Value);
4107 Err_Vars.Error_Msg_Name_1 :=
4108 In_Tree.Projects.Table (Pid).Name;
4112 "library directory cannot be the same " &
4113 "as source directory { of project %%",
4120 end loop Project_Loop;
4124 Data.Library_Dir := No_Path;
4125 Data.Display_Library_Dir := No_Path;
4127 elsif Current_Verbosity = High then
4129 -- Display the Library directory in high verbosity
4131 Write_Str ("Library directory =""");
4132 Write_Str (Get_Name_String (Data.Display_Library_Dir));
4142 Data.Library_Dir /= No_Path
4144 Data.Library_Name /= No_Name;
4146 if Data.Extends = No_Project then
4147 case Data.Qualifier is
4149 if Data.Library then
4152 "a standard project cannot be a library project",
4157 if not Data.Library then
4160 "not a library project",
4170 if Data.Library then
4171 if Get_Mode = Multi_Language then
4172 Support_For_Libraries := Data.Config.Lib_Support;
4175 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
4178 if Support_For_Libraries = Prj.None then
4181 "?libraries are not supported on this platform",
4183 Data.Library := False;
4186 if Lib_ALI_Dir.Value = Empty_String then
4187 if Current_Verbosity = High then
4188 Write_Line ("No library ALI directory specified");
4190 Data.Library_ALI_Dir := Data.Library_Dir;
4191 Data.Display_Library_ALI_Dir := Data.Display_Library_Dir;
4194 -- Find path name, check that it is a directory
4199 File_Name_Type (Lib_ALI_Dir.Value),
4200 Data.Display_Directory,
4201 Data.Library_ALI_Dir,
4202 Data.Display_Library_ALI_Dir,
4203 Create => "library ALI",
4204 Current_Dir => Current_Dir,
4205 Location => Lib_ALI_Dir.Location);
4207 if Data.Library_ALI_Dir = No_Path then
4209 -- Get the absolute name of the library ALI directory that
4210 -- does not exist, to report an error.
4213 Dir_Name : constant String :=
4214 Get_Name_String (Lib_ALI_Dir.Value);
4217 if Is_Absolute_Path (Dir_Name) then
4218 Err_Vars.Error_Msg_File_1 :=
4219 File_Name_Type (Lib_Dir.Value);
4222 Get_Name_String (Data.Display_Directory);
4224 if Name_Buffer (Name_Len) /= Directory_Separator then
4225 Name_Len := Name_Len + 1;
4226 Name_Buffer (Name_Len) := Directory_Separator;
4230 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
4232 Name_Len := Name_Len + Dir_Name'Length;
4233 Err_Vars.Error_Msg_File_1 := Name_Find;
4240 "library 'A'L'I directory { does not exist",
4241 Lib_ALI_Dir.Location);
4245 if Data.Library_ALI_Dir /= Data.Library_Dir then
4247 -- The library ALI directory cannot be the same as the
4248 -- Object directory.
4250 if Data.Library_ALI_Dir = Data.Object_Directory then
4253 "library 'A'L'I directory cannot be the same " &
4254 "as object directory",
4255 Lib_ALI_Dir.Location);
4256 Data.Library_ALI_Dir := No_Path;
4257 Data.Display_Library_ALI_Dir := No_Path;
4261 OK : Boolean := True;
4262 Dirs_Id : String_List_Id;
4263 Dir_Elem : String_Element;
4266 -- The library ALI directory cannot be the same as
4267 -- a source directory of the current project.
4269 Dirs_Id := Data.Source_Dirs;
4270 while Dirs_Id /= Nil_String loop
4271 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4272 Dirs_Id := Dir_Elem.Next;
4274 if Data.Library_ALI_Dir =
4275 Path_Name_Type (Dir_Elem.Value)
4277 Err_Vars.Error_Msg_File_1 :=
4278 File_Name_Type (Dir_Elem.Value);
4281 "library 'A'L'I directory cannot be " &
4282 "the same as source directory {",
4283 Lib_ALI_Dir.Location);
4291 -- The library ALI directory cannot be the same as
4292 -- a source directory of another project either.
4296 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4298 if Pid /= Project then
4300 In_Tree.Projects.Table (Pid).Source_Dirs;
4303 while Dirs_Id /= Nil_String loop
4305 In_Tree.String_Elements.Table (Dirs_Id);
4306 Dirs_Id := Dir_Elem.Next;
4308 if Data.Library_ALI_Dir =
4309 Path_Name_Type (Dir_Elem.Value)
4311 Err_Vars.Error_Msg_File_1 :=
4312 File_Name_Type (Dir_Elem.Value);
4313 Err_Vars.Error_Msg_Name_1 :=
4314 In_Tree.Projects.Table (Pid).Name;
4318 "library 'A'L'I directory cannot " &
4319 "be the same as source directory " &
4321 Lib_ALI_Dir.Location);
4323 exit ALI_Project_Loop;
4325 end loop ALI_Dir_Loop;
4327 end loop ALI_Project_Loop;
4331 Data.Library_ALI_Dir := No_Path;
4332 Data.Display_Library_ALI_Dir := No_Path;
4334 elsif Current_Verbosity = High then
4336 -- Display the Library ALI directory in high
4339 Write_Str ("Library ALI directory =""");
4341 (Get_Name_String (Data.Display_Library_ALI_Dir));
4349 pragma Assert (Lib_Version.Kind = Single);
4351 if Lib_Version.Value = Empty_String then
4352 if Current_Verbosity = High then
4353 Write_Line ("No library version specified");
4357 Data.Lib_Internal_Name := Lib_Version.Value;
4360 pragma Assert (The_Lib_Kind.Kind = Single);
4362 if The_Lib_Kind.Value = Empty_String then
4363 if Current_Verbosity = High then
4364 Write_Line ("No library kind specified");
4368 Get_Name_String (The_Lib_Kind.Value);
4371 Kind_Name : constant String :=
4372 To_Lower (Name_Buffer (1 .. Name_Len));
4374 OK : Boolean := True;
4377 if Kind_Name = "static" then
4378 Data.Library_Kind := Static;
4380 elsif Kind_Name = "dynamic" then
4381 Data.Library_Kind := Dynamic;
4383 elsif Kind_Name = "relocatable" then
4384 Data.Library_Kind := Relocatable;
4389 "illegal value for Library_Kind",
4390 The_Lib_Kind.Location);
4394 if Current_Verbosity = High and then OK then
4395 Write_Str ("Library kind = ");
4396 Write_Line (Kind_Name);
4399 if Data.Library_Kind /= Static and then
4400 Support_For_Libraries = Prj.Static_Only
4404 "only static libraries are supported " &
4406 The_Lib_Kind.Location);
4407 Data.Library := False;
4412 if Data.Library then
4413 if Current_Verbosity = High then
4414 Write_Line ("This is a library project file");
4417 if Get_Mode = Multi_Language then
4418 Check_Library (Data.Extends, Extends => True);
4420 Imported_Project_List := Data.Imported_Projects;
4421 while Imported_Project_List /= Empty_Project_List loop
4423 (In_Tree.Project_Lists.Table
4424 (Imported_Project_List).Project,
4426 Imported_Project_List :=
4427 In_Tree.Project_Lists.Table
4428 (Imported_Project_List).Next;
4436 if Data.Extends /= No_Project then
4437 In_Tree.Projects.Table (Data.Extends).Library := False;
4439 end Check_Library_Attributes;
4441 --------------------------
4442 -- Check_Package_Naming --
4443 --------------------------
4445 procedure Check_Package_Naming
4446 (Project : Project_Id;
4447 In_Tree : Project_Tree_Ref;
4448 Data : in out Project_Data)
4450 Naming_Id : constant Package_Id :=
4451 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4453 Naming : Package_Element;
4456 -- If there is a package Naming, we will put in Data.Naming
4457 -- what is in this package Naming.
4459 if Naming_Id /= No_Package then
4460 Naming := In_Tree.Packages.Table (Naming_Id);
4462 if Current_Verbosity = High then
4463 Write_Line ("Checking ""Naming"".");
4466 -- Check Spec_Suffix
4469 Spec_Suffixs : Array_Element_Id :=
4475 Suffix : Array_Element_Id;
4476 Element : Array_Element;
4477 Suffix2 : Array_Element_Id;
4480 -- If some suffixes have been specified, we make sure that
4481 -- for each language for which a default suffix has been
4482 -- specified, there is a suffix specified, either the one
4483 -- in the project file or if there were none, the default.
4485 if Spec_Suffixs /= No_Array_Element then
4486 Suffix := Data.Naming.Spec_Suffix;
4488 while Suffix /= No_Array_Element loop
4490 In_Tree.Array_Elements.Table (Suffix);
4491 Suffix2 := Spec_Suffixs;
4493 while Suffix2 /= No_Array_Element loop
4494 exit when In_Tree.Array_Elements.Table
4495 (Suffix2).Index = Element.Index;
4496 Suffix2 := In_Tree.Array_Elements.Table
4500 -- There is a registered default suffix, but no
4501 -- suffix specified in the project file.
4502 -- Add the default to the array.
4504 if Suffix2 = No_Array_Element then
4505 Array_Element_Table.Increment_Last
4506 (In_Tree.Array_Elements);
4507 In_Tree.Array_Elements.Table
4508 (Array_Element_Table.Last
4509 (In_Tree.Array_Elements)) :=
4510 (Index => Element.Index,
4511 Src_Index => Element.Src_Index,
4512 Index_Case_Sensitive => False,
4513 Value => Element.Value,
4514 Next => Spec_Suffixs);
4515 Spec_Suffixs := Array_Element_Table.Last
4516 (In_Tree.Array_Elements);
4519 Suffix := Element.Next;
4522 -- Put the resulting array as the specification suffixes
4524 Data.Naming.Spec_Suffix := Spec_Suffixs;
4529 Current : Array_Element_Id;
4530 Element : Array_Element;
4533 Current := Data.Naming.Spec_Suffix;
4534 while Current /= No_Array_Element loop
4535 Element := In_Tree.Array_Elements.Table (Current);
4536 Get_Name_String (Element.Value.Value);
4538 if Name_Len = 0 then
4541 "Spec_Suffix cannot be empty",
4542 Element.Value.Location);
4545 In_Tree.Array_Elements.Table (Current) := Element;
4546 Current := Element.Next;
4550 -- Check Body_Suffix
4553 Impl_Suffixs : Array_Element_Id :=
4559 Suffix : Array_Element_Id;
4560 Element : Array_Element;
4561 Suffix2 : Array_Element_Id;
4564 -- If some suffixes have been specified, we make sure that
4565 -- for each language for which a default suffix has been
4566 -- specified, there is a suffix specified, either the one
4567 -- in the project file or if there were none, the default.
4569 if Impl_Suffixs /= No_Array_Element then
4570 Suffix := Data.Naming.Body_Suffix;
4571 while Suffix /= No_Array_Element loop
4573 In_Tree.Array_Elements.Table (Suffix);
4575 Suffix2 := Impl_Suffixs;
4576 while Suffix2 /= No_Array_Element loop
4577 exit when In_Tree.Array_Elements.Table
4578 (Suffix2).Index = Element.Index;
4579 Suffix2 := In_Tree.Array_Elements.Table
4583 -- There is a registered default suffix, but no suffix was
4584 -- specified in the project file. Add default to the array.
4586 if Suffix2 = No_Array_Element then
4587 Array_Element_Table.Increment_Last
4588 (In_Tree.Array_Elements);
4589 In_Tree.Array_Elements.Table
4590 (Array_Element_Table.Last
4591 (In_Tree.Array_Elements)) :=
4592 (Index => Element.Index,
4593 Src_Index => Element.Src_Index,
4594 Index_Case_Sensitive => False,
4595 Value => Element.Value,
4596 Next => Impl_Suffixs);
4597 Impl_Suffixs := Array_Element_Table.Last
4598 (In_Tree.Array_Elements);
4601 Suffix := Element.Next;
4604 -- Put the resulting array as the implementation suffixes
4606 Data.Naming.Body_Suffix := Impl_Suffixs;
4611 Current : Array_Element_Id;
4612 Element : Array_Element;
4615 Current := Data.Naming.Body_Suffix;
4616 while Current /= No_Array_Element loop
4617 Element := In_Tree.Array_Elements.Table (Current);
4618 Get_Name_String (Element.Value.Value);
4620 if Name_Len = 0 then
4623 "Body_Suffix cannot be empty",
4624 Element.Value.Location);
4627 In_Tree.Array_Elements.Table (Current) := Element;
4628 Current := Element.Next;
4632 -- Get the exceptions, if any
4634 Data.Naming.Specification_Exceptions :=
4636 (Name_Specification_Exceptions,
4637 In_Arrays => Naming.Decl.Arrays,
4638 In_Tree => In_Tree);
4640 Data.Naming.Implementation_Exceptions :=
4642 (Name_Implementation_Exceptions,
4643 In_Arrays => Naming.Decl.Arrays,
4644 In_Tree => In_Tree);
4646 end Check_Package_Naming;
4648 ---------------------------------
4649 -- Check_Programming_Languages --
4650 ---------------------------------
4652 procedure Check_Programming_Languages
4653 (In_Tree : Project_Tree_Ref;
4654 Project : Project_Id;
4655 Data : in out Project_Data)
4657 Languages : Variable_Value := Nil_Variable_Value;
4658 Def_Lang : Variable_Value := Nil_Variable_Value;
4659 Def_Lang_Id : Name_Id;
4662 Data.First_Language_Processing := No_Language_Index;
4664 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4667 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4668 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4669 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4671 if Data.Source_Dirs /= Nil_String then
4673 -- Check if languages are specified in this project
4675 if Languages.Default then
4677 -- Attribute Languages is not specified. So, it defaults to
4678 -- a project of the default language only.
4680 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4681 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4683 -- In Ada_Only mode, the default language is Ada
4685 if Get_Mode = Ada_Only then
4686 In_Tree.Name_Lists.Table (Data.Languages) :=
4687 (Name => Name_Ada, Next => No_Name_List);
4689 -- Attribute Languages is not specified. So, it defaults to
4690 -- a project of language Ada only.
4692 Data.Langs (Ada_Language_Index) := True;
4694 -- No sources of languages other than Ada
4696 Data.Other_Sources_Present := False;
4699 -- If the configuration file does not define a language either
4701 if Def_Lang.Default then
4702 if not Default_Language_Is_Ada then
4706 "no languages defined for this project",
4708 Def_Lang_Id := No_Name;
4710 Def_Lang_Id := Name_Ada;
4714 -- ??? Are we supporting a single default language in the
4715 -- configuration file ?
4716 Get_Name_String (Def_Lang.Value);
4717 To_Lower (Name_Buffer (1 .. Name_Len));
4718 Def_Lang_Id := Name_Find;
4721 if Def_Lang_Id /= No_Name then
4722 In_Tree.Name_Lists.Table (Data.Languages) :=
4723 (Name => Def_Lang_Id, Next => No_Name_List);
4725 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4727 Data.First_Language_Processing :=
4728 Language_Data_Table.Last (In_Tree.Languages_Data);
4729 In_Tree.Languages_Data.Table
4730 (Data.First_Language_Processing) := No_Language_Data;
4731 In_Tree.Languages_Data.Table
4732 (Data.First_Language_Processing).Name := Def_Lang_Id;
4733 Get_Name_String (Def_Lang_Id);
4734 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4735 In_Tree.Languages_Data.Table
4736 (Data.First_Language_Processing).Display_Name := Name_Find;
4738 if Def_Lang_Id = Name_Ada then
4739 In_Tree.Languages_Data.Table
4740 (Data.First_Language_Processing).Config.Kind
4742 In_Tree.Languages_Data.Table
4743 (Data.First_Language_Processing).Config.Dependency_Kind
4745 Data.Unit_Based_Language_Name := Name_Ada;
4746 Data.Unit_Based_Language_Index :=
4747 Data.First_Language_Processing;
4749 In_Tree.Languages_Data.Table
4750 (Data.First_Language_Processing).Config.Kind
4758 Current : String_List_Id := Languages.Values;
4759 Element : String_Element;
4760 Lang_Name : Name_Id;
4761 Index : Language_Index;
4762 Lang_Data : Language_Data;
4763 NL_Id : Name_List_Index := No_Name_List;
4766 if Get_Mode = Ada_Only then
4768 -- Assume that there is no language specified yet
4770 Data.Other_Sources_Present := False;
4771 Data.Ada_Sources_Present := False;
4774 -- If there are no languages declared, there are no sources
4776 if Current = Nil_String then
4777 Data.Source_Dirs := Nil_String;
4779 if Data.Qualifier = Standard then
4783 "a standard project cannot have no language declared",
4784 Languages.Location);
4788 -- Look through all the languages specified in attribute
4791 while Current /= Nil_String loop
4793 In_Tree.String_Elements.Table (Current);
4794 Get_Name_String (Element.Value);
4795 To_Lower (Name_Buffer (1 .. Name_Len));
4796 Lang_Name := Name_Find;
4798 NL_Id := Data.Languages;
4799 while NL_Id /= No_Name_List loop
4801 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4802 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4805 if NL_Id = No_Name_List then
4806 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4808 if Data.Languages = No_Name_List then
4810 Name_List_Table.Last (In_Tree.Name_Lists);
4813 NL_Id := Data.Languages;
4814 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4817 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4820 In_Tree.Name_Lists.Table (NL_Id).Next :=
4821 Name_List_Table.Last (In_Tree.Name_Lists);
4824 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4825 In_Tree.Name_Lists.Table (NL_Id) :=
4826 (Lang_Name, No_Name_List);
4828 if Get_Mode = Ada_Only then
4829 Index := Language_Indexes.Get (Lang_Name);
4831 if Index = No_Language_Index then
4832 Add_Language_Name (Lang_Name);
4833 Index := Last_Language_Index;
4836 Set (Index, True, Data, In_Tree);
4837 Set (Language_Processing =>
4838 Default_Language_Processing_Data,
4839 For_Language => Index,
4841 In_Tree => In_Tree);
4843 if Index = Ada_Language_Index then
4844 Data.Ada_Sources_Present := True;
4847 Data.Other_Sources_Present := True;
4851 Language_Data_Table.Increment_Last
4852 (In_Tree.Languages_Data);
4854 Language_Data_Table.Last (In_Tree.Languages_Data);
4855 Lang_Data.Name := Lang_Name;
4856 Lang_Data.Display_Name := Element.Value;
4857 Lang_Data.Next := Data.First_Language_Processing;
4859 if Lang_Name = Name_Ada then
4860 Lang_Data.Config.Kind := Unit_Based;
4861 Lang_Data.Config.Dependency_Kind := ALI_File;
4862 Data.Unit_Based_Language_Name := Name_Ada;
4863 Data.Unit_Based_Language_Index := Index;
4866 Lang_Data.Config.Kind := File_Based;
4867 Lang_Data.Config.Dependency_Kind := None;
4870 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4871 Data.First_Language_Processing := Index;
4875 Current := Element.Next;
4881 end Check_Programming_Languages;
4887 function Check_Project
4889 Root_Project : Project_Id;
4890 In_Tree : Project_Tree_Ref;
4891 Extending : Boolean) return Boolean
4894 if P = Root_Project then
4897 elsif Extending then
4899 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4902 while Data.Extends /= No_Project loop
4903 if P = Data.Extends then
4907 Data := In_Tree.Projects.Table (Data.Extends);
4915 -------------------------------
4916 -- Check_Stand_Alone_Library --
4917 -------------------------------
4919 procedure Check_Stand_Alone_Library
4920 (Project : Project_Id;
4921 In_Tree : Project_Tree_Ref;
4922 Data : in out Project_Data;
4923 Current_Dir : String;
4924 Extending : Boolean)
4926 Lib_Interfaces : constant Prj.Variable_Value :=
4928 (Snames.Name_Library_Interface,
4929 Data.Decl.Attributes,
4932 Lib_Auto_Init : constant Prj.Variable_Value :=
4934 (Snames.Name_Library_Auto_Init,
4935 Data.Decl.Attributes,
4938 Lib_Src_Dir : constant Prj.Variable_Value :=
4940 (Snames.Name_Library_Src_Dir,
4941 Data.Decl.Attributes,
4944 Lib_Symbol_File : constant Prj.Variable_Value :=
4946 (Snames.Name_Library_Symbol_File,
4947 Data.Decl.Attributes,
4950 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4952 (Snames.Name_Library_Symbol_Policy,
4953 Data.Decl.Attributes,
4956 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4958 (Snames.Name_Library_Reference_Symbol_File,
4959 Data.Decl.Attributes,
4962 Auto_Init_Supported : Boolean;
4963 OK : Boolean := True;
4965 Next_Proj : Project_Id;
4968 if Get_Mode = Multi_Language then
4969 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4971 Auto_Init_Supported :=
4972 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4975 pragma Assert (Lib_Interfaces.Kind = List);
4977 -- It is a stand-alone library project file if attribute
4978 -- Library_Interface is defined.
4980 if not Lib_Interfaces.Default then
4981 SAL_Library : declare
4982 Interfaces : String_List_Id := Lib_Interfaces.Values;
4983 Interface_ALIs : String_List_Id := Nil_String;
4985 The_Unit_Id : Unit_Index;
4986 The_Unit_Data : Unit_Data;
4988 procedure Add_ALI_For (Source : File_Name_Type);
4989 -- Add an ALI file name to the list of Interface ALIs
4995 procedure Add_ALI_For (Source : File_Name_Type) is
4997 Get_Name_String (Source);
5000 ALI : constant String :=
5001 ALI_File_Name (Name_Buffer (1 .. Name_Len));
5002 ALI_Name_Id : Name_Id;
5005 Name_Len := ALI'Length;
5006 Name_Buffer (1 .. Name_Len) := ALI;
5007 ALI_Name_Id := Name_Find;
5009 String_Element_Table.Increment_Last
5010 (In_Tree.String_Elements);
5011 In_Tree.String_Elements.Table
5012 (String_Element_Table.Last
5013 (In_Tree.String_Elements)) :=
5014 (Value => ALI_Name_Id,
5016 Display_Value => ALI_Name_Id,
5018 In_Tree.String_Elements.Table
5019 (Interfaces).Location,
5021 Next => Interface_ALIs);
5022 Interface_ALIs := String_Element_Table.Last
5023 (In_Tree.String_Elements);
5027 -- Start of processing for SAL_Library
5030 Data.Standalone_Library := True;
5032 -- Library_Interface cannot be an empty list
5034 if Interfaces = Nil_String then
5037 "Library_Interface cannot be an empty list",
5038 Lib_Interfaces.Location);
5041 -- Process each unit name specified in the attribute
5042 -- Library_Interface.
5044 while Interfaces /= Nil_String loop
5046 (In_Tree.String_Elements.Table (Interfaces).Value);
5047 To_Lower (Name_Buffer (1 .. Name_Len));
5049 if Name_Len = 0 then
5052 "an interface cannot be an empty string",
5053 In_Tree.String_Elements.Table (Interfaces).Location);
5057 Error_Msg_Name_1 := Unit;
5059 if Get_Mode = Ada_Only then
5061 Units_Htable.Get (In_Tree.Units_HT, Unit);
5063 if The_Unit_Id = No_Unit_Index then
5067 In_Tree.String_Elements.Table
5068 (Interfaces).Location);
5071 -- Check that the unit is part of the project
5074 In_Tree.Units.Table (The_Unit_Id);
5076 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
5077 and then The_Unit_Data.File_Names (Body_Part).Path /=
5081 (The_Unit_Data.File_Names (Body_Part).Project,
5082 Project, In_Tree, Extending)
5084 -- There is a body for this unit.
5085 -- If there is no spec, we need to check
5086 -- that it is not a subunit.
5088 if The_Unit_Data.File_Names
5089 (Specification).Name = No_File
5092 Src_Ind : Source_File_Index;
5095 Src_Ind := Sinput.P.Load_Project_File
5097 (The_Unit_Data.File_Names
5100 if Sinput.P.Source_File_Is_Subunit
5105 "%% is a subunit; " &
5106 "it cannot be an interface",
5108 String_Elements.Table
5109 (Interfaces).Location);
5114 -- The unit is not a subunit, so we add
5115 -- to the Interface ALIs the ALI file
5116 -- corresponding to the body.
5119 (The_Unit_Data.File_Names (Body_Part).Name);
5124 "%% is not an unit of this project",
5125 In_Tree.String_Elements.Table
5126 (Interfaces).Location);
5129 elsif The_Unit_Data.File_Names
5130 (Specification).Name /= No_File
5131 and then The_Unit_Data.File_Names
5132 (Specification).Path /= Slash
5133 and then Check_Project
5134 (The_Unit_Data.File_Names
5135 (Specification).Project,
5136 Project, In_Tree, Extending)
5139 -- The unit is part of the project, it has
5140 -- a spec, but no body. We add to the Interface
5141 -- ALIs the ALI file corresponding to the spec.
5144 (The_Unit_Data.File_Names (Specification).Name);
5149 "%% is not an unit of this project",
5150 In_Tree.String_Elements.Table
5151 (Interfaces).Location);
5156 -- Multi_Language mode
5158 Next_Proj := Data.Extends;
5159 Source := Data.First_Source;
5162 while Source /= No_Source and then
5163 In_Tree.Sources.Table (Source).Unit /= Unit
5166 In_Tree.Sources.Table (Source).Next_In_Project;
5169 exit when Source /= No_Source or else
5170 Next_Proj = No_Project;
5173 In_Tree.Projects.Table (Next_Proj).First_Source;
5175 In_Tree.Projects.Table (Next_Proj).Extends;
5178 if Source /= No_Source then
5179 if In_Tree.Sources.Table (Source).Kind = Sep then
5180 Source := No_Source;
5182 elsif In_Tree.Sources.Table (Source).Kind = Spec
5184 In_Tree.Sources.Table (Source).Other_Part /=
5187 Source := In_Tree.Sources.Table (Source).Other_Part;
5191 if Source /= No_Source then
5192 if In_Tree.Sources.Table (Source).Project /= Project
5196 In_Tree.Sources.Table (Source).Project,
5199 Source := No_Source;
5203 if Source = No_Source then
5206 "%% is not an unit of this project",
5207 In_Tree.String_Elements.Table
5208 (Interfaces).Location);
5211 if In_Tree.Sources.Table (Source).Kind = Spec and then
5212 In_Tree.Sources.Table (Source).Other_Part /=
5216 In_Tree.Sources.Table (Source).Other_Part;
5219 String_Element_Table.Increment_Last
5220 (In_Tree.String_Elements);
5221 In_Tree.String_Elements.Table
5222 (String_Element_Table.Last
5223 (In_Tree.String_Elements)) :=
5225 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5228 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5230 In_Tree.String_Elements.Table
5231 (Interfaces).Location,
5233 Next => Interface_ALIs);
5234 Interface_ALIs := String_Element_Table.Last
5235 (In_Tree.String_Elements);
5243 In_Tree.String_Elements.Table (Interfaces).Next;
5246 -- Put the list of Interface ALIs in the project data
5248 Data.Lib_Interface_ALIs := Interface_ALIs;
5250 -- Check value of attribute Library_Auto_Init and set
5251 -- Lib_Auto_Init accordingly.
5253 if Lib_Auto_Init.Default then
5255 -- If no attribute Library_Auto_Init is declared, then set auto
5256 -- init only if it is supported.
5258 Data.Lib_Auto_Init := Auto_Init_Supported;
5261 Get_Name_String (Lib_Auto_Init.Value);
5262 To_Lower (Name_Buffer (1 .. Name_Len));
5264 if Name_Buffer (1 .. Name_Len) = "false" then
5265 Data.Lib_Auto_Init := False;
5267 elsif Name_Buffer (1 .. Name_Len) = "true" then
5268 if Auto_Init_Supported then
5269 Data.Lib_Auto_Init := True;
5272 -- Library_Auto_Init cannot be "true" if auto init is not
5277 "library auto init not supported " &
5279 Lib_Auto_Init.Location);
5285 "invalid value for attribute Library_Auto_Init",
5286 Lib_Auto_Init.Location);
5291 -- If attribute Library_Src_Dir is defined and not the empty string,
5292 -- check if the directory exist and is not the object directory or
5293 -- one of the source directories. This is the directory where copies
5294 -- of the interface sources will be copied. Note that this directory
5295 -- may be the library directory.
5297 if Lib_Src_Dir.Value /= Empty_String then
5299 Dir_Id : constant File_Name_Type :=
5300 File_Name_Type (Lib_Src_Dir.Value);
5307 Data.Display_Directory,
5308 Data.Library_Src_Dir,
5309 Data.Display_Library_Src_Dir,
5310 Create => "library source copy",
5311 Current_Dir => Current_Dir,
5312 Location => Lib_Src_Dir.Location);
5314 -- If directory does not exist, report an error
5316 if Data.Library_Src_Dir = No_Path then
5318 -- Get the absolute name of the library directory that does
5319 -- not exist, to report an error.
5322 Dir_Name : constant String :=
5323 Get_Name_String (Dir_Id);
5326 if Is_Absolute_Path (Dir_Name) then
5327 Err_Vars.Error_Msg_File_1 := Dir_Id;
5330 Get_Name_String (Data.Directory);
5332 if Name_Buffer (Name_Len) /=
5335 Name_Len := Name_Len + 1;
5336 Name_Buffer (Name_Len) :=
5337 Directory_Separator;
5342 Name_Len + Dir_Name'Length) :=
5344 Name_Len := Name_Len + Dir_Name'Length;
5345 Err_Vars.Error_Msg_Name_1 := Name_Find;
5350 Error_Msg_File_1 := Dir_Id;
5353 "Directory { does not exist",
5354 Lib_Src_Dir.Location);
5357 -- Report error if it is the same as the object directory
5359 elsif Data.Library_Src_Dir = Data.Object_Directory then
5362 "directory to copy interfaces cannot be " &
5363 "the object directory",
5364 Lib_Src_Dir.Location);
5365 Data.Library_Src_Dir := No_Path;
5369 Src_Dirs : String_List_Id;
5370 Src_Dir : String_Element;
5373 -- Interface copy directory cannot be one of the source
5374 -- directory of the current project.
5376 Src_Dirs := Data.Source_Dirs;
5377 while Src_Dirs /= Nil_String loop
5378 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5380 -- Report error if it is one of the source directories
5382 if Data.Library_Src_Dir =
5383 Path_Name_Type (Src_Dir.Value)
5387 "directory to copy interfaces cannot " &
5388 "be one of the source directories",
5389 Lib_Src_Dir.Location);
5390 Data.Library_Src_Dir := No_Path;
5394 Src_Dirs := Src_Dir.Next;
5397 if Data.Library_Src_Dir /= No_Path then
5399 -- It cannot be a source directory of any other
5402 Project_Loop : for Pid in 1 ..
5403 Project_Table.Last (In_Tree.Projects)
5406 In_Tree.Projects.Table (Pid).Source_Dirs;
5407 Dir_Loop : while Src_Dirs /= Nil_String loop
5409 In_Tree.String_Elements.Table (Src_Dirs);
5411 -- Report error if it is one of the source
5414 if Data.Library_Src_Dir =
5415 Path_Name_Type (Src_Dir.Value)
5418 File_Name_Type (Src_Dir.Value);
5420 In_Tree.Projects.Table (Pid).Name;
5423 "directory to copy interfaces cannot " &
5424 "be the same as source directory { of " &
5426 Lib_Src_Dir.Location);
5427 Data.Library_Src_Dir := No_Path;
5431 Src_Dirs := Src_Dir.Next;
5433 end loop Project_Loop;
5437 -- In high verbosity, if there is a valid Library_Src_Dir,
5438 -- display its path name.
5440 if Data.Library_Src_Dir /= No_Path
5441 and then Current_Verbosity = High
5443 Write_Str ("Directory to copy interfaces =""");
5444 Write_Str (Get_Name_String (Data.Library_Src_Dir));
5451 -- Check the symbol related attributes
5453 -- First, the symbol policy
5455 if not Lib_Symbol_Policy.Default then
5457 Value : constant String :=
5459 (Get_Name_String (Lib_Symbol_Policy.Value));
5462 -- Symbol policy must hove one of a limited number of values
5464 if Value = "autonomous" or else Value = "default" then
5465 Data.Symbol_Data.Symbol_Policy := Autonomous;
5467 elsif Value = "compliant" then
5468 Data.Symbol_Data.Symbol_Policy := Compliant;
5470 elsif Value = "controlled" then
5471 Data.Symbol_Data.Symbol_Policy := Controlled;
5473 elsif Value = "restricted" then
5474 Data.Symbol_Data.Symbol_Policy := Restricted;
5476 elsif Value = "direct" then
5477 Data.Symbol_Data.Symbol_Policy := Direct;
5482 "illegal value for Library_Symbol_Policy",
5483 Lib_Symbol_Policy.Location);
5488 -- If attribute Library_Symbol_File is not specified, symbol policy
5489 -- cannot be Restricted.
5491 if Lib_Symbol_File.Default then
5492 if Data.Symbol_Data.Symbol_Policy = Restricted then
5495 "Library_Symbol_File needs to be defined when " &
5496 "symbol policy is Restricted",
5497 Lib_Symbol_Policy.Location);
5501 -- Library_Symbol_File is defined
5503 Data.Symbol_Data.Symbol_File :=
5504 Path_Name_Type (Lib_Symbol_File.Value);
5506 Get_Name_String (Lib_Symbol_File.Value);
5508 if Name_Len = 0 then
5511 "symbol file name cannot be an empty string",
5512 Lib_Symbol_File.Location);
5515 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5518 for J in 1 .. Name_Len loop
5519 if Name_Buffer (J) = '/'
5520 or else Name_Buffer (J) = Directory_Separator
5529 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5532 "symbol file name { is illegal. " &
5533 "Name cannot include directory info.",
5534 Lib_Symbol_File.Location);
5539 -- If attribute Library_Reference_Symbol_File is not defined,
5540 -- symbol policy cannot be Compliant or Controlled.
5542 if Lib_Ref_Symbol_File.Default then
5543 if Data.Symbol_Data.Symbol_Policy = Compliant
5544 or else Data.Symbol_Data.Symbol_Policy = Controlled
5548 "a reference symbol file need to be defined",
5549 Lib_Symbol_Policy.Location);
5553 -- Library_Reference_Symbol_File is defined, check file exists
5555 Data.Symbol_Data.Reference :=
5556 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5558 Get_Name_String (Lib_Ref_Symbol_File.Value);
5560 if Name_Len = 0 then
5563 "reference symbol file name cannot be an empty string",
5564 Lib_Symbol_File.Location);
5567 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5569 Add_Str_To_Name_Buffer (Get_Name_String (Data.Directory));
5570 Add_Char_To_Name_Buffer (Directory_Separator);
5571 Add_Str_To_Name_Buffer
5572 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5573 Data.Symbol_Data.Reference := Name_Find;
5576 if not Is_Regular_File
5577 (Get_Name_String (Data.Symbol_Data.Reference))
5580 File_Name_Type (Lib_Ref_Symbol_File.Value);
5582 -- For controlled and direct symbol policies, it is an error
5583 -- if the reference symbol file does not exist. For other
5584 -- symbol policies, this is just a warning
5587 Data.Symbol_Data.Symbol_Policy /= Controlled
5588 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5592 "<library reference symbol file { does not exist",
5593 Lib_Ref_Symbol_File.Location);
5595 -- In addition in the non-controlled case, if symbol policy
5596 -- is Compliant, it is changed to Autonomous, because there
5597 -- is no reference to check against, and we don't want to
5598 -- fail in this case.
5600 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5601 if Data.Symbol_Data.Symbol_Policy = Compliant then
5602 Data.Symbol_Data.Symbol_Policy := Autonomous;
5607 -- If both the reference symbol file and the symbol file are
5608 -- defined, then check that they are not the same file.
5610 if Data.Symbol_Data.Symbol_File /= No_Path then
5611 Get_Name_String (Data.Symbol_Data.Symbol_File);
5613 if Name_Len > 0 then
5615 Symb_Path : constant String :=
5618 (Data.Object_Directory) &
5619 Directory_Separator &
5620 Name_Buffer (1 .. Name_Len),
5621 Directory => Current_Dir,
5623 Opt.Follow_Links_For_Files);
5624 Ref_Path : constant String :=
5627 (Data.Symbol_Data.Reference),
5628 Directory => Current_Dir,
5630 Opt.Follow_Links_For_Files);
5632 if Symb_Path = Ref_Path then
5635 "library reference symbol file and library" &
5636 " symbol file cannot be the same file",
5637 Lib_Ref_Symbol_File.Location);
5645 end Check_Stand_Alone_Library;
5647 ----------------------------
5648 -- Compute_Directory_Last --
5649 ----------------------------
5651 function Compute_Directory_Last (Dir : String) return Natural is
5654 and then (Dir (Dir'Last - 1) = Directory_Separator
5655 or else Dir (Dir'Last - 1) = '/')
5657 return Dir'Last - 1;
5661 end Compute_Directory_Last;
5668 (Project : Project_Id;
5669 In_Tree : Project_Tree_Ref;
5671 Flag_Location : Source_Ptr)
5673 Real_Location : Source_Ptr := Flag_Location;
5674 Error_Buffer : String (1 .. 5_000);
5675 Error_Last : Natural := 0;
5676 Name_Number : Natural := 0;
5677 File_Number : Natural := 0;
5678 First : Positive := Msg'First;
5681 procedure Add (C : Character);
5682 -- Add a character to the buffer
5684 procedure Add (S : String);
5685 -- Add a string to the buffer
5688 -- Add a name to the buffer
5691 -- Add a file name to the buffer
5697 procedure Add (C : Character) is
5699 Error_Last := Error_Last + 1;
5700 Error_Buffer (Error_Last) := C;
5703 procedure Add (S : String) is
5705 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5706 Error_Last := Error_Last + S'Length;
5713 procedure Add_File is
5714 File : File_Name_Type;
5718 File_Number := File_Number + 1;
5722 File := Err_Vars.Error_Msg_File_1;
5724 File := Err_Vars.Error_Msg_File_2;
5726 File := Err_Vars.Error_Msg_File_3;
5731 Get_Name_String (File);
5732 Add (Name_Buffer (1 .. Name_Len));
5740 procedure Add_Name is
5745 Name_Number := Name_Number + 1;
5749 Name := Err_Vars.Error_Msg_Name_1;
5751 Name := Err_Vars.Error_Msg_Name_2;
5753 Name := Err_Vars.Error_Msg_Name_3;
5758 Get_Name_String (Name);
5759 Add (Name_Buffer (1 .. Name_Len));
5763 -- Start of processing for Error_Msg
5766 -- If location of error is unknown, use the location of the project
5768 if Real_Location = No_Location then
5769 Real_Location := In_Tree.Projects.Table (Project).Location;
5772 if Error_Report = null then
5773 Prj.Err.Error_Msg (Msg, Real_Location);
5777 -- Ignore continuation character
5779 if Msg (First) = '\' then
5783 -- Warning character is always the first one in this package
5784 -- this is an undocumented kludge???
5786 if Msg (First) = '?' then
5790 elsif Msg (First) = '<' then
5793 if Err_Vars.Error_Msg_Warn then
5799 while Index <= Msg'Last loop
5800 if Msg (Index) = '{' then
5803 elsif Msg (Index) = '%' then
5804 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5816 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5819 ----------------------
5820 -- Find_Ada_Sources --
5821 ----------------------
5823 procedure Find_Ada_Sources
5824 (Project : Project_Id;
5825 In_Tree : Project_Tree_Ref;
5826 Data : in out Project_Data;
5827 Current_Dir : String)
5829 Source_Dir : String_List_Id := Data.Source_Dirs;
5830 Element : String_Element;
5832 Current_Source : String_List_Id := Nil_String;
5833 Source_Recorded : Boolean := False;
5836 if Current_Verbosity = High then
5837 Write_Line ("Looking for sources:");
5840 -- For each subdirectory
5842 while Source_Dir /= Nil_String loop
5844 Source_Recorded := False;
5845 Element := In_Tree.String_Elements.Table (Source_Dir);
5846 if Element.Value /= No_Name then
5847 Get_Name_String (Element.Display_Value);
5850 Source_Directory : constant String :=
5851 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5852 Dir_Last : constant Natural :=
5853 Compute_Directory_Last (Source_Directory);
5856 if Current_Verbosity = High then
5857 Write_Str ("Source_Dir = ");
5858 Write_Line (Source_Directory);
5861 -- We look at every entry in the source directory
5864 Source_Directory (Source_Directory'First .. Dir_Last));
5867 Read (Dir, Name_Buffer, Name_Len);
5869 if Current_Verbosity = High then
5870 Write_Str (" Checking ");
5871 Write_Line (Name_Buffer (1 .. Name_Len));
5874 exit when Name_Len = 0;
5877 File_Name : constant File_Name_Type := Name_Find;
5879 -- ??? We could probably optimize the following call:
5880 -- we need to resolve links only once for the
5881 -- directory itself, and then do a single call to
5882 -- readlink() for each file. Unfortunately that would
5883 -- require a change in Normalize_Pathname so that it
5884 -- has the option of not resolving links for its
5885 -- Directory parameter, only for Name.
5887 Path : constant String :=
5889 (Name => Name_Buffer (1 .. Name_Len),
5892 (Source_Directory'First .. Dir_Last),
5894 Opt.Follow_Links_For_Files,
5895 Case_Sensitive => True);
5897 Path_Name : Path_Name_Type;
5900 Name_Len := Path'Length;
5901 Name_Buffer (1 .. Name_Len) := Path;
5902 Path_Name := Name_Find;
5904 -- We attempt to register it as a source. However,
5905 -- there is no error if the file does not contain a
5906 -- valid source. But there is an error if we have a
5907 -- duplicate unit name.
5910 (File_Name => File_Name,
5911 Path_Name => Path_Name,
5915 Location => No_Location,
5916 Current_Source => Current_Source,
5917 Source_Recorded => Source_Recorded,
5918 Current_Dir => Current_Dir);
5927 when Directory_Error =>
5931 if Source_Recorded then
5932 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5936 Source_Dir := Element.Next;
5939 if Current_Verbosity = High then
5940 Write_Line ("end Looking for sources.");
5943 end Find_Ada_Sources;
5949 procedure Find_Sources
5950 (Project : Project_Id;
5951 In_Tree : Project_Tree_Ref;
5952 Data : in out Project_Data;
5953 For_Language : Language_Index;
5954 Current_Dir : String)
5956 Source_Dir : String_List_Id;
5957 Element : String_Element;
5959 Current_Source : String_List_Id := Nil_String;
5960 Source_Recorded : Boolean := False;
5963 if Current_Verbosity = High then
5964 Write_Line ("Looking for sources:");
5967 -- Loop through subdirectories
5969 Source_Dir := Data.Source_Dirs;
5970 while Source_Dir /= Nil_String loop
5972 Source_Recorded := False;
5973 Element := In_Tree.String_Elements.Table (Source_Dir);
5975 if Element.Value /= No_Name then
5976 Get_Name_String (Element.Display_Value);
5979 Source_Directory : constant String :=
5980 Name_Buffer (1 .. Name_Len) &
5981 Directory_Separator;
5983 Dir_Last : constant Natural :=
5984 Compute_Directory_Last (Source_Directory);
5987 if Current_Verbosity = High then
5988 Write_Str ("Source_Dir = ");
5989 Write_Line (Source_Directory);
5992 -- We look to every entry in the source directory
5994 Open (Dir, Source_Directory
5995 (Source_Directory'First .. Dir_Last));
5998 Read (Dir, Name_Buffer, Name_Len);
6000 if Current_Verbosity = High then
6001 Write_Str (" Checking ");
6002 Write_Line (Name_Buffer (1 .. Name_Len));
6005 exit when Name_Len = 0;
6008 File_Name : constant File_Name_Type := Name_Find;
6009 Path : constant String :=
6011 (Name => Name_Buffer (1 .. Name_Len),
6012 Directory => Source_Directory
6013 (Source_Directory'First .. Dir_Last),
6014 Resolve_Links => Opt.Follow_Links_For_Files,
6015 Case_Sensitive => True);
6016 Path_Name : Path_Name_Type;
6019 Name_Len := Path'Length;
6020 Name_Buffer (1 .. Name_Len) := Path;
6021 Path_Name := Name_Find;
6023 if For_Language = Ada_Language_Index then
6025 -- We attempt to register it as a source. However,
6026 -- there is no error if the file does not contain
6027 -- a valid source. But there is an error if we have
6028 -- a duplicate unit name.
6031 (File_Name => File_Name,
6032 Path_Name => Path_Name,
6036 Location => No_Location,
6037 Current_Source => Current_Source,
6038 Source_Recorded => Source_Recorded,
6039 Current_Dir => Current_Dir);
6043 (File_Name => File_Name,
6044 Path_Name => Path_Name,
6048 Location => No_Location,
6049 Language => For_Language,
6051 Body_Suffix_Of (For_Language, Data, In_Tree),
6052 Naming_Exception => False);
6062 when Directory_Error =>
6066 if Source_Recorded then
6067 In_Tree.String_Elements.Table (Source_Dir).Flag :=
6071 Source_Dir := Element.Next;
6074 if Current_Verbosity = High then
6075 Write_Line ("end Looking for sources.");
6078 if For_Language = Ada_Language_Index then
6080 -- If we have looked for sources and found none, then it is an error,
6081 -- except if it is an extending project. If a non extending project
6082 -- is not supposed to contain any source files, then never call
6085 if Current_Source /= Nil_String then
6086 Data.Ada_Sources_Present := True;
6088 elsif Data.Extends = No_Project then
6089 Report_No_Sources (Project, "Ada", In_Tree, Data.Location);
6094 --------------------------------
6095 -- Free_Ada_Naming_Exceptions --
6096 --------------------------------
6098 procedure Free_Ada_Naming_Exceptions is
6100 Ada_Naming_Exception_Table.Set_Last (0);
6101 Ada_Naming_Exceptions.Reset;
6102 Reverse_Ada_Naming_Exceptions.Reset;
6103 end Free_Ada_Naming_Exceptions;
6105 ---------------------
6106 -- Get_Directories --
6107 ---------------------
6109 procedure Get_Directories
6110 (Project : Project_Id;
6111 In_Tree : Project_Tree_Ref;
6112 Current_Dir : String;
6113 Data : in out Project_Data)
6115 Object_Dir : constant Variable_Value :=
6117 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
6119 Exec_Dir : constant Variable_Value :=
6121 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
6123 Source_Dirs : constant Variable_Value :=
6125 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
6127 Excluded_Source_Dirs : constant Variable_Value :=
6129 (Name_Excluded_Source_Dirs,
6130 Data.Decl.Attributes,
6133 Source_Files : constant Variable_Value :=
6135 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
6137 Last_Source_Dir : String_List_Id := Nil_String;
6139 procedure Find_Source_Dirs
6140 (From : File_Name_Type;
6141 Location : Source_Ptr;
6142 Removed : Boolean := False);
6143 -- Find one or several source directories, and add (or remove, if
6144 -- Removed is True) them to list of source directories of the project.
6146 ----------------------
6147 -- Find_Source_Dirs --
6148 ----------------------
6150 procedure Find_Source_Dirs
6151 (From : File_Name_Type;
6152 Location : Source_Ptr;
6153 Removed : Boolean := False)
6155 Directory : constant String := Get_Name_String (From);
6156 Element : String_Element;
6158 procedure Recursive_Find_Dirs (Path : Name_Id);
6159 -- Find all the subdirectories (recursively) of Path and add them
6160 -- to the list of source directories of the project.
6162 -------------------------
6163 -- Recursive_Find_Dirs --
6164 -------------------------
6166 procedure Recursive_Find_Dirs (Path : Name_Id) is
6168 Name : String (1 .. 250);
6170 List : String_List_Id;
6171 Prev : String_List_Id;
6172 Element : String_Element;
6173 Found : Boolean := False;
6175 Non_Canonical_Path : Name_Id := No_Name;
6176 Canonical_Path : Name_Id := No_Name;
6178 The_Path : constant String :=
6180 (Get_Name_String (Path),
6181 Directory => Current_Dir,
6182 Resolve_Links => Opt.Follow_Links_For_Dirs) &
6183 Directory_Separator;
6185 The_Path_Last : constant Natural :=
6186 Compute_Directory_Last (The_Path);
6189 Name_Len := The_Path_Last - The_Path'First + 1;
6190 Name_Buffer (1 .. Name_Len) :=
6191 The_Path (The_Path'First .. The_Path_Last);
6192 Non_Canonical_Path := Name_Find;
6194 if Osint.File_Names_Case_Sensitive then
6195 Canonical_Path := Non_Canonical_Path;
6197 Get_Name_String (Non_Canonical_Path);
6198 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6199 Canonical_Path := Name_Find;
6202 -- To avoid processing the same directory several times, check
6203 -- if the directory is already in Recursive_Dirs. If it is, then
6204 -- there is nothing to do, just return. If it is not, put it there
6205 -- and continue recursive processing.
6208 if Recursive_Dirs.Get (Canonical_Path) then
6211 Recursive_Dirs.Set (Canonical_Path, True);
6215 -- Check if directory is already in list
6217 List := Data.Source_Dirs;
6219 while List /= Nil_String loop
6220 Element := In_Tree.String_Elements.Table (List);
6222 if Element.Value /= No_Name then
6223 Found := Element.Value = Canonical_Path;
6228 List := Element.Next;
6231 -- If directory is not already in list, put it there
6233 if (not Removed) and (not Found) then
6234 if Current_Verbosity = High then
6236 Write_Line (The_Path (The_Path'First .. The_Path_Last));
6239 String_Element_Table.Increment_Last
6240 (In_Tree.String_Elements);
6242 (Value => Canonical_Path,
6243 Display_Value => Non_Canonical_Path,
6244 Location => No_Location,
6249 -- Case of first source directory
6251 if Last_Source_Dir = Nil_String then
6252 Data.Source_Dirs := String_Element_Table.Last
6253 (In_Tree.String_Elements);
6255 -- Here we already have source directories
6258 -- Link the previous last to the new one
6260 In_Tree.String_Elements.Table
6261 (Last_Source_Dir).Next :=
6262 String_Element_Table.Last
6263 (In_Tree.String_Elements);
6266 -- And register this source directory as the new last
6268 Last_Source_Dir := String_Element_Table.Last
6269 (In_Tree.String_Elements);
6270 In_Tree.String_Elements.Table (Last_Source_Dir) :=
6273 elsif Removed and Found then
6274 if Prev = Nil_String then
6276 In_Tree.String_Elements.Table (List).Next;
6278 In_Tree.String_Elements.Table (Prev).Next :=
6279 In_Tree.String_Elements.Table (List).Next;
6283 -- Now look for subdirectories. We do that even when this
6284 -- directory is already in the list, because some of its
6285 -- subdirectories may not be in the list yet.
6287 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
6290 Read (Dir, Name, Last);
6293 if Name (1 .. Last) /= "."
6294 and then Name (1 .. Last) /= ".."
6296 -- Avoid . and .. directories
6298 if Current_Verbosity = High then
6299 Write_Str (" Checking ");
6300 Write_Line (Name (1 .. Last));
6304 Path_Name : constant String :=
6306 (Name => Name (1 .. Last),
6308 The_Path (The_Path'First .. The_Path_Last),
6309 Resolve_Links => Opt.Follow_Links_For_Dirs,
6310 Case_Sensitive => True);
6313 if Is_Directory (Path_Name) then
6314 -- We have found a new subdirectory, call self
6316 Name_Len := Path_Name'Length;
6317 Name_Buffer (1 .. Name_Len) := Path_Name;
6318 Recursive_Find_Dirs (Name_Find);
6327 when Directory_Error =>
6329 end Recursive_Find_Dirs;
6331 -- Start of processing for Find_Source_Dirs
6334 if Current_Verbosity = High and then not Removed then
6335 Write_Str ("Find_Source_Dirs (""");
6336 Write_Str (Directory);
6340 -- First, check if we are looking for a directory tree, indicated
6341 -- by "/**" at the end.
6343 if Directory'Length >= 3
6344 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
6345 and then (Directory (Directory'Last - 2) = '/'
6347 Directory (Directory'Last - 2) = Directory_Separator)
6350 Data.Known_Order_Of_Source_Dirs := False;
6353 Name_Len := Directory'Length - 3;
6355 if Name_Len = 0 then
6357 -- Case of "/**": all directories in file system
6360 Name_Buffer (1) := Directory (Directory'First);
6363 Name_Buffer (1 .. Name_Len) :=
6364 Directory (Directory'First .. Directory'Last - 3);
6367 if Current_Verbosity = High then
6368 Write_Str ("Looking for all subdirectories of """);
6369 Write_Str (Name_Buffer (1 .. Name_Len));
6374 Base_Dir : constant File_Name_Type := Name_Find;
6375 Root_Dir : constant String :=
6377 (Name => Get_Name_String (Base_Dir),
6379 Get_Name_String (Data.Display_Directory),
6380 Resolve_Links => False,
6381 Case_Sensitive => True);
6384 if Root_Dir'Length = 0 then
6385 Err_Vars.Error_Msg_File_1 := Base_Dir;
6387 if Location = No_Location then
6390 "{ is not a valid directory.",
6395 "{ is not a valid directory.",
6400 -- We have an existing directory, we register it and all of
6401 -- its subdirectories.
6403 if Current_Verbosity = High then
6404 Write_Line ("Looking for source directories:");
6407 Name_Len := Root_Dir'Length;
6408 Name_Buffer (1 .. Name_Len) := Root_Dir;
6409 Recursive_Find_Dirs (Name_Find);
6411 if Current_Verbosity = High then
6412 Write_Line ("End of looking for source directories.");
6417 -- We have a single directory
6421 Path_Name : Path_Name_Type;
6422 Display_Path_Name : Path_Name_Type;
6423 List : String_List_Id;
6424 Prev : String_List_Id;
6428 (Project => Project,
6431 Parent => Data.Display_Directory,
6433 Display => Display_Path_Name,
6434 Current_Dir => Current_Dir);
6436 if Path_Name = No_Path then
6437 Err_Vars.Error_Msg_File_1 := From;
6439 if Location = No_Location then
6442 "{ is not a valid directory",
6447 "{ is not a valid directory",
6453 Path : constant String :=
6454 Get_Name_String (Path_Name) &
6455 Directory_Separator;
6456 Last_Path : constant Natural :=
6457 Compute_Directory_Last (Path);
6459 Display_Path : constant String :=
6461 (Display_Path_Name) &
6462 Directory_Separator;
6463 Last_Display_Path : constant Natural :=
6464 Compute_Directory_Last
6466 Display_Path_Id : Name_Id;
6470 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6471 Path_Id := Name_Find;
6473 Add_Str_To_Name_Buffer
6475 (Display_Path'First .. Last_Display_Path));
6476 Display_Path_Id := Name_Find;
6480 -- As it is an existing directory, we add it to the
6481 -- list of directories.
6483 String_Element_Table.Increment_Last
6484 (In_Tree.String_Elements);
6488 Display_Value => Display_Path_Id,
6489 Location => No_Location,
6491 Next => Nil_String);
6493 if Last_Source_Dir = Nil_String then
6495 -- This is the first source directory
6497 Data.Source_Dirs := String_Element_Table.Last
6498 (In_Tree.String_Elements);
6501 -- We already have source directories, link the
6502 -- previous last to the new one.
6504 In_Tree.String_Elements.Table
6505 (Last_Source_Dir).Next :=
6506 String_Element_Table.Last
6507 (In_Tree.String_Elements);
6510 -- And register this source directory as the new last
6512 Last_Source_Dir := String_Element_Table.Last
6513 (In_Tree.String_Elements);
6514 In_Tree.String_Elements.Table
6515 (Last_Source_Dir) := Element;
6518 -- Remove source dir, if present
6520 List := Data.Source_Dirs;
6523 -- Look for source dir in current list
6525 while List /= Nil_String loop
6526 Element := In_Tree.String_Elements.Table (List);
6527 exit when Element.Value = Path_Id;
6529 List := Element.Next;
6532 if List /= Nil_String then
6533 -- Source dir was found, remove it from the list
6535 if Prev = Nil_String then
6537 In_Tree.String_Elements.Table (List).Next;
6540 In_Tree.String_Elements.Table (Prev).Next :=
6541 In_Tree.String_Elements.Table (List).Next;
6549 end Find_Source_Dirs;
6551 -- Start of processing for Get_Directories
6554 if Current_Verbosity = High then
6555 Write_Line ("Starting to look for directories");
6558 -- Check the object directory
6560 pragma Assert (Object_Dir.Kind = Single,
6561 "Object_Dir is not a single string");
6563 -- We set the object directory to its default
6565 Data.Object_Directory := Data.Directory;
6566 Data.Display_Object_Dir := Data.Display_Directory;
6568 if Object_Dir.Value /= Empty_String then
6569 Get_Name_String (Object_Dir.Value);
6571 if Name_Len = 0 then
6574 "Object_Dir cannot be empty",
6575 Object_Dir.Location);
6578 -- We check that the specified object directory does exist
6583 File_Name_Type (Object_Dir.Value),
6584 Data.Display_Directory,
6585 Data.Object_Directory,
6586 Data.Display_Object_Dir,
6588 Location => Object_Dir.Location,
6589 Current_Dir => Current_Dir);
6591 if Data.Object_Directory = No_Path then
6593 -- The object directory does not exist, report an error if the
6594 -- project is not externally built.
6596 if not Data.Externally_Built then
6597 Err_Vars.Error_Msg_File_1 :=
6598 File_Name_Type (Object_Dir.Value);
6601 "the object directory { cannot be found",
6605 -- Do not keep a nil Object_Directory. Set it to the specified
6606 -- (relative or absolute) path. This is for the benefit of
6607 -- tools that recover from errors; for example, these tools
6608 -- could create the non existent directory.
6610 Data.Display_Object_Dir := Path_Name_Type (Object_Dir.Value);
6612 if Osint.File_Names_Case_Sensitive then
6613 Data.Object_Directory := Path_Name_Type (Object_Dir.Value);
6615 Get_Name_String (Object_Dir.Value);
6616 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6617 Data.Object_Directory := Name_Find;
6622 elsif Subdirs /= null then
6624 Name_Buffer (1) := '.';
6629 Data.Display_Directory,
6630 Data.Object_Directory,
6631 Data.Display_Object_Dir,
6633 Location => Object_Dir.Location,
6634 Current_Dir => Current_Dir);
6637 if Current_Verbosity = High then
6638 if Data.Object_Directory = No_Path then
6639 Write_Line ("No object directory");
6641 Write_Str ("Object directory: """);
6642 Write_Str (Get_Name_String (Data.Display_Object_Dir));
6647 -- Check the exec directory
6649 pragma Assert (Exec_Dir.Kind = Single,
6650 "Exec_Dir is not a single string");
6652 -- We set the object directory to its default
6654 Data.Exec_Directory := Data.Object_Directory;
6655 Data.Display_Exec_Dir := Data.Display_Object_Dir;
6657 if Exec_Dir.Value /= Empty_String then
6658 Get_Name_String (Exec_Dir.Value);
6660 if Name_Len = 0 then
6663 "Exec_Dir cannot be empty",
6667 -- We check that the specified exec directory does exist
6672 File_Name_Type (Exec_Dir.Value),
6673 Data.Display_Directory,
6674 Data.Exec_Directory,
6675 Data.Display_Exec_Dir,
6677 Location => Exec_Dir.Location,
6678 Current_Dir => Current_Dir);
6680 if Data.Exec_Directory = No_Path then
6681 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6684 "the exec directory { cannot be found",
6690 if Current_Verbosity = High then
6691 if Data.Exec_Directory = No_Path then
6692 Write_Line ("No exec directory");
6694 Write_Str ("Exec directory: """);
6695 Write_Str (Get_Name_String (Data.Display_Exec_Dir));
6700 -- Look for the source directories
6702 if Current_Verbosity = High then
6703 Write_Line ("Starting to look for source directories");
6706 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6708 if (not Source_Files.Default) and then
6709 Source_Files.Values = Nil_String
6711 Data.Source_Dirs := Nil_String;
6713 if Data.Qualifier = Standard then
6717 "a standard project cannot have no sources",
6718 Source_Files.Location);
6721 if Data.Extends = No_Project
6722 and then Data.Object_Directory = Data.Directory
6724 Data.Object_Directory := No_Path;
6727 elsif Source_Dirs.Default then
6729 -- No Source_Dirs specified: the single source directory is the one
6730 -- containing the project file
6732 String_Element_Table.Increment_Last
6733 (In_Tree.String_Elements);
6734 Data.Source_Dirs := String_Element_Table.Last
6735 (In_Tree.String_Elements);
6736 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6737 (Value => Name_Id (Data.Directory),
6738 Display_Value => Name_Id (Data.Display_Directory),
6739 Location => No_Location,
6744 if Current_Verbosity = High then
6745 Write_Line ("Single source directory:");
6747 Write_Str (Get_Name_String (Data.Display_Directory));
6751 elsif Source_Dirs.Values = Nil_String then
6752 if Data.Qualifier = Standard then
6756 "a standard project cannot have no source directories",
6757 Source_Dirs.Location);
6760 -- If Source_Dirs is an empty string list, this means that this
6761 -- project contains no source. For projects that don't extend other
6762 -- projects, this also means that there is no need for an object
6763 -- directory, if not specified.
6765 if Data.Extends = No_Project
6766 and then Data.Object_Directory = Data.Directory
6768 Data.Object_Directory := No_Path;
6771 Data.Source_Dirs := Nil_String;
6775 Source_Dir : String_List_Id;
6776 Element : String_Element;
6779 -- Process the source directories for each element of the list
6781 Source_Dir := Source_Dirs.Values;
6782 while Source_Dir /= Nil_String loop
6784 In_Tree.String_Elements.Table (Source_Dir);
6786 (File_Name_Type (Element.Value), Element.Location);
6787 Source_Dir := Element.Next;
6792 if not Excluded_Source_Dirs.Default
6793 and then Excluded_Source_Dirs.Values /= Nil_String
6796 Source_Dir : String_List_Id;
6797 Element : String_Element;
6800 -- Process the source directories for each element of the list
6802 Source_Dir := Excluded_Source_Dirs.Values;
6803 while Source_Dir /= Nil_String loop
6805 In_Tree.String_Elements.Table (Source_Dir);
6807 (File_Name_Type (Element.Value),
6810 Source_Dir := Element.Next;
6815 if Current_Verbosity = High then
6816 Write_Line ("Putting source directories in canonical cases");
6820 Current : String_List_Id := Data.Source_Dirs;
6821 Element : String_Element;
6824 while Current /= Nil_String loop
6825 Element := In_Tree.String_Elements.Table (Current);
6826 if Element.Value /= No_Name then
6827 if not Osint.File_Names_Case_Sensitive then
6828 Get_Name_String (Element.Value);
6829 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6830 Element.Value := Name_Find;
6833 In_Tree.String_Elements.Table (Current) := Element;
6836 Current := Element.Next;
6840 end Get_Directories;
6847 (Project : Project_Id;
6848 In_Tree : Project_Tree_Ref;
6849 Data : in out Project_Data)
6851 Mains : constant Variable_Value :=
6852 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6855 Data.Mains := Mains.Values;
6857 -- If no Mains were specified, and if we are an extending project,
6858 -- inherit the Mains from the project we are extending.
6860 if Mains.Default then
6861 if not Data.Library and then Data.Extends /= No_Project then
6863 In_Tree.Projects.Table (Data.Extends).Mains;
6866 -- In a library project file, Main cannot be specified
6868 elsif Data.Library then
6871 "a library project file cannot have Main specified",
6876 ---------------------------
6877 -- Get_Sources_From_File --
6878 ---------------------------
6880 procedure Get_Sources_From_File
6882 Location : Source_Ptr;
6883 Project : Project_Id;
6884 In_Tree : Project_Tree_Ref)
6886 File : Prj.Util.Text_File;
6887 Line : String (1 .. 250);
6889 Source_Name : File_Name_Type;
6890 Name_Loc : Name_Location;
6893 if Get_Mode = Ada_Only then
6897 if Current_Verbosity = High then
6898 Write_Str ("Opening """);
6905 Prj.Util.Open (File, Path);
6907 if not Prj.Util.Is_Valid (File) then
6908 Error_Msg (Project, In_Tree, "file does not exist", Location);
6910 -- Read the lines one by one
6912 while not Prj.Util.End_Of_File (File) loop
6913 Prj.Util.Get_Line (File, Line, Last);
6915 -- A non empty, non comment line should contain a file name
6918 and then (Last = 1 or else Line (1 .. 2) /= "--")
6921 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6922 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6923 Source_Name := Name_Find;
6925 -- Check that there is no directory information
6927 for J in 1 .. Last loop
6928 if Line (J) = '/' or else Line (J) = Directory_Separator then
6929 Error_Msg_File_1 := Source_Name;
6933 "file name cannot include directory information ({)",
6939 Name_Loc := Source_Names.Get (Source_Name);
6941 if Name_Loc = No_Name_Location then
6943 (Name => Source_Name,
6944 Location => Location,
6945 Source => No_Source,
6950 Source_Names.Set (Source_Name, Name_Loc);
6954 Prj.Util.Close (File);
6957 end Get_Sources_From_File;
6964 (In_Tree : Project_Tree_Ref;
6965 Canonical_File_Name : File_Name_Type;
6966 Naming : Naming_Data;
6967 Exception_Id : out Ada_Naming_Exception_Id;
6968 Unit_Name : out Name_Id;
6969 Unit_Kind : out Spec_Or_Body;
6970 Needs_Pragma : out Boolean)
6972 Info_Id : Ada_Naming_Exception_Id :=
6973 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6974 VMS_Name : File_Name_Type;
6977 if Info_Id = No_Ada_Naming_Exception then
6978 if Hostparm.OpenVMS then
6979 VMS_Name := Canonical_File_Name;
6980 Get_Name_String (VMS_Name);
6982 if Name_Buffer (Name_Len) = '.' then
6983 Name_Len := Name_Len - 1;
6984 VMS_Name := Name_Find;
6987 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6992 if Info_Id /= No_Ada_Naming_Exception then
6993 Exception_Id := Info_Id;
6994 Unit_Name := No_Name;
6995 Unit_Kind := Specification;
6996 Needs_Pragma := True;
7000 Needs_Pragma := False;
7001 Exception_Id := No_Ada_Naming_Exception;
7003 Get_Name_String (Canonical_File_Name);
7005 -- How about some comments and a name for this declare block ???
7006 -- In fact the whole code below needs more comments ???
7009 File : String := Name_Buffer (1 .. Name_Len);
7010 First : constant Positive := File'First;
7011 Last : Natural := File'Last;
7012 Standard_GNAT : Boolean;
7013 Spec : constant File_Name_Type :=
7014 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
7015 Body_Suff : constant File_Name_Type :=
7016 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
7019 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
7020 and then Body_Suff = Default_Ada_Body_Suffix;
7023 Spec_Suffix : constant String := Get_Name_String (Spec);
7024 Body_Suffix : constant String := Get_Name_String (Body_Suff);
7025 Sep_Suffix : constant String :=
7026 Get_Name_String (Naming.Separate_Suffix);
7028 May_Be_Spec : Boolean;
7029 May_Be_Body : Boolean;
7030 May_Be_Sep : Boolean;
7034 File'Length > Spec_Suffix'Length
7036 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
7039 File'Length > Body_Suffix'Length
7041 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
7044 File'Length > Sep_Suffix'Length
7046 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
7048 -- If two May_Be_ booleans are True, always choose the longer one
7051 if May_Be_Body and then
7052 Spec_Suffix'Length < Body_Suffix'Length
7054 Unit_Kind := Body_Part;
7056 if May_Be_Sep and then
7057 Body_Suffix'Length < Sep_Suffix'Length
7059 Last := Last - Sep_Suffix'Length;
7060 May_Be_Body := False;
7063 Last := Last - Body_Suffix'Length;
7064 May_Be_Sep := False;
7067 elsif May_Be_Sep and then
7068 Spec_Suffix'Length < Sep_Suffix'Length
7070 Unit_Kind := Body_Part;
7071 Last := Last - Sep_Suffix'Length;
7074 Unit_Kind := Specification;
7075 Last := Last - Spec_Suffix'Length;
7078 elsif May_Be_Body then
7079 Unit_Kind := Body_Part;
7081 if May_Be_Sep and then
7082 Body_Suffix'Length < Sep_Suffix'Length
7084 Last := Last - Sep_Suffix'Length;
7085 May_Be_Body := False;
7087 Last := Last - Body_Suffix'Length;
7088 May_Be_Sep := False;
7091 elsif May_Be_Sep then
7092 Unit_Kind := Body_Part;
7093 Last := Last - Sep_Suffix'Length;
7101 -- This is not a source file
7103 Unit_Name := No_Name;
7104 Unit_Kind := Specification;
7106 if Current_Verbosity = High then
7107 Write_Line (" Not a valid file name.");
7112 elsif Current_Verbosity = High then
7114 when Specification =>
7115 Write_Str (" Specification: ");
7116 Write_Line (File (First .. Last + Spec_Suffix'Length));
7120 Write_Str (" Body: ");
7121 Write_Line (File (First .. Last + Body_Suffix'Length));
7124 Write_Str (" Separate: ");
7125 Write_Line (File (First .. Last + Sep_Suffix'Length));
7131 Get_Name_String (Naming.Dot_Replacement);
7133 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
7135 if Name_Buffer (1 .. Name_Len) /= "." then
7137 -- If Dot_Replacement is not a single dot, then there should not
7138 -- be any dot in the name.
7140 for Index in First .. Last loop
7141 if File (Index) = '.' then
7142 if Current_Verbosity = High then
7144 (" Not a valid file name (some dot not replaced).");
7147 Unit_Name := No_Name;
7153 -- Replace the substring Dot_Replacement with dots
7156 Index : Positive := First;
7159 while Index <= Last - Name_Len + 1 loop
7161 if File (Index .. Index + Name_Len - 1) =
7162 Name_Buffer (1 .. Name_Len)
7164 File (Index) := '.';
7166 if Name_Len > 1 and then Index < Last then
7167 File (Index + 1 .. Last - Name_Len + 1) :=
7168 File (Index + Name_Len .. Last);
7171 Last := Last - Name_Len + 1;
7179 -- Check if the casing is right
7182 Src : String := File (First .. Last);
7183 Src_Last : Positive := Last;
7186 case Naming.Casing is
7187 when All_Lower_Case =>
7190 Mapping => Lower_Case_Map);
7192 when All_Upper_Case =>
7195 Mapping => Upper_Case_Map);
7197 when Mixed_Case | Unknown =>
7201 if Src /= File (First .. Last) then
7202 if Current_Verbosity = High then
7203 Write_Line (" Not a valid file name (casing).");
7206 Unit_Name := No_Name;
7210 -- We put the name in lower case
7214 Mapping => Lower_Case_Map);
7216 -- In the standard GNAT naming scheme, check for special cases:
7217 -- children or separates of A, G, I or S, and run time sources.
7219 if Standard_GNAT and then Src'Length >= 3 then
7221 S1 : constant Character := Src (Src'First);
7222 S2 : constant Character := Src (Src'First + 1);
7223 S3 : constant Character := Src (Src'First + 2);
7231 -- Children or separates of packages A, G, I or S. These
7232 -- names are x__ ... or x~... (where x is a, g, i, or s).
7233 -- Both versions (x__... and x~...) are allowed in all
7234 -- platforms, because it is not possible to know the
7235 -- platform before processing of the project files.
7237 if S2 = '_' and then S3 = '_' then
7238 Src (Src'First + 1) := '.';
7239 Src_Last := Src_Last - 1;
7240 Src (Src'First + 2 .. Src_Last) :=
7241 Src (Src'First + 3 .. Src_Last + 1);
7244 Src (Src'First + 1) := '.';
7246 -- If it is potentially a run time source, disable
7247 -- filling of the mapping file to avoid warnings.
7250 Set_Mapping_File_Initial_State_To_Empty;
7256 if Current_Verbosity = High then
7258 Write_Line (Src (Src'First .. Src_Last));
7261 -- Now, we check if this name is a valid unit name
7264 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
7274 function Hash (Unit : Unit_Info) return Header_Num is
7276 return Header_Num (Unit.Unit mod 2048);
7279 -----------------------
7280 -- Is_Illegal_Suffix --
7281 -----------------------
7283 function Is_Illegal_Suffix
7285 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
7288 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
7292 -- If dot replacement is a single dot, and first character of suffix is
7295 if Dot_Replacement_Is_A_Single_Dot
7296 and then Suffix (Suffix'First) = '.'
7298 for Index in Suffix'First + 1 .. Suffix'Last loop
7300 -- If there is another dot
7302 if Suffix (Index) = '.' then
7304 -- It is illegal to have a letter following the initial dot
7306 return Is_Letter (Suffix (Suffix'First + 1));
7314 end Is_Illegal_Suffix;
7316 ----------------------
7317 -- Locate_Directory --
7318 ----------------------
7320 procedure Locate_Directory
7321 (Project : Project_Id;
7322 In_Tree : Project_Tree_Ref;
7323 Name : File_Name_Type;
7324 Parent : Path_Name_Type;
7325 Dir : out Path_Name_Type;
7326 Display : out Path_Name_Type;
7327 Create : String := "";
7328 Current_Dir : String;
7329 Location : Source_Ptr := No_Location)
7331 The_Parent : constant String :=
7332 Get_Name_String (Parent) & Directory_Separator;
7334 The_Parent_Last : constant Natural :=
7335 Compute_Directory_Last (The_Parent);
7337 Full_Name : File_Name_Type;
7339 The_Name : File_Name_Type;
7342 Get_Name_String (Name);
7344 -- Add Subdirs.all if it is a directory that may be created and
7345 -- Subdirs is not null;
7347 if Create /= "" and then Subdirs /= null then
7348 if Name_Buffer (Name_Len) /= Directory_Separator then
7349 Add_Char_To_Name_Buffer (Directory_Separator);
7352 Add_Str_To_Name_Buffer (Subdirs.all);
7355 -- Convert '/' to directory separator (for Windows)
7357 for J in 1 .. Name_Len loop
7358 if Name_Buffer (J) = '/' then
7359 Name_Buffer (J) := Directory_Separator;
7363 The_Name := Name_Find;
7365 if Current_Verbosity = High then
7366 Write_Str ("Locate_Directory (""");
7367 Write_Str (Get_Name_String (The_Name));
7368 Write_Str (""", """);
7369 Write_Str (The_Parent);
7376 if Is_Absolute_Path (Get_Name_String (The_Name)) then
7377 Full_Name := The_Name;
7381 Add_Str_To_Name_Buffer
7382 (The_Parent (The_Parent'First .. The_Parent_Last));
7383 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7384 Full_Name := Name_Find;
7388 Full_Path_Name : constant String := Get_Name_String (Full_Name);
7391 if (Setup_Projects or else Subdirs /= null)
7392 and then Create'Length > 0
7393 and then not Is_Directory (Full_Path_Name)
7396 Create_Path (Full_Path_Name);
7398 if not Quiet_Output then
7400 Write_Str (" directory """);
7401 Write_Str (Full_Path_Name);
7402 Write_Line (""" created");
7409 "could not create " & Create &
7410 " directory " & Full_Path_Name,
7415 if Is_Directory (Full_Path_Name) then
7417 Normed : constant String :=
7420 Directory => Current_Dir,
7421 Resolve_Links => False,
7422 Case_Sensitive => True);
7424 Canonical_Path : constant String :=
7427 Directory => Current_Dir,
7429 Opt.Follow_Links_For_Dirs,
7430 Case_Sensitive => False);
7433 Name_Len := Normed'Length;
7434 Name_Buffer (1 .. Name_Len) := Normed;
7435 Display := Name_Find;
7437 Name_Len := Canonical_Path'Length;
7438 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7443 end Locate_Directory;
7445 ---------------------------
7446 -- Find_Excluded_Sources --
7447 ---------------------------
7449 procedure Find_Excluded_Sources
7450 (Project : Project_Id;
7451 In_Tree : Project_Tree_Ref;
7452 Data : Project_Data)
7454 Excluded_Sources : Variable_Value;
7456 Excluded_Source_List_File : Variable_Value;
7458 Current : String_List_Id;
7460 Element : String_Element;
7462 Location : Source_Ptr;
7464 Name : File_Name_Type;
7466 File : Prj.Util.Text_File;
7467 Line : String (1 .. 300);
7470 Locally_Removed : Boolean := False;
7472 Excluded_Source_List_File :=
7474 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7478 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7480 -- If Excluded_Source_Files is not declared, check
7481 -- Locally_Removed_Files.
7483 if Excluded_Sources.Default then
7484 Locally_Removed := True;
7487 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7490 Excluded_Sources_Htable.Reset;
7492 -- If there are excluded sources, put them in the table
7494 if not Excluded_Sources.Default then
7495 if not Excluded_Source_List_File.Default then
7496 if Locally_Removed then
7499 "?both attributes Locally_Removed_Files and " &
7500 "Excluded_Source_List_File are present",
7501 Excluded_Source_List_File.Location);
7505 "?both attributes Excluded_Source_Files and " &
7506 "Excluded_Source_List_File are present",
7507 Excluded_Source_List_File.Location);
7511 Current := Excluded_Sources.Values;
7512 while Current /= Nil_String loop
7513 Element := In_Tree.String_Elements.Table (Current);
7515 if Osint.File_Names_Case_Sensitive then
7516 Name := File_Name_Type (Element.Value);
7518 Get_Name_String (Element.Value);
7519 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7523 -- If the element has no location, then use the location
7524 -- of Excluded_Sources to report possible errors.
7526 if Element.Location = No_Location then
7527 Location := Excluded_Sources.Location;
7529 Location := Element.Location;
7532 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7533 Current := Element.Next;
7536 elsif not Excluded_Source_List_File.Default then
7537 Location := Excluded_Source_List_File.Location;
7540 Source_File_Path_Name : constant String :=
7543 (Excluded_Source_List_File.Value),
7547 if Source_File_Path_Name'Length = 0 then
7548 Err_Vars.Error_Msg_File_1 :=
7549 File_Name_Type (Excluded_Source_List_File.Value);
7552 "file with excluded sources { does not exist",
7553 Excluded_Source_List_File.Location);
7558 Prj.Util.Open (File, Source_File_Path_Name);
7560 if not Prj.Util.Is_Valid (File) then
7562 (Project, In_Tree, "file does not exist", Location);
7564 -- Read the lines one by one
7566 while not Prj.Util.End_Of_File (File) loop
7567 Prj.Util.Get_Line (File, Line, Last);
7569 -- A non empty, non comment line should contain a file
7573 and then (Last = 1 or else Line (1 .. 2) /= "--")
7576 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7577 Canonical_Case_File_Name
7578 (Name_Buffer (1 .. Name_Len));
7581 -- Check that there is no directory information
7583 for J in 1 .. Last loop
7585 or else Line (J) = Directory_Separator
7587 Error_Msg_File_1 := Name;
7591 "file name cannot include " &
7592 "directory information ({)",
7598 Excluded_Sources_Htable.Set
7599 (Name, (Name, False, Location));
7603 Prj.Util.Close (File);
7608 end Find_Excluded_Sources;
7610 ---------------------------
7611 -- Find_Explicit_Sources --
7612 ---------------------------
7614 procedure Find_Explicit_Sources
7615 (Lang : Language_Index;
7616 Current_Dir : String;
7617 Project : Project_Id;
7618 In_Tree : Project_Tree_Ref;
7619 Data : in out Project_Data)
7621 Sources : constant Variable_Value :=
7624 Data.Decl.Attributes,
7626 Source_List_File : constant Variable_Value :=
7628 (Name_Source_List_File,
7629 Data.Decl.Attributes,
7631 Name_Loc : Name_Location;
7634 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7636 (Source_List_File.Kind = Single,
7637 "Source_List_File is not a single string");
7639 -- If the user has specified a Sources attribute
7641 if not Sources.Default then
7642 if not Source_List_File.Default then
7645 "?both attributes source_files and " &
7646 "source_list_file are present",
7647 Source_List_File.Location);
7650 -- Sources is a list of file names
7653 Current : String_List_Id := Sources.Values;
7654 Element : String_Element;
7655 Location : Source_Ptr;
7656 Name : File_Name_Type;
7659 if Get_Mode = Ada_Only then
7660 Data.Ada_Sources_Present := Current /= Nil_String;
7663 -- If we are processing other languages in the case of gprmake,
7664 -- we should not reset the list of sources, which was already
7665 -- initialized for the Ada files.
7667 if Get_Mode /= Ada_Only or else Lang /= Ada_Language_Index then
7668 if Current = Nil_String then
7671 Data.Source_Dirs := Nil_String;
7672 when Multi_Language =>
7673 Data.First_Language_Processing := No_Language_Index;
7676 -- This project contains no source. For projects that
7677 -- don't extend other projects, this also means that
7678 -- there is no need for an object directory, if not
7681 if Data.Extends = No_Project
7682 and then Data.Object_Directory = Data.Directory
7684 Data.Object_Directory := No_Path;
7689 while Current /= Nil_String loop
7690 Element := In_Tree.String_Elements.Table (Current);
7691 Get_Name_String (Element.Value);
7693 if Osint.File_Names_Case_Sensitive then
7694 Name := File_Name_Type (Element.Value);
7696 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7700 -- If the element has no location, then use the
7701 -- location of Sources to report possible errors.
7703 if Element.Location = No_Location then
7704 Location := Sources.Location;
7706 Location := Element.Location;
7709 -- Check that there is no directory information
7711 for J in 1 .. Name_Len loop
7712 if Name_Buffer (J) = '/'
7713 or else Name_Buffer (J) = Directory_Separator
7715 Error_Msg_File_1 := Name;
7719 "file name cannot include directory " &
7726 -- In Multi_Language mode, check whether the file is
7727 -- already there: the same file name may be in the list; if
7728 -- the source is missing, the error will be on the first
7729 -- mention of the source file name.
7733 Name_Loc := No_Name_Location;
7734 when Multi_Language =>
7735 Name_Loc := Source_Names.Get (Name);
7738 if Name_Loc = No_Name_Location then
7741 Location => Location,
7742 Source => No_Source,
7745 Source_Names.Set (Name, Name_Loc);
7748 Current := Element.Next;
7751 if Get_Mode = Ada_Only then
7752 if Lang = Ada_Language_Index then
7753 Get_Path_Names_And_Record_Ada_Sources
7754 (Project, In_Tree, Data, Current_Dir);
7756 Record_Other_Sources
7757 (Project => Project,
7761 Naming_Exceptions => False);
7766 -- If we have no Source_Files attribute, check the Source_List_File
7769 elsif not Source_List_File.Default then
7771 -- Source_List_File is the name of the file
7772 -- that contains the source file names
7775 Source_File_Path_Name : constant String :=
7777 (File_Name_Type (Source_List_File.Value), Data.Directory);
7780 if Source_File_Path_Name'Length = 0 then
7781 Err_Vars.Error_Msg_File_1 :=
7782 File_Name_Type (Source_List_File.Value);
7785 "file with sources { does not exist",
7786 Source_List_File.Location);
7789 Get_Sources_From_File
7790 (Source_File_Path_Name, Source_List_File.Location,
7793 if Get_Mode = Ada_Only then
7794 -- Look in the source directories to find those sources
7796 if Lang = Ada_Language_Index then
7797 Get_Path_Names_And_Record_Ada_Sources
7798 (Project, In_Tree, Data, Current_Dir);
7801 Record_Other_Sources
7802 (Project => Project,
7806 Naming_Exceptions => False);
7813 -- Neither Source_Files nor Source_List_File has been
7814 -- specified. Find all the files that satisfy the naming
7815 -- scheme in all the source directories.
7819 if Lang = Ada_Language_Index then
7820 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7822 -- Find all the files that satisfy the naming scheme in
7823 -- all the source directories. All the naming exceptions
7824 -- that effectively exist are also part of the source
7825 -- of this language.
7827 Find_Sources (Project, In_Tree, Data, Lang, Current_Dir);
7830 when Multi_Language =>
7835 if Get_Mode = Multi_Language then
7837 (Project, In_Tree, Data,
7839 Sources.Default and then Source_List_File.Default);
7841 -- Check if all exceptions have been found.
7842 -- For Ada, it is an error if an exception is not found.
7843 -- For other language, the source is simply removed.
7847 Src_Data : Source_Data;
7850 Source := Data.First_Source;
7851 while Source /= No_Source loop
7852 Src_Data := In_Tree.Sources.Table (Source);
7854 if Src_Data.Naming_Exception
7855 and then Src_Data.Path = No_Path
7857 if Src_Data.Unit /= No_Name then
7858 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7859 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7862 "source file %% for unit %% not found",
7866 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7869 Source := Src_Data.Next_In_Project;
7873 -- Check that all sources in Source_Files or the file
7874 -- Source_List_File has been found.
7877 Name_Loc : Name_Location;
7880 Name_Loc := Source_Names.Get_First;
7881 while Name_Loc /= No_Name_Location loop
7882 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7883 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7887 "file %% not found",
7891 Name_Loc := Source_Names.Get_Next;
7896 if Get_Mode = Ada_Only
7897 and then Lang = Ada_Language_Index
7898 and then Data.Extends = No_Project
7900 -- We should have found at least one source, if not report an error
7902 if Data.Ada_Sources = Nil_String then
7904 (Project, "Ada", In_Tree, Source_List_File.Location);
7908 end Find_Explicit_Sources;
7910 -------------------------------------------
7911 -- Get_Path_Names_And_Record_Ada_Sources --
7912 -------------------------------------------
7914 procedure Get_Path_Names_And_Record_Ada_Sources
7915 (Project : Project_Id;
7916 In_Tree : Project_Tree_Ref;
7917 Data : in out Project_Data;
7918 Current_Dir : String)
7920 Source_Dir : String_List_Id;
7921 Element : String_Element;
7922 Path : Path_Name_Type;
7924 Name : File_Name_Type;
7925 Canonical_Name : File_Name_Type;
7926 Name_Str : String (1 .. 1_024);
7927 Last : Natural := 0;
7929 Current_Source : String_List_Id := Nil_String;
7930 First_Error : Boolean := True;
7931 Source_Recorded : Boolean := False;
7934 -- We look in all source directories for the file names in the hash
7935 -- table Source_Names.
7937 Source_Dir := Data.Source_Dirs;
7938 while Source_Dir /= Nil_String loop
7939 Source_Recorded := False;
7940 Element := In_Tree.String_Elements.Table (Source_Dir);
7943 Dir_Path : constant String :=
7944 Get_Name_String (Element.Display_Value);
7946 if Current_Verbosity = High then
7947 Write_Str ("checking directory """);
7948 Write_Str (Dir_Path);
7952 Open (Dir, Dir_Path);
7955 Read (Dir, Name_Str, Last);
7959 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7962 if Osint.File_Names_Case_Sensitive then
7963 Canonical_Name := Name;
7965 Canonical_Case_File_Name (Name_Str (1 .. Last));
7966 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7967 Canonical_Name := Name_Find;
7970 NL := Source_Names.Get (Canonical_Name);
7972 if NL /= No_Name_Location and then not NL.Found then
7974 Source_Names.Set (Canonical_Name, NL);
7975 Name_Len := Dir_Path'Length;
7976 Name_Buffer (1 .. Name_Len) := Dir_Path;
7978 if Name_Buffer (Name_Len) /= Directory_Separator then
7979 Add_Char_To_Name_Buffer (Directory_Separator);
7982 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7985 if Current_Verbosity = High then
7986 Write_Str (" found ");
7987 Write_Line (Get_Name_String (Name));
7990 -- Register the source if it is an Ada compilation unit
7998 Location => NL.Location,
7999 Current_Source => Current_Source,
8000 Source_Recorded => Source_Recorded,
8001 Current_Dir => Current_Dir);
8008 if Source_Recorded then
8009 In_Tree.String_Elements.Table (Source_Dir).Flag :=
8013 Source_Dir := Element.Next;
8016 -- It is an error if a source file name in a source list or
8017 -- in a source list file is not found.
8019 NL := Source_Names.Get_First;
8020 while NL /= No_Name_Location loop
8021 if not NL.Found then
8022 Err_Vars.Error_Msg_File_1 := NL.Name;
8027 "source file { cannot be found",
8029 First_Error := False;
8034 "\source file { cannot be found",
8039 NL := Source_Names.Get_Next;
8041 end Get_Path_Names_And_Record_Ada_Sources;
8043 --------------------------
8044 -- Check_Naming_Schemes --
8045 --------------------------
8047 procedure Check_Naming_Schemes
8048 (In_Tree : Project_Tree_Ref;
8049 Data : in out Project_Data;
8051 File_Name : File_Name_Type;
8052 Alternate_Languages : out Alternate_Language_Id;
8053 Language : out Language_Index;
8054 Language_Name : out Name_Id;
8055 Display_Language_Name : out Name_Id;
8057 Lang_Kind : out Language_Kind;
8058 Kind : out Source_Kind)
8060 Last : Positive := Filename'Last;
8061 Config : Language_Config;
8062 Lang : Name_List_Index := Data.Languages;
8063 Header_File : Boolean := False;
8064 First_Language : Language_Index;
8067 Last_Spec : Natural;
8068 Last_Body : Natural;
8073 Alternate_Languages := No_Alternate_Language;
8075 while Lang /= No_Name_List loop
8076 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
8077 Language := Data.First_Language_Processing;
8079 if Current_Verbosity = High then
8081 (" Testing language "
8082 & Get_Name_String (Language_Name)
8083 & " Header_File=" & Header_File'Img);
8086 while Language /= No_Language_Index loop
8087 if In_Tree.Languages_Data.Table (Language).Name =
8090 Display_Language_Name :=
8091 In_Tree.Languages_Data.Table (Language).Display_Name;
8092 Config := In_Tree.Languages_Data.Table (Language).Config;
8093 Lang_Kind := Config.Kind;
8095 if Config.Kind = File_Based then
8097 -- For file based languages, there is no Unit. Just
8098 -- check if the file name has the implementation or,
8099 -- if it is specified, the template suffix of the
8105 and then Config.Naming_Data.Body_Suffix /= No_File
8108 Impl_Suffix : constant String :=
8109 Get_Name_String (Config.Naming_Data.Body_Suffix);
8112 if Filename'Length > Impl_Suffix'Length
8115 (Last - Impl_Suffix'Length + 1 .. Last) =
8120 if Current_Verbosity = High then
8121 Write_Str (" source of language ");
8123 (Get_Name_String (Display_Language_Name));
8131 if Config.Naming_Data.Spec_Suffix /= No_File then
8133 Spec_Suffix : constant String :=
8135 (Config.Naming_Data.Spec_Suffix);
8138 if Filename'Length > Spec_Suffix'Length
8141 (Last - Spec_Suffix'Length + 1 .. Last) =
8146 if Current_Verbosity = High then
8147 Write_Str (" header file of language ");
8149 (Get_Name_String (Display_Language_Name));
8153 Alternate_Language_Table.Increment_Last
8154 (In_Tree.Alt_Langs);
8155 In_Tree.Alt_Langs.Table
8156 (Alternate_Language_Table.Last
8157 (In_Tree.Alt_Langs)) :=
8158 (Language => Language,
8159 Next => Alternate_Languages);
8160 Alternate_Languages :=
8161 Alternate_Language_Table.Last
8162 (In_Tree.Alt_Langs);
8164 Header_File := True;
8165 First_Language := Language;
8171 elsif not Header_File then
8172 -- Unit based language
8174 OK := Config.Naming_Data.Dot_Replacement /= No_File;
8179 -- ??? Are we doing this once per file in the project ?
8180 -- It should be done only once per project.
8182 case Config.Naming_Data.Casing is
8183 when All_Lower_Case =>
8184 for J in Filename'Range loop
8185 if Is_Letter (Filename (J)) then
8186 if not Is_Lower (Filename (J)) then
8193 when All_Upper_Case =>
8194 for J in Filename'Range loop
8195 if Is_Letter (Filename (J)) then
8196 if not Is_Upper (Filename (J)) then
8209 Last_Spec := Natural'Last;
8210 Last_Body := Natural'Last;
8211 Last_Sep := Natural'Last;
8213 if Config.Naming_Data.Separate_Suffix /= No_File
8215 Config.Naming_Data.Separate_Suffix /=
8216 Config.Naming_Data.Body_Suffix
8219 Suffix : constant String :=
8221 (Config.Naming_Data.Separate_Suffix);
8223 if Filename'Length > Suffix'Length
8226 (Last - Suffix'Length + 1 .. Last) =
8229 Last_Sep := Last - Suffix'Length;
8234 if Config.Naming_Data.Body_Suffix /= No_File then
8236 Suffix : constant String :=
8238 (Config.Naming_Data.Body_Suffix);
8240 if Filename'Length > Suffix'Length
8243 (Last - Suffix'Length + 1 .. Last) =
8246 Last_Body := Last - Suffix'Length;
8251 if Config.Naming_Data.Spec_Suffix /= No_File then
8253 Suffix : constant String :=
8255 (Config.Naming_Data.Spec_Suffix);
8257 if Filename'Length > Suffix'Length
8260 (Last - Suffix'Length + 1 .. Last) =
8263 Last_Spec := Last - Suffix'Length;
8269 Last_Min : constant Natural :=
8270 Natural'Min (Natural'Min (Last_Spec,
8275 OK := Last_Min < Last;
8280 if Last_Min = Last_Spec then
8283 elsif Last_Min = Last_Body then
8295 -- Replace dot replacements with dots
8300 J : Positive := Filename'First;
8302 Dot_Replacement : constant String :=
8304 (Config.Naming_Data.
8307 Max : constant Positive :=
8308 Last - Dot_Replacement'Length + 1;
8312 Name_Len := Name_Len + 1;
8314 if J <= Max and then
8316 (J .. J + Dot_Replacement'Length - 1) =
8319 Name_Buffer (Name_Len) := '.';
8320 J := J + Dot_Replacement'Length;
8323 if Filename (J) = '.' then
8328 Name_Buffer (Name_Len) :=
8329 GNAT.Case_Util.To_Lower (Filename (J));
8340 -- The name buffer should contain the name of the
8341 -- the unit, if it is one.
8343 -- Check that this is a valid unit name
8345 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
8347 if Unit /= No_Name then
8349 if Current_Verbosity = High then
8351 Write_Str (" spec of ");
8353 Write_Str (" body of ");
8356 Write_Str (Get_Name_String (Unit));
8357 Write_Str (" (language ");
8359 (Get_Name_String (Display_Language_Name));
8363 -- Comments required, declare block should
8367 Unit_Except : constant Unit_Exception :=
8368 Unit_Exceptions.Get (Unit);
8370 procedure Masked_Unit (Spec : Boolean);
8371 -- Indicate that there is an exception for
8372 -- the same unit, so the file is not a
8373 -- source for the unit.
8379 procedure Masked_Unit (Spec : Boolean) is
8381 if Current_Verbosity = High then
8383 Write_Str (Filename);
8384 Write_Str (""" contains the ");
8393 (" of a unit that is found in """);
8398 (Unit_Except.Spec));
8402 (Unit_Except.Impl));
8405 Write_Line (""" (ignored)");
8408 Language := No_Language_Index;
8413 if Unit_Except.Spec /= No_File
8414 and then Unit_Except.Spec /= File_Name
8416 Masked_Unit (Spec => True);
8420 if Unit_Except.Impl /= No_File
8421 and then Unit_Except.Impl /= File_Name
8423 Masked_Unit (Spec => False);
8434 Language := In_Tree.Languages_Data.Table (Language).Next;
8437 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8440 -- Comment needed here ???
8443 Language := First_Language;
8446 Language := No_Language_Index;
8448 if Current_Verbosity = High then
8449 Write_Line (" not a source of any language");
8452 end Check_Naming_Schemes;
8458 procedure Check_File
8459 (Project : Project_Id;
8460 In_Tree : Project_Tree_Ref;
8461 Data : in out Project_Data;
8463 File_Name : File_Name_Type;
8464 Display_File_Name : File_Name_Type;
8465 Source_Directory : String;
8466 For_All_Sources : Boolean)
8468 Display_Path : constant String :=
8471 Directory => Source_Directory,
8472 Resolve_Links => Opt.Follow_Links_For_Files,
8473 Case_Sensitive => True);
8475 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8476 Path_Id : Path_Name_Type;
8477 Display_Path_Id : Path_Name_Type;
8478 Check_Name : Boolean := False;
8479 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8480 Language : Language_Index;
8482 Other_Part : Source_Id;
8484 Src_Ind : Source_File_Index;
8485 Src_Data : Source_Data;
8487 Source_To_Replace : Source_Id := No_Source;
8488 Language_Name : Name_Id;
8489 Display_Language_Name : Name_Id;
8490 Lang_Kind : Language_Kind;
8491 Kind : Source_Kind := Spec;
8494 Name_Len := Display_Path'Length;
8495 Name_Buffer (1 .. Name_Len) := Display_Path;
8496 Display_Path_Id := Name_Find;
8498 if Osint.File_Names_Case_Sensitive then
8499 Path_Id := Display_Path_Id;
8501 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8502 Path_Id := Name_Find;
8505 if Name_Loc = No_Name_Location then
8506 Check_Name := For_All_Sources;
8509 if Name_Loc.Found then
8511 -- Check if it is OK to have the same file name in several
8512 -- source directories.
8514 if not Data.Known_Order_Of_Source_Dirs then
8515 Error_Msg_File_1 := File_Name;
8518 "{ is found in several source directories",
8523 Name_Loc.Found := True;
8525 Source_Names.Set (File_Name, Name_Loc);
8527 if Name_Loc.Source = No_Source then
8531 In_Tree.Sources.Table (Name_Loc.Source).Path := Path_Id;
8532 In_Tree.Sources.Table
8533 (Name_Loc.Source).Display_Path := Display_Path_Id;
8535 Source_Paths_Htable.Set
8536 (In_Tree.Source_Paths_HT,
8540 -- Check if this is a subunit
8542 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8544 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8546 Src_Ind := Sinput.P.Load_Project_File
8547 (Get_Name_String (Path_Id));
8549 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8550 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8558 Other_Part := No_Source;
8560 Check_Naming_Schemes
8561 (In_Tree => In_Tree,
8563 Filename => Get_Name_String (File_Name),
8564 File_Name => File_Name,
8565 Alternate_Languages => Alternate_Languages,
8566 Language => Language,
8567 Language_Name => Language_Name,
8568 Display_Language_Name => Display_Language_Name,
8570 Lang_Kind => Lang_Kind,
8573 if Language = No_Language_Index then
8575 -- A file name in a list must be a source of a language
8577 if Name_Loc.Found then
8578 Error_Msg_File_1 := File_Name;
8582 "language unknown for {",
8587 -- Check if the same file name or unit is used in the prj tree
8589 Source := In_Tree.First_Source;
8591 while Source /= No_Source loop
8592 Src_Data := In_Tree.Sources.Table (Source);
8595 and then Src_Data.Unit = Unit
8597 ((Src_Data.Kind = Spec and then Kind = Impl)
8599 (Src_Data.Kind = Impl and then Kind = Spec))
8601 Other_Part := Source;
8603 elsif (Unit /= No_Name
8604 and then Src_Data.Unit = Unit
8606 (Src_Data.Kind = Kind
8608 (Src_Data.Kind = Sep and then Kind = Impl)
8610 (Src_Data.Kind = Impl and then Kind = Sep)))
8611 or else (Unit = No_Name and then Src_Data.File = File_Name)
8613 -- Duplication of file/unit in same project is only
8614 -- allowed if order of source directories is known.
8616 if Project = Src_Data.Project then
8617 if Data.Known_Order_Of_Source_Dirs then
8620 elsif Unit /= No_Name then
8621 Error_Msg_Name_1 := Unit;
8623 (Project, In_Tree, "duplicate unit %%", No_Location);
8627 Error_Msg_File_1 := File_Name;
8629 (Project, In_Tree, "duplicate source file name {",
8634 -- Do not allow the same unit name in different
8635 -- projects, except if one is extending the other.
8637 -- For a file based language, the same file name
8638 -- replaces a file in a project being extended, but
8639 -- it is allowed to have the same file name in
8640 -- unrelated projects.
8643 (Project, Src_Data.Project, In_Tree)
8645 Source_To_Replace := Source;
8647 elsif Unit /= No_Name then
8648 Error_Msg_Name_1 := Unit;
8651 "unit %% cannot belong to several projects",
8654 Error_Msg_Name_1 := In_Tree.Projects.Table (Project).Name;
8655 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8657 (Project, In_Tree, "\ project %%, %%", No_Location);
8660 In_Tree.Projects.Table (Src_Data.Project).Name;
8661 Error_Msg_Name_2 := Name_Id (Src_Data.Display_Path);
8663 (Project, In_Tree, "\ project %%, %%", No_Location);
8669 Source := Src_Data.Next_In_Sources;
8678 Lang => Language_Name,
8679 Lang_Id => Language,
8680 Lang_Kind => Lang_Kind,
8682 Alternate_Languages => Alternate_Languages,
8683 File_Name => File_Name,
8684 Display_File => Display_File_Name,
8685 Other_Part => Other_Part,
8688 Display_Path => Display_Path_Id,
8689 Source_To_Replace => Source_To_Replace);
8695 ------------------------
8696 -- Search_Directories --
8697 ------------------------
8699 procedure Search_Directories
8700 (Project : Project_Id;
8701 In_Tree : Project_Tree_Ref;
8702 Data : in out Project_Data;
8703 For_All_Sources : Boolean)
8705 Source_Dir : String_List_Id;
8706 Element : String_Element;
8708 Name : String (1 .. 1_000);
8710 File_Name : File_Name_Type;
8711 Display_File_Name : File_Name_Type;
8714 if Current_Verbosity = High then
8715 Write_Line ("Looking for sources:");
8718 -- Loop through subdirectories
8720 Source_Dir := Data.Source_Dirs;
8721 while Source_Dir /= Nil_String loop
8723 Element := In_Tree.String_Elements.Table (Source_Dir);
8724 if Element.Value /= No_Name then
8725 Get_Name_String (Element.Display_Value);
8728 Source_Directory : constant String :=
8729 Name_Buffer (1 .. Name_Len) &
8730 Directory_Separator;
8732 Dir_Last : constant Natural :=
8733 Compute_Directory_Last
8737 if Current_Verbosity = High then
8738 Write_Str ("Source_Dir = ");
8739 Write_Line (Source_Directory);
8742 -- We look to every entry in the source directory
8744 Open (Dir, Source_Directory);
8747 Read (Dir, Name, Last);
8751 -- ??? Duplicate system call here, we just did a
8752 -- a similar one. Maybe Ada.Directories would be more
8756 (Source_Directory & Name (1 .. Last))
8758 if Current_Verbosity = High then
8759 Write_Str (" Checking ");
8760 Write_Line (Name (1 .. Last));
8764 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8765 Display_File_Name := Name_Find;
8767 if Osint.File_Names_Case_Sensitive then
8768 File_Name := Display_File_Name;
8770 Canonical_Case_File_Name
8771 (Name_Buffer (1 .. Name_Len));
8772 File_Name := Name_Find;
8777 Excluded_Sources_Htable.Get (File_Name);
8780 if FF /= No_File_Found then
8781 if not FF.Found then
8783 Excluded_Sources_Htable.Set
8786 if Current_Verbosity = High then
8787 Write_Str (" excluded source """);
8788 Write_Str (Get_Name_String (File_Name));
8795 (Project => Project,
8798 Name => Name (1 .. Last),
8799 File_Name => File_Name,
8800 Display_File_Name => Display_File_Name,
8801 Source_Directory => Source_Directory
8802 (Source_Directory'First .. Dir_Last),
8803 For_All_Sources => For_All_Sources);
8814 when Directory_Error =>
8818 Source_Dir := Element.Next;
8821 if Current_Verbosity = High then
8822 Write_Line ("end Looking for sources.");
8824 end Search_Directories;
8826 ----------------------
8827 -- Look_For_Sources --
8828 ----------------------
8830 procedure Look_For_Sources
8831 (Project : Project_Id;
8832 In_Tree : Project_Tree_Ref;
8833 Data : in out Project_Data;
8834 Current_Dir : String)
8836 procedure Remove_Locally_Removed_Files_From_Units;
8837 -- Mark all locally removed sources as such in the Units table
8839 procedure Process_Other_Sources_In_Ada_Only_Mode;
8840 -- Find sources for language other than Ada when in Ada_Only mode
8842 procedure Process_Sources_In_Multi_Language_Mode;
8843 -- Find all source files when in multi language mode
8845 ---------------------------------------------
8846 -- Remove_Locally_Removed_Files_From_Units --
8847 ---------------------------------------------
8849 procedure Remove_Locally_Removed_Files_From_Units is
8850 Excluded : File_Found;
8853 Extended : Project_Id;
8856 Excluded := Excluded_Sources_Htable.Get_First;
8857 while Excluded /= No_File_Found loop
8861 for Index in Unit_Table.First ..
8862 Unit_Table.Last (In_Tree.Units)
8864 Unit := In_Tree.Units.Table (Index);
8866 for Kind in Spec_Or_Body'Range loop
8867 if Unit.File_Names (Kind).Name = Excluded.File then
8870 -- Check that this is from the current project or
8871 -- that the current project extends.
8873 Extended := Unit.File_Names (Kind).Project;
8875 if Extended = Project
8876 or else Project_Extends (Project, Extended, In_Tree)
8878 Unit.File_Names (Kind).Path := Slash;
8879 Unit.File_Names (Kind).Needs_Pragma := False;
8880 In_Tree.Units.Table (Index) := Unit;
8881 Add_Forbidden_File_Name
8882 (Unit.File_Names (Kind).Name);
8886 "cannot remove a source from " &
8893 end loop For_Each_Unit;
8896 Err_Vars.Error_Msg_File_1 := Excluded.File;
8898 (Project, In_Tree, "unknown file {", Excluded.Location);
8901 Excluded := Excluded_Sources_Htable.Get_Next;
8903 end Remove_Locally_Removed_Files_From_Units;
8905 --------------------------------------------
8906 -- Process_Other_Sources_In_Ada_Only_Mode --
8907 --------------------------------------------
8909 procedure Process_Other_Sources_In_Ada_Only_Mode is
8911 -- Set Source_Present to False. It will be set back to True
8912 -- whenever a source is found.
8914 Data.Other_Sources_Present := False;
8915 for Lang in Ada_Language_Index + 1 .. Last_Language_Index loop
8917 -- For each language (other than Ada) in the project file
8919 if Is_Present (Lang, Data, In_Tree) then
8921 -- Reset the indication that there are sources of this
8922 -- language. It will be set back to True whenever we find
8923 -- a source of the language.
8925 Set (Lang, False, Data, In_Tree);
8927 -- First, get the source suffix for the language
8929 Set (Suffix => Suffix_For (Lang, Data.Naming, In_Tree),
8930 For_Language => Lang,
8932 In_Tree => In_Tree);
8934 -- Then, deal with the naming exceptions, if any
8939 Naming_Exceptions : constant Variable_Value :=
8941 (Index => Language_Names.Table (Lang),
8943 In_Array => Data.Naming.Implementation_Exceptions,
8944 In_Tree => In_Tree);
8945 Element_Id : String_List_Id;
8946 Element : String_Element;
8947 File_Id : File_Name_Type;
8948 Source_Found : Boolean := False;
8951 -- If there are naming exceptions, look through them one
8954 if Naming_Exceptions /= Nil_Variable_Value then
8955 Element_Id := Naming_Exceptions.Values;
8957 while Element_Id /= Nil_String loop
8958 Element := In_Tree.String_Elements.Table (Element_Id);
8960 if Osint.File_Names_Case_Sensitive then
8961 File_Id := File_Name_Type (Element.Value);
8963 Get_Name_String (Element.Value);
8964 Canonical_Case_File_Name
8965 (Name_Buffer (1 .. Name_Len));
8966 File_Id := Name_Find;
8969 -- Put each naming exception in the Source_Names hash
8970 -- table, but if there are repetition, don't bother
8971 -- after the first instance.
8973 if Source_Names.Get (File_Id) = No_Name_Location then
8974 Source_Found := True;
8978 Location => Element.Location,
8979 Source => No_Source,
8984 Element_Id := Element.Next;
8987 -- If there is at least one naming exception, record
8988 -- those that are found in the source directories.
8990 if Source_Found then
8991 Record_Other_Sources
8992 (Project => Project,
8996 Naming_Exceptions => True);
9002 -- Now, check if a list of sources is declared either through
9003 -- a string list (attribute Source_Files) or a text file
9004 -- (attribute Source_List_File). If a source list is declared,
9005 -- we will consider only those naming exceptions that are
9009 Find_Explicit_Sources
9010 (Lang, Current_Dir, Project, In_Tree, Data);
9013 end Process_Other_Sources_In_Ada_Only_Mode;
9015 --------------------------------------------
9016 -- Process_Sources_In_Multi_Language_Mode --
9017 --------------------------------------------
9019 procedure Process_Sources_In_Multi_Language_Mode is
9021 Src_Data : Source_Data;
9022 Name_Loc : Name_Location;
9027 -- First, put all naming exceptions if any, in the Source_Names table
9029 Unit_Exceptions.Reset;
9031 Source := Data.First_Source;
9032 while Source /= No_Source loop
9033 Src_Data := In_Tree.Sources.Table (Source);
9035 -- A file that is excluded cannot also be an exception file name
9037 if Excluded_Sources_Htable.Get (Src_Data.File) /=
9040 Error_Msg_File_1 := Src_Data.File;
9043 "{ cannot be both excluded and an exception file name",
9047 Name_Loc := (Name => Src_Data.File,
9048 Location => No_Location,
9050 Except => Src_Data.Unit /= No_Name,
9053 if Current_Verbosity = High then
9054 Write_Str ("Putting source #");
9055 Write_Str (Source'Img);
9056 Write_Str (", file ");
9057 Write_Str (Get_Name_String (Src_Data.File));
9058 Write_Line (" in Source_Names");
9061 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
9063 -- If this is an Ada exception, record it in table Unit_Exceptions
9065 if Src_Data.Unit /= No_Name then
9067 Unit_Except : Unit_Exception :=
9068 Unit_Exceptions.Get (Src_Data.Unit);
9071 Unit_Except.Name := Src_Data.Unit;
9073 if Src_Data.Kind = Spec then
9074 Unit_Except.Spec := Src_Data.File;
9076 Unit_Except.Impl := Src_Data.File;
9079 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
9083 Source := Src_Data.Next_In_Project;
9086 Find_Explicit_Sources
9087 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
9089 -- Mark as such the sources that are declared as excluded
9091 FF := Excluded_Sources_Htable.Get_First;
9092 while FF /= No_File_Found loop
9094 Source := In_Tree.First_Source;
9096 while Source /= No_Source loop
9097 Src_Data := In_Tree.Sources.Table (Source);
9099 if Src_Data.File = FF.File then
9101 -- Check that this is from this project or a project that
9102 -- the current project extends.
9104 if Src_Data.Project = Project or else
9105 Is_Extending (Project, Src_Data.Project, In_Tree)
9107 Src_Data.Locally_Removed := True;
9108 Src_Data.In_Interfaces := False;
9109 In_Tree.Sources.Table (Source) := Src_Data;
9110 Add_Forbidden_File_Name (FF.File);
9116 Source := Src_Data.Next_In_Sources;
9119 if not FF.Found and not OK then
9120 Err_Vars.Error_Msg_File_1 := FF.File;
9121 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
9124 FF := Excluded_Sources_Htable.Get_Next;
9127 -- Check that two sources of this project do not have the same object
9130 Check_Object_File_Names : declare
9132 Src_Data : Source_Data;
9133 Source_Name : File_Name_Type;
9135 procedure Check_Object;
9136 -- Check if object file name of the current source is already in
9137 -- hash table Object_File_Names. If it is, report an error. If it
9138 -- is not, put it there with the file name of the current source.
9144 procedure Check_Object is
9146 Source_Name := Object_File_Names.Get (Src_Data.Object);
9148 if Source_Name /= No_File then
9149 Error_Msg_File_1 := Src_Data.File;
9150 Error_Msg_File_2 := Source_Name;
9154 "{ and { have the same object file name",
9158 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
9162 -- Start of processing for Check_Object_File_Names
9165 Object_File_Names.Reset;
9166 Src_Id := In_Tree.First_Source;
9167 while Src_Id /= No_Source loop
9168 Src_Data := In_Tree.Sources.Table (Src_Id);
9170 if Src_Data.Compiled and then Src_Data.Object_Exists
9171 and then Project_Extends (Project, Src_Data.Project, In_Tree)
9173 if Src_Data.Unit = No_Name then
9174 if Src_Data.Kind = Impl then
9179 case Src_Data.Kind is
9181 if Src_Data.Other_Part = No_Source then
9189 if Src_Data.Other_Part /= No_Source then
9193 -- Check if it is a subunit
9196 Src_Ind : constant Source_File_Index :=
9197 Sinput.P.Load_Project_File
9202 if Sinput.P.Source_File_Is_Subunit
9205 In_Tree.Sources.Table (Src_Id).Kind := Sep;
9215 Src_Id := Src_Data.Next_In_Sources;
9217 end Check_Object_File_Names;
9218 end Process_Sources_In_Multi_Language_Mode;
9220 -- Start of processing for Look_For_Sources
9224 Find_Excluded_Sources (Project, In_Tree, Data);
9228 if Is_A_Language (In_Tree, Data, Name_Ada) then
9229 Find_Explicit_Sources
9230 (Ada_Language_Index, Current_Dir, Project, In_Tree, Data);
9231 Remove_Locally_Removed_Files_From_Units;
9234 if Data.Other_Sources_Present then
9235 Process_Other_Sources_In_Ada_Only_Mode;
9238 when Multi_Language =>
9239 if Data.First_Language_Processing /= No_Language_Index then
9240 Process_Sources_In_Multi_Language_Mode;
9243 end Look_For_Sources;
9249 function Path_Name_Of
9250 (File_Name : File_Name_Type;
9251 Directory : Path_Name_Type) return String
9253 Result : String_Access;
9254 The_Directory : constant String := Get_Name_String (Directory);
9257 Get_Name_String (File_Name);
9260 (File_Name => Name_Buffer (1 .. Name_Len),
9261 Path => The_Directory);
9263 if Result = null then
9266 Canonical_Case_File_Name (Result.all);
9271 -------------------------------
9272 -- Prepare_Ada_Naming_Exceptions --
9273 -------------------------------
9275 procedure Prepare_Ada_Naming_Exceptions
9276 (List : Array_Element_Id;
9277 In_Tree : Project_Tree_Ref;
9278 Kind : Spec_Or_Body)
9280 Current : Array_Element_Id;
9281 Element : Array_Element;
9285 -- Traverse the list
9288 while Current /= No_Array_Element loop
9289 Element := In_Tree.Array_Elements.Table (Current);
9291 if Element.Index /= No_Name then
9294 Unit => Element.Index,
9295 Next => No_Ada_Naming_Exception);
9296 Reverse_Ada_Naming_Exceptions.Set
9297 (Unit, (Element.Value.Value, Element.Value.Index));
9299 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
9300 Ada_Naming_Exception_Table.Increment_Last;
9301 Ada_Naming_Exception_Table.Table
9302 (Ada_Naming_Exception_Table.Last) := Unit;
9303 Ada_Naming_Exceptions.Set
9304 (File_Name_Type (Element.Value.Value),
9305 Ada_Naming_Exception_Table.Last);
9308 Current := Element.Next;
9310 end Prepare_Ada_Naming_Exceptions;
9312 ---------------------
9313 -- Project_Extends --
9314 ---------------------
9316 function Project_Extends
9317 (Extending : Project_Id;
9318 Extended : Project_Id;
9319 In_Tree : Project_Tree_Ref) return Boolean
9321 Current : Project_Id := Extending;
9325 if Current = No_Project then
9328 elsif Current = Extended then
9332 Current := In_Tree.Projects.Table (Current).Extends;
9334 end Project_Extends;
9336 -----------------------
9337 -- Record_Ada_Source --
9338 -----------------------
9340 procedure Record_Ada_Source
9341 (File_Name : File_Name_Type;
9342 Path_Name : Path_Name_Type;
9343 Project : Project_Id;
9344 In_Tree : Project_Tree_Ref;
9345 Data : in out Project_Data;
9346 Location : Source_Ptr;
9347 Current_Source : in out String_List_Id;
9348 Source_Recorded : in out Boolean;
9349 Current_Dir : String)
9351 Canonical_File_Name : File_Name_Type;
9352 Canonical_Path_Name : Path_Name_Type;
9354 Exception_Id : Ada_Naming_Exception_Id;
9355 Unit_Name : Name_Id;
9356 Unit_Kind : Spec_Or_Body;
9357 Unit_Ind : Int := 0;
9359 Name_Index : Name_And_Index;
9360 Needs_Pragma : Boolean;
9362 The_Location : Source_Ptr := Location;
9363 Previous_Source : constant String_List_Id := Current_Source;
9364 Except_Name : Name_And_Index := No_Name_And_Index;
9366 Unit_Prj : Unit_Project;
9368 File_Name_Recorded : Boolean := False;
9371 if Osint.File_Names_Case_Sensitive then
9372 Canonical_File_Name := File_Name;
9373 Canonical_Path_Name := Path_Name;
9375 Get_Name_String (File_Name);
9376 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9377 Canonical_File_Name := Name_Find;
9380 Canonical_Path : constant String :=
9382 (Get_Name_String (Path_Name),
9383 Directory => Current_Dir,
9384 Resolve_Links => Opt.Follow_Links_For_Files,
9385 Case_Sensitive => False);
9388 Add_Str_To_Name_Buffer (Canonical_Path);
9389 Canonical_Path_Name := Name_Find;
9393 -- Find out the unit name, the unit kind and if it needs
9394 -- a specific SFN pragma.
9397 (In_Tree => In_Tree,
9398 Canonical_File_Name => Canonical_File_Name,
9399 Naming => Data.Naming,
9400 Exception_Id => Exception_Id,
9401 Unit_Name => Unit_Name,
9402 Unit_Kind => Unit_Kind,
9403 Needs_Pragma => Needs_Pragma);
9405 if Exception_Id = No_Ada_Naming_Exception
9406 and then Unit_Name = No_Name
9408 if Current_Verbosity = High then
9410 Write_Str (Get_Name_String (Canonical_File_Name));
9411 Write_Line (""" is not a valid source file name (ignored).");
9415 -- Check to see if the source has been hidden by an exception,
9416 -- but only if it is not an exception.
9418 if not Needs_Pragma then
9420 Reverse_Ada_Naming_Exceptions.Get
9421 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
9423 if Except_Name /= No_Name_And_Index then
9424 if Current_Verbosity = High then
9426 Write_Str (Get_Name_String (Canonical_File_Name));
9427 Write_Str (""" contains a unit that is found in """);
9428 Write_Str (Get_Name_String (Except_Name.Name));
9429 Write_Line (""" (ignored).");
9432 -- The file is not included in the source of the project since
9433 -- it is hidden by the exception. So, nothing else to do.
9440 if Exception_Id /= No_Ada_Naming_Exception then
9441 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
9442 Exception_Id := Info.Next;
9443 Info.Next := No_Ada_Naming_Exception;
9444 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
9446 Unit_Name := Info.Unit;
9447 Unit_Ind := Name_Index.Index;
9448 Unit_Kind := Info.Kind;
9451 -- Put the file name in the list of sources of the project
9453 String_Element_Table.Increment_Last (In_Tree.String_Elements);
9454 In_Tree.String_Elements.Table
9455 (String_Element_Table.Last (In_Tree.String_Elements)) :=
9456 (Value => Name_Id (Canonical_File_Name),
9457 Display_Value => Name_Id (File_Name),
9458 Location => No_Location,
9463 if Current_Source = Nil_String then
9465 String_Element_Table.Last (In_Tree.String_Elements);
9466 Data.Sources := Data.Ada_Sources;
9468 In_Tree.String_Elements.Table (Current_Source).Next :=
9469 String_Element_Table.Last (In_Tree.String_Elements);
9473 String_Element_Table.Last (In_Tree.String_Elements);
9475 -- Put the unit in unit list
9478 The_Unit : Unit_Index :=
9479 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
9481 The_Unit_Data : Unit_Data;
9484 if Current_Verbosity = High then
9485 Write_Str ("Putting ");
9486 Write_Str (Get_Name_String (Unit_Name));
9487 Write_Line (" in the unit list.");
9490 -- The unit is already in the list, but may be it is
9491 -- only the other unit kind (spec or body), or what is
9492 -- in the unit list is a unit of a project we are extending.
9494 if The_Unit /= No_Unit_Index then
9495 The_Unit_Data := In_Tree.Units.Table (The_Unit);
9497 if (The_Unit_Data.File_Names (Unit_Kind).Name =
9500 The_Unit_Data.File_Names (Unit_Kind).Path = Slash)
9501 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
9502 or else Project_Extends
9504 The_Unit_Data.File_Names (Unit_Kind).Project,
9507 if The_Unit_Data.File_Names (Unit_Kind).Path = Slash then
9508 Remove_Forbidden_File_Name
9509 (The_Unit_Data.File_Names (Unit_Kind).Name);
9512 -- Record the file name in the hash table Files_Htable
9514 Unit_Prj := (Unit => The_Unit, Project => Project);
9517 Canonical_File_Name,
9520 The_Unit_Data.File_Names (Unit_Kind) :=
9521 (Name => Canonical_File_Name,
9523 Display_Name => File_Name,
9524 Path => Canonical_Path_Name,
9525 Display_Path => Path_Name,
9527 Needs_Pragma => Needs_Pragma);
9528 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9529 Source_Recorded := True;
9531 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
9532 and then (Data.Known_Order_Of_Source_Dirs
9534 The_Unit_Data.File_Names (Unit_Kind).Path =
9535 Canonical_Path_Name)
9537 if Previous_Source = Nil_String then
9538 Data.Ada_Sources := Nil_String;
9539 Data.Sources := Nil_String;
9541 In_Tree.String_Elements.Table (Previous_Source).Next :=
9543 String_Element_Table.Decrement_Last
9544 (In_Tree.String_Elements);
9547 Current_Source := Previous_Source;
9550 -- It is an error to have two units with the same name
9551 -- and the same kind (spec or body).
9553 if The_Location = No_Location then
9555 In_Tree.Projects.Table (Project).Location;
9558 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9560 (Project, In_Tree, "duplicate unit %%", The_Location);
9562 Err_Vars.Error_Msg_Name_1 :=
9563 In_Tree.Projects.Table
9564 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9565 Err_Vars.Error_Msg_File_1 :=
9567 (The_Unit_Data.File_Names (Unit_Kind).Path);
9570 "\ project file %%, {", The_Location);
9572 Err_Vars.Error_Msg_Name_1 :=
9573 In_Tree.Projects.Table (Project).Name;
9574 Err_Vars.Error_Msg_File_1 :=
9575 File_Name_Type (Canonical_Path_Name);
9578 "\ project file %%, {", The_Location);
9581 -- It is a new unit, create a new record
9584 -- First, check if there is no other unit with this file
9585 -- name in another project. If it is, report error but note
9586 -- we do that only for the first unit in the source file.
9589 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
9591 if not File_Name_Recorded and then
9592 Unit_Prj /= No_Unit_Project
9594 Error_Msg_File_1 := File_Name;
9596 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9599 "{ is already a source of project %%",
9603 Unit_Table.Increment_Last (In_Tree.Units);
9604 The_Unit := Unit_Table.Last (In_Tree.Units);
9606 (In_Tree.Units_HT, Unit_Name, The_Unit);
9607 Unit_Prj := (Unit => The_Unit, Project => Project);
9610 Canonical_File_Name,
9612 The_Unit_Data.Name := Unit_Name;
9613 The_Unit_Data.File_Names (Unit_Kind) :=
9614 (Name => Canonical_File_Name,
9616 Display_Name => File_Name,
9617 Path => Canonical_Path_Name,
9618 Display_Path => Path_Name,
9620 Needs_Pragma => Needs_Pragma);
9621 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9622 Source_Recorded := True;
9627 exit when Exception_Id = No_Ada_Naming_Exception;
9628 File_Name_Recorded := True;
9631 end Record_Ada_Source;
9633 --------------------------
9634 -- Record_Other_Sources --
9635 --------------------------
9637 procedure Record_Other_Sources
9638 (Project : Project_Id;
9639 In_Tree : Project_Tree_Ref;
9640 Data : in out Project_Data;
9641 Language : Language_Index;
9642 Naming_Exceptions : Boolean)
9644 Source_Dir : String_List_Id;
9645 Element : String_Element;
9646 Path : Path_Name_Type;
9648 Canonical_Name : File_Name_Type;
9649 Name_Str : String (1 .. 1_024);
9650 Last : Natural := 0;
9652 First_Error : Boolean := True;
9653 Suffix : constant String :=
9654 Body_Suffix_Of (Language, Data, In_Tree);
9657 Source_Dir := Data.Source_Dirs;
9658 while Source_Dir /= Nil_String loop
9659 Element := In_Tree.String_Elements.Table (Source_Dir);
9662 Dir_Path : constant String :=
9663 Get_Name_String (Element.Display_Value);
9665 if Current_Verbosity = High then
9666 Write_Str ("checking directory """);
9667 Write_Str (Dir_Path);
9668 Write_Str (""" for ");
9670 if Naming_Exceptions then
9671 Write_Str ("naming exceptions");
9673 Write_Str ("sources");
9676 Write_Str (" of Language ");
9677 Display_Language_Name (Language);
9680 Open (Dir, Dir_Path);
9683 Read (Dir, Name_Str, Last);
9687 (Dir_Path & Directory_Separator & Name_Str (1 .. Last))
9690 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
9691 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9692 Canonical_Name := Name_Find;
9693 NL := Source_Names.Get (Canonical_Name);
9695 if NL /= No_Name_Location then
9697 if not Data.Known_Order_Of_Source_Dirs then
9698 Error_Msg_File_1 := Canonical_Name;
9701 "{ is found in several source directories",
9707 Source_Names.Set (Canonical_Name, NL);
9708 Name_Len := Dir_Path'Length;
9709 Name_Buffer (1 .. Name_Len) := Dir_Path;
9710 Add_Char_To_Name_Buffer (Directory_Separator);
9711 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
9715 (File_Name => Canonical_Name,
9720 Location => NL.Location,
9721 Language => Language,
9723 Naming_Exception => Naming_Exceptions);
9732 Source_Dir := Element.Next;
9735 if not Naming_Exceptions then
9736 NL := Source_Names.Get_First;
9738 -- It is an error if a source file name in a source list or
9739 -- in a source list file is not found.
9741 while NL /= No_Name_Location loop
9742 if not NL.Found then
9743 Err_Vars.Error_Msg_File_1 := NL.Name;
9747 (Project, In_Tree, "source file { cannot be found",
9749 First_Error := False;
9753 (Project, In_Tree, "\source file { cannot be found",
9758 NL := Source_Names.Get_Next;
9761 -- Any naming exception of this language that is not in a list
9762 -- of sources must be removed.
9765 Source_Id : Other_Source_Id;
9766 Prev_Id : Other_Source_Id;
9767 Source : Other_Source;
9770 Prev_Id := No_Other_Source;
9771 Source_Id := Data.First_Other_Source;
9772 while Source_Id /= No_Other_Source loop
9773 Source := In_Tree.Other_Sources.Table (Source_Id);
9775 if Source.Language = Language
9776 and then Source.Naming_Exception
9778 if Current_Verbosity = High then
9779 Write_Str ("Naming exception """);
9780 Write_Str (Get_Name_String (Source.File_Name));
9781 Write_Str (""" is not in the list of sources,");
9782 Write_Line (" so it is removed.");
9785 if Prev_Id = No_Other_Source then
9786 Data.First_Other_Source := Source.Next;
9788 In_Tree.Other_Sources.Table (Prev_Id).Next := Source.Next;
9791 Source_Id := Source.Next;
9793 if Source_Id = No_Other_Source then
9794 Data.Last_Other_Source := Prev_Id;
9798 Prev_Id := Source_Id;
9799 Source_Id := Source.Next;
9804 end Record_Other_Sources;
9810 procedure Remove_Source
9812 Replaced_By : Source_Id;
9813 Project : Project_Id;
9814 Data : in out Project_Data;
9815 In_Tree : Project_Tree_Ref)
9817 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9821 if Current_Verbosity = High then
9822 Write_Str ("Removing source #");
9823 Write_Line (Id'Img);
9826 if Replaced_By /= No_Source then
9827 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9828 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9829 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9832 -- Remove the source from the global source list
9834 Source := In_Tree.First_Source;
9837 In_Tree.First_Source := Src_Data.Next_In_Sources;
9840 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9841 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9844 In_Tree.Sources.Table (Source).Next_In_Sources :=
9845 Src_Data.Next_In_Sources;
9848 -- Remove the source from the project list
9850 if Src_Data.Project = Project then
9851 Source := Data.First_Source;
9854 Data.First_Source := Src_Data.Next_In_Project;
9856 if Src_Data.Next_In_Project = No_Source then
9857 Data.Last_Source := No_Source;
9861 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9862 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9865 In_Tree.Sources.Table (Source).Next_In_Project :=
9866 Src_Data.Next_In_Project;
9868 if Src_Data.Next_In_Project = No_Source then
9869 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9874 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9877 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9878 Src_Data.Next_In_Project;
9880 if Src_Data.Next_In_Project = No_Source then
9881 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9886 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9887 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9890 In_Tree.Sources.Table (Source).Next_In_Project :=
9891 Src_Data.Next_In_Project;
9893 if Src_Data.Next_In_Project = No_Source then
9894 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9899 -- Remove source from the language list
9901 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9904 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9905 Src_Data.Next_In_Lang;
9908 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9909 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9912 In_Tree.Sources.Table (Source).Next_In_Lang :=
9913 Src_Data.Next_In_Lang;
9917 -----------------------
9918 -- Report_No_Sources --
9919 -----------------------
9921 procedure Report_No_Sources
9922 (Project : Project_Id;
9924 In_Tree : Project_Tree_Ref;
9925 Location : Source_Ptr;
9926 Continuation : Boolean := False)
9929 case When_No_Sources is
9933 when Warning | Error =>
9935 Msg : constant String :=
9938 " sources in this project";
9941 Error_Msg_Warn := When_No_Sources = Warning;
9943 if Continuation then
9945 (Project, In_Tree, "\" & Msg, Location);
9949 (Project, In_Tree, Msg, Location);
9953 end Report_No_Sources;
9955 ----------------------
9956 -- Show_Source_Dirs --
9957 ----------------------
9959 procedure Show_Source_Dirs
9960 (Data : Project_Data;
9961 In_Tree : Project_Tree_Ref)
9963 Current : String_List_Id;
9964 Element : String_Element;
9967 Write_Line ("Source_Dirs:");
9969 Current := Data.Source_Dirs;
9970 while Current /= Nil_String loop
9971 Element := In_Tree.String_Elements.Table (Current);
9973 Write_Line (Get_Name_String (Element.Value));
9974 Current := Element.Next;
9977 Write_Line ("end Source_Dirs.");
9978 end Show_Source_Dirs;
9985 (Language : Language_Index;
9986 Naming : Naming_Data;
9987 In_Tree : Project_Tree_Ref) return File_Name_Type
9989 Suffix : constant Variable_Value :=
9991 (Index => Language_Names.Table (Language),
9993 In_Array => Naming.Body_Suffix,
9994 In_Tree => In_Tree);
9997 -- If no suffix for this language in package Naming, use the default
9999 if Suffix = Nil_Variable_Value then
10003 when Ada_Language_Index =>
10004 Add_Str_To_Name_Buffer (".adb");
10006 when C_Language_Index =>
10007 Add_Str_To_Name_Buffer (".c");
10009 when C_Plus_Plus_Language_Index =>
10010 Add_Str_To_Name_Buffer (".cpp");
10016 -- Otherwise use the one specified
10019 Get_Name_String (Suffix.Value);
10022 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
10026 -------------------------
10027 -- Warn_If_Not_Sources --
10028 -------------------------
10030 -- comments needed in this body ???
10032 procedure Warn_If_Not_Sources
10033 (Project : Project_Id;
10034 In_Tree : Project_Tree_Ref;
10035 Conventions : Array_Element_Id;
10037 Extending : Boolean)
10039 Conv : Array_Element_Id;
10041 The_Unit_Id : Unit_Index;
10042 The_Unit_Data : Unit_Data;
10043 Location : Source_Ptr;
10046 Conv := Conventions;
10047 while Conv /= No_Array_Element loop
10048 Unit := In_Tree.Array_Elements.Table (Conv).Index;
10049 Error_Msg_Name_1 := Unit;
10050 Get_Name_String (Unit);
10051 To_Lower (Name_Buffer (1 .. Name_Len));
10053 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
10054 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
10056 if The_Unit_Id = No_Unit_Index then
10057 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
10060 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
10061 Error_Msg_Name_2 :=
10062 In_Tree.Array_Elements.Table (Conv).Value.Value;
10065 if not Check_Project
10066 (The_Unit_Data.File_Names (Specification).Project,
10067 Project, In_Tree, Extending)
10071 "?source of spec of unit %% (%%)" &
10072 " cannot be found in this project",
10077 if not Check_Project
10078 (The_Unit_Data.File_Names (Body_Part).Project,
10079 Project, In_Tree, Extending)
10083 "?source of body of unit %% (%%)" &
10084 " cannot be found in this project",
10090 Conv := In_Tree.Array_Elements.Table (Conv).Next;
10092 end Warn_If_Not_Sources;