1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
30 with Err_Vars; use Err_Vars;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
39 with Prj.Util; use Prj.Util;
41 with Snames; use Snames;
42 with Table; use Table;
43 with Targparm; use Targparm;
45 with Ada.Characters.Handling; use Ada.Characters.Handling;
46 with Ada.Directories; use Ada.Directories;
47 with Ada.Strings; use Ada.Strings;
48 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
49 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
51 package body Prj.Nmsc is
53 No_Continuation_String : aliased String := "";
54 Continuation_String : aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
68 type Name_Location is record
69 Name : File_Name_Type;
70 Location : Source_Ptr;
71 Source : Source_Id := No_Source;
72 Except : Boolean := False;
73 Found : Boolean := False;
75 -- Information about file names found in string list attribute
76 -- Source_Files or in a source list file, stored in hash table
77 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
79 No_Name_Location : constant Name_Location :=
81 Location => No_Location,
86 package Source_Names is new GNAT.HTable.Simple_HTable
87 (Header_Num => Header_Num,
88 Element => Name_Location,
89 No_Element => No_Name_Location,
90 Key => File_Name_Type,
93 -- Hash table to store file names found in string list attribute
94 -- Source_Files or in a source list file, stored in hash table
95 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97 -- More documentation needed on what unit exceptions are about ???
99 type Unit_Exception is record
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
104 -- Record special naming schemes for Ada units (name of spec file and name
105 -- of implementation file).
107 No_Unit_Exception : constant Unit_Exception :=
112 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
113 (Header_Num => Header_Num,
114 Element => Unit_Exception,
115 No_Element => No_Unit_Exception,
119 -- Hash table to store the unit exceptions
121 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
122 (Header_Num => Header_Num,
128 -- Hash table to store recursive source directories, to avoid looking
129 -- several times, and to avoid cycles that may be introduced by symbolic
132 type Ada_Naming_Exception_Id is new Nat;
133 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
135 type Unit_Info is record
138 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
142 -- Why is the following commented out ???
143 -- No_Unit : constant Unit_Info :=
144 -- (Specification, No_Name, No_Ada_Naming_Exception);
146 package Ada_Naming_Exception_Table is new Table.Table
147 (Table_Component_Type => Unit_Info,
148 Table_Index_Type => Ada_Naming_Exception_Id,
149 Table_Low_Bound => 1,
151 Table_Increment => 100,
152 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
154 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
155 (Header_Num => Header_Num,
156 Element => Ada_Naming_Exception_Id,
157 No_Element => No_Ada_Naming_Exception,
158 Key => File_Name_Type,
161 -- A hash table to store naming exceptions for Ada. For each file name
162 -- there is one or several unit in table Ada_Naming_Exception_Table.
164 package Object_File_Names is new GNAT.HTable.Simple_HTable
165 (Header_Num => Header_Num,
166 Element => File_Name_Type,
167 No_Element => No_File,
168 Key => File_Name_Type,
171 -- A hash table to store the object file names for a project, to check that
172 -- two different sources have different object file names.
174 type File_Found is record
175 File : File_Name_Type := No_File;
176 Found : Boolean := False;
177 Location : Source_Ptr := No_Location;
179 No_File_Found : constant File_Found := (No_File, False, No_Location);
180 -- Comments needed ???
182 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
183 (Header_Num => Header_Num,
184 Element => File_Found,
185 No_Element => No_File_Found,
186 Key => File_Name_Type,
189 -- A hash table to store the excluded files, if any. This is filled by
190 -- Find_Excluded_Sources below.
192 procedure Find_Excluded_Sources
193 (Project : Project_Id;
194 In_Tree : Project_Tree_Ref;
195 Data : Project_Data);
196 -- Find the list of files that should not be considered as source files
197 -- for this project. Sets the list in the Excluded_Sources_Htable.
199 function Hash (Unit : Unit_Info) return Header_Num;
201 type Name_And_Index is record
202 Name : Name_Id := No_Name;
205 No_Name_And_Index : constant Name_And_Index :=
206 (Name => No_Name, Index => 0);
208 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
209 (Header_Num => Header_Num,
210 Element => Name_And_Index,
211 No_Element => No_Name_And_Index,
215 -- A table to check if a unit with an exceptional name will hide a source
216 -- with a file name following the naming convention.
218 procedure Load_Naming_Exceptions
219 (Project : Project_Id;
220 In_Tree : Project_Tree_Ref;
221 Data : in out Project_Data);
222 -- All source files in Data.First_Source are considered as naming
223 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
228 Data : in out Project_Data;
229 In_Tree : Project_Tree_Ref;
230 Project : Project_Id;
232 Lang_Id : Language_Index;
234 File_Name : File_Name_Type;
235 Display_File : File_Name_Type;
236 Lang_Kind : Language_Kind;
237 Naming_Exception : Boolean := False;
238 Path : Path_Name_Type := No_Path;
239 Display_Path : Path_Name_Type := No_Path;
240 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
241 Other_Part : Source_Id := No_Source;
242 Unit : Name_Id := No_Name;
244 Source_To_Replace : Source_Id := No_Source);
245 -- Add a new source to the different lists: list of all sources in the
246 -- project tree, list of source of a project and list of sources of a
249 -- If Path is specified, the file is also added to Source_Paths_HT.
250 -- If Source_To_Replace is specified, it points to the source in the
251 -- extended project that the new file is overriding.
253 function ALI_File_Name (Source : String) return String;
254 -- Return the ALI file name corresponding to a source
256 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
257 -- Check that a name is a valid Ada unit name
259 procedure Check_Naming_Schemes
260 (Data : in out Project_Data;
261 Project : Project_Id;
262 In_Tree : Project_Tree_Ref);
263 -- Check the naming scheme part of Data
265 procedure Check_Ada_Naming_Scheme_Validity
266 (Project : Project_Id;
267 In_Tree : Project_Tree_Ref;
268 Naming : Naming_Data);
269 -- Check that the package Naming is correct
271 procedure Check_Configuration
272 (Project : Project_Id;
273 In_Tree : Project_Tree_Ref;
274 Data : in out Project_Data);
275 -- Check the configuration attributes for the project
277 procedure Check_If_Externally_Built
278 (Project : Project_Id;
279 In_Tree : Project_Tree_Ref;
280 Data : in out Project_Data);
281 -- Check attribute Externally_Built of project Project in project tree
282 -- In_Tree and modify its data Data if it has the value "true".
284 procedure Check_Interfaces
285 (Project : Project_Id;
286 In_Tree : Project_Tree_Ref;
287 Data : in out Project_Data);
288 -- If a list of sources is specified in attribute Interfaces, set
289 -- In_Interfaces only for the sources specified in the list.
291 procedure Check_Library_Attributes
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Current_Dir : String;
295 Data : in out Project_Data);
296 -- Check the library attributes of project Project in project tree In_Tree
297 -- and modify its data Data accordingly.
298 -- Current_Dir should represent the current directory, and is passed for
299 -- efficiency to avoid system calls to recompute it.
301 procedure Check_Package_Naming
302 (Project : Project_Id;
303 In_Tree : Project_Tree_Ref;
304 Data : in out Project_Data);
305 -- Check package Naming of project Project in project tree In_Tree and
306 -- modify its data Data accordingly.
308 procedure Check_Programming_Languages
309 (In_Tree : Project_Tree_Ref;
310 Project : Project_Id;
311 Data : in out Project_Data);
312 -- Check attribute Languages for the project with data Data in project
313 -- tree In_Tree and set the components of Data for all the programming
314 -- languages indicated in attribute Languages, if any.
316 function Check_Project
318 Root_Project : Project_Id;
319 In_Tree : Project_Tree_Ref;
320 Extending : Boolean) return Boolean;
321 -- Returns True if P is Root_Project or, if Extending is True, a project
322 -- extended by Root_Project.
324 procedure Check_Stand_Alone_Library
325 (Project : Project_Id;
326 In_Tree : Project_Tree_Ref;
327 Data : in out Project_Data;
328 Current_Dir : String;
329 Extending : Boolean);
330 -- Check if project Project in project tree In_Tree is a Stand-Alone
331 -- Library project, and modify its data Data accordingly if it is one.
332 -- Current_Dir should represent the current directory, and is passed for
333 -- efficiency to avoid system calls to recompute it.
335 procedure Get_Path_Names_And_Record_Ada_Sources
336 (Project : Project_Id;
337 In_Tree : Project_Tree_Ref;
338 Data : in out Project_Data;
339 Current_Dir : String);
340 -- Find the path names of the source files in the Source_Names table
341 -- in the source directories and record those that are Ada sources.
343 function Compute_Directory_Last (Dir : String) return Natural;
344 -- Return the index of the last significant character in Dir. This is used
345 -- to avoid duplicate '/' (slash) characters at the end of directory names.
348 (Project : Project_Id;
349 In_Tree : Project_Tree_Ref;
351 Flag_Location : Source_Ptr);
352 -- Output an error message. If Error_Report is null, simply call
353 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
356 procedure Find_Ada_Sources
357 (Project : Project_Id;
358 In_Tree : Project_Tree_Ref;
359 Data : in out Project_Data;
360 Current_Dir : String);
361 -- Find all the Ada sources in all of the source directories of a project
362 -- Current_Dir should represent the current directory, and is passed for
363 -- efficiency to avoid system calls to recompute it.
365 procedure Search_Directories
366 (Project : Project_Id;
367 In_Tree : Project_Tree_Ref;
368 Data : in out Project_Data;
369 For_All_Sources : Boolean);
370 -- Search the source directories to find the sources.
371 -- If For_All_Sources is True, check each regular file name against the
372 -- naming schemes of the different languages. Otherwise consider only the
373 -- file names in the hash table Source_Names.
376 (Project : Project_Id;
377 In_Tree : Project_Tree_Ref;
378 Data : in out Project_Data;
380 File_Name : File_Name_Type;
381 Display_File_Name : File_Name_Type;
382 Source_Directory : String;
383 For_All_Sources : Boolean);
384 -- Check if file File_Name is a valid source of the project. This is used
385 -- in multi-language mode only.
386 -- When the file matches one of the naming schemes, it is added to
387 -- various htables through Add_Source and to Source_Paths_Htable.
389 -- Name is the name of the candidate file. It hasn't been normalized yet
390 -- and is the direct result of readdir().
392 -- File_Name is the same as Name, but has been normalized.
393 -- Display_File_Name, however, has not been normalized.
395 -- Source_Directory is the directory in which the file
396 -- was found. It hasn't been normalized (nor has had links resolved).
397 -- It should not end with a directory separator, to avoid duplicates
400 -- If For_All_Sources is True, then all possible file names are analyzed
401 -- otherwise only those currently set in the Source_Names htable.
403 procedure Check_Naming_Schemes
404 (In_Tree : Project_Tree_Ref;
405 Data : in out Project_Data;
407 File_Name : File_Name_Type;
408 Alternate_Languages : out Alternate_Language_Id;
409 Language : out Language_Index;
410 Language_Name : out Name_Id;
411 Display_Language_Name : out Name_Id;
413 Lang_Kind : out Language_Kind;
414 Kind : out Source_Kind);
415 -- Check if the file name File_Name conforms to one of the naming
416 -- schemes of the project.
418 -- If the file does not match one of the naming schemes, set Language
419 -- to No_Language_Index.
421 -- Filename is the name of the file being investigated. It has been
422 -- normalized (case-folded). File_Name is the same value.
424 procedure Free_Ada_Naming_Exceptions;
425 -- Free the internal hash tables used for checking naming exceptions
427 procedure Get_Directories
428 (Project : Project_Id;
429 In_Tree : Project_Tree_Ref;
430 Current_Dir : String;
431 Data : in out Project_Data);
432 -- Get the object directory, the exec directory and the source directories
435 -- Current_Dir should represent the current directory, and is passed for
436 -- efficiency to avoid system calls to recompute it.
439 (Project : Project_Id;
440 In_Tree : Project_Tree_Ref;
441 Data : in out Project_Data);
442 -- Get the mains of a project from attribute Main, if it exists, and put
443 -- them in the project data.
445 procedure Get_Sources_From_File
447 Location : Source_Ptr;
448 Project : Project_Id;
449 In_Tree : Project_Tree_Ref);
450 -- Get the list of sources from a text file and put them in hash table
453 procedure Find_Explicit_Sources
454 (Current_Dir : String;
455 Project : Project_Id;
456 In_Tree : Project_Tree_Ref;
457 Data : in out Project_Data);
458 -- Process the Source_Files and Source_List_File attributes, and store
459 -- the list of source files into the Source_Names htable.
461 -- Lang indicates which language is being processed when in Ada_Only mode
462 -- (all languages are processed anyway when in Multi_Language mode).
465 (In_Tree : Project_Tree_Ref;
466 Canonical_File_Name : File_Name_Type;
467 Naming : Naming_Data;
468 Exception_Id : out Ada_Naming_Exception_Id;
469 Unit_Name : out Name_Id;
470 Unit_Kind : out Spec_Or_Body;
471 Needs_Pragma : out Boolean);
472 -- Find out, from a file name, the unit name, the unit kind and if a
473 -- specific SFN pragma is needed. If the file name corresponds to no unit,
474 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
475 -- exception to the naming scheme, then Exception_Id is set to the unit or
476 -- units that the source contains.
478 function Is_Illegal_Suffix
480 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
481 -- Returns True if the string Suffix cannot be used as a spec suffix, a
482 -- body suffix or a separate suffix.
484 procedure Locate_Directory
485 (Project : Project_Id;
486 In_Tree : Project_Tree_Ref;
487 Name : File_Name_Type;
488 Parent : Path_Name_Type;
489 Dir : out Path_Name_Type;
490 Display : out Path_Name_Type;
491 Create : String := "";
492 Current_Dir : String;
493 Location : Source_Ptr := No_Location;
494 Externally_Built : Boolean := False);
495 -- Locate a directory. Name is the directory name. Parent is the root
496 -- directory, if Name a relative path name. Dir is set to the canonical
497 -- case path name of the directory, and Display is the directory path name
498 -- for display purposes. If the directory does not exist and Setup_Projects
499 -- is True and Create is a non null string, an attempt is made to create
500 -- the directory. If the directory does not exist and Setup_Projects is
501 -- false, then Dir and Display are set to No_Name.
503 -- Current_Dir should represent the current directory, and is passed for
504 -- efficiency to avoid system calls to recompute it.
506 procedure Look_For_Sources
507 (Project : Project_Id;
508 In_Tree : Project_Tree_Ref;
509 Data : in out Project_Data;
510 Current_Dir : String);
511 -- Find all the sources of project Project in project tree In_Tree and
512 -- update its Data accordingly. This assumes that Data.First_Source has
513 -- been initialized with the list of excluded sources.
515 -- Current_Dir should represent the current directory, and is passed for
516 -- efficiency to avoid system calls to recompute it.
518 function Path_Name_Of
519 (File_Name : File_Name_Type;
520 Directory : Path_Name_Type) return String;
521 -- Returns the path name of a (non project) file. Returns an empty string
522 -- if file cannot be found.
524 procedure Prepare_Ada_Naming_Exceptions
525 (List : Array_Element_Id;
526 In_Tree : Project_Tree_Ref;
527 Kind : Spec_Or_Body);
528 -- Prepare the internal hash tables used for checking naming exceptions
529 -- for Ada. Insert all elements of List in the tables.
531 procedure Record_Ada_Source
532 (File_Name : File_Name_Type;
533 Path_Name : Path_Name_Type;
534 Project : Project_Id;
535 In_Tree : Project_Tree_Ref;
536 Data : in out Project_Data;
537 Location : Source_Ptr;
538 Current_Source : in out String_List_Id;
539 Source_Recorded : in out Boolean;
540 Current_Dir : String);
541 -- Put a unit in the list of units of a project, if the file name
542 -- corresponds to a valid unit name.
544 -- Current_Dir should represent the current directory, and is passed for
545 -- efficiency to avoid system calls to recompute it.
547 procedure Remove_Source
549 Replaced_By : Source_Id;
550 Project : Project_Id;
551 Data : in out Project_Data;
552 In_Tree : Project_Tree_Ref);
555 procedure Report_No_Sources
556 (Project : Project_Id;
558 In_Tree : Project_Tree_Ref;
559 Location : Source_Ptr;
560 Continuation : Boolean := False);
561 -- Report an error or a warning depending on the value of When_No_Sources
562 -- when there are no sources for language Lang_Name.
564 procedure Show_Source_Dirs
565 (Data : Project_Data; In_Tree : Project_Tree_Ref);
566 -- List all the source directories of a project
568 procedure Warn_If_Not_Sources
569 (Project : Project_Id;
570 In_Tree : Project_Tree_Ref;
571 Conventions : Array_Element_Id;
573 Extending : Boolean);
574 -- Check that individual naming conventions apply to immediate sources of
575 -- the project. If not, issue a warning.
583 Data : in out Project_Data;
584 In_Tree : Project_Tree_Ref;
585 Project : Project_Id;
587 Lang_Id : Language_Index;
589 File_Name : File_Name_Type;
590 Display_File : File_Name_Type;
591 Lang_Kind : Language_Kind;
592 Naming_Exception : Boolean := False;
593 Path : Path_Name_Type := No_Path;
594 Display_Path : Path_Name_Type := No_Path;
595 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
596 Other_Part : Source_Id := No_Source;
597 Unit : Name_Id := No_Name;
599 Source_To_Replace : Source_Id := No_Source)
601 Source : constant Source_Id := Data.Last_Source;
602 Src_Data : Source_Data := No_Source_Data;
603 Config : constant Language_Config :=
604 In_Tree.Languages_Data.Table (Lang_Id).Config;
607 -- This is a new source so create an entry for it in the Sources table
609 Source_Data_Table.Increment_Last (In_Tree.Sources);
610 Id := Source_Data_Table.Last (In_Tree.Sources);
612 if Current_Verbosity = High then
613 Write_Str ("Adding source #");
615 Write_Str (", File : ");
616 Write_Str (Get_Name_String (File_Name));
618 if Lang_Kind = Unit_Based then
619 Write_Str (", Unit : ");
620 Write_Str (Get_Name_String (Unit));
626 Src_Data.Project := Project;
627 Src_Data.Language_Name := Lang;
628 Src_Data.Language := Lang_Id;
629 Src_Data.Lang_Kind := Lang_Kind;
630 Src_Data.Compiled := In_Tree.Languages_Data.Table
631 (Lang_Id).Config.Compiler_Driver /=
633 Src_Data.Kind := Kind;
634 Src_Data.Alternate_Languages := Alternate_Languages;
635 Src_Data.Other_Part := Other_Part;
637 Src_Data.Object_Exists := Config.Object_Generated;
638 Src_Data.Object_Linked := Config.Objects_Linked;
640 if Other_Part /= No_Source then
641 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
644 Src_Data.Unit := Unit;
645 Src_Data.Index := Index;
646 Src_Data.File := File_Name;
647 Src_Data.Display_File := Display_File;
648 Src_Data.Dependency := In_Tree.Languages_Data.Table
649 (Lang_Id).Config.Dependency_Kind;
650 Src_Data.Dep_Name := Dependency_Name
651 (File_Name, Src_Data.Dependency);
652 Src_Data.Naming_Exception := Naming_Exception;
654 if Src_Data.Compiled and then Src_Data.Object_Exists then
656 Object_Name (File_Name, Config.Object_File_Suffix);
657 Src_Data.Switches := Switches_Name (File_Name);
660 if Path /= No_Path then
661 Src_Data.Path := (Path, Display_Path);
662 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
665 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
668 if Unit /= No_Name then
669 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
672 -- Add the source to the global list
674 Src_Data.Next_In_Sources := In_Tree.First_Source;
675 In_Tree.First_Source := Id;
677 -- Add the source to the project list
679 if Source = No_Source then
680 Data.First_Source := Id;
682 In_Tree.Sources.Table (Source).Next_In_Project := Id;
685 Data.Last_Source := Id;
687 -- Add the source to the language list
689 Src_Data.Next_In_Lang :=
690 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
691 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
693 In_Tree.Sources.Table (Id) := Src_Data;
695 if Source_To_Replace /= No_Source then
696 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
704 function ALI_File_Name (Source : String) return String is
706 -- If the source name has an extension, then replace it with
709 for Index in reverse Source'First + 1 .. Source'Last loop
710 if Source (Index) = '.' then
711 return Source (Source'First .. Index - 1) & ALI_Suffix;
715 -- If there is no dot, or if it is the first character, just add the
718 return Source & ALI_Suffix;
726 (Project : Project_Id;
727 In_Tree : Project_Tree_Ref;
728 Report_Error : Put_Line_Access;
729 When_No_Sources : Error_Warning;
730 Current_Dir : String)
732 Data : Project_Data := In_Tree.Projects.Table (Project);
733 Extending : Boolean := False;
736 Nmsc.When_No_Sources := When_No_Sources;
737 Error_Report := Report_Error;
739 Recursive_Dirs.Reset;
741 Check_If_Externally_Built (Project, In_Tree, Data);
743 -- Object, exec and source directories
745 Get_Directories (Project, In_Tree, Current_Dir, Data);
747 -- Get the programming languages
749 Check_Programming_Languages (In_Tree, Project, Data);
751 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
754 "an abstract project needs to have no language, no sources " &
755 "or no source directories",
759 -- Check configuration in multi language mode
761 if Must_Check_Configuration then
762 Check_Configuration (Project, In_Tree, Data);
765 -- Library attributes
767 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
769 if Current_Verbosity = High then
770 Show_Source_Dirs (Data, In_Tree);
773 Check_Package_Naming (Project, In_Tree, Data);
775 Extending := Data.Extends /= No_Project;
777 Check_Naming_Schemes (Data, Project, In_Tree);
779 if Get_Mode = Ada_Only then
780 Prepare_Ada_Naming_Exceptions
781 (Data.Naming.Bodies, In_Tree, Body_Part);
782 Prepare_Ada_Naming_Exceptions
783 (Data.Naming.Specs, In_Tree, Specification);
788 if Data.Source_Dirs /= Nil_String then
789 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
791 if Get_Mode = Ada_Only then
793 -- Check that all individual naming conventions apply to sources
794 -- of this project file.
797 (Project, In_Tree, Data.Naming.Bodies,
799 Extending => Extending);
801 (Project, In_Tree, Data.Naming.Specs,
803 Extending => Extending);
805 elsif Get_Mode = Multi_Language and then
806 (not Data.Externally_Built) and then
810 Language : Language_Index;
812 Alt_Lang : Alternate_Language_Id;
813 Alt_Lang_Data : Alternate_Language_Data;
814 Continuation : Boolean := False;
817 Language := Data.First_Language_Processing;
818 while Language /= No_Language_Index loop
819 Source := Data.First_Source;
820 Source_Loop : while Source /= No_Source loop
822 Src_Data : Source_Data renames
823 In_Tree.Sources.Table (Source);
826 exit Source_Loop when Src_Data.Language = Language;
828 Alt_Lang := Src_Data.Alternate_Languages;
831 while Alt_Lang /= No_Alternate_Language loop
833 In_Tree.Alt_Langs.Table (Alt_Lang);
835 when Alt_Lang_Data.Language = Language;
836 Alt_Lang := Alt_Lang_Data.Next;
837 end loop Alternate_Loop;
839 Source := Src_Data.Next_In_Project;
841 end loop Source_Loop;
843 if Source = No_Source then
847 (In_Tree.Languages_Data.Table
848 (Language).Display_Name),
852 Continuation := True;
855 Language := In_Tree.Languages_Data.Table (Language).Next;
861 if Get_Mode = Multi_Language then
863 -- If a list of sources is specified in attribute Interfaces, set
864 -- In_Interfaces only for the sources specified in the list.
866 Check_Interfaces (Project, In_Tree, Data);
869 -- If it is a library project file, check if it is a standalone library
872 Check_Stand_Alone_Library
873 (Project, In_Tree, Data, Current_Dir, Extending);
876 -- Put the list of Mains, if any, in the project data
878 Get_Mains (Project, In_Tree, Data);
880 -- Update the project data in the Projects table
882 In_Tree.Projects.Table (Project) := Data;
884 Free_Ada_Naming_Exceptions;
891 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
892 The_Name : String := Name;
894 Need_Letter : Boolean := True;
895 Last_Underscore : Boolean := False;
896 OK : Boolean := The_Name'Length > 0;
899 function Is_Reserved (Name : Name_Id) return Boolean;
900 function Is_Reserved (S : String) return Boolean;
901 -- Check that the given name is not an Ada 95 reserved word. The reason
902 -- for the Ada 95 here is that we do not want to exclude the case of an
903 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
904 -- name would be rejected anyway by the compiler. That means there is no
905 -- requirement that the project file parser reject this.
911 function Is_Reserved (S : String) return Boolean is
914 Add_Str_To_Name_Buffer (S);
915 return Is_Reserved (Name_Find);
922 function Is_Reserved (Name : Name_Id) return Boolean is
924 if Get_Name_Table_Byte (Name) /= 0
925 and then Name /= Name_Project
926 and then Name /= Name_Extends
927 and then Name /= Name_External
928 and then Name not in Ada_2005_Reserved_Words
932 if Current_Verbosity = High then
933 Write_Str (The_Name);
934 Write_Line (" is an Ada reserved word.");
944 -- Start of processing for Check_Ada_Name
949 Name_Len := The_Name'Length;
950 Name_Buffer (1 .. Name_Len) := The_Name;
952 -- Special cases of children of packages A, G, I and S on VMS
955 and then Name_Len > 3
956 and then Name_Buffer (2 .. 3) = "__"
958 ((Name_Buffer (1) = 'a') or else
959 (Name_Buffer (1) = 'g') or else
960 (Name_Buffer (1) = 'i') or else
961 (Name_Buffer (1) = 's'))
963 Name_Buffer (2) := '.';
964 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
965 Name_Len := Name_Len - 1;
968 Real_Name := Name_Find;
970 if Is_Reserved (Real_Name) then
974 First := The_Name'First;
976 for Index in The_Name'Range loop
979 -- We need a letter (at the beginning, and following a dot),
980 -- but we don't have one.
982 if Is_Letter (The_Name (Index)) then
983 Need_Letter := False;
988 if Current_Verbosity = High then
989 Write_Int (Types.Int (Index));
991 Write_Char (The_Name (Index));
992 Write_Line ("' is not a letter.");
998 elsif Last_Underscore
999 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1001 -- Two underscores are illegal, and a dot cannot follow
1006 if Current_Verbosity = High then
1007 Write_Int (Types.Int (Index));
1009 Write_Char (The_Name (Index));
1010 Write_Line ("' is illegal here.");
1015 elsif The_Name (Index) = '.' then
1017 -- First, check if the name before the dot is not a reserved word
1018 if Is_Reserved (The_Name (First .. Index - 1)) then
1024 -- We need a letter after a dot
1026 Need_Letter := True;
1028 elsif The_Name (Index) = '_' then
1029 Last_Underscore := True;
1032 -- We need an letter or a digit
1034 Last_Underscore := False;
1036 if not Is_Alphanumeric (The_Name (Index)) then
1039 if Current_Verbosity = High then
1040 Write_Int (Types.Int (Index));
1042 Write_Char (The_Name (Index));
1043 Write_Line ("' is not alphanumeric.");
1051 -- Cannot end with an underscore or a dot
1053 OK := OK and then not Need_Letter and then not Last_Underscore;
1056 if First /= Name'First and then
1057 Is_Reserved (The_Name (First .. The_Name'Last))
1065 -- Signal a problem with No_Name
1071 --------------------------------------
1072 -- Check_Ada_Naming_Scheme_Validity --
1073 --------------------------------------
1075 procedure Check_Ada_Naming_Scheme_Validity
1076 (Project : Project_Id;
1077 In_Tree : Project_Tree_Ref;
1078 Naming : Naming_Data)
1081 -- Only check if we are not using the Default naming scheme
1083 if Naming /= In_Tree.Private_Part.Default_Naming then
1085 Dot_Replacement : constant String :=
1087 (Naming.Dot_Replacement);
1089 Spec_Suffix : constant String :=
1090 Spec_Suffix_Of (In_Tree, "ada", Naming);
1092 Body_Suffix : constant String :=
1093 Body_Suffix_Of (In_Tree, "ada", Naming);
1095 Separate_Suffix : constant String :=
1097 (Naming.Separate_Suffix);
1100 -- Dot_Replacement cannot
1103 -- - start or end with an alphanumeric
1104 -- - be a single '_'
1105 -- - start with an '_' followed by an alphanumeric
1106 -- - contain a '.' except if it is "."
1108 if Dot_Replacement'Length = 0
1109 or else Is_Alphanumeric
1110 (Dot_Replacement (Dot_Replacement'First))
1111 or else Is_Alphanumeric
1112 (Dot_Replacement (Dot_Replacement'Last))
1113 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1115 (Dot_Replacement'Length = 1
1118 (Dot_Replacement (Dot_Replacement'First + 1))))
1119 or else (Dot_Replacement'Length > 1
1121 Index (Source => Dot_Replacement,
1122 Pattern => ".") /= 0)
1126 '"' & Dot_Replacement &
1127 """ is illegal for Dot_Replacement.",
1128 Naming.Dot_Repl_Loc);
1134 if Is_Illegal_Suffix
1135 (Spec_Suffix, Dot_Replacement = ".")
1137 Err_Vars.Error_Msg_File_1 :=
1138 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1141 "{ is illegal for Spec_Suffix",
1142 Naming.Ada_Spec_Suffix_Loc);
1145 if Is_Illegal_Suffix
1146 (Body_Suffix, Dot_Replacement = ".")
1148 Err_Vars.Error_Msg_File_1 :=
1149 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1152 "{ is illegal for Body_Suffix",
1153 Naming.Ada_Body_Suffix_Loc);
1156 if Body_Suffix /= Separate_Suffix then
1157 if Is_Illegal_Suffix
1158 (Separate_Suffix, Dot_Replacement = ".")
1160 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1163 "{ is illegal for Separate_Suffix",
1164 Naming.Sep_Suffix_Loc);
1168 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1169 -- since that would cause a clear ambiguity. Note that we do
1170 -- allow a Spec_Suffix to have the same termination as one of
1171 -- these, which causes a potential ambiguity, but we resolve
1172 -- that my matching the longest possible suffix.
1174 if Spec_Suffix = Body_Suffix then
1179 """) cannot be the same as Spec_Suffix.",
1180 Naming.Ada_Body_Suffix_Loc);
1183 if Body_Suffix /= Separate_Suffix
1184 and then Spec_Suffix = Separate_Suffix
1188 "Separate_Suffix (""" &
1190 """) cannot be the same as Spec_Suffix.",
1191 Naming.Sep_Suffix_Loc);
1195 end Check_Ada_Naming_Scheme_Validity;
1197 -------------------------
1198 -- Check_Configuration --
1199 -------------------------
1201 procedure Check_Configuration
1202 (Project : Project_Id;
1203 In_Tree : Project_Tree_Ref;
1204 Data : in out Project_Data)
1206 Dot_Replacement : File_Name_Type := No_File;
1207 Casing : Casing_Type := All_Lower_Case;
1208 Separate_Suffix : File_Name_Type := No_File;
1210 Lang_Index : Language_Index := No_Language_Index;
1211 -- The index of the language data being checked
1213 Prev_Index : Language_Index := No_Language_Index;
1214 -- The index of the previous language
1216 Current_Language : Name_Id := No_Name;
1217 -- The name of the language
1219 Lang_Data : Language_Data;
1220 -- The data of the language being checked
1222 procedure Get_Language_Index_Of (Language : Name_Id);
1223 -- Get the language index of Language, if Language is one of the
1224 -- languages of the project.
1226 procedure Process_Project_Level_Simple_Attributes;
1227 -- Process the simple attributes at the project level
1229 procedure Process_Project_Level_Array_Attributes;
1230 -- Process the associate array attributes at the project level
1232 procedure Process_Packages;
1233 -- Read the packages of the project
1235 ---------------------------
1236 -- Get_Language_Index_Of --
1237 ---------------------------
1239 procedure Get_Language_Index_Of (Language : Name_Id) is
1240 Real_Language : Name_Id;
1243 Get_Name_String (Language);
1244 To_Lower (Name_Buffer (1 .. Name_Len));
1245 Real_Language := Name_Find;
1247 -- Nothing to do if the language is the same as the current language
1249 if Current_Language /= Real_Language then
1250 Lang_Index := Data.First_Language_Processing;
1251 while Lang_Index /= No_Language_Index loop
1252 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1255 In_Tree.Languages_Data.Table (Lang_Index).Next;
1258 if Lang_Index = No_Language_Index then
1259 Current_Language := No_Name;
1261 Current_Language := Real_Language;
1264 end Get_Language_Index_Of;
1266 ----------------------
1267 -- Process_Packages --
1268 ----------------------
1270 procedure Process_Packages is
1271 Packages : Package_Id;
1272 Element : Package_Element;
1274 procedure Process_Binder (Arrays : Array_Id);
1275 -- Process the associate array attributes of package Binder
1277 procedure Process_Builder (Attributes : Variable_Id);
1278 -- Process the simple attributes of package Builder
1280 procedure Process_Compiler (Arrays : Array_Id);
1281 -- Process the associate array attributes of package Compiler
1283 procedure Process_Naming (Attributes : Variable_Id);
1284 -- Process the simple attributes of package Naming
1286 procedure Process_Naming (Arrays : Array_Id);
1287 -- Process the associate array attributes of package Naming
1289 procedure Process_Linker (Attributes : Variable_Id);
1290 -- Process the simple attributes of package Linker of a
1291 -- configuration project.
1293 --------------------
1294 -- Process_Binder --
1295 --------------------
1297 procedure Process_Binder (Arrays : Array_Id) is
1298 Current_Array_Id : Array_Id;
1299 Current_Array : Array_Data;
1300 Element_Id : Array_Element_Id;
1301 Element : Array_Element;
1304 -- Process the associative array attribute of package Binder
1306 Current_Array_Id := Arrays;
1307 while Current_Array_Id /= No_Array loop
1308 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1310 Element_Id := Current_Array.Value;
1311 while Element_Id /= No_Array_Element loop
1312 Element := In_Tree.Array_Elements.Table (Element_Id);
1314 if Element.Index /= All_Other_Names then
1316 -- Get the name of the language
1318 Get_Language_Index_Of (Element.Index);
1320 if Lang_Index /= No_Language_Index then
1321 case Current_Array.Name is
1324 -- Attribute Driver (<language>)
1326 In_Tree.Languages_Data.Table
1327 (Lang_Index).Config.Binder_Driver :=
1328 File_Name_Type (Element.Value.Value);
1330 when Name_Required_Switches =>
1332 In_Tree.Languages_Data.Table
1333 (Lang_Index).Config.Binder_Required_Switches,
1334 From_List => Element.Value.Values,
1335 In_Tree => In_Tree);
1339 -- Attribute Prefix (<language>)
1341 In_Tree.Languages_Data.Table
1342 (Lang_Index).Config.Binder_Prefix :=
1343 Element.Value.Value;
1345 when Name_Objects_Path =>
1347 -- Attribute Objects_Path (<language>)
1349 In_Tree.Languages_Data.Table
1350 (Lang_Index).Config.Objects_Path :=
1351 Element.Value.Value;
1353 when Name_Objects_Path_File =>
1355 -- Attribute Objects_Path (<language>)
1357 In_Tree.Languages_Data.Table
1358 (Lang_Index).Config.Objects_Path_File :=
1359 Element.Value.Value;
1367 Element_Id := Element.Next;
1370 Current_Array_Id := Current_Array.Next;
1374 ---------------------
1375 -- Process_Builder --
1376 ---------------------
1378 procedure Process_Builder (Attributes : Variable_Id) is
1379 Attribute_Id : Variable_Id;
1380 Attribute : Variable;
1383 -- Process non associated array attribute from package Builder
1385 Attribute_Id := Attributes;
1386 while Attribute_Id /= No_Variable loop
1388 In_Tree.Variable_Elements.Table (Attribute_Id);
1390 if not Attribute.Value.Default then
1391 if Attribute.Name = Name_Executable_Suffix then
1393 -- Attribute Executable_Suffix: the suffix of the
1396 Data.Config.Executable_Suffix :=
1397 Attribute.Value.Value;
1401 Attribute_Id := Attribute.Next;
1403 end Process_Builder;
1405 ----------------------
1406 -- Process_Compiler --
1407 ----------------------
1409 procedure Process_Compiler (Arrays : Array_Id) is
1410 Current_Array_Id : Array_Id;
1411 Current_Array : Array_Data;
1412 Element_Id : Array_Element_Id;
1413 Element : Array_Element;
1414 List : String_List_Id;
1417 -- Process the associative array attribute of package Compiler
1419 Current_Array_Id := Arrays;
1420 while Current_Array_Id /= No_Array loop
1421 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1423 Element_Id := Current_Array.Value;
1424 while Element_Id /= No_Array_Element loop
1425 Element := In_Tree.Array_Elements.Table (Element_Id);
1427 if Element.Index /= All_Other_Names then
1429 -- Get the name of the language
1431 Get_Language_Index_Of (Element.Index);
1433 if Lang_Index /= No_Language_Index then
1434 case Current_Array.Name is
1435 when Name_Dependency_Switches =>
1437 -- Attribute Dependency_Switches (<language>)
1439 if In_Tree.Languages_Data.Table
1440 (Lang_Index).Config.Dependency_Kind = None
1442 In_Tree.Languages_Data.Table
1443 (Lang_Index).Config.Dependency_Kind :=
1447 List := Element.Value.Values;
1449 if List /= Nil_String then
1451 In_Tree.Languages_Data.Table
1452 (Lang_Index).Config.Dependency_Option,
1454 In_Tree => In_Tree);
1457 when Name_Dependency_Driver =>
1459 -- Attribute Dependency_Driver (<language>)
1461 if In_Tree.Languages_Data.Table
1462 (Lang_Index).Config.Dependency_Kind = None
1464 In_Tree.Languages_Data.Table
1465 (Lang_Index).Config.Dependency_Kind :=
1469 List := Element.Value.Values;
1471 if List /= Nil_String then
1473 In_Tree.Languages_Data.Table
1474 (Lang_Index).Config.Compute_Dependency,
1476 In_Tree => In_Tree);
1479 when Name_Include_Switches =>
1481 -- Attribute Include_Switches (<language>)
1483 List := Element.Value.Values;
1485 if List = Nil_String then
1489 "include option cannot be null",
1490 Element.Value.Location);
1494 In_Tree.Languages_Data.Table
1495 (Lang_Index).Config.Include_Option,
1497 In_Tree => In_Tree);
1499 when Name_Include_Path =>
1501 -- Attribute Include_Path (<language>)
1503 In_Tree.Languages_Data.Table
1504 (Lang_Index).Config.Include_Path :=
1505 Element.Value.Value;
1507 when Name_Include_Path_File =>
1509 -- Attribute Include_Path_File (<language>)
1511 In_Tree.Languages_Data.Table
1512 (Lang_Index).Config.Include_Path_File :=
1513 Element.Value.Value;
1517 -- Attribute Driver (<language>)
1519 Get_Name_String (Element.Value.Value);
1521 In_Tree.Languages_Data.Table
1522 (Lang_Index).Config.Compiler_Driver :=
1523 File_Name_Type (Element.Value.Value);
1525 when Name_Required_Switches =>
1527 In_Tree.Languages_Data.Table
1528 (Lang_Index).Config.
1529 Compiler_Required_Switches,
1530 From_List => Element.Value.Values,
1531 In_Tree => In_Tree);
1533 when Name_Path_Syntax =>
1535 In_Tree.Languages_Data.Table
1536 (Lang_Index).Config.Path_Syntax :=
1537 Path_Syntax_Kind'Value
1538 (Get_Name_String (Element.Value.Value));
1541 when Constraint_Error =>
1545 "invalid value for Path_Syntax",
1546 Element.Value.Location);
1549 when Name_Object_File_Suffix =>
1550 if Get_Name_String (Element.Value.Value) = "" then
1553 "object file suffix cannot be empty",
1554 Element.Value.Location);
1557 In_Tree.Languages_Data.Table
1558 (Lang_Index).Config.Object_File_Suffix :=
1559 Element.Value.Value;
1562 when Name_Pic_Option =>
1564 -- Attribute Compiler_Pic_Option (<language>)
1566 List := Element.Value.Values;
1568 if List = Nil_String then
1572 "compiler PIC option cannot be null",
1573 Element.Value.Location);
1577 In_Tree.Languages_Data.Table
1578 (Lang_Index).Config.Compilation_PIC_Option,
1580 In_Tree => In_Tree);
1582 when Name_Mapping_File_Switches =>
1584 -- Attribute Mapping_File_Switches (<language>)
1586 List := Element.Value.Values;
1588 if List = Nil_String then
1592 "mapping file switches cannot be null",
1593 Element.Value.Location);
1597 In_Tree.Languages_Data.Table
1598 (Lang_Index).Config.Mapping_File_Switches,
1600 In_Tree => In_Tree);
1602 when Name_Mapping_Spec_Suffix =>
1604 -- Attribute Mapping_Spec_Suffix (<language>)
1606 In_Tree.Languages_Data.Table
1607 (Lang_Index).Config.Mapping_Spec_Suffix :=
1608 File_Name_Type (Element.Value.Value);
1610 when Name_Mapping_Body_Suffix =>
1612 -- Attribute Mapping_Body_Suffix (<language>)
1614 In_Tree.Languages_Data.Table
1615 (Lang_Index).Config.Mapping_Body_Suffix :=
1616 File_Name_Type (Element.Value.Value);
1618 when Name_Config_File_Switches =>
1620 -- Attribute Config_File_Switches (<language>)
1622 List := Element.Value.Values;
1624 if List = Nil_String then
1628 "config file switches cannot be null",
1629 Element.Value.Location);
1633 In_Tree.Languages_Data.Table
1634 (Lang_Index).Config.Config_File_Switches,
1636 In_Tree => In_Tree);
1638 when Name_Objects_Path =>
1640 -- Attribute Objects_Path (<language>)
1642 In_Tree.Languages_Data.Table
1643 (Lang_Index).Config.Objects_Path :=
1644 Element.Value.Value;
1646 when Name_Objects_Path_File =>
1648 -- Attribute Objects_Path_File (<language>)
1650 In_Tree.Languages_Data.Table
1651 (Lang_Index).Config.Objects_Path_File :=
1652 Element.Value.Value;
1654 when Name_Config_Body_File_Name =>
1656 -- Attribute Config_Body_File_Name (<language>)
1658 In_Tree.Languages_Data.Table
1659 (Lang_Index).Config.Config_Body :=
1660 Element.Value.Value;
1662 when Name_Config_Body_File_Name_Pattern =>
1664 -- Attribute Config_Body_File_Name_Pattern
1667 In_Tree.Languages_Data.Table
1668 (Lang_Index).Config.Config_Body_Pattern :=
1669 Element.Value.Value;
1671 when Name_Config_Spec_File_Name =>
1673 -- Attribute Config_Spec_File_Name (<language>)
1675 In_Tree.Languages_Data.Table
1676 (Lang_Index).Config.Config_Spec :=
1677 Element.Value.Value;
1679 when Name_Config_Spec_File_Name_Pattern =>
1681 -- Attribute Config_Spec_File_Name_Pattern
1684 In_Tree.Languages_Data.Table
1685 (Lang_Index).Config.Config_Spec_Pattern :=
1686 Element.Value.Value;
1688 when Name_Config_File_Unique =>
1690 -- Attribute Config_File_Unique (<language>)
1693 In_Tree.Languages_Data.Table
1694 (Lang_Index).Config.Config_File_Unique :=
1696 (Get_Name_String (Element.Value.Value));
1698 when Constraint_Error =>
1702 "illegal value for Config_File_Unique",
1703 Element.Value.Location);
1712 Element_Id := Element.Next;
1715 Current_Array_Id := Current_Array.Next;
1717 end Process_Compiler;
1719 --------------------
1720 -- Process_Naming --
1721 --------------------
1723 procedure Process_Naming (Attributes : Variable_Id) is
1724 Attribute_Id : Variable_Id;
1725 Attribute : Variable;
1728 -- Process non associated array attribute from package Naming
1730 Attribute_Id := Attributes;
1731 while Attribute_Id /= No_Variable loop
1732 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1734 if not Attribute.Value.Default then
1735 if Attribute.Name = Name_Separate_Suffix then
1737 -- Attribute Separate_Suffix
1739 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1741 elsif Attribute.Name = Name_Casing then
1747 Value (Get_Name_String (Attribute.Value.Value));
1750 when Constraint_Error =>
1754 "invalid value for Casing",
1755 Attribute.Value.Location);
1758 elsif Attribute.Name = Name_Dot_Replacement then
1760 -- Attribute Dot_Replacement
1762 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1767 Attribute_Id := Attribute.Next;
1771 procedure Process_Naming (Arrays : Array_Id) is
1772 Current_Array_Id : Array_Id;
1773 Current_Array : Array_Data;
1774 Element_Id : Array_Element_Id;
1775 Element : Array_Element;
1777 -- Process the associative array attribute of package Naming
1779 Current_Array_Id := Arrays;
1780 while Current_Array_Id /= No_Array loop
1781 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1783 Element_Id := Current_Array.Value;
1784 while Element_Id /= No_Array_Element loop
1785 Element := In_Tree.Array_Elements.Table (Element_Id);
1787 -- Get the name of the language
1789 Get_Language_Index_Of (Element.Index);
1791 if Lang_Index /= No_Language_Index then
1792 case Current_Array.Name is
1793 when Name_Specification_Suffix | Name_Spec_Suffix =>
1795 -- Attribute Spec_Suffix (<language>)
1797 In_Tree.Languages_Data.Table
1798 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1799 File_Name_Type (Element.Value.Value);
1801 when Name_Implementation_Suffix | Name_Body_Suffix =>
1803 -- Attribute Body_Suffix (<language>)
1805 In_Tree.Languages_Data.Table
1806 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1807 File_Name_Type (Element.Value.Value);
1809 In_Tree.Languages_Data.Table
1810 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1811 File_Name_Type (Element.Value.Value);
1818 Element_Id := Element.Next;
1821 Current_Array_Id := Current_Array.Next;
1825 --------------------
1826 -- Process_Linker --
1827 --------------------
1829 procedure Process_Linker (Attributes : Variable_Id) is
1830 Attribute_Id : Variable_Id;
1831 Attribute : Variable;
1834 -- Process non associated array attribute from package Linker
1836 Attribute_Id := Attributes;
1837 while Attribute_Id /= No_Variable loop
1839 In_Tree.Variable_Elements.Table (Attribute_Id);
1841 if not Attribute.Value.Default then
1842 if Attribute.Name = Name_Driver then
1844 -- Attribute Linker'Driver: the default linker to use
1846 Data.Config.Linker :=
1847 Path_Name_Type (Attribute.Value.Value);
1849 -- Linker'Driver is also used to link shared libraries
1850 -- if the obsolescent attribute Library_GCC has not been
1853 if Data.Config.Shared_Lib_Driver = No_File then
1854 Data.Config.Shared_Lib_Driver :=
1855 File_Name_Type (Attribute.Value.Value);
1858 elsif Attribute.Name = Name_Required_Switches then
1860 -- Attribute Required_Switches: the minimum
1861 -- options to use when invoking the linker
1864 Data.Config.Minimum_Linker_Options,
1865 From_List => Attribute.Value.Values,
1866 In_Tree => In_Tree);
1868 elsif Attribute.Name = Name_Map_File_Option then
1869 Data.Config.Map_File_Option := Attribute.Value.Value;
1871 elsif Attribute.Name = Name_Max_Command_Line_Length then
1873 Data.Config.Max_Command_Line_Length :=
1874 Natural'Value (Get_Name_String
1875 (Attribute.Value.Value));
1878 when Constraint_Error =>
1882 "value must be positive or equal to 0",
1883 Attribute.Value.Location);
1886 elsif Attribute.Name = Name_Response_File_Format then
1891 Get_Name_String (Attribute.Value.Value);
1892 To_Lower (Name_Buffer (1 .. Name_Len));
1895 if Name = Name_None then
1896 Data.Config.Resp_File_Format := None;
1898 elsif Name = Name_Gnu then
1899 Data.Config.Resp_File_Format := GNU;
1901 elsif Name = Name_Object_List then
1902 Data.Config.Resp_File_Format := Object_List;
1904 elsif Name = Name_Option_List then
1905 Data.Config.Resp_File_Format := Option_List;
1911 "illegal response file format",
1912 Attribute.Value.Location);
1916 elsif Attribute.Name = Name_Response_File_Switches then
1918 Data.Config.Resp_File_Options,
1919 From_List => Attribute.Value.Values,
1920 In_Tree => In_Tree);
1924 Attribute_Id := Attribute.Next;
1928 -- Start of processing for Process_Packages
1931 Packages := Data.Decl.Packages;
1932 while Packages /= No_Package loop
1933 Element := In_Tree.Packages.Table (Packages);
1935 case Element.Name is
1938 -- Process attributes of package Binder
1940 Process_Binder (Element.Decl.Arrays);
1942 when Name_Builder =>
1944 -- Process attributes of package Builder
1946 Process_Builder (Element.Decl.Attributes);
1948 when Name_Compiler =>
1950 -- Process attributes of package Compiler
1952 Process_Compiler (Element.Decl.Arrays);
1956 -- Process attributes of package Linker
1958 Process_Linker (Element.Decl.Attributes);
1962 -- Process attributes of package Naming
1964 Process_Naming (Element.Decl.Attributes);
1965 Process_Naming (Element.Decl.Arrays);
1971 Packages := Element.Next;
1973 end Process_Packages;
1975 ---------------------------------------------
1976 -- Process_Project_Level_Simple_Attributes --
1977 ---------------------------------------------
1979 procedure Process_Project_Level_Simple_Attributes is
1980 Attribute_Id : Variable_Id;
1981 Attribute : Variable;
1982 List : String_List_Id;
1985 -- Process non associated array attribute at project level
1987 Attribute_Id := Data.Decl.Attributes;
1988 while Attribute_Id /= No_Variable loop
1990 In_Tree.Variable_Elements.Table (Attribute_Id);
1992 if not Attribute.Value.Default then
1993 if Attribute.Name = Name_Target then
1995 -- Attribute Target: the target specified
1997 Data.Config.Target := Attribute.Value.Value;
1999 elsif Attribute.Name = Name_Library_Builder then
2001 -- Attribute Library_Builder: the application to invoke
2002 -- to build libraries.
2004 Data.Config.Library_Builder :=
2005 Path_Name_Type (Attribute.Value.Value);
2007 elsif Attribute.Name = Name_Archive_Builder then
2009 -- Attribute Archive_Builder: the archive builder
2010 -- (usually "ar") and its minimum options (usually "cr").
2012 List := Attribute.Value.Values;
2014 if List = Nil_String then
2018 "archive builder cannot be null",
2019 Attribute.Value.Location);
2022 Put (Into_List => Data.Config.Archive_Builder,
2024 In_Tree => In_Tree);
2026 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
2028 -- Attribute Archive_Builder: the archive builder
2029 -- (usually "ar") and its minimum options (usually "cr").
2031 List := Attribute.Value.Values;
2033 if List /= Nil_String then
2035 (Into_List => Data.Config.Archive_Builder_Append_Option,
2037 In_Tree => In_Tree);
2040 elsif Attribute.Name = Name_Archive_Indexer then
2042 -- Attribute Archive_Indexer: the optional archive
2043 -- indexer (usually "ranlib") with its minimum options
2046 List := Attribute.Value.Values;
2048 if List = Nil_String then
2052 "archive indexer cannot be null",
2053 Attribute.Value.Location);
2056 Put (Into_List => Data.Config.Archive_Indexer,
2058 In_Tree => In_Tree);
2060 elsif Attribute.Name = Name_Library_Partial_Linker then
2062 -- Attribute Library_Partial_Linker: the optional linker
2063 -- driver with its minimum options, to partially link
2066 List := Attribute.Value.Values;
2068 if List = Nil_String then
2072 "partial linker cannot be null",
2073 Attribute.Value.Location);
2076 Put (Into_List => Data.Config.Lib_Partial_Linker,
2078 In_Tree => In_Tree);
2080 elsif Attribute.Name = Name_Library_GCC then
2081 Data.Config.Shared_Lib_Driver :=
2082 File_Name_Type (Attribute.Value.Value);
2086 "?Library_'G'C'C is an obsolescent attribute, " &
2087 "use Linker''Driver instead",
2088 Attribute.Value.Location);
2090 elsif Attribute.Name = Name_Archive_Suffix then
2091 Data.Config.Archive_Suffix :=
2092 File_Name_Type (Attribute.Value.Value);
2094 elsif Attribute.Name = Name_Linker_Executable_Option then
2096 -- Attribute Linker_Executable_Option: optional options
2097 -- to specify an executable name. Defaults to "-o".
2099 List := Attribute.Value.Values;
2101 if List = Nil_String then
2105 "linker executable option cannot be null",
2106 Attribute.Value.Location);
2109 Put (Into_List => Data.Config.Linker_Executable_Option,
2111 In_Tree => In_Tree);
2113 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2115 -- Attribute Linker_Lib_Dir_Option: optional options
2116 -- to specify a library search directory. Defaults to
2119 Get_Name_String (Attribute.Value.Value);
2121 if Name_Len = 0 then
2125 "linker library directory option cannot be empty",
2126 Attribute.Value.Location);
2129 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2131 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2133 -- Attribute Linker_Lib_Name_Option: optional options
2134 -- to specify the name of a library to be linked in.
2135 -- Defaults to "-l".
2137 Get_Name_String (Attribute.Value.Value);
2139 if Name_Len = 0 then
2143 "linker library name option cannot be empty",
2144 Attribute.Value.Location);
2147 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2149 elsif Attribute.Name = Name_Run_Path_Option then
2151 -- Attribute Run_Path_Option: optional options to
2152 -- specify a path for libraries.
2154 List := Attribute.Value.Values;
2156 if List /= Nil_String then
2157 Put (Into_List => Data.Config.Run_Path_Option,
2159 In_Tree => In_Tree);
2162 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2164 pragma Unsuppress (All_Checks);
2166 Data.Config.Separate_Run_Path_Options :=
2167 Boolean'Value (Get_Name_String
2168 (Attribute.Value.Value));
2170 when Constraint_Error =>
2174 "invalid value """ &
2175 Get_Name_String (Attribute.Value.Value) &
2176 """ for Separate_Run_Path_Options",
2177 Attribute.Value.Location);
2180 elsif Attribute.Name = Name_Library_Support then
2182 pragma Unsuppress (All_Checks);
2184 Data.Config.Lib_Support :=
2185 Library_Support'Value (Get_Name_String
2186 (Attribute.Value.Value));
2188 when Constraint_Error =>
2192 "invalid value """ &
2193 Get_Name_String (Attribute.Value.Value) &
2194 """ for Library_Support",
2195 Attribute.Value.Location);
2198 elsif Attribute.Name = Name_Shared_Library_Prefix then
2199 Data.Config.Shared_Lib_Prefix :=
2200 File_Name_Type (Attribute.Value.Value);
2202 elsif Attribute.Name = Name_Shared_Library_Suffix then
2203 Data.Config.Shared_Lib_Suffix :=
2204 File_Name_Type (Attribute.Value.Value);
2206 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2208 pragma Unsuppress (All_Checks);
2210 Data.Config.Symbolic_Link_Supported :=
2211 Boolean'Value (Get_Name_String
2212 (Attribute.Value.Value));
2214 when Constraint_Error =>
2219 & Get_Name_String (Attribute.Value.Value)
2220 & """ for Symbolic_Link_Supported",
2221 Attribute.Value.Location);
2225 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2228 pragma Unsuppress (All_Checks);
2230 Data.Config.Lib_Maj_Min_Id_Supported :=
2231 Boolean'Value (Get_Name_String
2232 (Attribute.Value.Value));
2234 when Constraint_Error =>
2238 "invalid value """ &
2239 Get_Name_String (Attribute.Value.Value) &
2240 """ for Library_Major_Minor_Id_Supported",
2241 Attribute.Value.Location);
2244 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2246 pragma Unsuppress (All_Checks);
2248 Data.Config.Auto_Init_Supported :=
2249 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2251 when Constraint_Error =>
2256 & Get_Name_String (Attribute.Value.Value)
2257 & """ for Library_Auto_Init_Supported",
2258 Attribute.Value.Location);
2261 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2262 List := Attribute.Value.Values;
2264 if List /= Nil_String then
2265 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2267 In_Tree => In_Tree);
2270 elsif Attribute.Name = Name_Library_Version_Switches then
2271 List := Attribute.Value.Values;
2273 if List /= Nil_String then
2274 Put (Into_List => Data.Config.Lib_Version_Options,
2276 In_Tree => In_Tree);
2281 Attribute_Id := Attribute.Next;
2283 end Process_Project_Level_Simple_Attributes;
2285 --------------------------------------------
2286 -- Process_Project_Level_Array_Attributes --
2287 --------------------------------------------
2289 procedure Process_Project_Level_Array_Attributes is
2290 Current_Array_Id : Array_Id;
2291 Current_Array : Array_Data;
2292 Element_Id : Array_Element_Id;
2293 Element : Array_Element;
2294 List : String_List_Id;
2297 -- Process the associative array attributes at project level
2299 Current_Array_Id := Data.Decl.Arrays;
2300 while Current_Array_Id /= No_Array loop
2301 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2303 Element_Id := Current_Array.Value;
2304 while Element_Id /= No_Array_Element loop
2305 Element := In_Tree.Array_Elements.Table (Element_Id);
2307 -- Get the name of the language
2309 Get_Language_Index_Of (Element.Index);
2311 if Lang_Index /= No_Language_Index then
2312 case Current_Array.Name is
2313 when Name_Inherit_Source_Path =>
2314 List := Element.Value.Values;
2316 if List /= Nil_String then
2319 In_Tree.Languages_Data.Table (Lang_Index).
2320 Config.Include_Compatible_Languages,
2323 Lower_Case => True);
2326 when Name_Toolchain_Description =>
2328 -- Attribute Toolchain_Description (<language>)
2330 In_Tree.Languages_Data.Table
2331 (Lang_Index).Config.Toolchain_Description :=
2332 Element.Value.Value;
2334 when Name_Toolchain_Version =>
2336 -- Attribute Toolchain_Version (<language>)
2338 In_Tree.Languages_Data.Table
2339 (Lang_Index).Config.Toolchain_Version :=
2340 Element.Value.Value;
2342 when Name_Runtime_Library_Dir =>
2344 -- Attribute Runtime_Library_Dir (<language>)
2346 In_Tree.Languages_Data.Table
2347 (Lang_Index).Config.Runtime_Library_Dir :=
2348 Element.Value.Value;
2350 when Name_Runtime_Source_Dir =>
2352 -- Attribute Runtime_Library_Dir (<language>)
2354 In_Tree.Languages_Data.Table
2355 (Lang_Index).Config.Runtime_Source_Dir :=
2356 Element.Value.Value;
2358 when Name_Object_Generated =>
2360 pragma Unsuppress (All_Checks);
2366 (Get_Name_String (Element.Value.Value));
2368 In_Tree.Languages_Data.Table
2369 (Lang_Index).Config.Object_Generated := Value;
2371 -- If no object is generated, no object may be
2375 In_Tree.Languages_Data.Table
2376 (Lang_Index).Config.Objects_Linked := False;
2380 when Constraint_Error =>
2385 & Get_Name_String (Element.Value.Value)
2386 & """ for Object_Generated",
2387 Element.Value.Location);
2390 when Name_Objects_Linked =>
2392 pragma Unsuppress (All_Checks);
2398 (Get_Name_String (Element.Value.Value));
2400 -- No change if Object_Generated is False, as this
2401 -- forces Objects_Linked to be False too.
2403 if In_Tree.Languages_Data.Table
2404 (Lang_Index).Config.Object_Generated
2406 In_Tree.Languages_Data.Table
2407 (Lang_Index).Config.Objects_Linked :=
2412 when Constraint_Error =>
2417 & Get_Name_String (Element.Value.Value)
2418 & """ for Objects_Linked",
2419 Element.Value.Location);
2426 Element_Id := Element.Next;
2429 Current_Array_Id := Current_Array.Next;
2431 end Process_Project_Level_Array_Attributes;
2434 Process_Project_Level_Simple_Attributes;
2435 Process_Project_Level_Array_Attributes;
2438 -- For unit based languages, set Casing, Dot_Replacement and
2439 -- Separate_Suffix in Naming_Data.
2441 Lang_Index := Data.First_Language_Processing;
2442 while Lang_Index /= No_Language_Index loop
2443 if In_Tree.Languages_Data.Table
2444 (Lang_Index).Name = Name_Ada
2446 In_Tree.Languages_Data.Table
2447 (Lang_Index).Config.Naming_Data.Casing := Casing;
2448 In_Tree.Languages_Data.Table
2449 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2452 if Separate_Suffix /= No_File then
2453 In_Tree.Languages_Data.Table
2454 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2461 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2464 -- Give empty names to various prefixes/suffixes, if they have not
2465 -- been specified in the configuration.
2467 if Data.Config.Archive_Suffix = No_File then
2468 Data.Config.Archive_Suffix := Empty_File;
2471 if Data.Config.Shared_Lib_Prefix = No_File then
2472 Data.Config.Shared_Lib_Prefix := Empty_File;
2475 if Data.Config.Shared_Lib_Suffix = No_File then
2476 Data.Config.Shared_Lib_Suffix := Empty_File;
2479 Lang_Index := Data.First_Language_Processing;
2480 while Lang_Index /= No_Language_Index loop
2481 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2483 Current_Language := Lang_Data.Display_Name;
2485 -- For all languages, Compiler_Driver needs to be specified
2487 if Lang_Data.Config.Compiler_Driver = No_File then
2488 Error_Msg_Name_1 := Current_Language;
2492 "?no compiler specified for language %%" &
2493 ", ignoring all its sources",
2496 if Lang_Index = Data.First_Language_Processing then
2497 Data.First_Language_Processing :=
2500 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2504 elsif Lang_Data.Name = Name_Ada then
2505 Prev_Index := Lang_Index;
2507 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2508 -- Body_Suffix need to be specified.
2510 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2514 "Dot_Replacement not specified for Ada",
2518 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2522 "Spec_Suffix not specified for Ada",
2526 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2530 "Body_Suffix not specified for Ada",
2535 Prev_Index := Lang_Index;
2537 -- For file based languages, either Spec_Suffix or Body_Suffix
2538 -- need to be specified.
2540 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2541 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2543 Error_Msg_Name_1 := Current_Language;
2547 "no suffixes specified for %%",
2552 Lang_Index := Lang_Data.Next;
2554 end Check_Configuration;
2556 -------------------------------
2557 -- Check_If_Externally_Built --
2558 -------------------------------
2560 procedure Check_If_Externally_Built
2561 (Project : Project_Id;
2562 In_Tree : Project_Tree_Ref;
2563 Data : in out Project_Data)
2565 Externally_Built : constant Variable_Value :=
2567 (Name_Externally_Built,
2568 Data.Decl.Attributes, In_Tree);
2571 if not Externally_Built.Default then
2572 Get_Name_String (Externally_Built.Value);
2573 To_Lower (Name_Buffer (1 .. Name_Len));
2575 if Name_Buffer (1 .. Name_Len) = "true" then
2576 Data.Externally_Built := True;
2578 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2579 Error_Msg (Project, In_Tree,
2580 "Externally_Built may only be true or false",
2581 Externally_Built.Location);
2585 -- A virtual project extending an externally built project is itself
2586 -- externally built.
2588 if Data.Virtual and then Data.Extends /= No_Project then
2589 Data.Externally_Built :=
2590 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2593 if Current_Verbosity = High then
2594 Write_Str ("Project is ");
2596 if not Data.Externally_Built then
2600 Write_Line ("externally built.");
2602 end Check_If_Externally_Built;
2604 ----------------------
2605 -- Check_Interfaces --
2606 ----------------------
2608 procedure Check_Interfaces
2609 (Project : Project_Id;
2610 In_Tree : Project_Tree_Ref;
2611 Data : in out Project_Data)
2613 Interfaces : constant Prj.Variable_Value :=
2615 (Snames.Name_Interfaces,
2616 Data.Decl.Attributes,
2619 List : String_List_Id;
2620 Element : String_Element;
2621 Name : File_Name_Type;
2625 Project_2 : Project_Id;
2626 Data_2 : Project_Data;
2629 if not Interfaces.Default then
2631 -- Set In_Interfaces to False for all sources. It will be set to True
2632 -- later for the sources in the Interfaces list.
2634 Project_2 := Project;
2637 Source := Data_2.First_Source;
2638 while Source /= No_Source loop
2640 Src_Data : Source_Data renames
2641 In_Tree.Sources.Table (Source);
2643 Src_Data.In_Interfaces := False;
2644 Source := Src_Data.Next_In_Project;
2648 Project_2 := Data_2.Extends;
2650 exit when Project_2 = No_Project;
2652 Data_2 := In_Tree.Projects.Table (Project_2);
2655 List := Interfaces.Values;
2656 while List /= Nil_String loop
2657 Element := In_Tree.String_Elements.Table (List);
2658 Get_Name_String (Element.Value);
2659 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2662 Project_2 := Project;
2666 Source := Data_2.First_Source;
2667 while Source /= No_Source loop
2669 Src_Data : Source_Data renames
2670 In_Tree.Sources.Table (Source);
2673 if Src_Data.File = Name then
2674 if not Src_Data.Locally_Removed then
2675 Src_Data.In_Interfaces := True;
2676 Src_Data.Declared_In_Interfaces := True;
2678 if Src_Data.Other_Part /= No_Source then
2679 In_Tree.Sources.Table
2680 (Src_Data.Other_Part).In_Interfaces := True;
2681 In_Tree.Sources.Table
2682 (Src_Data.Other_Part).Declared_In_Interfaces :=
2686 if Current_Verbosity = High then
2687 Write_Str (" interface: ");
2689 (Get_Name_String (Src_Data.Path.Name));
2696 Source := Src_Data.Next_In_Project;
2700 Project_2 := Data_2.Extends;
2702 exit Big_Loop when Project_2 = No_Project;
2704 Data_2 := In_Tree.Projects.Table (Project_2);
2707 if Source = No_Source then
2708 Error_Msg_File_1 := File_Name_Type (Element.Value);
2709 Error_Msg_Name_1 := Data.Name;
2714 "{ cannot be an interface of project %% "
2715 & "as it is not one of its sources",
2719 List := Element.Next;
2722 Data.Interfaces_Defined := True;
2724 elsif Data.Extends /= No_Project then
2725 Data.Interfaces_Defined :=
2726 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2728 if Data.Interfaces_Defined then
2729 Source := Data.First_Source;
2730 while Source /= No_Source loop
2732 Src_Data : Source_Data renames
2733 In_Tree.Sources.Table (Source);
2736 if not Src_Data.Declared_In_Interfaces then
2737 Src_Data.In_Interfaces := False;
2740 Source := Src_Data.Next_In_Project;
2745 end Check_Interfaces;
2747 --------------------------
2748 -- Check_Naming_Schemes --
2749 --------------------------
2751 procedure Check_Naming_Schemes
2752 (Data : in out Project_Data;
2753 Project : Project_Id;
2754 In_Tree : Project_Tree_Ref)
2756 Naming_Id : constant Package_Id :=
2757 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2758 Naming : Package_Element;
2760 procedure Check_Unit_Names (List : Array_Element_Id);
2761 -- Check that a list of unit names contains only valid names
2763 procedure Get_Exceptions (Kind : Source_Kind);
2764 -- Comment required ???
2766 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2767 -- Comment required ???
2769 ----------------------
2770 -- Check_Unit_Names --
2771 ----------------------
2773 procedure Check_Unit_Names (List : Array_Element_Id) is
2774 Current : Array_Element_Id;
2775 Element : Array_Element;
2776 Unit_Name : Name_Id;
2779 -- Loop through elements of the string list
2782 while Current /= No_Array_Element loop
2783 Element := In_Tree.Array_Elements.Table (Current);
2785 -- Put file name in canonical case
2787 if not Osint.File_Names_Case_Sensitive then
2788 Get_Name_String (Element.Value.Value);
2789 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2790 Element.Value.Value := Name_Find;
2793 -- Check that it contains a valid unit name
2795 Get_Name_String (Element.Index);
2796 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2798 if Unit_Name = No_Name then
2799 Err_Vars.Error_Msg_Name_1 := Element.Index;
2802 "%% is not a valid unit name.",
2803 Element.Value.Location);
2806 if Current_Verbosity = High then
2807 Write_Str (" Unit (""");
2808 Write_Str (Get_Name_String (Unit_Name));
2812 Element.Index := Unit_Name;
2813 In_Tree.Array_Elements.Table (Current) := Element;
2816 Current := Element.Next;
2818 end Check_Unit_Names;
2820 --------------------
2821 -- Get_Exceptions --
2822 --------------------
2824 procedure Get_Exceptions (Kind : Source_Kind) is
2825 Exceptions : Array_Element_Id;
2826 Exception_List : Variable_Value;
2827 Element_Id : String_List_Id;
2828 Element : String_Element;
2829 File_Name : File_Name_Type;
2830 Lang_Id : Language_Index;
2832 Lang_Kind : Language_Kind;
2839 (Name_Implementation_Exceptions,
2840 In_Arrays => Naming.Decl.Arrays,
2841 In_Tree => In_Tree);
2846 (Name_Specification_Exceptions,
2847 In_Arrays => Naming.Decl.Arrays,
2848 In_Tree => In_Tree);
2851 Lang_Id := Data.First_Language_Processing;
2852 while Lang_Id /= No_Language_Index loop
2853 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2856 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2858 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2860 Exception_List := Value_Of
2862 In_Array => Exceptions,
2863 In_Tree => In_Tree);
2865 if Exception_List /= Nil_Variable_Value then
2866 Element_Id := Exception_List.Values;
2867 while Element_Id /= Nil_String loop
2868 Element := In_Tree.String_Elements.Table (Element_Id);
2870 if Osint.File_Names_Case_Sensitive then
2871 File_Name := File_Name_Type (Element.Value);
2873 Get_Name_String (Element.Value);
2874 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2875 File_Name := Name_Find;
2878 Source := Data.First_Source;
2879 while Source /= No_Source
2881 In_Tree.Sources.Table (Source).File /= File_Name
2884 In_Tree.Sources.Table (Source).Next_In_Project;
2887 if Source = No_Source then
2896 File_Name => File_Name,
2897 Display_File => File_Name_Type (Element.Value),
2898 Naming_Exception => True,
2899 Lang_Kind => Lang_Kind);
2902 -- Check if the file name is already recorded for
2903 -- another language or another kind.
2906 In_Tree.Sources.Table (Source).Language /= Lang_Id
2911 "the same file cannot be a source " &
2915 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2919 "the same file cannot be a source " &
2924 -- If the file is already recorded for the same
2925 -- language and the same kind, it means that the file
2926 -- name appears several times in the *_Exceptions
2927 -- attribute; so there is nothing to do.
2931 Element_Id := Element.Next;
2936 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2940 -------------------------
2941 -- Get_Unit_Exceptions --
2942 -------------------------
2944 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2945 Exceptions : Array_Element_Id;
2946 Element : Array_Element;
2949 File_Name : File_Name_Type;
2950 Lang_Id : constant Language_Index :=
2951 Data.Unit_Based_Language_Index;
2952 Lang : constant Name_Id :=
2953 Data.Unit_Based_Language_Name;
2956 Source_To_Replace : Source_Id := No_Source;
2958 Other_Project : Project_Id;
2959 Other_Part : Source_Id := No_Source;
2962 if Lang_Id = No_Language_Index or else Lang = No_Name then
2967 Exceptions := Value_Of
2969 In_Arrays => Naming.Decl.Arrays,
2970 In_Tree => In_Tree);
2972 if Exceptions = No_Array_Element then
2975 (Name_Implementation,
2976 In_Arrays => Naming.Decl.Arrays,
2977 In_Tree => In_Tree);
2984 In_Arrays => Naming.Decl.Arrays,
2985 In_Tree => In_Tree);
2987 if Exceptions = No_Array_Element then
2988 Exceptions := Value_Of
2989 (Name_Specification,
2990 In_Arrays => Naming.Decl.Arrays,
2991 In_Tree => In_Tree);
2996 while Exceptions /= No_Array_Element loop
2997 Element := In_Tree.Array_Elements.Table (Exceptions);
2999 if Osint.File_Names_Case_Sensitive then
3000 File_Name := File_Name_Type (Element.Value.Value);
3002 Get_Name_String (Element.Value.Value);
3003 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3004 File_Name := Name_Find;
3007 Get_Name_String (Element.Index);
3008 To_Lower (Name_Buffer (1 .. Name_Len));
3011 Index := Element.Value.Index;
3013 -- For Ada, check if it is a valid unit name
3015 if Lang = Name_Ada then
3016 Get_Name_String (Element.Index);
3017 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3019 if Unit = No_Name then
3020 Err_Vars.Error_Msg_Name_1 := Element.Index;
3023 "%% is not a valid unit name.",
3024 Element.Value.Location);
3028 if Unit /= No_Name then
3030 -- Check if the source already exists
3032 Source := In_Tree.First_Source;
3033 Source_To_Replace := No_Source;
3035 while Source /= No_Source and then
3036 (In_Tree.Sources.Table (Source).Unit /= Unit or else
3037 In_Tree.Sources.Table (Source).Index /= Index)
3039 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
3042 if Source /= No_Source then
3043 if In_Tree.Sources.Table (Source).Kind /= Kind then
3044 Other_Part := Source;
3048 In_Tree.Sources.Table (Source).Next_In_Sources;
3050 exit when Source = No_Source or else
3051 (In_Tree.Sources.Table (Source).Unit = Unit
3053 In_Tree.Sources.Table (Source).Index = Index);
3057 if Source /= No_Source then
3058 Other_Project := In_Tree.Sources.Table (Source).Project;
3060 if Is_Extending (Project, Other_Project, In_Tree) then
3062 In_Tree.Sources.Table (Source).Other_Part;
3064 -- Record the source to be removed
3066 Source_To_Replace := Source;
3067 Source := No_Source;
3070 Error_Msg_Name_1 := Unit;
3072 In_Tree.Projects.Table (Other_Project).Name;
3076 "%% is already a source of project %%",
3077 Element.Value.Location);
3082 if Source = No_Source then
3091 File_Name => File_Name,
3092 Display_File => File_Name_Type (Element.Value.Value),
3093 Lang_Kind => Unit_Based,
3094 Other_Part => Other_Part,
3097 Naming_Exception => True,
3098 Source_To_Replace => Source_To_Replace);
3102 Exceptions := Element.Next;
3105 end Get_Unit_Exceptions;
3107 -- Start of processing for Check_Naming_Schemes
3110 if Get_Mode = Ada_Only then
3112 -- If there is a package Naming, we will put in Data.Naming what is
3113 -- in this package Naming.
3115 if Naming_Id /= No_Package then
3116 Naming := In_Tree.Packages.Table (Naming_Id);
3118 if Current_Verbosity = High then
3119 Write_Line ("Checking ""Naming"" for Ada.");
3123 Bodies : constant Array_Element_Id :=
3125 (Name_Body, Naming.Decl.Arrays, In_Tree);
3127 Specs : constant Array_Element_Id :=
3129 (Name_Spec, Naming.Decl.Arrays, In_Tree);
3132 if Bodies /= No_Array_Element then
3134 -- We have elements in the array Body_Part
3136 if Current_Verbosity = High then
3137 Write_Line ("Found Bodies.");
3140 Data.Naming.Bodies := Bodies;
3141 Check_Unit_Names (Bodies);
3144 if Current_Verbosity = High then
3145 Write_Line ("No Bodies.");
3149 if Specs /= No_Array_Element then
3151 -- We have elements in the array Specs
3153 if Current_Verbosity = High then
3154 Write_Line ("Found Specs.");
3157 Data.Naming.Specs := Specs;
3158 Check_Unit_Names (Specs);
3161 if Current_Verbosity = High then
3162 Write_Line ("No Specs.");
3167 -- We are now checking if variables Dot_Replacement, Casing,
3168 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3170 -- For each variable, if it does not exist, we do nothing,
3171 -- because we already have the default.
3173 -- Check Dot_Replacement
3176 Dot_Replacement : constant Variable_Value :=
3178 (Name_Dot_Replacement,
3179 Naming.Decl.Attributes, In_Tree);
3182 pragma Assert (Dot_Replacement.Kind = Single,
3183 "Dot_Replacement is not a single string");
3185 if not Dot_Replacement.Default then
3186 Get_Name_String (Dot_Replacement.Value);
3188 if Name_Len = 0 then
3191 "Dot_Replacement cannot be empty",
3192 Dot_Replacement.Location);
3195 if Osint.File_Names_Case_Sensitive then
3196 Data.Naming.Dot_Replacement :=
3197 File_Name_Type (Dot_Replacement.Value);
3199 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3200 Data.Naming.Dot_Replacement := Name_Find;
3202 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3207 if Current_Verbosity = High then
3208 Write_Str (" Dot_Replacement = """);
3209 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3217 Casing_String : constant Variable_Value :=
3220 Naming.Decl.Attributes,
3224 pragma Assert (Casing_String.Kind = Single,
3225 "Casing is not a single string");
3227 if not Casing_String.Default then
3229 Casing_Image : constant String :=
3230 Get_Name_String (Casing_String.Value);
3233 Casing_Value : constant Casing_Type :=
3234 Value (Casing_Image);
3236 Data.Naming.Casing := Casing_Value;
3240 when Constraint_Error =>
3241 if Casing_Image'Length = 0 then
3244 "Casing cannot be an empty string",
3245 Casing_String.Location);
3248 Name_Len := Casing_Image'Length;
3249 Name_Buffer (1 .. Name_Len) := Casing_Image;
3250 Err_Vars.Error_Msg_Name_1 := Name_Find;
3253 "%% is not a correct Casing",
3254 Casing_String.Location);
3260 if Current_Verbosity = High then
3261 Write_Str (" Casing = ");
3262 Write_Str (Image (Data.Naming.Casing));
3267 -- Check Spec_Suffix
3270 Ada_Spec_Suffix : constant Variable_Value :=
3274 In_Array => Data.Naming.Spec_Suffix,
3275 In_Tree => In_Tree);
3278 if Ada_Spec_Suffix.Kind = Single
3279 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3281 Get_Name_String (Ada_Spec_Suffix.Value);
3282 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3283 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3284 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3291 Default_Ada_Spec_Suffix);
3295 if Current_Verbosity = High then
3296 Write_Str (" Spec_Suffix = """);
3297 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3302 -- Check Body_Suffix
3305 Ada_Body_Suffix : constant Variable_Value :=
3309 In_Array => Data.Naming.Body_Suffix,
3310 In_Tree => In_Tree);
3313 if Ada_Body_Suffix.Kind = Single
3314 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3316 Get_Name_String (Ada_Body_Suffix.Value);
3317 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3318 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3319 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3326 Default_Ada_Body_Suffix);
3330 if Current_Verbosity = High then
3331 Write_Str (" Body_Suffix = """);
3332 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3337 -- Check Separate_Suffix
3340 Ada_Sep_Suffix : constant Variable_Value :=
3342 (Variable_Name => Name_Separate_Suffix,
3343 In_Variables => Naming.Decl.Attributes,
3344 In_Tree => In_Tree);
3347 if Ada_Sep_Suffix.Default then
3348 Data.Naming.Separate_Suffix :=
3349 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3352 Get_Name_String (Ada_Sep_Suffix.Value);
3354 if Name_Len = 0 then
3357 "Separate_Suffix cannot be empty",
3358 Ada_Sep_Suffix.Location);
3361 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3362 Data.Naming.Separate_Suffix := Name_Find;
3363 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3368 if Current_Verbosity = High then
3369 Write_Str (" Separate_Suffix = """);
3370 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3375 -- Check if Data.Naming is valid
3377 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3380 elsif not In_Configuration then
3382 -- Look into package Naming, if there is one
3384 if Naming_Id /= No_Package then
3385 Naming := In_Tree.Packages.Table (Naming_Id);
3387 if Current_Verbosity = High then
3388 Write_Line ("Checking package Naming.");
3391 -- We are now checking if attribute Dot_Replacement, Casing,
3392 -- and/or Separate_Suffix exist.
3394 -- For each attribute, if it does not exist, we do nothing,
3395 -- because we already have the default.
3396 -- Otherwise, for all unit-based languages, we put the declared
3397 -- value in the language config.
3400 Dot_Repl : constant Variable_Value :=
3402 (Name_Dot_Replacement,
3403 Naming.Decl.Attributes, In_Tree);
3404 Dot_Replacement : File_Name_Type := No_File;
3406 Casing_String : constant Variable_Value :=
3409 Naming.Decl.Attributes,
3412 Casing : Casing_Type := All_Lower_Case;
3413 -- Casing type (junk initialization to stop bad gcc warning)
3415 Casing_Defined : Boolean := False;
3417 Sep_Suffix : constant Variable_Value :=
3419 (Variable_Name => Name_Separate_Suffix,
3420 In_Variables => Naming.Decl.Attributes,
3421 In_Tree => In_Tree);
3423 Separate_Suffix : File_Name_Type := No_File;
3424 Lang_Id : Language_Index;
3427 -- Check attribute Dot_Replacement
3429 if not Dot_Repl.Default then
3430 Get_Name_String (Dot_Repl.Value);
3432 if Name_Len = 0 then
3435 "Dot_Replacement cannot be empty",
3439 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3440 Dot_Replacement := Name_Find;
3442 if Current_Verbosity = High then
3443 Write_Str (" Dot_Replacement = """);
3444 Write_Str (Get_Name_String (Dot_Replacement));
3451 -- Check attribute Casing
3453 if not Casing_String.Default then
3455 Casing_Image : constant String :=
3456 Get_Name_String (Casing_String.Value);
3459 Casing_Value : constant Casing_Type :=
3460 Value (Casing_Image);
3462 Casing := Casing_Value;
3463 Casing_Defined := True;
3465 if Current_Verbosity = High then
3466 Write_Str (" Casing = ");
3467 Write_Str (Image (Casing));
3474 when Constraint_Error =>
3475 if Casing_Image'Length = 0 then
3478 "Casing cannot be an empty string",
3479 Casing_String.Location);
3482 Name_Len := Casing_Image'Length;
3483 Name_Buffer (1 .. Name_Len) := Casing_Image;
3484 Err_Vars.Error_Msg_Name_1 := Name_Find;
3487 "%% is not a correct Casing",
3488 Casing_String.Location);
3493 if not Sep_Suffix.Default then
3494 Get_Name_String (Sep_Suffix.Value);
3496 if Name_Len = 0 then
3499 "Separate_Suffix cannot be empty",
3500 Sep_Suffix.Location);
3503 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3504 Separate_Suffix := Name_Find;
3506 if Current_Verbosity = High then
3507 Write_Str (" Separate_Suffix = """);
3508 Write_Str (Get_Name_String (Separate_Suffix));
3515 -- For all unit based languages, if any, set the specified
3516 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3518 if Dot_Replacement /= No_File
3519 or else Casing_Defined
3520 or else Separate_Suffix /= No_File
3522 Lang_Id := Data.First_Language_Processing;
3523 while Lang_Id /= No_Language_Index loop
3524 if In_Tree.Languages_Data.Table
3525 (Lang_Id).Config.Kind = Unit_Based
3527 if Dot_Replacement /= No_File then
3528 In_Tree.Languages_Data.Table
3529 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3533 if Casing_Defined then
3534 In_Tree.Languages_Data.Table
3535 (Lang_Id).Config.Naming_Data.Casing := Casing;
3538 if Separate_Suffix /= No_File then
3539 In_Tree.Languages_Data.Table
3540 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3546 In_Tree.Languages_Data.Table (Lang_Id).Next;
3551 -- Next, get the spec and body suffixes
3554 Suffix : Variable_Value;
3555 Lang_Id : Language_Index;
3559 Lang_Id := Data.First_Language_Processing;
3560 while Lang_Id /= No_Language_Index loop
3561 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3567 Attribute_Or_Array_Name => Name_Spec_Suffix,
3568 In_Package => Naming_Id,
3569 In_Tree => In_Tree);
3571 if Suffix = Nil_Variable_Value then
3574 Attribute_Or_Array_Name => Name_Specification_Suffix,
3575 In_Package => Naming_Id,
3576 In_Tree => In_Tree);
3579 if Suffix /= Nil_Variable_Value then
3580 In_Tree.Languages_Data.Table (Lang_Id).
3581 Config.Naming_Data.Spec_Suffix :=
3582 File_Name_Type (Suffix.Value);
3589 Attribute_Or_Array_Name => Name_Body_Suffix,
3590 In_Package => Naming_Id,
3591 In_Tree => In_Tree);
3593 if Suffix = Nil_Variable_Value then
3596 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3597 In_Package => Naming_Id,
3598 In_Tree => In_Tree);
3601 if Suffix /= Nil_Variable_Value then
3602 In_Tree.Languages_Data.Table (Lang_Id).
3603 Config.Naming_Data.Body_Suffix :=
3604 File_Name_Type (Suffix.Value);
3607 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3611 -- Get the exceptions for file based languages
3613 Get_Exceptions (Spec);
3614 Get_Exceptions (Impl);
3616 -- Get the exceptions for unit based languages
3618 Get_Unit_Exceptions (Spec);
3619 Get_Unit_Exceptions (Impl);
3623 end Check_Naming_Schemes;
3625 ------------------------------
3626 -- Check_Library_Attributes --
3627 ------------------------------
3629 procedure Check_Library_Attributes
3630 (Project : Project_Id;
3631 In_Tree : Project_Tree_Ref;
3632 Current_Dir : String;
3633 Data : in out Project_Data)
3635 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3637 Lib_Dir : constant Prj.Variable_Value :=
3639 (Snames.Name_Library_Dir, Attributes, In_Tree);
3641 Lib_Name : constant Prj.Variable_Value :=
3643 (Snames.Name_Library_Name, Attributes, In_Tree);
3645 Lib_Version : constant Prj.Variable_Value :=
3647 (Snames.Name_Library_Version, Attributes, In_Tree);
3649 Lib_ALI_Dir : constant Prj.Variable_Value :=
3651 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3653 Lib_GCC : constant Prj.Variable_Value :=
3655 (Snames.Name_Library_GCC, Attributes, In_Tree);
3657 The_Lib_Kind : constant Prj.Variable_Value :=
3659 (Snames.Name_Library_Kind, Attributes, In_Tree);
3661 Imported_Project_List : Project_List := Empty_Project_List;
3663 Continuation : String_Access := No_Continuation_String'Access;
3665 Support_For_Libraries : Library_Support;
3667 Library_Directory_Present : Boolean;
3669 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3670 -- Check if an imported or extended project if also a library project
3676 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3677 Proj_Data : Project_Data;
3681 if Proj /= No_Project then
3682 Proj_Data := In_Tree.Projects.Table (Proj);
3684 if not Proj_Data.Library then
3686 -- The only not library projects that are OK are those that
3687 -- have no sources. However, header files from non-Ada
3688 -- languages are OK, as there is nothing to compile.
3690 Src_Id := Proj_Data.First_Source;
3691 while Src_Id /= No_Source loop
3693 Src : Source_Data renames In_Tree.Sources.Table (Src_Id);
3695 exit when Src.Lang_Kind /= File_Based
3696 or else Src.Kind /= Spec;
3697 Src_Id := Src.Next_In_Project;
3701 if Src_Id /= No_Source then
3702 Error_Msg_Name_1 := Data.Name;
3703 Error_Msg_Name_2 := Proj_Data.Name;
3706 if Data.Library_Kind /= Static then
3710 "shared library project %% cannot extend " &
3711 "project %% that is not a library project",
3713 Continuation := Continuation_String'Access;
3716 elsif Data.Library_Kind /= Static then
3720 "shared library project %% cannot import project %% " &
3721 "that is not a shared library project",
3723 Continuation := Continuation_String'Access;
3727 elsif Data.Library_Kind /= Static and then
3728 Proj_Data.Library_Kind = Static
3730 Error_Msg_Name_1 := Data.Name;
3731 Error_Msg_Name_2 := Proj_Data.Name;
3737 "shared library project %% cannot extend static " &
3738 "library project %%",
3745 "shared library project %% cannot import static " &
3746 "library project %%",
3750 Continuation := Continuation_String'Access;
3755 -- Start of processing for Check_Library_Attributes
3758 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3760 -- Special case of extending project
3762 if Data.Extends /= No_Project then
3764 Extended_Data : constant Project_Data :=
3765 In_Tree.Projects.Table (Data.Extends);
3768 -- If the project extended is a library project, we inherit the
3769 -- library name, if it is not redefined; we check that the library
3770 -- directory is specified.
3772 if Extended_Data.Library then
3773 if Data.Qualifier = Standard then
3776 "a standard project cannot extend a library project",
3780 if Lib_Name.Default then
3781 Data.Library_Name := Extended_Data.Library_Name;
3784 if Lib_Dir.Default then
3785 if not Data.Virtual then
3788 "a project extending a library project must " &
3789 "specify an attribute Library_Dir",
3793 -- For a virtual project extending a library project,
3794 -- inherit library directory.
3796 Data.Library_Dir := Extended_Data.Library_Dir;
3797 Library_Directory_Present := True;
3805 pragma Assert (Lib_Name.Kind = Single);
3807 if Lib_Name.Value = Empty_String then
3808 if Current_Verbosity = High
3809 and then Data.Library_Name = No_Name
3811 Write_Line ("No library name");
3815 -- There is no restriction on the syntax of library names
3817 Data.Library_Name := Lib_Name.Value;
3820 if Data.Library_Name /= No_Name then
3821 if Current_Verbosity = High then
3822 Write_Str ("Library name = """);
3823 Write_Str (Get_Name_String (Data.Library_Name));
3827 pragma Assert (Lib_Dir.Kind = Single);
3829 if not Library_Directory_Present then
3830 if Current_Verbosity = High then
3831 Write_Line ("No library directory");
3835 -- Find path name (unless inherited), check that it is a directory
3837 if Data.Library_Dir = No_Path_Information then
3841 File_Name_Type (Lib_Dir.Value),
3842 Data.Directory.Display_Name,
3843 Data.Library_Dir.Name,
3844 Data.Library_Dir.Display_Name,
3845 Create => "library",
3846 Current_Dir => Current_Dir,
3847 Location => Lib_Dir.Location,
3848 Externally_Built => Data.Externally_Built);
3851 if Data.Library_Dir = No_Path_Information then
3853 -- Get the absolute name of the library directory that
3854 -- does not exist, to report an error.
3857 Dir_Name : constant String :=
3858 Get_Name_String (Lib_Dir.Value);
3861 if Is_Absolute_Path (Dir_Name) then
3862 Err_Vars.Error_Msg_File_1 :=
3863 File_Name_Type (Lib_Dir.Value);
3866 Get_Name_String (Data.Directory.Display_Name);
3868 if Name_Buffer (Name_Len) /= Directory_Separator then
3869 Name_Len := Name_Len + 1;
3870 Name_Buffer (Name_Len) := Directory_Separator;
3874 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3876 Name_Len := Name_Len + Dir_Name'Length;
3877 Err_Vars.Error_Msg_File_1 := Name_Find;
3884 "library directory { does not exist",
3888 -- The library directory cannot be the same as the Object
3891 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3894 "library directory cannot be the same " &
3895 "as object directory",
3897 Data.Library_Dir := No_Path_Information;
3901 OK : Boolean := True;
3902 Dirs_Id : String_List_Id;
3903 Dir_Elem : String_Element;
3906 -- The library directory cannot be the same as a source
3907 -- directory of the current project.
3909 Dirs_Id := Data.Source_Dirs;
3910 while Dirs_Id /= Nil_String loop
3911 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3912 Dirs_Id := Dir_Elem.Next;
3915 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3917 Err_Vars.Error_Msg_File_1 :=
3918 File_Name_Type (Dir_Elem.Value);
3921 "library directory cannot be the same " &
3922 "as source directory {",
3931 -- The library directory cannot be the same as a source
3932 -- directory of another project either.
3935 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3936 if Pid /= Project then
3937 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3939 Dir_Loop : while Dirs_Id /= Nil_String loop
3941 In_Tree.String_Elements.Table (Dirs_Id);
3942 Dirs_Id := Dir_Elem.Next;
3944 if Data.Library_Dir.Name =
3945 Path_Name_Type (Dir_Elem.Value)
3947 Err_Vars.Error_Msg_File_1 :=
3948 File_Name_Type (Dir_Elem.Value);
3949 Err_Vars.Error_Msg_Name_1 :=
3950 In_Tree.Projects.Table (Pid).Name;
3954 "library directory cannot be the same " &
3955 "as source directory { of project %%",
3962 end loop Project_Loop;
3966 Data.Library_Dir := No_Path_Information;
3968 elsif Current_Verbosity = High then
3970 -- Display the Library directory in high verbosity
3972 Write_Str ("Library directory =""");
3974 (Get_Name_String (Data.Library_Dir.Display_Name));
3984 Data.Library_Dir /= No_Path_Information
3986 Data.Library_Name /= No_Name;
3988 if Data.Extends = No_Project then
3989 case Data.Qualifier is
3991 if Data.Library then
3994 "a standard project cannot be a library project",
3999 if not Data.Library then
4000 if Data.Library_Dir = No_Path_Information then
4003 "\attribute Library_Dir not declared",
4007 if Data.Library_Name = No_Name then
4010 "\attribute Library_Name not declared",
4021 if Data.Library then
4022 if Get_Mode = Multi_Language then
4023 Support_For_Libraries := Data.Config.Lib_Support;
4026 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
4029 if Support_For_Libraries = Prj.None then
4032 "?libraries are not supported on this platform",
4034 Data.Library := False;
4037 if Lib_ALI_Dir.Value = Empty_String then
4038 if Current_Verbosity = High then
4039 Write_Line ("No library ALI directory specified");
4041 Data.Library_ALI_Dir := Data.Library_Dir;
4044 -- Find path name, check that it is a directory
4049 File_Name_Type (Lib_ALI_Dir.Value),
4050 Data.Directory.Display_Name,
4051 Data.Library_ALI_Dir.Name,
4052 Data.Library_ALI_Dir.Display_Name,
4053 Create => "library ALI",
4054 Current_Dir => Current_Dir,
4055 Location => Lib_ALI_Dir.Location,
4056 Externally_Built => Data.Externally_Built);
4058 if Data.Library_ALI_Dir = No_Path_Information then
4060 -- Get the absolute name of the library ALI directory that
4061 -- does not exist, to report an error.
4064 Dir_Name : constant String :=
4065 Get_Name_String (Lib_ALI_Dir.Value);
4068 if Is_Absolute_Path (Dir_Name) then
4069 Err_Vars.Error_Msg_File_1 :=
4070 File_Name_Type (Lib_Dir.Value);
4073 Get_Name_String (Data.Directory.Display_Name);
4075 if Name_Buffer (Name_Len) /= Directory_Separator then
4076 Name_Len := Name_Len + 1;
4077 Name_Buffer (Name_Len) := Directory_Separator;
4081 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
4083 Name_Len := Name_Len + Dir_Name'Length;
4084 Err_Vars.Error_Msg_File_1 := Name_Find;
4091 "library 'A'L'I directory { does not exist",
4092 Lib_ALI_Dir.Location);
4096 if Data.Library_ALI_Dir /= Data.Library_Dir then
4098 -- The library ALI directory cannot be the same as the
4099 -- Object directory.
4101 if Data.Library_ALI_Dir = Data.Object_Directory then
4104 "library 'A'L'I directory cannot be the same " &
4105 "as object directory",
4106 Lib_ALI_Dir.Location);
4107 Data.Library_ALI_Dir := No_Path_Information;
4111 OK : Boolean := True;
4112 Dirs_Id : String_List_Id;
4113 Dir_Elem : String_Element;
4116 -- The library ALI directory cannot be the same as
4117 -- a source directory of the current project.
4119 Dirs_Id := Data.Source_Dirs;
4120 while Dirs_Id /= Nil_String loop
4121 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4122 Dirs_Id := Dir_Elem.Next;
4124 if Data.Library_ALI_Dir.Name =
4125 Path_Name_Type (Dir_Elem.Value)
4127 Err_Vars.Error_Msg_File_1 :=
4128 File_Name_Type (Dir_Elem.Value);
4131 "library 'A'L'I directory cannot be " &
4132 "the same as source directory {",
4133 Lib_ALI_Dir.Location);
4141 -- The library ALI directory cannot be the same as
4142 -- a source directory of another project either.
4146 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4148 if Pid /= Project then
4150 In_Tree.Projects.Table (Pid).Source_Dirs;
4153 while Dirs_Id /= Nil_String loop
4155 In_Tree.String_Elements.Table (Dirs_Id);
4156 Dirs_Id := Dir_Elem.Next;
4158 if Data.Library_ALI_Dir.Name =
4159 Path_Name_Type (Dir_Elem.Value)
4161 Err_Vars.Error_Msg_File_1 :=
4162 File_Name_Type (Dir_Elem.Value);
4163 Err_Vars.Error_Msg_Name_1 :=
4164 In_Tree.Projects.Table (Pid).Name;
4168 "library 'A'L'I directory cannot " &
4169 "be the same as source directory " &
4171 Lib_ALI_Dir.Location);
4173 exit ALI_Project_Loop;
4175 end loop ALI_Dir_Loop;
4177 end loop ALI_Project_Loop;
4181 Data.Library_ALI_Dir := No_Path_Information;
4183 elsif Current_Verbosity = High then
4185 -- Display the Library ALI directory in high
4188 Write_Str ("Library ALI directory =""");
4191 (Data.Library_ALI_Dir.Display_Name));
4199 pragma Assert (Lib_Version.Kind = Single);
4201 if Lib_Version.Value = Empty_String then
4202 if Current_Verbosity = High then
4203 Write_Line ("No library version specified");
4207 Data.Lib_Internal_Name := Lib_Version.Value;
4210 pragma Assert (The_Lib_Kind.Kind = Single);
4212 if The_Lib_Kind.Value = Empty_String then
4213 if Current_Verbosity = High then
4214 Write_Line ("No library kind specified");
4218 Get_Name_String (The_Lib_Kind.Value);
4221 Kind_Name : constant String :=
4222 To_Lower (Name_Buffer (1 .. Name_Len));
4224 OK : Boolean := True;
4227 if Kind_Name = "static" then
4228 Data.Library_Kind := Static;
4230 elsif Kind_Name = "dynamic" then
4231 Data.Library_Kind := Dynamic;
4233 elsif Kind_Name = "relocatable" then
4234 Data.Library_Kind := Relocatable;
4239 "illegal value for Library_Kind",
4240 The_Lib_Kind.Location);
4244 if Current_Verbosity = High and then OK then
4245 Write_Str ("Library kind = ");
4246 Write_Line (Kind_Name);
4249 if Data.Library_Kind /= Static then
4250 if Support_For_Libraries = Prj.Static_Only then
4253 "only static libraries are supported " &
4255 The_Lib_Kind.Location);
4256 Data.Library := False;
4259 -- Check if (obsolescent) attribute Library_GCC or
4260 -- Linker'Driver is declared.
4262 if Lib_GCC.Value /= Empty_String then
4266 "?Library_'G'C'C is an obsolescent attribute, " &
4267 "use Linker''Driver instead",
4269 Data.Config.Shared_Lib_Driver :=
4270 File_Name_Type (Lib_GCC.Value);
4274 Linker : constant Package_Id :=
4279 Driver : constant Variable_Value :=
4282 Attribute_Or_Array_Name =>
4284 In_Package => Linker,
4289 if Driver /= Nil_Variable_Value
4290 and then Driver.Value /= Empty_String
4292 Data.Config.Shared_Lib_Driver :=
4293 File_Name_Type (Driver.Value);
4302 if Data.Library then
4303 if Current_Verbosity = High then
4304 Write_Line ("This is a library project file");
4307 if Get_Mode = Multi_Language then
4308 Check_Library (Data.Extends, Extends => True);
4310 Imported_Project_List := Data.Imported_Projects;
4311 while Imported_Project_List /= Empty_Project_List loop
4313 (In_Tree.Project_Lists.Table
4314 (Imported_Project_List).Project,
4316 Imported_Project_List :=
4317 In_Tree.Project_Lists.Table
4318 (Imported_Project_List).Next;
4326 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4327 -- Warn if they are declared, as it is a common error to think that
4328 -- library are "linked" with Linker switches.
4330 if Data.Library then
4332 Linker_Package_Id : constant Package_Id :=
4334 (Name_Linker, Data.Decl.Packages, In_Tree);
4335 Linker_Package : Package_Element;
4336 Switches : Array_Element_Id := No_Array_Element;
4339 if Linker_Package_Id /= No_Package then
4340 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4344 (Name => Name_Switches,
4345 In_Arrays => Linker_Package.Decl.Arrays,
4346 In_Tree => In_Tree);
4348 if Switches = No_Array_Element then
4351 (Name => Name_Default_Switches,
4352 In_Arrays => Linker_Package.Decl.Arrays,
4353 In_Tree => In_Tree);
4356 if Switches /= No_Array_Element then
4359 "?Linker switches not taken into account in library " &
4367 if Data.Extends /= No_Project then
4368 In_Tree.Projects.Table (Data.Extends).Library := False;
4370 end Check_Library_Attributes;
4372 --------------------------
4373 -- Check_Package_Naming --
4374 --------------------------
4376 procedure Check_Package_Naming
4377 (Project : Project_Id;
4378 In_Tree : Project_Tree_Ref;
4379 Data : in out Project_Data)
4381 Naming_Id : constant Package_Id :=
4382 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4384 Naming : Package_Element;
4387 -- If there is a package Naming, we will put in Data.Naming
4388 -- what is in this package Naming.
4390 if Naming_Id /= No_Package then
4391 Naming := In_Tree.Packages.Table (Naming_Id);
4393 if Current_Verbosity = High then
4394 Write_Line ("Checking ""Naming"".");
4397 -- Check Spec_Suffix
4400 Spec_Suffixs : Array_Element_Id :=
4406 Suffix : Array_Element_Id;
4407 Element : Array_Element;
4408 Suffix2 : Array_Element_Id;
4411 -- If some suffixes have been specified, we make sure that
4412 -- for each language for which a default suffix has been
4413 -- specified, there is a suffix specified, either the one
4414 -- in the project file or if there were none, the default.
4416 if Spec_Suffixs /= No_Array_Element then
4417 Suffix := Data.Naming.Spec_Suffix;
4419 while Suffix /= No_Array_Element loop
4421 In_Tree.Array_Elements.Table (Suffix);
4422 Suffix2 := Spec_Suffixs;
4424 while Suffix2 /= No_Array_Element loop
4425 exit when In_Tree.Array_Elements.Table
4426 (Suffix2).Index = Element.Index;
4427 Suffix2 := In_Tree.Array_Elements.Table
4431 -- There is a registered default suffix, but no
4432 -- suffix specified in the project file.
4433 -- Add the default to the array.
4435 if Suffix2 = No_Array_Element then
4436 Array_Element_Table.Increment_Last
4437 (In_Tree.Array_Elements);
4438 In_Tree.Array_Elements.Table
4439 (Array_Element_Table.Last
4440 (In_Tree.Array_Elements)) :=
4441 (Index => Element.Index,
4442 Src_Index => Element.Src_Index,
4443 Index_Case_Sensitive => False,
4444 Value => Element.Value,
4445 Next => Spec_Suffixs);
4446 Spec_Suffixs := Array_Element_Table.Last
4447 (In_Tree.Array_Elements);
4450 Suffix := Element.Next;
4453 -- Put the resulting array as the specification suffixes
4455 Data.Naming.Spec_Suffix := Spec_Suffixs;
4460 Current : Array_Element_Id;
4461 Element : Array_Element;
4464 Current := Data.Naming.Spec_Suffix;
4465 while Current /= No_Array_Element loop
4466 Element := In_Tree.Array_Elements.Table (Current);
4467 Get_Name_String (Element.Value.Value);
4469 if Name_Len = 0 then
4472 "Spec_Suffix cannot be empty",
4473 Element.Value.Location);
4476 In_Tree.Array_Elements.Table (Current) := Element;
4477 Current := Element.Next;
4481 -- Check Body_Suffix
4484 Impl_Suffixs : Array_Element_Id :=
4490 Suffix : Array_Element_Id;
4491 Element : Array_Element;
4492 Suffix2 : Array_Element_Id;
4495 -- If some suffixes have been specified, we make sure that
4496 -- for each language for which a default suffix has been
4497 -- specified, there is a suffix specified, either the one
4498 -- in the project file or if there were none, the default.
4500 if Impl_Suffixs /= No_Array_Element then
4501 Suffix := Data.Naming.Body_Suffix;
4502 while Suffix /= No_Array_Element loop
4504 In_Tree.Array_Elements.Table (Suffix);
4506 Suffix2 := Impl_Suffixs;
4507 while Suffix2 /= No_Array_Element loop
4508 exit when In_Tree.Array_Elements.Table
4509 (Suffix2).Index = Element.Index;
4510 Suffix2 := In_Tree.Array_Elements.Table
4514 -- There is a registered default suffix, but no suffix was
4515 -- specified in the project file. Add default to the array.
4517 if Suffix2 = No_Array_Element then
4518 Array_Element_Table.Increment_Last
4519 (In_Tree.Array_Elements);
4520 In_Tree.Array_Elements.Table
4521 (Array_Element_Table.Last
4522 (In_Tree.Array_Elements)) :=
4523 (Index => Element.Index,
4524 Src_Index => Element.Src_Index,
4525 Index_Case_Sensitive => False,
4526 Value => Element.Value,
4527 Next => Impl_Suffixs);
4528 Impl_Suffixs := Array_Element_Table.Last
4529 (In_Tree.Array_Elements);
4532 Suffix := Element.Next;
4535 -- Put the resulting array as the implementation suffixes
4537 Data.Naming.Body_Suffix := Impl_Suffixs;
4542 Current : Array_Element_Id;
4543 Element : Array_Element;
4546 Current := Data.Naming.Body_Suffix;
4547 while Current /= No_Array_Element loop
4548 Element := In_Tree.Array_Elements.Table (Current);
4549 Get_Name_String (Element.Value.Value);
4551 if Name_Len = 0 then
4554 "Body_Suffix cannot be empty",
4555 Element.Value.Location);
4558 In_Tree.Array_Elements.Table (Current) := Element;
4559 Current := Element.Next;
4563 -- Get the exceptions, if any
4565 Data.Naming.Specification_Exceptions :=
4567 (Name_Specification_Exceptions,
4568 In_Arrays => Naming.Decl.Arrays,
4569 In_Tree => In_Tree);
4571 Data.Naming.Implementation_Exceptions :=
4573 (Name_Implementation_Exceptions,
4574 In_Arrays => Naming.Decl.Arrays,
4575 In_Tree => In_Tree);
4577 end Check_Package_Naming;
4579 ---------------------------------
4580 -- Check_Programming_Languages --
4581 ---------------------------------
4583 procedure Check_Programming_Languages
4584 (In_Tree : Project_Tree_Ref;
4585 Project : Project_Id;
4586 Data : in out Project_Data)
4588 Languages : Variable_Value := Nil_Variable_Value;
4589 Def_Lang : Variable_Value := Nil_Variable_Value;
4590 Def_Lang_Id : Name_Id;
4593 Data.First_Language_Processing := No_Language_Index;
4595 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4598 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4599 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4600 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4602 if Data.Source_Dirs /= Nil_String then
4604 -- Check if languages are specified in this project
4606 if Languages.Default then
4608 -- Attribute Languages is not specified. So, it defaults to
4609 -- a project of the default language only.
4611 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4612 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4614 -- In Ada_Only mode, the default language is Ada
4616 if Get_Mode = Ada_Only then
4617 In_Tree.Name_Lists.Table (Data.Languages) :=
4618 (Name => Name_Ada, Next => No_Name_List);
4620 -- Attribute Languages is not specified. So, it defaults to
4621 -- a project of language Ada only. No sources of languages
4624 Data.Other_Sources_Present := False;
4627 -- Fail if there is no default language defined
4629 if Def_Lang.Default then
4630 if not Default_Language_Is_Ada then
4634 "no languages defined for this project",
4636 Def_Lang_Id := No_Name;
4638 Def_Lang_Id := Name_Ada;
4642 Get_Name_String (Def_Lang.Value);
4643 To_Lower (Name_Buffer (1 .. Name_Len));
4644 Def_Lang_Id := Name_Find;
4647 if Def_Lang_Id /= No_Name then
4648 In_Tree.Name_Lists.Table (Data.Languages) :=
4649 (Name => Def_Lang_Id, Next => No_Name_List);
4651 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4653 Data.First_Language_Processing :=
4654 Language_Data_Table.Last (In_Tree.Languages_Data);
4655 In_Tree.Languages_Data.Table
4656 (Data.First_Language_Processing) := No_Language_Data;
4657 In_Tree.Languages_Data.Table
4658 (Data.First_Language_Processing).Name := Def_Lang_Id;
4659 Get_Name_String (Def_Lang_Id);
4660 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4661 In_Tree.Languages_Data.Table
4662 (Data.First_Language_Processing).Display_Name := Name_Find;
4664 if Def_Lang_Id = Name_Ada then
4665 In_Tree.Languages_Data.Table
4666 (Data.First_Language_Processing).Config.Kind
4668 In_Tree.Languages_Data.Table
4669 (Data.First_Language_Processing).Config.Dependency_Kind
4671 Data.Unit_Based_Language_Name := Name_Ada;
4672 Data.Unit_Based_Language_Index :=
4673 Data.First_Language_Processing;
4675 In_Tree.Languages_Data.Table
4676 (Data.First_Language_Processing).Config.Kind
4684 Current : String_List_Id := Languages.Values;
4685 Element : String_Element;
4686 Lang_Name : Name_Id;
4687 Index : Language_Index;
4688 Lang_Data : Language_Data;
4689 NL_Id : Name_List_Index := No_Name_List;
4692 -- Assume there are no language declared
4694 Data.Ada_Sources_Present := False;
4695 Data.Other_Sources_Present := False;
4697 -- If there are no languages declared, there are no sources
4699 if Current = Nil_String then
4700 Data.Source_Dirs := Nil_String;
4702 if Data.Qualifier = Standard then
4706 "a standard project cannot have no language declared",
4707 Languages.Location);
4711 -- Look through all the languages specified in attribute
4714 while Current /= Nil_String loop
4716 In_Tree.String_Elements.Table (Current);
4717 Get_Name_String (Element.Value);
4718 To_Lower (Name_Buffer (1 .. Name_Len));
4719 Lang_Name := Name_Find;
4721 NL_Id := Data.Languages;
4722 while NL_Id /= No_Name_List loop
4724 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4725 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4728 if NL_Id = No_Name_List then
4729 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4731 if Data.Languages = No_Name_List then
4733 Name_List_Table.Last (In_Tree.Name_Lists);
4736 NL_Id := Data.Languages;
4737 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4740 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4743 In_Tree.Name_Lists.Table (NL_Id).Next :=
4744 Name_List_Table.Last (In_Tree.Name_Lists);
4747 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4748 In_Tree.Name_Lists.Table (NL_Id) :=
4749 (Lang_Name, No_Name_List);
4751 if Get_Mode = Ada_Only then
4752 -- Check for language Ada
4754 if Lang_Name = Name_Ada then
4755 Data.Ada_Sources_Present := True;
4758 Data.Other_Sources_Present := True;
4762 Language_Data_Table.Increment_Last
4763 (In_Tree.Languages_Data);
4765 Language_Data_Table.Last (In_Tree.Languages_Data);
4766 Lang_Data.Name := Lang_Name;
4767 Lang_Data.Display_Name := Element.Value;
4768 Lang_Data.Next := Data.First_Language_Processing;
4770 if Lang_Name = Name_Ada then
4771 Lang_Data.Config.Kind := Unit_Based;
4772 Lang_Data.Config.Dependency_Kind := ALI_File;
4773 Data.Unit_Based_Language_Name := Name_Ada;
4774 Data.Unit_Based_Language_Index := Index;
4777 Lang_Data.Config.Kind := File_Based;
4778 Lang_Data.Config.Dependency_Kind := None;
4781 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4782 Data.First_Language_Processing := Index;
4786 Current := Element.Next;
4792 end Check_Programming_Languages;
4798 function Check_Project
4800 Root_Project : Project_Id;
4801 In_Tree : Project_Tree_Ref;
4802 Extending : Boolean) return Boolean
4805 if P = Root_Project then
4808 elsif Extending then
4810 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4813 while Data.Extends /= No_Project loop
4814 if P = Data.Extends then
4818 Data := In_Tree.Projects.Table (Data.Extends);
4826 -------------------------------
4827 -- Check_Stand_Alone_Library --
4828 -------------------------------
4830 procedure Check_Stand_Alone_Library
4831 (Project : Project_Id;
4832 In_Tree : Project_Tree_Ref;
4833 Data : in out Project_Data;
4834 Current_Dir : String;
4835 Extending : Boolean)
4837 Lib_Interfaces : constant Prj.Variable_Value :=
4839 (Snames.Name_Library_Interface,
4840 Data.Decl.Attributes,
4843 Lib_Auto_Init : constant Prj.Variable_Value :=
4845 (Snames.Name_Library_Auto_Init,
4846 Data.Decl.Attributes,
4849 Lib_Src_Dir : constant Prj.Variable_Value :=
4851 (Snames.Name_Library_Src_Dir,
4852 Data.Decl.Attributes,
4855 Lib_Symbol_File : constant Prj.Variable_Value :=
4857 (Snames.Name_Library_Symbol_File,
4858 Data.Decl.Attributes,
4861 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4863 (Snames.Name_Library_Symbol_Policy,
4864 Data.Decl.Attributes,
4867 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4869 (Snames.Name_Library_Reference_Symbol_File,
4870 Data.Decl.Attributes,
4873 Auto_Init_Supported : Boolean;
4874 OK : Boolean := True;
4876 Next_Proj : Project_Id;
4879 if Get_Mode = Multi_Language then
4880 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4882 Auto_Init_Supported :=
4883 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4886 pragma Assert (Lib_Interfaces.Kind = List);
4888 -- It is a stand-alone library project file if attribute
4889 -- Library_Interface is defined.
4891 if not Lib_Interfaces.Default then
4892 SAL_Library : declare
4893 Interfaces : String_List_Id := Lib_Interfaces.Values;
4894 Interface_ALIs : String_List_Id := Nil_String;
4896 The_Unit_Id : Unit_Index;
4897 The_Unit_Data : Unit_Data;
4899 procedure Add_ALI_For (Source : File_Name_Type);
4900 -- Add an ALI file name to the list of Interface ALIs
4906 procedure Add_ALI_For (Source : File_Name_Type) is
4908 Get_Name_String (Source);
4911 ALI : constant String :=
4912 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4913 ALI_Name_Id : Name_Id;
4916 Name_Len := ALI'Length;
4917 Name_Buffer (1 .. Name_Len) := ALI;
4918 ALI_Name_Id := Name_Find;
4920 String_Element_Table.Increment_Last
4921 (In_Tree.String_Elements);
4922 In_Tree.String_Elements.Table
4923 (String_Element_Table.Last
4924 (In_Tree.String_Elements)) :=
4925 (Value => ALI_Name_Id,
4927 Display_Value => ALI_Name_Id,
4929 In_Tree.String_Elements.Table
4930 (Interfaces).Location,
4932 Next => Interface_ALIs);
4933 Interface_ALIs := String_Element_Table.Last
4934 (In_Tree.String_Elements);
4938 -- Start of processing for SAL_Library
4941 Data.Standalone_Library := True;
4943 -- Library_Interface cannot be an empty list
4945 if Interfaces = Nil_String then
4948 "Library_Interface cannot be an empty list",
4949 Lib_Interfaces.Location);
4952 -- Process each unit name specified in the attribute
4953 -- Library_Interface.
4955 while Interfaces /= Nil_String loop
4957 (In_Tree.String_Elements.Table (Interfaces).Value);
4958 To_Lower (Name_Buffer (1 .. Name_Len));
4960 if Name_Len = 0 then
4963 "an interface cannot be an empty string",
4964 In_Tree.String_Elements.Table (Interfaces).Location);
4968 Error_Msg_Name_1 := Unit;
4970 if Get_Mode = Ada_Only then
4972 Units_Htable.Get (In_Tree.Units_HT, Unit);
4974 if The_Unit_Id = No_Unit_Index then
4978 In_Tree.String_Elements.Table
4979 (Interfaces).Location);
4982 -- Check that the unit is part of the project
4985 In_Tree.Units.Table (The_Unit_Id);
4987 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4988 and then The_Unit_Data.File_Names
4989 (Body_Part).Path.Name /= Slash
4992 (The_Unit_Data.File_Names (Body_Part).Project,
4993 Project, In_Tree, Extending)
4995 -- There is a body for this unit.
4996 -- If there is no spec, we need to check
4997 -- that it is not a subunit.
4999 if The_Unit_Data.File_Names
5000 (Specification).Name = No_File
5003 Src_Ind : Source_File_Index;
5006 Src_Ind := Sinput.P.Load_Project_File
5008 (The_Unit_Data.File_Names
5009 (Body_Part).Path.Name));
5011 if Sinput.P.Source_File_Is_Subunit
5016 "%% is a subunit; " &
5017 "it cannot be an interface",
5019 String_Elements.Table
5020 (Interfaces).Location);
5025 -- The unit is not a subunit, so we add
5026 -- to the Interface ALIs the ALI file
5027 -- corresponding to the body.
5030 (The_Unit_Data.File_Names (Body_Part).Name);
5035 "%% is not an unit of this project",
5036 In_Tree.String_Elements.Table
5037 (Interfaces).Location);
5040 elsif The_Unit_Data.File_Names
5041 (Specification).Name /= No_File
5042 and then The_Unit_Data.File_Names
5043 (Specification).Path.Name /= Slash
5044 and then Check_Project
5045 (The_Unit_Data.File_Names
5046 (Specification).Project,
5047 Project, In_Tree, Extending)
5050 -- The unit is part of the project, it has
5051 -- a spec, but no body. We add to the Interface
5052 -- ALIs the ALI file corresponding to the spec.
5055 (The_Unit_Data.File_Names (Specification).Name);
5060 "%% is not an unit of this project",
5061 In_Tree.String_Elements.Table
5062 (Interfaces).Location);
5067 -- Multi_Language mode
5069 Next_Proj := Data.Extends;
5070 Source := Data.First_Source;
5073 while Source /= No_Source and then
5074 In_Tree.Sources.Table (Source).Unit /= Unit
5077 In_Tree.Sources.Table (Source).Next_In_Project;
5080 exit when Source /= No_Source or else
5081 Next_Proj = No_Project;
5084 In_Tree.Projects.Table (Next_Proj).First_Source;
5086 In_Tree.Projects.Table (Next_Proj).Extends;
5089 if Source /= No_Source then
5090 if In_Tree.Sources.Table (Source).Kind = Sep then
5091 Source := No_Source;
5093 elsif In_Tree.Sources.Table (Source).Kind = Spec
5095 In_Tree.Sources.Table (Source).Other_Part /=
5098 Source := In_Tree.Sources.Table (Source).Other_Part;
5102 if Source /= No_Source then
5103 if In_Tree.Sources.Table (Source).Project /= Project
5107 In_Tree.Sources.Table (Source).Project,
5110 Source := No_Source;
5114 if Source = No_Source then
5117 "%% is not an unit of this project",
5118 In_Tree.String_Elements.Table
5119 (Interfaces).Location);
5122 if In_Tree.Sources.Table (Source).Kind = Spec and then
5123 In_Tree.Sources.Table (Source).Other_Part /=
5126 Source := In_Tree.Sources.Table (Source).Other_Part;
5129 String_Element_Table.Increment_Last
5130 (In_Tree.String_Elements);
5131 In_Tree.String_Elements.Table
5132 (String_Element_Table.Last
5133 (In_Tree.String_Elements)) :=
5135 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5138 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5140 In_Tree.String_Elements.Table
5141 (Interfaces).Location,
5143 Next => Interface_ALIs);
5144 Interface_ALIs := String_Element_Table.Last
5145 (In_Tree.String_Elements);
5153 In_Tree.String_Elements.Table (Interfaces).Next;
5156 -- Put the list of Interface ALIs in the project data
5158 Data.Lib_Interface_ALIs := Interface_ALIs;
5160 -- Check value of attribute Library_Auto_Init and set
5161 -- Lib_Auto_Init accordingly.
5163 if Lib_Auto_Init.Default then
5165 -- If no attribute Library_Auto_Init is declared, then set auto
5166 -- init only if it is supported.
5168 Data.Lib_Auto_Init := Auto_Init_Supported;
5171 Get_Name_String (Lib_Auto_Init.Value);
5172 To_Lower (Name_Buffer (1 .. Name_Len));
5174 if Name_Buffer (1 .. Name_Len) = "false" then
5175 Data.Lib_Auto_Init := False;
5177 elsif Name_Buffer (1 .. Name_Len) = "true" then
5178 if Auto_Init_Supported then
5179 Data.Lib_Auto_Init := True;
5182 -- Library_Auto_Init cannot be "true" if auto init is not
5187 "library auto init not supported " &
5189 Lib_Auto_Init.Location);
5195 "invalid value for attribute Library_Auto_Init",
5196 Lib_Auto_Init.Location);
5201 -- If attribute Library_Src_Dir is defined and not the empty string,
5202 -- check if the directory exist and is not the object directory or
5203 -- one of the source directories. This is the directory where copies
5204 -- of the interface sources will be copied. Note that this directory
5205 -- may be the library directory.
5207 if Lib_Src_Dir.Value /= Empty_String then
5209 Dir_Id : constant File_Name_Type :=
5210 File_Name_Type (Lib_Src_Dir.Value);
5217 Data.Directory.Display_Name,
5218 Data.Library_Src_Dir.Name,
5219 Data.Library_Src_Dir.Display_Name,
5220 Create => "library source copy",
5221 Current_Dir => Current_Dir,
5222 Location => Lib_Src_Dir.Location,
5223 Externally_Built => Data.Externally_Built);
5225 -- If directory does not exist, report an error
5227 if Data.Library_Src_Dir = No_Path_Information then
5229 -- Get the absolute name of the library directory that does
5230 -- not exist, to report an error.
5233 Dir_Name : constant String :=
5234 Get_Name_String (Dir_Id);
5237 if Is_Absolute_Path (Dir_Name) then
5238 Err_Vars.Error_Msg_File_1 := Dir_Id;
5241 Get_Name_String (Data.Directory.Name);
5243 if Name_Buffer (Name_Len) /=
5246 Name_Len := Name_Len + 1;
5247 Name_Buffer (Name_Len) :=
5248 Directory_Separator;
5253 Name_Len + Dir_Name'Length) :=
5255 Name_Len := Name_Len + Dir_Name'Length;
5256 Err_Vars.Error_Msg_Name_1 := Name_Find;
5261 Error_Msg_File_1 := Dir_Id;
5264 "Directory { does not exist",
5265 Lib_Src_Dir.Location);
5268 -- Report error if it is the same as the object directory
5270 elsif Data.Library_Src_Dir = Data.Object_Directory then
5273 "directory to copy interfaces cannot be " &
5274 "the object directory",
5275 Lib_Src_Dir.Location);
5276 Data.Library_Src_Dir := No_Path_Information;
5280 Src_Dirs : String_List_Id;
5281 Src_Dir : String_Element;
5284 -- Interface copy directory cannot be one of the source
5285 -- directory of the current project.
5287 Src_Dirs := Data.Source_Dirs;
5288 while Src_Dirs /= Nil_String loop
5289 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5291 -- Report error if it is one of the source directories
5293 if Data.Library_Src_Dir.Name =
5294 Path_Name_Type (Src_Dir.Value)
5298 "directory to copy interfaces cannot " &
5299 "be one of the source directories",
5300 Lib_Src_Dir.Location);
5301 Data.Library_Src_Dir := No_Path_Information;
5305 Src_Dirs := Src_Dir.Next;
5308 if Data.Library_Src_Dir /= No_Path_Information then
5310 -- It cannot be a source directory of any other
5313 Project_Loop : for Pid in 1 ..
5314 Project_Table.Last (In_Tree.Projects)
5317 In_Tree.Projects.Table (Pid).Source_Dirs;
5318 Dir_Loop : while Src_Dirs /= Nil_String loop
5320 In_Tree.String_Elements.Table (Src_Dirs);
5322 -- Report error if it is one of the source
5325 if Data.Library_Src_Dir.Name =
5326 Path_Name_Type (Src_Dir.Value)
5329 File_Name_Type (Src_Dir.Value);
5331 In_Tree.Projects.Table (Pid).Name;
5334 "directory to copy interfaces cannot " &
5335 "be the same as source directory { of " &
5337 Lib_Src_Dir.Location);
5338 Data.Library_Src_Dir := No_Path_Information;
5342 Src_Dirs := Src_Dir.Next;
5344 end loop Project_Loop;
5348 -- In high verbosity, if there is a valid Library_Src_Dir,
5349 -- display its path name.
5351 if Data.Library_Src_Dir /= No_Path_Information
5352 and then Current_Verbosity = High
5354 Write_Str ("Directory to copy interfaces =""");
5355 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5362 -- Check the symbol related attributes
5364 -- First, the symbol policy
5366 if not Lib_Symbol_Policy.Default then
5368 Value : constant String :=
5370 (Get_Name_String (Lib_Symbol_Policy.Value));
5373 -- Symbol policy must hove one of a limited number of values
5375 if Value = "autonomous" or else Value = "default" then
5376 Data.Symbol_Data.Symbol_Policy := Autonomous;
5378 elsif Value = "compliant" then
5379 Data.Symbol_Data.Symbol_Policy := Compliant;
5381 elsif Value = "controlled" then
5382 Data.Symbol_Data.Symbol_Policy := Controlled;
5384 elsif Value = "restricted" then
5385 Data.Symbol_Data.Symbol_Policy := Restricted;
5387 elsif Value = "direct" then
5388 Data.Symbol_Data.Symbol_Policy := Direct;
5393 "illegal value for Library_Symbol_Policy",
5394 Lib_Symbol_Policy.Location);
5399 -- If attribute Library_Symbol_File is not specified, symbol policy
5400 -- cannot be Restricted.
5402 if Lib_Symbol_File.Default then
5403 if Data.Symbol_Data.Symbol_Policy = Restricted then
5406 "Library_Symbol_File needs to be defined when " &
5407 "symbol policy is Restricted",
5408 Lib_Symbol_Policy.Location);
5412 -- Library_Symbol_File is defined
5414 Data.Symbol_Data.Symbol_File :=
5415 Path_Name_Type (Lib_Symbol_File.Value);
5417 Get_Name_String (Lib_Symbol_File.Value);
5419 if Name_Len = 0 then
5422 "symbol file name cannot be an empty string",
5423 Lib_Symbol_File.Location);
5426 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5429 for J in 1 .. Name_Len loop
5430 if Name_Buffer (J) = '/'
5431 or else Name_Buffer (J) = Directory_Separator
5440 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5443 "symbol file name { is illegal. " &
5444 "Name cannot include directory info.",
5445 Lib_Symbol_File.Location);
5450 -- If attribute Library_Reference_Symbol_File is not defined,
5451 -- symbol policy cannot be Compliant or Controlled.
5453 if Lib_Ref_Symbol_File.Default then
5454 if Data.Symbol_Data.Symbol_Policy = Compliant
5455 or else Data.Symbol_Data.Symbol_Policy = Controlled
5459 "a reference symbol file needs to be defined",
5460 Lib_Symbol_Policy.Location);
5464 -- Library_Reference_Symbol_File is defined, check file exists
5466 Data.Symbol_Data.Reference :=
5467 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5469 Get_Name_String (Lib_Ref_Symbol_File.Value);
5471 if Name_Len = 0 then
5474 "reference symbol file name cannot be an empty string",
5475 Lib_Symbol_File.Location);
5478 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5480 Add_Str_To_Name_Buffer
5481 (Get_Name_String (Data.Directory.Name));
5482 Add_Char_To_Name_Buffer (Directory_Separator);
5483 Add_Str_To_Name_Buffer
5484 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5485 Data.Symbol_Data.Reference := Name_Find;
5488 if not Is_Regular_File
5489 (Get_Name_String (Data.Symbol_Data.Reference))
5492 File_Name_Type (Lib_Ref_Symbol_File.Value);
5494 -- For controlled and direct symbol policies, it is an error
5495 -- if the reference symbol file does not exist. For other
5496 -- symbol policies, this is just a warning
5499 Data.Symbol_Data.Symbol_Policy /= Controlled
5500 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5504 "<library reference symbol file { does not exist",
5505 Lib_Ref_Symbol_File.Location);
5507 -- In addition in the non-controlled case, if symbol policy
5508 -- is Compliant, it is changed to Autonomous, because there
5509 -- is no reference to check against, and we don't want to
5510 -- fail in this case.
5512 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5513 if Data.Symbol_Data.Symbol_Policy = Compliant then
5514 Data.Symbol_Data.Symbol_Policy := Autonomous;
5519 -- If both the reference symbol file and the symbol file are
5520 -- defined, then check that they are not the same file.
5522 if Data.Symbol_Data.Symbol_File /= No_Path then
5523 Get_Name_String (Data.Symbol_Data.Symbol_File);
5525 if Name_Len > 0 then
5527 Symb_Path : constant String :=
5530 (Data.Object_Directory.Name) &
5531 Directory_Separator &
5532 Name_Buffer (1 .. Name_Len),
5533 Directory => Current_Dir,
5535 Opt.Follow_Links_For_Files);
5536 Ref_Path : constant String :=
5539 (Data.Symbol_Data.Reference),
5540 Directory => Current_Dir,
5542 Opt.Follow_Links_For_Files);
5544 if Symb_Path = Ref_Path then
5547 "library reference symbol file and library" &
5548 " symbol file cannot be the same file",
5549 Lib_Ref_Symbol_File.Location);
5557 end Check_Stand_Alone_Library;
5559 ----------------------------
5560 -- Compute_Directory_Last --
5561 ----------------------------
5563 function Compute_Directory_Last (Dir : String) return Natural is
5566 and then (Dir (Dir'Last - 1) = Directory_Separator
5567 or else Dir (Dir'Last - 1) = '/')
5569 return Dir'Last - 1;
5573 end Compute_Directory_Last;
5580 (Project : Project_Id;
5581 In_Tree : Project_Tree_Ref;
5583 Flag_Location : Source_Ptr)
5585 Real_Location : Source_Ptr := Flag_Location;
5586 Error_Buffer : String (1 .. 5_000);
5587 Error_Last : Natural := 0;
5588 Name_Number : Natural := 0;
5589 File_Number : Natural := 0;
5590 First : Positive := Msg'First;
5593 procedure Add (C : Character);
5594 -- Add a character to the buffer
5596 procedure Add (S : String);
5597 -- Add a string to the buffer
5600 -- Add a name to the buffer
5603 -- Add a file name to the buffer
5609 procedure Add (C : Character) is
5611 Error_Last := Error_Last + 1;
5612 Error_Buffer (Error_Last) := C;
5615 procedure Add (S : String) is
5617 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5618 Error_Last := Error_Last + S'Length;
5625 procedure Add_File is
5626 File : File_Name_Type;
5630 File_Number := File_Number + 1;
5634 File := Err_Vars.Error_Msg_File_1;
5636 File := Err_Vars.Error_Msg_File_2;
5638 File := Err_Vars.Error_Msg_File_3;
5643 Get_Name_String (File);
5644 Add (Name_Buffer (1 .. Name_Len));
5652 procedure Add_Name is
5657 Name_Number := Name_Number + 1;
5661 Name := Err_Vars.Error_Msg_Name_1;
5663 Name := Err_Vars.Error_Msg_Name_2;
5665 Name := Err_Vars.Error_Msg_Name_3;
5670 Get_Name_String (Name);
5671 Add (Name_Buffer (1 .. Name_Len));
5675 -- Start of processing for Error_Msg
5678 -- If location of error is unknown, use the location of the project
5680 if Real_Location = No_Location then
5681 Real_Location := In_Tree.Projects.Table (Project).Location;
5684 if Error_Report = null then
5685 Prj.Err.Error_Msg (Msg, Real_Location);
5689 -- Ignore continuation character
5691 if Msg (First) = '\' then
5695 -- Warning character is always the first one in this package
5696 -- this is an undocumented kludge???
5698 if Msg (First) = '?' then
5702 elsif Msg (First) = '<' then
5705 if Err_Vars.Error_Msg_Warn then
5711 while Index <= Msg'Last loop
5712 if Msg (Index) = '{' then
5715 elsif Msg (Index) = '%' then
5716 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5728 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5731 ----------------------
5732 -- Find_Ada_Sources --
5733 ----------------------
5735 procedure Find_Ada_Sources
5736 (Project : Project_Id;
5737 In_Tree : Project_Tree_Ref;
5738 Data : in out Project_Data;
5739 Current_Dir : String)
5741 Source_Dir : String_List_Id := Data.Source_Dirs;
5742 Element : String_Element;
5744 Current_Source : String_List_Id := Nil_String;
5745 Source_Recorded : Boolean := False;
5748 if Current_Verbosity = High then
5749 Write_Line ("Looking for sources:");
5752 -- For each subdirectory
5754 while Source_Dir /= Nil_String loop
5756 Source_Recorded := False;
5757 Element := In_Tree.String_Elements.Table (Source_Dir);
5758 if Element.Value /= No_Name then
5759 Get_Name_String (Element.Display_Value);
5762 Source_Directory : constant String :=
5763 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5764 Dir_Last : constant Natural :=
5765 Compute_Directory_Last (Source_Directory);
5768 if Current_Verbosity = High then
5769 Write_Str ("Source_Dir = ");
5770 Write_Line (Source_Directory);
5773 -- We look at every entry in the source directory
5776 Source_Directory (Source_Directory'First .. Dir_Last));
5779 Read (Dir, Name_Buffer, Name_Len);
5781 if Current_Verbosity = High then
5782 Write_Str (" Checking ");
5783 Write_Line (Name_Buffer (1 .. Name_Len));
5786 exit when Name_Len = 0;
5789 File_Name : constant File_Name_Type := Name_Find;
5791 -- ??? We could probably optimize the following call:
5792 -- we need to resolve links only once for the
5793 -- directory itself, and then do a single call to
5794 -- readlink() for each file. Unfortunately that would
5795 -- require a change in Normalize_Pathname so that it
5796 -- has the option of not resolving links for its
5797 -- Directory parameter, only for Name.
5799 Path : constant String :=
5801 (Name => Name_Buffer (1 .. Name_Len),
5804 (Source_Directory'First .. Dir_Last),
5806 Opt.Follow_Links_For_Files,
5807 Case_Sensitive => True);
5809 Path_Name : Path_Name_Type;
5812 Name_Len := Path'Length;
5813 Name_Buffer (1 .. Name_Len) := Path;
5814 Path_Name := Name_Find;
5816 -- We attempt to register it as a source. However,
5817 -- there is no error if the file does not contain a
5818 -- valid source. But there is an error if we have a
5819 -- duplicate unit name.
5822 (File_Name => File_Name,
5823 Path_Name => Path_Name,
5827 Location => No_Location,
5828 Current_Source => Current_Source,
5829 Source_Recorded => Source_Recorded,
5830 Current_Dir => Current_Dir);
5839 when Directory_Error =>
5843 if Source_Recorded then
5844 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5848 Source_Dir := Element.Next;
5851 if Current_Verbosity = High then
5852 Write_Line ("end Looking for sources.");
5855 end Find_Ada_Sources;
5857 --------------------------------
5858 -- Free_Ada_Naming_Exceptions --
5859 --------------------------------
5861 procedure Free_Ada_Naming_Exceptions is
5863 Ada_Naming_Exception_Table.Set_Last (0);
5864 Ada_Naming_Exceptions.Reset;
5865 Reverse_Ada_Naming_Exceptions.Reset;
5866 end Free_Ada_Naming_Exceptions;
5868 ---------------------
5869 -- Get_Directories --
5870 ---------------------
5872 procedure Get_Directories
5873 (Project : Project_Id;
5874 In_Tree : Project_Tree_Ref;
5875 Current_Dir : String;
5876 Data : in out Project_Data)
5878 Object_Dir : constant Variable_Value :=
5880 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5882 Exec_Dir : constant Variable_Value :=
5884 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5886 Source_Dirs : constant Variable_Value :=
5888 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5890 Excluded_Source_Dirs : constant Variable_Value :=
5892 (Name_Excluded_Source_Dirs,
5893 Data.Decl.Attributes,
5896 Source_Files : constant Variable_Value :=
5898 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5900 Last_Source_Dir : String_List_Id := Nil_String;
5902 Languages : constant Variable_Value :=
5904 (Name_Languages, Data.Decl.Attributes, In_Tree);
5906 procedure Find_Source_Dirs
5907 (From : File_Name_Type;
5908 Location : Source_Ptr;
5909 Removed : Boolean := False);
5910 -- Find one or several source directories, and add (or remove, if
5911 -- Removed is True) them to list of source directories of the project.
5913 ----------------------
5914 -- Find_Source_Dirs --
5915 ----------------------
5917 procedure Find_Source_Dirs
5918 (From : File_Name_Type;
5919 Location : Source_Ptr;
5920 Removed : Boolean := False)
5922 Directory : constant String := Get_Name_String (From);
5923 Element : String_Element;
5925 procedure Recursive_Find_Dirs (Path : Name_Id);
5926 -- Find all the subdirectories (recursively) of Path and add them
5927 -- to the list of source directories of the project.
5929 -------------------------
5930 -- Recursive_Find_Dirs --
5931 -------------------------
5933 procedure Recursive_Find_Dirs (Path : Name_Id) is
5935 Name : String (1 .. 250);
5937 List : String_List_Id;
5938 Prev : String_List_Id;
5939 Element : String_Element;
5940 Found : Boolean := False;
5942 Non_Canonical_Path : Name_Id := No_Name;
5943 Canonical_Path : Name_Id := No_Name;
5945 The_Path : constant String :=
5947 (Get_Name_String (Path),
5948 Directory => Current_Dir,
5949 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5950 Directory_Separator;
5952 The_Path_Last : constant Natural :=
5953 Compute_Directory_Last (The_Path);
5956 Name_Len := The_Path_Last - The_Path'First + 1;
5957 Name_Buffer (1 .. Name_Len) :=
5958 The_Path (The_Path'First .. The_Path_Last);
5959 Non_Canonical_Path := Name_Find;
5961 if Osint.File_Names_Case_Sensitive then
5962 Canonical_Path := Non_Canonical_Path;
5964 Get_Name_String (Non_Canonical_Path);
5965 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5966 Canonical_Path := Name_Find;
5969 -- To avoid processing the same directory several times, check
5970 -- if the directory is already in Recursive_Dirs. If it is, then
5971 -- there is nothing to do, just return. If it is not, put it there
5972 -- and continue recursive processing.
5975 if Recursive_Dirs.Get (Canonical_Path) then
5978 Recursive_Dirs.Set (Canonical_Path, True);
5982 -- Check if directory is already in list
5984 List := Data.Source_Dirs;
5986 while List /= Nil_String loop
5987 Element := In_Tree.String_Elements.Table (List);
5989 if Element.Value /= No_Name then
5990 Found := Element.Value = Canonical_Path;
5995 List := Element.Next;
5998 -- If directory is not already in list, put it there
6000 if (not Removed) and (not Found) then
6001 if Current_Verbosity = High then
6003 Write_Line (The_Path (The_Path'First .. The_Path_Last));
6006 String_Element_Table.Increment_Last
6007 (In_Tree.String_Elements);
6009 (Value => Canonical_Path,
6010 Display_Value => Non_Canonical_Path,
6011 Location => No_Location,
6016 -- Case of first source directory
6018 if Last_Source_Dir = Nil_String then
6019 Data.Source_Dirs := String_Element_Table.Last
6020 (In_Tree.String_Elements);
6022 -- Here we already have source directories
6025 -- Link the previous last to the new one
6027 In_Tree.String_Elements.Table
6028 (Last_Source_Dir).Next :=
6029 String_Element_Table.Last
6030 (In_Tree.String_Elements);
6033 -- And register this source directory as the new last
6035 Last_Source_Dir := String_Element_Table.Last
6036 (In_Tree.String_Elements);
6037 In_Tree.String_Elements.Table (Last_Source_Dir) :=
6040 elsif Removed and Found then
6041 if Prev = Nil_String then
6043 In_Tree.String_Elements.Table (List).Next;
6045 In_Tree.String_Elements.Table (Prev).Next :=
6046 In_Tree.String_Elements.Table (List).Next;
6050 -- Now look for subdirectories. We do that even when this
6051 -- directory is already in the list, because some of its
6052 -- subdirectories may not be in the list yet.
6054 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
6057 Read (Dir, Name, Last);
6060 if Name (1 .. Last) /= "."
6061 and then Name (1 .. Last) /= ".."
6063 -- Avoid . and .. directories
6065 if Current_Verbosity = High then
6066 Write_Str (" Checking ");
6067 Write_Line (Name (1 .. Last));
6071 Path_Name : constant String :=
6073 (Name => Name (1 .. Last),
6075 The_Path (The_Path'First .. The_Path_Last),
6076 Resolve_Links => Opt.Follow_Links_For_Dirs,
6077 Case_Sensitive => True);
6080 if Is_Directory (Path_Name) then
6081 -- We have found a new subdirectory, call self
6083 Name_Len := Path_Name'Length;
6084 Name_Buffer (1 .. Name_Len) := Path_Name;
6085 Recursive_Find_Dirs (Name_Find);
6094 when Directory_Error =>
6096 end Recursive_Find_Dirs;
6098 -- Start of processing for Find_Source_Dirs
6101 if Current_Verbosity = High and then not Removed then
6102 Write_Str ("Find_Source_Dirs (""");
6103 Write_Str (Directory);
6107 -- First, check if we are looking for a directory tree, indicated
6108 -- by "/**" at the end.
6110 if Directory'Length >= 3
6111 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
6112 and then (Directory (Directory'Last - 2) = '/'
6114 Directory (Directory'Last - 2) = Directory_Separator)
6117 Data.Known_Order_Of_Source_Dirs := False;
6120 Name_Len := Directory'Length - 3;
6122 if Name_Len = 0 then
6124 -- Case of "/**": all directories in file system
6127 Name_Buffer (1) := Directory (Directory'First);
6130 Name_Buffer (1 .. Name_Len) :=
6131 Directory (Directory'First .. Directory'Last - 3);
6134 if Current_Verbosity = High then
6135 Write_Str ("Looking for all subdirectories of """);
6136 Write_Str (Name_Buffer (1 .. Name_Len));
6141 Base_Dir : constant File_Name_Type := Name_Find;
6142 Root_Dir : constant String :=
6144 (Name => Get_Name_String (Base_Dir),
6146 Get_Name_String (Data.Directory.Display_Name),
6147 Resolve_Links => False,
6148 Case_Sensitive => True);
6151 if Root_Dir'Length = 0 then
6152 Err_Vars.Error_Msg_File_1 := Base_Dir;
6154 if Location = No_Location then
6157 "{ is not a valid directory.",
6162 "{ is not a valid directory.",
6167 -- We have an existing directory, we register it and all of
6168 -- its subdirectories.
6170 if Current_Verbosity = High then
6171 Write_Line ("Looking for source directories:");
6174 Name_Len := Root_Dir'Length;
6175 Name_Buffer (1 .. Name_Len) := Root_Dir;
6176 Recursive_Find_Dirs (Name_Find);
6178 if Current_Verbosity = High then
6179 Write_Line ("End of looking for source directories.");
6184 -- We have a single directory
6188 Path_Name : Path_Name_Type;
6189 Display_Path_Name : Path_Name_Type;
6190 List : String_List_Id;
6191 Prev : String_List_Id;
6195 (Project => Project,
6198 Parent => Data.Directory.Display_Name,
6200 Display => Display_Path_Name,
6201 Current_Dir => Current_Dir);
6203 if Path_Name = No_Path then
6204 Err_Vars.Error_Msg_File_1 := From;
6206 if Location = No_Location then
6209 "{ is not a valid directory",
6214 "{ is not a valid directory",
6220 Path : constant String :=
6221 Get_Name_String (Path_Name) &
6222 Directory_Separator;
6223 Last_Path : constant Natural :=
6224 Compute_Directory_Last (Path);
6226 Display_Path : constant String :=
6228 (Display_Path_Name) &
6229 Directory_Separator;
6230 Last_Display_Path : constant Natural :=
6231 Compute_Directory_Last
6233 Display_Path_Id : Name_Id;
6237 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6238 Path_Id := Name_Find;
6240 Add_Str_To_Name_Buffer
6242 (Display_Path'First .. Last_Display_Path));
6243 Display_Path_Id := Name_Find;
6247 -- As it is an existing directory, we add it to the
6248 -- list of directories.
6250 String_Element_Table.Increment_Last
6251 (In_Tree.String_Elements);
6255 Display_Value => Display_Path_Id,
6256 Location => No_Location,
6258 Next => Nil_String);
6260 if Last_Source_Dir = Nil_String then
6262 -- This is the first source directory
6264 Data.Source_Dirs := String_Element_Table.Last
6265 (In_Tree.String_Elements);
6268 -- We already have source directories, link the
6269 -- previous last to the new one.
6271 In_Tree.String_Elements.Table
6272 (Last_Source_Dir).Next :=
6273 String_Element_Table.Last
6274 (In_Tree.String_Elements);
6277 -- And register this source directory as the new last
6279 Last_Source_Dir := String_Element_Table.Last
6280 (In_Tree.String_Elements);
6281 In_Tree.String_Elements.Table
6282 (Last_Source_Dir) := Element;
6285 -- Remove source dir, if present
6287 List := Data.Source_Dirs;
6290 -- Look for source dir in current list
6292 while List /= Nil_String loop
6293 Element := In_Tree.String_Elements.Table (List);
6294 exit when Element.Value = Path_Id;
6296 List := Element.Next;
6299 if List /= Nil_String then
6300 -- Source dir was found, remove it from the list
6302 if Prev = Nil_String then
6304 In_Tree.String_Elements.Table (List).Next;
6307 In_Tree.String_Elements.Table (Prev).Next :=
6308 In_Tree.String_Elements.Table (List).Next;
6316 end Find_Source_Dirs;
6318 -- Start of processing for Get_Directories
6321 if Current_Verbosity = High then
6322 Write_Line ("Starting to look for directories");
6325 -- Set the object directory to its default which may be nil, if there
6326 -- is no sources in the project.
6328 if (((not Source_Files.Default)
6329 and then Source_Files.Values = Nil_String)
6331 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
6333 ((not Languages.Default) and then Languages.Values = Nil_String))
6334 and then Data.Extends = No_Project
6336 Data.Object_Directory := No_Path_Information;
6339 Data.Object_Directory := Data.Directory;
6342 -- Check the object directory
6344 if Object_Dir.Value /= Empty_String then
6345 Get_Name_String (Object_Dir.Value);
6347 if Name_Len = 0 then
6350 "Object_Dir cannot be empty",
6351 Object_Dir.Location);
6354 -- We check that the specified object directory does exist
6359 File_Name_Type (Object_Dir.Value),
6360 Data.Directory.Display_Name,
6361 Data.Object_Directory.Name,
6362 Data.Object_Directory.Display_Name,
6364 Location => Object_Dir.Location,
6365 Current_Dir => Current_Dir,
6366 Externally_Built => Data.Externally_Built);
6368 if Data.Object_Directory = No_Path_Information then
6370 -- The object directory does not exist, report an error if the
6371 -- project is not externally built.
6373 if not Data.Externally_Built then
6374 Err_Vars.Error_Msg_File_1 :=
6375 File_Name_Type (Object_Dir.Value);
6378 "the object directory { cannot be found",
6382 -- Do not keep a nil Object_Directory. Set it to the specified
6383 -- (relative or absolute) path. This is for the benefit of
6384 -- tools that recover from errors; for example, these tools
6385 -- could create the non existent directory.
6387 Data.Object_Directory.Display_Name :=
6388 Path_Name_Type (Object_Dir.Value);
6390 if Osint.File_Names_Case_Sensitive then
6391 Data.Object_Directory.Name :=
6392 Path_Name_Type (Object_Dir.Value);
6394 Get_Name_String (Object_Dir.Value);
6395 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6396 Data.Object_Directory.Name := Name_Find;
6401 elsif Data.Object_Directory /= No_Path_Information and then
6405 Name_Buffer (1) := '.';
6410 Data.Directory.Display_Name,
6411 Data.Object_Directory.Name,
6412 Data.Object_Directory.Display_Name,
6414 Location => Object_Dir.Location,
6415 Current_Dir => Current_Dir,
6416 Externally_Built => Data.Externally_Built);
6419 if Current_Verbosity = High then
6420 if Data.Object_Directory = No_Path_Information then
6421 Write_Line ("No object directory");
6423 Write_Str ("Object directory: """);
6424 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6429 -- Check the exec directory
6431 -- We set the object directory to its default
6433 Data.Exec_Directory := Data.Object_Directory;
6435 if Exec_Dir.Value /= Empty_String then
6436 Get_Name_String (Exec_Dir.Value);
6438 if Name_Len = 0 then
6441 "Exec_Dir cannot be empty",
6445 -- We check that the specified exec directory does exist
6450 File_Name_Type (Exec_Dir.Value),
6451 Data.Directory.Display_Name,
6452 Data.Exec_Directory.Name,
6453 Data.Exec_Directory.Display_Name,
6455 Location => Exec_Dir.Location,
6456 Current_Dir => Current_Dir,
6457 Externally_Built => Data.Externally_Built);
6459 if Data.Exec_Directory = No_Path_Information then
6460 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6463 "the exec directory { cannot be found",
6469 if Current_Verbosity = High then
6470 if Data.Exec_Directory = No_Path_Information then
6471 Write_Line ("No exec directory");
6473 Write_Str ("Exec directory: """);
6474 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6479 -- Look for the source directories
6481 if Current_Verbosity = High then
6482 Write_Line ("Starting to look for source directories");
6485 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6487 if (not Source_Files.Default) and then
6488 Source_Files.Values = Nil_String
6490 Data.Source_Dirs := Nil_String;
6492 if Data.Qualifier = Standard then
6496 "a standard project cannot have no sources",
6497 Source_Files.Location);
6500 elsif Source_Dirs.Default then
6502 -- No Source_Dirs specified: the single source directory is the one
6503 -- containing the project file
6505 String_Element_Table.Increment_Last
6506 (In_Tree.String_Elements);
6507 Data.Source_Dirs := String_Element_Table.Last
6508 (In_Tree.String_Elements);
6509 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6510 (Value => Name_Id (Data.Directory.Name),
6511 Display_Value => Name_Id (Data.Directory.Display_Name),
6512 Location => No_Location,
6517 if Current_Verbosity = High then
6518 Write_Line ("Single source directory:");
6520 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6524 elsif Source_Dirs.Values = Nil_String then
6525 if Data.Qualifier = Standard then
6529 "a standard project cannot have no source directories",
6530 Source_Dirs.Location);
6533 Data.Source_Dirs := Nil_String;
6537 Source_Dir : String_List_Id;
6538 Element : String_Element;
6541 -- Process the source directories for each element of the list
6543 Source_Dir := Source_Dirs.Values;
6544 while Source_Dir /= Nil_String loop
6545 Element := In_Tree.String_Elements.Table (Source_Dir);
6547 (File_Name_Type (Element.Value), Element.Location);
6548 Source_Dir := Element.Next;
6553 if not Excluded_Source_Dirs.Default
6554 and then Excluded_Source_Dirs.Values /= Nil_String
6557 Source_Dir : String_List_Id;
6558 Element : String_Element;
6561 -- Process the source directories for each element of the list
6563 Source_Dir := Excluded_Source_Dirs.Values;
6564 while Source_Dir /= Nil_String loop
6565 Element := In_Tree.String_Elements.Table (Source_Dir);
6567 (File_Name_Type (Element.Value),
6570 Source_Dir := Element.Next;
6575 if Current_Verbosity = High then
6576 Write_Line ("Putting source directories in canonical cases");
6580 Current : String_List_Id := Data.Source_Dirs;
6581 Element : String_Element;
6584 while Current /= Nil_String loop
6585 Element := In_Tree.String_Elements.Table (Current);
6586 if Element.Value /= No_Name then
6587 if not Osint.File_Names_Case_Sensitive then
6588 Get_Name_String (Element.Value);
6589 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6590 Element.Value := Name_Find;
6593 In_Tree.String_Elements.Table (Current) := Element;
6596 Current := Element.Next;
6599 end Get_Directories;
6606 (Project : Project_Id;
6607 In_Tree : Project_Tree_Ref;
6608 Data : in out Project_Data)
6610 Mains : constant Variable_Value :=
6611 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6612 List : String_List_Id;
6613 Elem : String_Element;
6616 Data.Mains := Mains.Values;
6618 -- If no Mains were specified, and if we are an extending project,
6619 -- inherit the Mains from the project we are extending.
6621 if Mains.Default then
6622 if not Data.Library and then Data.Extends /= No_Project then
6624 In_Tree.Projects.Table (Data.Extends).Mains;
6627 -- In a library project file, Main cannot be specified
6629 elsif Data.Library then
6632 "a library project file cannot have Main specified",
6636 List := Mains.Values;
6637 while List /= Nil_String loop
6638 Elem := In_Tree.String_Elements.Table (List);
6640 if Length_Of_Name (Elem.Value) = 0 then
6643 "?a main cannot have an empty name",
6653 ---------------------------
6654 -- Get_Sources_From_File --
6655 ---------------------------
6657 procedure Get_Sources_From_File
6659 Location : Source_Ptr;
6660 Project : Project_Id;
6661 In_Tree : Project_Tree_Ref)
6663 File : Prj.Util.Text_File;
6664 Line : String (1 .. 250);
6666 Source_Name : File_Name_Type;
6667 Name_Loc : Name_Location;
6670 if Get_Mode = Ada_Only then
6674 if Current_Verbosity = High then
6675 Write_Str ("Opening """);
6682 Prj.Util.Open (File, Path);
6684 if not Prj.Util.Is_Valid (File) then
6685 Error_Msg (Project, In_Tree, "file does not exist", Location);
6688 -- Read the lines one by one
6690 while not Prj.Util.End_Of_File (File) loop
6691 Prj.Util.Get_Line (File, Line, Last);
6693 -- A non empty, non comment line should contain a file name
6696 and then (Last = 1 or else Line (1 .. 2) /= "--")
6699 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6700 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6701 Source_Name := Name_Find;
6703 -- Check that there is no directory information
6705 for J in 1 .. Last loop
6706 if Line (J) = '/' or else Line (J) = Directory_Separator then
6707 Error_Msg_File_1 := Source_Name;
6711 "file name cannot include directory information ({)",
6717 Name_Loc := Source_Names.Get (Source_Name);
6719 if Name_Loc = No_Name_Location then
6721 (Name => Source_Name,
6722 Location => Location,
6723 Source => No_Source,
6728 Source_Names.Set (Source_Name, Name_Loc);
6732 Prj.Util.Close (File);
6735 end Get_Sources_From_File;
6742 (In_Tree : Project_Tree_Ref;
6743 Canonical_File_Name : File_Name_Type;
6744 Naming : Naming_Data;
6745 Exception_Id : out Ada_Naming_Exception_Id;
6746 Unit_Name : out Name_Id;
6747 Unit_Kind : out Spec_Or_Body;
6748 Needs_Pragma : out Boolean)
6750 Info_Id : Ada_Naming_Exception_Id :=
6751 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6752 VMS_Name : File_Name_Type;
6755 if Info_Id = No_Ada_Naming_Exception then
6756 if Hostparm.OpenVMS then
6757 VMS_Name := Canonical_File_Name;
6758 Get_Name_String (VMS_Name);
6760 if Name_Buffer (Name_Len) = '.' then
6761 Name_Len := Name_Len - 1;
6762 VMS_Name := Name_Find;
6765 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6770 if Info_Id /= No_Ada_Naming_Exception then
6771 Exception_Id := Info_Id;
6772 Unit_Name := No_Name;
6773 Unit_Kind := Specification;
6774 Needs_Pragma := True;
6778 Needs_Pragma := False;
6779 Exception_Id := No_Ada_Naming_Exception;
6781 Get_Name_String (Canonical_File_Name);
6783 -- How about some comments and a name for this declare block ???
6784 -- In fact the whole code below needs more comments ???
6787 File : String := Name_Buffer (1 .. Name_Len);
6788 First : constant Positive := File'First;
6789 Last : Natural := File'Last;
6790 Standard_GNAT : Boolean;
6791 Spec : constant File_Name_Type :=
6792 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6793 Body_Suff : constant File_Name_Type :=
6794 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6797 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6798 and then Body_Suff = Default_Ada_Body_Suffix;
6801 Spec_Suffix : constant String := Get_Name_String (Spec);
6802 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6803 Sep_Suffix : constant String :=
6804 Get_Name_String (Naming.Separate_Suffix);
6806 May_Be_Spec : Boolean;
6807 May_Be_Body : Boolean;
6808 May_Be_Sep : Boolean;
6812 File'Length > Spec_Suffix'Length
6814 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6817 File'Length > Body_Suffix'Length
6819 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6822 File'Length > Sep_Suffix'Length
6824 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6826 -- If two May_Be_ booleans are True, always choose the longer one
6829 if May_Be_Body and then
6830 Spec_Suffix'Length < Body_Suffix'Length
6832 Unit_Kind := Body_Part;
6834 if May_Be_Sep and then
6835 Body_Suffix'Length < Sep_Suffix'Length
6837 Last := Last - Sep_Suffix'Length;
6838 May_Be_Body := False;
6841 Last := Last - Body_Suffix'Length;
6842 May_Be_Sep := False;
6845 elsif May_Be_Sep and then
6846 Spec_Suffix'Length < Sep_Suffix'Length
6848 Unit_Kind := Body_Part;
6849 Last := Last - Sep_Suffix'Length;
6852 Unit_Kind := Specification;
6853 Last := Last - Spec_Suffix'Length;
6856 elsif May_Be_Body then
6857 Unit_Kind := Body_Part;
6859 if May_Be_Sep and then
6860 Body_Suffix'Length < Sep_Suffix'Length
6862 Last := Last - Sep_Suffix'Length;
6863 May_Be_Body := False;
6865 Last := Last - Body_Suffix'Length;
6866 May_Be_Sep := False;
6869 elsif May_Be_Sep then
6870 Unit_Kind := Body_Part;
6871 Last := Last - Sep_Suffix'Length;
6879 -- This is not a source file
6881 Unit_Name := No_Name;
6882 Unit_Kind := Specification;
6884 if Current_Verbosity = High then
6885 Write_Line (" Not a valid file name.");
6890 elsif Current_Verbosity = High then
6892 when Specification =>
6893 Write_Str (" Specification: ");
6894 Write_Line (File (First .. Last + Spec_Suffix'Length));
6898 Write_Str (" Body: ");
6899 Write_Line (File (First .. Last + Body_Suffix'Length));
6902 Write_Str (" Separate: ");
6903 Write_Line (File (First .. Last + Sep_Suffix'Length));
6909 Get_Name_String (Naming.Dot_Replacement);
6911 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6913 if Name_Buffer (1 .. Name_Len) /= "." then
6915 -- If Dot_Replacement is not a single dot, then there should not
6916 -- be any dot in the name.
6918 for Index in First .. Last loop
6919 if File (Index) = '.' then
6920 if Current_Verbosity = High then
6922 (" Not a valid file name (some dot not replaced).");
6925 Unit_Name := No_Name;
6931 -- Replace the substring Dot_Replacement with dots
6934 Index : Positive := First;
6937 while Index <= Last - Name_Len + 1 loop
6939 if File (Index .. Index + Name_Len - 1) =
6940 Name_Buffer (1 .. Name_Len)
6942 File (Index) := '.';
6944 if Name_Len > 1 and then Index < Last then
6945 File (Index + 1 .. Last - Name_Len + 1) :=
6946 File (Index + Name_Len .. Last);
6949 Last := Last - Name_Len + 1;
6957 -- Check if the file casing is right
6960 Src : String := File (First .. Last);
6961 Src_Last : Positive := Last;
6964 -- If casing is significant, deal with upper/lower case translate
6966 if File_Names_Case_Sensitive then
6967 case Naming.Casing is
6968 when All_Lower_Case =>
6971 Mapping => Lower_Case_Map);
6973 when All_Upper_Case =>
6976 Mapping => Upper_Case_Map);
6978 when Mixed_Case | Unknown =>
6982 if Src /= File (First .. Last) then
6983 if Current_Verbosity = High then
6984 Write_Line (" Not a valid file name (casing).");
6987 Unit_Name := No_Name;
6992 -- Put the name in lower case
6996 Mapping => Lower_Case_Map);
6998 -- In the standard GNAT naming scheme, check for special cases:
6999 -- children or separates of A, G, I or S, and run time sources.
7001 if Standard_GNAT and then Src'Length >= 3 then
7003 S1 : constant Character := Src (Src'First);
7004 S2 : constant Character := Src (Src'First + 1);
7005 S3 : constant Character := Src (Src'First + 2);
7013 -- Children or separates of packages A, G, I or S. These
7014 -- names are x__ ... or x~... (where x is a, g, i, or s).
7015 -- Both versions (x__... and x~...) are allowed in all
7016 -- platforms, because it is not possible to know the
7017 -- platform before processing of the project files.
7019 if S2 = '_' and then S3 = '_' then
7020 Src (Src'First + 1) := '.';
7021 Src_Last := Src_Last - 1;
7022 Src (Src'First + 2 .. Src_Last) :=
7023 Src (Src'First + 3 .. Src_Last + 1);
7026 Src (Src'First + 1) := '.';
7028 -- If it is potentially a run time source, disable
7029 -- filling of the mapping file to avoid warnings.
7032 Set_Mapping_File_Initial_State_To_Empty;
7038 if Current_Verbosity = High then
7040 Write_Line (Src (Src'First .. Src_Last));
7043 -- Now, we check if this name is a valid unit name
7046 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
7056 function Hash (Unit : Unit_Info) return Header_Num is
7058 return Header_Num (Unit.Unit mod 2048);
7061 -----------------------
7062 -- Is_Illegal_Suffix --
7063 -----------------------
7065 function Is_Illegal_Suffix
7067 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
7070 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
7074 -- If dot replacement is a single dot, and first character of suffix is
7077 if Dot_Replacement_Is_A_Single_Dot
7078 and then Suffix (Suffix'First) = '.'
7080 for Index in Suffix'First + 1 .. Suffix'Last loop
7082 -- If there is another dot
7084 if Suffix (Index) = '.' then
7086 -- It is illegal to have a letter following the initial dot
7088 return Is_Letter (Suffix (Suffix'First + 1));
7096 end Is_Illegal_Suffix;
7098 ----------------------
7099 -- Locate_Directory --
7100 ----------------------
7102 procedure Locate_Directory
7103 (Project : Project_Id;
7104 In_Tree : Project_Tree_Ref;
7105 Name : File_Name_Type;
7106 Parent : Path_Name_Type;
7107 Dir : out Path_Name_Type;
7108 Display : out Path_Name_Type;
7109 Create : String := "";
7110 Current_Dir : String;
7111 Location : Source_Ptr := No_Location;
7112 Externally_Built : Boolean := False)
7114 The_Parent : constant String :=
7115 Get_Name_String (Parent) & Directory_Separator;
7117 The_Parent_Last : constant Natural :=
7118 Compute_Directory_Last (The_Parent);
7120 Full_Name : File_Name_Type;
7122 The_Name : File_Name_Type;
7125 Get_Name_String (Name);
7127 -- Add Subdirs.all if it is a directory that may be created and
7128 -- Subdirs is not null;
7130 if Create /= "" and then Subdirs /= null then
7131 if Name_Buffer (Name_Len) /= Directory_Separator then
7132 Add_Char_To_Name_Buffer (Directory_Separator);
7135 Add_Str_To_Name_Buffer (Subdirs.all);
7138 -- Convert '/' to directory separator (for Windows)
7140 for J in 1 .. Name_Len loop
7141 if Name_Buffer (J) = '/' then
7142 Name_Buffer (J) := Directory_Separator;
7146 The_Name := Name_Find;
7148 if Current_Verbosity = High then
7149 Write_Str ("Locate_Directory (""");
7150 Write_Str (Get_Name_String (The_Name));
7151 Write_Str (""", """);
7152 Write_Str (The_Parent);
7159 if Is_Absolute_Path (Get_Name_String (The_Name)) then
7160 Full_Name := The_Name;
7164 Add_Str_To_Name_Buffer
7165 (The_Parent (The_Parent'First .. The_Parent_Last));
7166 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
7167 Full_Name := Name_Find;
7171 Full_Path_Name : String_Access :=
7172 new String'(Get_Name_String (Full_Name));
7175 if (Setup_Projects or else Subdirs /= null)
7176 and then Create'Length > 0
7178 if not Is_Directory (Full_Path_Name.all) then
7179 -- If project is externally built, do not create a subdir,
7180 -- use the specified directory, without the subdir.
7182 if Externally_Built then
7183 if Is_Absolute_Path (Get_Name_String (Name)) then
7184 Get_Name_String (Name);
7188 Add_Str_To_Name_Buffer
7189 (The_Parent (The_Parent'First .. The_Parent_Last));
7190 Add_Str_To_Name_Buffer (Get_Name_String (Name));
7193 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
7197 Create_Path (Full_Path_Name.all);
7199 if not Quiet_Output then
7201 Write_Str (" directory """);
7202 Write_Str (Full_Path_Name.all);
7203 Write_Line (""" created");
7210 "could not create " & Create &
7211 " directory " & Full_Path_Name.all,
7218 if Is_Directory (Full_Path_Name.all) then
7220 Normed : constant String :=
7222 (Full_Path_Name.all,
7223 Directory => Current_Dir,
7224 Resolve_Links => False,
7225 Case_Sensitive => True);
7227 Canonical_Path : constant String :=
7230 Directory => Current_Dir,
7232 Opt.Follow_Links_For_Dirs,
7233 Case_Sensitive => False);
7236 Name_Len := Normed'Length;
7237 Name_Buffer (1 .. Name_Len) := Normed;
7238 Display := Name_Find;
7240 Name_Len := Canonical_Path'Length;
7241 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7246 Free (Full_Path_Name);
7248 end Locate_Directory;
7250 ---------------------------
7251 -- Find_Excluded_Sources --
7252 ---------------------------
7254 procedure Find_Excluded_Sources
7255 (Project : Project_Id;
7256 In_Tree : Project_Tree_Ref;
7257 Data : Project_Data)
7259 Excluded_Sources : Variable_Value;
7261 Excluded_Source_List_File : Variable_Value;
7263 Current : String_List_Id;
7265 Element : String_Element;
7267 Location : Source_Ptr;
7269 Name : File_Name_Type;
7271 File : Prj.Util.Text_File;
7272 Line : String (1 .. 300);
7275 Locally_Removed : Boolean := False;
7277 Excluded_Source_List_File :=
7279 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7283 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7285 -- If Excluded_Source_Files is not declared, check
7286 -- Locally_Removed_Files.
7288 if Excluded_Sources.Default then
7289 Locally_Removed := True;
7292 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7295 Excluded_Sources_Htable.Reset;
7297 -- If there are excluded sources, put them in the table
7299 if not Excluded_Sources.Default then
7300 if not Excluded_Source_List_File.Default then
7301 if Locally_Removed then
7304 "?both attributes Locally_Removed_Files and " &
7305 "Excluded_Source_List_File are present",
7306 Excluded_Source_List_File.Location);
7310 "?both attributes Excluded_Source_Files and " &
7311 "Excluded_Source_List_File are present",
7312 Excluded_Source_List_File.Location);
7316 Current := Excluded_Sources.Values;
7317 while Current /= Nil_String loop
7318 Element := In_Tree.String_Elements.Table (Current);
7320 if Osint.File_Names_Case_Sensitive then
7321 Name := File_Name_Type (Element.Value);
7323 Get_Name_String (Element.Value);
7324 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7328 -- If the element has no location, then use the location
7329 -- of Excluded_Sources to report possible errors.
7331 if Element.Location = No_Location then
7332 Location := Excluded_Sources.Location;
7334 Location := Element.Location;
7337 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7338 Current := Element.Next;
7341 elsif not Excluded_Source_List_File.Default then
7342 Location := Excluded_Source_List_File.Location;
7345 Source_File_Path_Name : constant String :=
7348 (Excluded_Source_List_File.Value),
7349 Data.Directory.Name);
7352 if Source_File_Path_Name'Length = 0 then
7353 Err_Vars.Error_Msg_File_1 :=
7354 File_Name_Type (Excluded_Source_List_File.Value);
7357 "file with excluded sources { does not exist",
7358 Excluded_Source_List_File.Location);
7363 Prj.Util.Open (File, Source_File_Path_Name);
7365 if not Prj.Util.Is_Valid (File) then
7367 (Project, In_Tree, "file does not exist", Location);
7369 -- Read the lines one by one
7371 while not Prj.Util.End_Of_File (File) loop
7372 Prj.Util.Get_Line (File, Line, Last);
7374 -- A non empty, non comment line should contain a file
7378 and then (Last = 1 or else Line (1 .. 2) /= "--")
7381 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7382 Canonical_Case_File_Name
7383 (Name_Buffer (1 .. Name_Len));
7386 -- Check that there is no directory information
7388 for J in 1 .. Last loop
7390 or else Line (J) = Directory_Separator
7392 Error_Msg_File_1 := Name;
7396 "file name cannot include " &
7397 "directory information ({)",
7403 Excluded_Sources_Htable.Set
7404 (Name, (Name, False, Location));
7408 Prj.Util.Close (File);
7413 end Find_Excluded_Sources;
7415 ---------------------------
7416 -- Find_Explicit_Sources --
7417 ---------------------------
7419 procedure Find_Explicit_Sources
7420 (Current_Dir : String;
7421 Project : Project_Id;
7422 In_Tree : Project_Tree_Ref;
7423 Data : in out Project_Data)
7425 Sources : constant Variable_Value :=
7428 Data.Decl.Attributes,
7430 Source_List_File : constant Variable_Value :=
7432 (Name_Source_List_File,
7433 Data.Decl.Attributes,
7435 Name_Loc : Name_Location;
7438 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7440 (Source_List_File.Kind = Single,
7441 "Source_List_File is not a single string");
7443 -- If the user has specified a Sources attribute
7445 if not Sources.Default then
7446 if not Source_List_File.Default then
7449 "?both attributes source_files and " &
7450 "source_list_file are present",
7451 Source_List_File.Location);
7454 -- Sources is a list of file names
7457 Current : String_List_Id := Sources.Values;
7458 Element : String_Element;
7459 Location : Source_Ptr;
7460 Name : File_Name_Type;
7463 if Get_Mode = Ada_Only then
7464 Data.Ada_Sources_Present := Current /= Nil_String;
7467 if Get_Mode = Multi_Language then
7468 if Current = Nil_String then
7469 Data.First_Language_Processing := No_Language_Index;
7471 -- This project contains no source. For projects that
7472 -- don't extend other projects, this also means that
7473 -- there is no need for an object directory, if not
7476 if Data.Extends = No_Project
7477 and then Data.Object_Directory = Data.Directory
7479 Data.Object_Directory := No_Path_Information;
7484 while Current /= Nil_String loop
7485 Element := In_Tree.String_Elements.Table (Current);
7486 Get_Name_String (Element.Value);
7488 if Osint.File_Names_Case_Sensitive then
7489 Name := File_Name_Type (Element.Value);
7491 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7495 -- If the element has no location, then use the
7496 -- location of Sources to report possible errors.
7498 if Element.Location = No_Location then
7499 Location := Sources.Location;
7501 Location := Element.Location;
7504 -- Check that there is no directory information
7506 for J in 1 .. Name_Len loop
7507 if Name_Buffer (J) = '/'
7508 or else Name_Buffer (J) = Directory_Separator
7510 Error_Msg_File_1 := Name;
7514 "file name cannot include directory " &
7521 -- In Multi_Language mode, check whether the file is
7522 -- already there: the same file name may be in the list; if
7523 -- the source is missing, the error will be on the first
7524 -- mention of the source file name.
7528 Name_Loc := No_Name_Location;
7529 when Multi_Language =>
7530 Name_Loc := Source_Names.Get (Name);
7533 if Name_Loc = No_Name_Location then
7536 Location => Location,
7537 Source => No_Source,
7540 Source_Names.Set (Name, Name_Loc);
7543 Current := Element.Next;
7546 if Get_Mode = Ada_Only then
7547 Get_Path_Names_And_Record_Ada_Sources
7548 (Project, In_Tree, Data, Current_Dir);
7552 -- If we have no Source_Files attribute, check the Source_List_File
7555 elsif not Source_List_File.Default then
7557 -- Source_List_File is the name of the file
7558 -- that contains the source file names
7561 Source_File_Path_Name : constant String :=
7563 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7566 if Source_File_Path_Name'Length = 0 then
7567 Err_Vars.Error_Msg_File_1 :=
7568 File_Name_Type (Source_List_File.Value);
7571 "file with sources { does not exist",
7572 Source_List_File.Location);
7575 Get_Sources_From_File
7576 (Source_File_Path_Name, Source_List_File.Location,
7579 if Get_Mode = Ada_Only then
7580 -- Look in the source directories to find those sources
7582 Get_Path_Names_And_Record_Ada_Sources
7583 (Project, In_Tree, Data, Current_Dir);
7589 -- Neither Source_Files nor Source_List_File has been
7590 -- specified. Find all the files that satisfy the naming
7591 -- scheme in all the source directories.
7593 if Get_Mode = Ada_Only then
7594 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7598 if Get_Mode = Multi_Language then
7600 (Project, In_Tree, Data,
7602 Sources.Default and then Source_List_File.Default);
7604 -- Check if all exceptions have been found.
7605 -- For Ada, it is an error if an exception is not found.
7606 -- For other language, the source is simply removed.
7612 Source := Data.First_Source;
7613 while Source /= No_Source loop
7615 Src_Data : Source_Data renames
7616 In_Tree.Sources.Table (Source);
7619 if Src_Data.Naming_Exception
7620 and then Src_Data.Path = No_Path_Information
7622 if Src_Data.Unit /= No_Name then
7623 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7624 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7627 "source file %% for unit %% not found",
7631 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7634 Source := Src_Data.Next_In_Project;
7639 -- Check that all sources in Source_Files or the file
7640 -- Source_List_File has been found.
7643 Name_Loc : Name_Location;
7646 Name_Loc := Source_Names.Get_First;
7647 while Name_Loc /= No_Name_Location loop
7648 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7649 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7653 "file %% not found",
7657 Name_Loc := Source_Names.Get_Next;
7662 if Get_Mode = Ada_Only
7663 and then Data.Extends = No_Project
7665 -- We should have found at least one source, if not report an error
7667 if Data.Ada_Sources = Nil_String then
7669 (Project, "Ada", In_Tree, Source_List_File.Location);
7673 end Find_Explicit_Sources;
7675 -------------------------------------------
7676 -- Get_Path_Names_And_Record_Ada_Sources --
7677 -------------------------------------------
7679 procedure Get_Path_Names_And_Record_Ada_Sources
7680 (Project : Project_Id;
7681 In_Tree : Project_Tree_Ref;
7682 Data : in out Project_Data;
7683 Current_Dir : String)
7685 Source_Dir : String_List_Id;
7686 Element : String_Element;
7687 Path : Path_Name_Type;
7689 Name : File_Name_Type;
7690 Canonical_Name : File_Name_Type;
7691 Name_Str : String (1 .. 1_024);
7692 Last : Natural := 0;
7694 Current_Source : String_List_Id := Nil_String;
7695 First_Error : Boolean := True;
7696 Source_Recorded : Boolean := False;
7699 -- We look in all source directories for the file names in the hash
7700 -- table Source_Names.
7702 Source_Dir := Data.Source_Dirs;
7703 while Source_Dir /= Nil_String loop
7704 Source_Recorded := False;
7705 Element := In_Tree.String_Elements.Table (Source_Dir);
7708 Dir_Path : constant String :=
7709 Get_Name_String (Element.Display_Value);
7711 if Current_Verbosity = High then
7712 Write_Str ("checking directory """);
7713 Write_Str (Dir_Path);
7717 Open (Dir, Dir_Path);
7720 Read (Dir, Name_Str, Last);
7724 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7727 if Osint.File_Names_Case_Sensitive then
7728 Canonical_Name := Name;
7730 Canonical_Case_File_Name (Name_Str (1 .. Last));
7731 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7732 Canonical_Name := Name_Find;
7735 NL := Source_Names.Get (Canonical_Name);
7737 if NL /= No_Name_Location and then not NL.Found then
7739 Source_Names.Set (Canonical_Name, NL);
7740 Name_Len := Dir_Path'Length;
7741 Name_Buffer (1 .. Name_Len) := Dir_Path;
7743 if Name_Buffer (Name_Len) /= Directory_Separator then
7744 Add_Char_To_Name_Buffer (Directory_Separator);
7747 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7750 if Current_Verbosity = High then
7751 Write_Str (" found ");
7752 Write_Line (Get_Name_String (Name));
7755 -- Register the source if it is an Ada compilation unit
7763 Location => NL.Location,
7764 Current_Source => Current_Source,
7765 Source_Recorded => Source_Recorded,
7766 Current_Dir => Current_Dir);
7773 if Source_Recorded then
7774 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7778 Source_Dir := Element.Next;
7781 -- It is an error if a source file name in a source list or
7782 -- in a source list file is not found.
7784 NL := Source_Names.Get_First;
7785 while NL /= No_Name_Location loop
7786 if not NL.Found then
7787 Err_Vars.Error_Msg_File_1 := NL.Name;
7792 "source file { cannot be found",
7794 First_Error := False;
7799 "\source file { cannot be found",
7804 NL := Source_Names.Get_Next;
7806 end Get_Path_Names_And_Record_Ada_Sources;
7808 --------------------------
7809 -- Check_Naming_Schemes --
7810 --------------------------
7812 procedure Check_Naming_Schemes
7813 (In_Tree : Project_Tree_Ref;
7814 Data : in out Project_Data;
7816 File_Name : File_Name_Type;
7817 Alternate_Languages : out Alternate_Language_Id;
7818 Language : out Language_Index;
7819 Language_Name : out Name_Id;
7820 Display_Language_Name : out Name_Id;
7822 Lang_Kind : out Language_Kind;
7823 Kind : out Source_Kind)
7825 Last : Positive := Filename'Last;
7826 Config : Language_Config;
7827 Lang : Name_List_Index := Data.Languages;
7828 Header_File : Boolean := False;
7829 First_Language : Language_Index := No_Language_Index;
7832 Last_Spec : Natural;
7833 Last_Body : Natural;
7839 Alternate_Languages := No_Alternate_Language;
7840 Language := No_Language_Index;
7841 Language_Name := No_Name;
7842 Display_Language_Name := No_Name;
7844 Lang_Kind := File_Based;
7847 while Lang /= No_Name_List loop
7848 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7849 Language := Data.First_Language_Processing;
7851 if Current_Verbosity = High then
7853 (" Testing language "
7854 & Get_Name_String (Language_Name)
7855 & " Header_File=" & Header_File'Img);
7858 while Language /= No_Language_Index loop
7859 if In_Tree.Languages_Data.Table (Language).Name =
7862 Display_Language_Name :=
7863 In_Tree.Languages_Data.Table (Language).Display_Name;
7864 Config := In_Tree.Languages_Data.Table (Language).Config;
7865 Lang_Kind := Config.Kind;
7867 if Config.Kind = File_Based then
7869 -- For file based languages, there is no Unit. Just
7870 -- check if the file name has the implementation or,
7871 -- if it is specified, the template suffix of the
7877 and then Config.Naming_Data.Body_Suffix /= No_File
7880 Impl_Suffix : constant String :=
7881 Get_Name_String (Config.Naming_Data.Body_Suffix);
7884 if Filename'Length > Impl_Suffix'Length
7887 (Last - Impl_Suffix'Length + 1 .. Last) =
7892 if Current_Verbosity = High then
7893 Write_Str (" source of language ");
7895 (Get_Name_String (Display_Language_Name));
7903 if Config.Naming_Data.Spec_Suffix /= No_File then
7905 Spec_Suffix : constant String :=
7907 (Config.Naming_Data.Spec_Suffix);
7910 if Filename'Length > Spec_Suffix'Length
7913 (Last - Spec_Suffix'Length + 1 .. Last) =
7918 if Current_Verbosity = High then
7919 Write_Str (" header file of language ");
7921 (Get_Name_String (Display_Language_Name));
7925 Alternate_Language_Table.Increment_Last
7926 (In_Tree.Alt_Langs);
7927 In_Tree.Alt_Langs.Table
7928 (Alternate_Language_Table.Last
7929 (In_Tree.Alt_Langs)) :=
7930 (Language => Language,
7931 Next => Alternate_Languages);
7932 Alternate_Languages :=
7933 Alternate_Language_Table.Last
7934 (In_Tree.Alt_Langs);
7936 Header_File := True;
7937 First_Language := Language;
7943 elsif not Header_File then
7944 -- Unit based language
7946 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7951 -- ??? Are we doing this once per file in the project ?
7952 -- It should be done only once per project.
7954 case Config.Naming_Data.Casing is
7955 when All_Lower_Case =>
7956 for J in Filename'Range loop
7957 if Is_Letter (Filename (J)) then
7958 if not Is_Lower (Filename (J)) then
7965 when All_Upper_Case =>
7966 for J in Filename'Range loop
7967 if Is_Letter (Filename (J)) then
7968 if not Is_Upper (Filename (J)) then
7984 Last_Spec := Natural'Last;
7985 Last_Body := Natural'Last;
7986 Last_Sep := Natural'Last;
7988 if Config.Naming_Data.Separate_Suffix /= No_File
7990 Config.Naming_Data.Separate_Suffix /=
7991 Config.Naming_Data.Body_Suffix
7994 Suffix : constant String :=
7996 (Config.Naming_Data.Separate_Suffix);
7998 if Filename'Length > Suffix'Length
8001 (Last - Suffix'Length + 1 .. Last) =
8004 Last_Sep := Last - Suffix'Length;
8009 if Config.Naming_Data.Body_Suffix /= No_File then
8011 Suffix : constant String :=
8013 (Config.Naming_Data.Body_Suffix);
8015 if Filename'Length > Suffix'Length
8018 (Last - Suffix'Length + 1 .. Last) =
8021 Last_Body := Last - Suffix'Length;
8026 if Config.Naming_Data.Spec_Suffix /= No_File then
8028 Suffix : constant String :=
8030 (Config.Naming_Data.Spec_Suffix);
8032 if Filename'Length > Suffix'Length
8035 (Last - Suffix'Length + 1 .. Last) =
8038 Last_Spec := Last - Suffix'Length;
8044 Last_Min : constant Natural :=
8045 Natural'Min (Natural'Min (Last_Spec,
8050 OK := Last_Min < Last;
8055 if Last_Min = Last_Spec then
8058 elsif Last_Min = Last_Body then
8070 -- Replace dot replacements with dots
8075 J : Positive := Filename'First;
8077 Dot_Replacement : constant String :=
8079 (Config.Naming_Data.
8082 Max : constant Positive :=
8083 Last - Dot_Replacement'Length + 1;
8087 Name_Len := Name_Len + 1;
8089 if J <= Max and then
8091 (J .. J + Dot_Replacement'Length - 1) =
8094 Name_Buffer (Name_Len) := '.';
8095 J := J + Dot_Replacement'Length;
8098 if Filename (J) = '.' then
8103 Name_Buffer (Name_Len) :=
8104 GNAT.Case_Util.To_Lower (Filename (J));
8115 -- The name buffer should contain the name of the
8116 -- the unit, if it is one.
8118 -- Check that this is a valid unit name
8120 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
8122 if Unit /= No_Name then
8124 if Current_Verbosity = High then
8126 Write_Str (" spec of ");
8128 Write_Str (" body of ");
8131 Write_Str (Get_Name_String (Unit));
8132 Write_Str (" (language ");
8134 (Get_Name_String (Display_Language_Name));
8138 -- Comments required, declare block should
8142 Unit_Except : constant Unit_Exception :=
8143 Unit_Exceptions.Get (Unit);
8145 procedure Masked_Unit (Spec : Boolean);
8146 -- Indicate that there is an exception for
8147 -- the same unit, so the file is not a
8148 -- source for the unit.
8154 procedure Masked_Unit (Spec : Boolean) is
8156 if Current_Verbosity = High then
8158 Write_Str (Filename);
8159 Write_Str (""" contains the ");
8168 (" of a unit that is found in """);
8173 (Unit_Except.Spec));
8177 (Unit_Except.Impl));
8180 Write_Line (""" (ignored)");
8183 Language := No_Language_Index;
8188 if Unit_Except.Spec /= No_File
8189 and then Unit_Except.Spec /= File_Name
8191 Masked_Unit (Spec => True);
8195 if Unit_Except.Impl /= No_File
8196 and then Unit_Except.Impl /= File_Name
8198 Masked_Unit (Spec => False);
8209 Language := In_Tree.Languages_Data.Table (Language).Next;
8212 Lang := In_Tree.Name_Lists.Table (Lang).Next;
8215 -- Comment needed here ???
8218 Language := First_Language;
8221 Language := No_Language_Index;
8223 if Current_Verbosity = High then
8224 Write_Line (" not a source of any language");
8227 end Check_Naming_Schemes;
8233 procedure Check_File
8234 (Project : Project_Id;
8235 In_Tree : Project_Tree_Ref;
8236 Data : in out Project_Data;
8238 File_Name : File_Name_Type;
8239 Display_File_Name : File_Name_Type;
8240 Source_Directory : String;
8241 For_All_Sources : Boolean)
8243 Display_Path : constant String :=
8246 Directory => Source_Directory,
8247 Resolve_Links => Opt.Follow_Links_For_Files,
8248 Case_Sensitive => True);
8250 Name_Loc : Name_Location := Source_Names.Get (File_Name);
8251 Path_Id : Path_Name_Type;
8252 Display_Path_Id : Path_Name_Type;
8253 Check_Name : Boolean := False;
8254 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8255 Language : Language_Index;
8257 Other_Part : Source_Id;
8259 Src_Ind : Source_File_Index;
8261 Source_To_Replace : Source_Id := No_Source;
8262 Language_Name : Name_Id;
8263 Display_Language_Name : Name_Id;
8264 Lang_Kind : Language_Kind;
8265 Kind : Source_Kind := Spec;
8268 Name_Len := Display_Path'Length;
8269 Name_Buffer (1 .. Name_Len) := Display_Path;
8270 Display_Path_Id := Name_Find;
8272 if Osint.File_Names_Case_Sensitive then
8273 Path_Id := Display_Path_Id;
8275 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8276 Path_Id := Name_Find;
8279 if Name_Loc = No_Name_Location then
8280 Check_Name := For_All_Sources;
8283 if Name_Loc.Found then
8285 -- Check if it is OK to have the same file name in several
8286 -- source directories.
8288 if not Data.Known_Order_Of_Source_Dirs then
8289 Error_Msg_File_1 := File_Name;
8292 "{ is found in several source directories",
8297 Name_Loc.Found := True;
8299 Source_Names.Set (File_Name, Name_Loc);
8301 if Name_Loc.Source = No_Source then
8305 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8306 (Path_Id, Display_Path_Id);
8308 Source_Paths_Htable.Set
8309 (In_Tree.Source_Paths_HT,
8313 -- Check if this is a subunit
8315 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8317 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8319 Src_Ind := Sinput.P.Load_Project_File
8320 (Get_Name_String (Path_Id));
8322 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8323 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8331 Other_Part := No_Source;
8333 Check_Naming_Schemes
8334 (In_Tree => In_Tree,
8336 Filename => Get_Name_String (File_Name),
8337 File_Name => File_Name,
8338 Alternate_Languages => Alternate_Languages,
8339 Language => Language,
8340 Language_Name => Language_Name,
8341 Display_Language_Name => Display_Language_Name,
8343 Lang_Kind => Lang_Kind,
8346 if Language = No_Language_Index then
8348 -- A file name in a list must be a source of a language
8350 if Name_Loc.Found then
8351 Error_Msg_File_1 := File_Name;
8355 "language unknown for {",
8360 -- Check if the same file name or unit is used in the prj tree
8362 Source := In_Tree.First_Source;
8364 while Source /= No_Source loop
8366 Src_Data : Source_Data renames
8367 In_Tree.Sources.Table (Source);
8371 and then Src_Data.Unit = Unit
8373 ((Src_Data.Kind = Spec and then Kind = Impl)
8375 (Src_Data.Kind = Impl and then Kind = Spec))
8377 Other_Part := Source;
8379 elsif (Unit /= No_Name
8380 and then Src_Data.Unit = Unit
8382 (Src_Data.Kind = Kind
8384 (Src_Data.Kind = Sep and then Kind = Impl)
8386 (Src_Data.Kind = Impl and then Kind = Sep)))
8388 (Unit = No_Name and then Src_Data.File = File_Name)
8390 -- Duplication of file/unit in same project is only
8391 -- allowed if order of source directories is known.
8393 if Project = Src_Data.Project then
8394 if Data.Known_Order_Of_Source_Dirs then
8397 elsif Unit /= No_Name then
8398 Error_Msg_Name_1 := Unit;
8400 (Project, In_Tree, "duplicate unit %%",
8405 Error_Msg_File_1 := File_Name;
8407 (Project, In_Tree, "duplicate source file name {",
8412 -- Do not allow the same unit name in different
8413 -- projects, except if one is extending the other.
8415 -- For a file based language, the same file name
8416 -- replaces a file in a project being extended, but
8417 -- it is allowed to have the same file name in
8418 -- unrelated projects.
8421 (Project, Src_Data.Project, In_Tree)
8423 Source_To_Replace := Source;
8425 elsif Unit /= No_Name
8426 and then not Src_Data.Locally_Removed
8428 Error_Msg_Name_1 := Unit;
8431 "unit %% cannot belong to several projects",
8435 In_Tree.Projects.Table (Project).Name;
8436 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8438 (Project, In_Tree, "\ project %%, %%", No_Location);
8441 In_Tree.Projects.Table (Src_Data.Project).Name;
8443 Name_Id (Src_Data.Path.Display_Name);
8445 (Project, In_Tree, "\ project %%, %%", No_Location);
8451 Source := Src_Data.Next_In_Sources;
8461 Lang => Language_Name,
8462 Lang_Id => Language,
8463 Lang_Kind => Lang_Kind,
8465 Alternate_Languages => Alternate_Languages,
8466 File_Name => File_Name,
8467 Display_File => Display_File_Name,
8468 Other_Part => Other_Part,
8471 Display_Path => Display_Path_Id,
8472 Source_To_Replace => Source_To_Replace);
8478 ------------------------
8479 -- Search_Directories --
8480 ------------------------
8482 procedure Search_Directories
8483 (Project : Project_Id;
8484 In_Tree : Project_Tree_Ref;
8485 Data : in out Project_Data;
8486 For_All_Sources : Boolean)
8488 Source_Dir : String_List_Id;
8489 Element : String_Element;
8491 Name : String (1 .. 1_000);
8493 File_Name : File_Name_Type;
8494 Display_File_Name : File_Name_Type;
8497 if Current_Verbosity = High then
8498 Write_Line ("Looking for sources:");
8501 -- Loop through subdirectories
8503 Source_Dir := Data.Source_Dirs;
8504 while Source_Dir /= Nil_String loop
8506 Element := In_Tree.String_Elements.Table (Source_Dir);
8507 if Element.Value /= No_Name then
8508 Get_Name_String (Element.Display_Value);
8511 Source_Directory : constant String :=
8512 Name_Buffer (1 .. Name_Len) &
8513 Directory_Separator;
8515 Dir_Last : constant Natural :=
8516 Compute_Directory_Last
8520 if Current_Verbosity = High then
8521 Write_Str ("Source_Dir = ");
8522 Write_Line (Source_Directory);
8525 -- We look to every entry in the source directory
8527 Open (Dir, Source_Directory);
8530 Read (Dir, Name, Last);
8534 -- ??? Duplicate system call here, we just did a
8535 -- a similar one. Maybe Ada.Directories would be more
8539 (Source_Directory & Name (1 .. Last))
8541 if Current_Verbosity = High then
8542 Write_Str (" Checking ");
8543 Write_Line (Name (1 .. Last));
8547 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8548 Display_File_Name := Name_Find;
8550 if Osint.File_Names_Case_Sensitive then
8551 File_Name := Display_File_Name;
8553 Canonical_Case_File_Name
8554 (Name_Buffer (1 .. Name_Len));
8555 File_Name := Name_Find;
8560 Excluded_Sources_Htable.Get (File_Name);
8563 if FF /= No_File_Found then
8564 if not FF.Found then
8566 Excluded_Sources_Htable.Set
8569 if Current_Verbosity = High then
8570 Write_Str (" excluded source """);
8571 Write_Str (Get_Name_String (File_Name));
8578 (Project => Project,
8581 Name => Name (1 .. Last),
8582 File_Name => File_Name,
8583 Display_File_Name => Display_File_Name,
8584 Source_Directory => Source_Directory
8585 (Source_Directory'First .. Dir_Last),
8586 For_All_Sources => For_All_Sources);
8597 when Directory_Error =>
8601 Source_Dir := Element.Next;
8604 if Current_Verbosity = High then
8605 Write_Line ("end Looking for sources.");
8607 end Search_Directories;
8609 ----------------------------
8610 -- Load_Naming_Exceptions --
8611 ----------------------------
8613 procedure Load_Naming_Exceptions
8614 (Project : Project_Id;
8615 In_Tree : Project_Tree_Ref;
8616 Data : in out Project_Data)
8618 Source : Source_Id := Data.First_Source;
8619 File : File_Name_Type;
8622 Unit_Exceptions.Reset;
8624 while Source /= No_Source loop
8625 File := In_Tree.Sources.Table (Source).File;
8626 Unit := In_Tree.Sources.Table (Source).Unit;
8628 -- An excluded file cannot also be an exception file name
8630 if Excluded_Sources_Htable.Get (File) /= No_File_Found then
8631 Error_Msg_File_1 := File;
8634 "{ cannot be both excluded and an exception file name",
8638 if Current_Verbosity = High then
8639 Write_Str ("Naming exception: Putting source #");
8640 Write_Str (Source'Img);
8641 Write_Str (", file ");
8642 Write_Str (Get_Name_String (File));
8643 Write_Line (" in Source_Names");
8650 Location => No_Location,
8652 Except => Unit /= No_Name,
8655 -- If this is an Ada exception, record in table Unit_Exceptions
8657 if Unit /= No_Name then
8659 Unit_Except : Unit_Exception := Unit_Exceptions.Get (Unit);
8662 Unit_Except.Name := Unit;
8664 if In_Tree.Sources.Table (Source).Kind = Spec then
8665 Unit_Except.Spec := File;
8667 Unit_Except.Impl := File;
8670 Unit_Exceptions.Set (Unit, Unit_Except);
8674 Source := In_Tree.Sources.Table (Source).Next_In_Project;
8676 end Load_Naming_Exceptions;
8678 ----------------------
8679 -- Look_For_Sources --
8680 ----------------------
8682 procedure Look_For_Sources
8683 (Project : Project_Id;
8684 In_Tree : Project_Tree_Ref;
8685 Data : in out Project_Data;
8686 Current_Dir : String)
8688 procedure Process_Sources_In_Multi_Language_Mode;
8689 -- Find all source files when in multi language mode
8691 procedure Mark_Excluded_Sources;
8692 -- Mark as such the sources that are declared as excluded
8694 ---------------------------
8695 -- Mark_Excluded_Sources --
8696 ---------------------------
8698 procedure Mark_Excluded_Sources is
8699 Source : Source_Id := No_Source;
8702 Excluded : File_Found := Excluded_Sources_Htable.Get_First;
8705 (Extended : Project_Id; Index : Unit_Index; Kind : Spec_Or_Body);
8706 -- If the current file (Excluded) belongs to the current project or
8707 -- one that the current project extends, then mark this file/unit as
8708 -- excluded. It is an error to locally remove a file from another
8712 (Extended : Project_Id; Index : Unit_Index; Kind : Spec_Or_Body) is
8714 if Extended = Project
8715 or else Is_Extending (Project, Extended, In_Tree)
8719 if Index /= No_Unit_Index then
8720 Unit.File_Names (Kind).Path.Name := Slash;
8721 Unit.File_Names (Kind).Needs_Pragma := False;
8722 In_Tree.Units.Table (Index) := Unit;
8725 if Source /= No_Source then
8726 In_Tree.Sources.Table (Source).Locally_Removed := True;
8727 In_Tree.Sources.Table (Source).In_Interfaces := False;
8730 if Current_Verbosity = High then
8731 Write_Str ("Removing file ");
8732 Write_Line (Get_Name_String (Excluded.File));
8735 Add_Forbidden_File_Name (Excluded.File);
8740 "cannot remove a source from another project",
8746 while Excluded /= No_File_Found loop
8751 -- ??? This loop could be the same as for Multi_Language if
8752 -- we were setting In_Tree.First_Source when we search for
8753 -- Ada sources (basically once we have removed the use of
8754 -- Data.Ada_Sources).
8756 for Index in Unit_Table.First ..
8757 Unit_Table.Last (In_Tree.Units)
8759 Unit := In_Tree.Units.Table (Index);
8761 for Kind in Spec_Or_Body'Range loop
8762 if Unit.File_Names (Kind).Name = Excluded.File then
8763 Exclude (Unit.File_Names (Kind).Project, Index, Kind);
8767 end loop For_Each_Unit;
8769 when Multi_Language =>
8770 Source := In_Tree.First_Source;
8771 while Source /= No_Source loop
8772 if In_Tree.Sources.Table (Source).File = Excluded.File then
8774 (In_Tree.Sources.Table (Source).Project,
8775 No_Unit_Index, Specification);
8779 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
8782 OK := OK or Excluded.Found;
8786 Err_Vars.Error_Msg_File_1 := Excluded.File;
8788 (Project, In_Tree, "unknown file {", Excluded.Location);
8791 Excluded := Excluded_Sources_Htable.Get_Next;
8793 end Mark_Excluded_Sources;
8795 --------------------------------------------
8796 -- Process_Sources_In_Multi_Language_Mode --
8797 --------------------------------------------
8799 procedure Process_Sources_In_Multi_Language_Mode is
8801 -- Check that two sources of this project do not have the same object
8804 Check_Object_File_Names : declare
8806 Source_Name : File_Name_Type;
8808 procedure Check_Object (Src_Data : Source_Data);
8809 -- Check if object file name of the current source is already in
8810 -- hash table Object_File_Names. If it is, report an error. If it
8811 -- is not, put it there with the file name of the current source.
8817 procedure Check_Object (Src_Data : Source_Data) is
8819 Source_Name := Object_File_Names.Get (Src_Data.Object);
8821 if Source_Name /= No_File then
8822 Error_Msg_File_1 := Src_Data.File;
8823 Error_Msg_File_2 := Source_Name;
8827 "{ and { have the same object file name",
8831 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8835 -- Start of processing for Check_Object_File_Names
8838 Object_File_Names.Reset;
8839 Src_Id := In_Tree.First_Source;
8840 while Src_Id /= No_Source loop
8842 Src_Data : Source_Data renames
8843 In_Tree.Sources.Table (Src_Id);
8846 if Src_Data.Compiled and then Src_Data.Object_Exists
8847 and then Is_Extending (Project, Src_Data.Project, In_Tree)
8849 if Src_Data.Unit = No_Name then
8850 if Src_Data.Kind = Impl then
8851 Check_Object (Src_Data);
8855 case Src_Data.Kind is
8857 if Src_Data.Other_Part = No_Source then
8858 Check_Object (Src_Data);
8865 if Src_Data.Other_Part /= No_Source then
8866 Check_Object (Src_Data);
8869 -- Check if it is a subunit
8872 Src_Ind : constant Source_File_Index :=
8873 Sinput.P.Load_Project_File
8875 (Src_Data.Path.Name));
8877 if Sinput.P.Source_File_Is_Subunit
8880 In_Tree.Sources.Table (Src_Id).Kind :=
8883 Check_Object (Src_Data);
8891 Src_Id := Src_Data.Next_In_Sources;
8894 end Check_Object_File_Names;
8895 end Process_Sources_In_Multi_Language_Mode;
8897 -- Start of processing for Look_For_Sources
8901 Find_Excluded_Sources (Project, In_Tree, Data);
8905 if Is_A_Language (In_Tree, Data, Name_Ada) then
8906 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8907 Mark_Excluded_Sources;
8910 when Multi_Language =>
8911 if Data.First_Language_Processing /= No_Language_Index then
8912 Load_Naming_Exceptions (Project, In_Tree, Data);
8913 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8914 Mark_Excluded_Sources;
8915 Process_Sources_In_Multi_Language_Mode;
8918 end Look_For_Sources;
8924 function Path_Name_Of
8925 (File_Name : File_Name_Type;
8926 Directory : Path_Name_Type) return String
8928 Result : String_Access;
8929 The_Directory : constant String := Get_Name_String (Directory);
8932 Get_Name_String (File_Name);
8935 (File_Name => Name_Buffer (1 .. Name_Len),
8936 Path => The_Directory);
8938 if Result = null then
8942 R : String := Result.all;
8945 Canonical_Case_File_Name (R);
8951 -------------------------------
8952 -- Prepare_Ada_Naming_Exceptions --
8953 -------------------------------
8955 procedure Prepare_Ada_Naming_Exceptions
8956 (List : Array_Element_Id;
8957 In_Tree : Project_Tree_Ref;
8958 Kind : Spec_Or_Body)
8960 Current : Array_Element_Id;
8961 Element : Array_Element;
8965 -- Traverse the list
8968 while Current /= No_Array_Element loop
8969 Element := In_Tree.Array_Elements.Table (Current);
8971 if Element.Index /= No_Name then
8974 Unit => Element.Index,
8975 Next => No_Ada_Naming_Exception);
8976 Reverse_Ada_Naming_Exceptions.Set
8977 (Unit, (Element.Value.Value, Element.Value.Index));
8979 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8980 Ada_Naming_Exception_Table.Increment_Last;
8981 Ada_Naming_Exception_Table.Table
8982 (Ada_Naming_Exception_Table.Last) := Unit;
8983 Ada_Naming_Exceptions.Set
8984 (File_Name_Type (Element.Value.Value),
8985 Ada_Naming_Exception_Table.Last);
8988 Current := Element.Next;
8990 end Prepare_Ada_Naming_Exceptions;
8992 -----------------------
8993 -- Record_Ada_Source --
8994 -----------------------
8996 procedure Record_Ada_Source
8997 (File_Name : File_Name_Type;
8998 Path_Name : Path_Name_Type;
8999 Project : Project_Id;
9000 In_Tree : Project_Tree_Ref;
9001 Data : in out Project_Data;
9002 Location : Source_Ptr;
9003 Current_Source : in out String_List_Id;
9004 Source_Recorded : in out Boolean;
9005 Current_Dir : String)
9007 Canonical_File_Name : File_Name_Type;
9008 Canonical_Path_Name : Path_Name_Type;
9010 Exception_Id : Ada_Naming_Exception_Id;
9011 Unit_Name : Name_Id;
9012 Unit_Kind : Spec_Or_Body;
9013 Unit_Ind : Int := 0;
9015 Name_Index : Name_And_Index;
9016 Needs_Pragma : Boolean;
9018 The_Location : Source_Ptr := Location;
9019 Previous_Source : constant String_List_Id := Current_Source;
9020 Except_Name : Name_And_Index := No_Name_And_Index;
9022 Unit_Prj : Unit_Project;
9024 File_Name_Recorded : Boolean := False;
9027 if Osint.File_Names_Case_Sensitive then
9028 Canonical_File_Name := File_Name;
9029 Canonical_Path_Name := Path_Name;
9031 Get_Name_String (File_Name);
9032 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
9033 Canonical_File_Name := Name_Find;
9036 Canonical_Path : constant String :=
9038 (Get_Name_String (Path_Name),
9039 Directory => Current_Dir,
9040 Resolve_Links => Opt.Follow_Links_For_Files,
9041 Case_Sensitive => False);
9044 Add_Str_To_Name_Buffer (Canonical_Path);
9045 Canonical_Path_Name := Name_Find;
9049 -- Find out the unit name, the unit kind and if it needs
9050 -- a specific SFN pragma.
9053 (In_Tree => In_Tree,
9054 Canonical_File_Name => Canonical_File_Name,
9055 Naming => Data.Naming,
9056 Exception_Id => Exception_Id,
9057 Unit_Name => Unit_Name,
9058 Unit_Kind => Unit_Kind,
9059 Needs_Pragma => Needs_Pragma);
9061 if Exception_Id = No_Ada_Naming_Exception
9062 and then Unit_Name = No_Name
9064 if Current_Verbosity = High then
9066 Write_Str (Get_Name_String (Canonical_File_Name));
9067 Write_Line (""" is not a valid source file name (ignored).");
9071 -- Check to see if the source has been hidden by an exception,
9072 -- but only if it is not an exception.
9074 if not Needs_Pragma then
9076 Reverse_Ada_Naming_Exceptions.Get
9077 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
9079 if Except_Name /= No_Name_And_Index then
9080 if Current_Verbosity = High then
9082 Write_Str (Get_Name_String (Canonical_File_Name));
9083 Write_Str (""" contains a unit that is found in """);
9084 Write_Str (Get_Name_String (Except_Name.Name));
9085 Write_Line (""" (ignored).");
9088 -- The file is not included in the source of the project since
9089 -- it is hidden by the exception. So, nothing else to do.
9096 if Exception_Id /= No_Ada_Naming_Exception then
9097 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
9098 Exception_Id := Info.Next;
9099 Info.Next := No_Ada_Naming_Exception;
9100 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
9102 Unit_Name := Info.Unit;
9103 Unit_Ind := Name_Index.Index;
9104 Unit_Kind := Info.Kind;
9107 -- Put the file name in the list of sources of the project
9109 String_Element_Table.Increment_Last (In_Tree.String_Elements);
9110 In_Tree.String_Elements.Table
9111 (String_Element_Table.Last (In_Tree.String_Elements)) :=
9112 (Value => Name_Id (Canonical_File_Name),
9113 Display_Value => Name_Id (File_Name),
9114 Location => No_Location,
9119 if Current_Source = Nil_String then
9121 String_Element_Table.Last (In_Tree.String_Elements);
9123 In_Tree.String_Elements.Table (Current_Source).Next :=
9124 String_Element_Table.Last (In_Tree.String_Elements);
9128 String_Element_Table.Last (In_Tree.String_Elements);
9130 -- Put the unit in unit list
9133 The_Unit : Unit_Index :=
9134 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
9136 The_Unit_Data : Unit_Data;
9139 if Current_Verbosity = High then
9140 Write_Str ("Putting ");
9141 Write_Str (Get_Name_String (Unit_Name));
9142 Write_Line (" in the unit list.");
9145 -- The unit is already in the list, but may be it is
9146 -- only the other unit kind (spec or body), or what is
9147 -- in the unit list is a unit of a project we are extending.
9149 if The_Unit /= No_Unit_Index then
9150 The_Unit_Data := In_Tree.Units.Table (The_Unit);
9152 if (The_Unit_Data.File_Names (Unit_Kind).Name =
9155 The_Unit_Data.File_Names
9156 (Unit_Kind).Path.Name = Slash)
9157 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
9158 or else Is_Extending
9160 The_Unit_Data.File_Names (Unit_Kind).Project,
9164 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
9166 Remove_Forbidden_File_Name
9167 (The_Unit_Data.File_Names (Unit_Kind).Name);
9170 -- Record the file name in the hash table Files_Htable
9172 Unit_Prj := (Unit => The_Unit, Project => Project);
9175 Canonical_File_Name,
9178 The_Unit_Data.File_Names (Unit_Kind) :=
9179 (Name => Canonical_File_Name,
9181 Display_Name => File_Name,
9182 Path => (Canonical_Path_Name, Path_Name),
9184 Needs_Pragma => Needs_Pragma);
9185 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9186 Source_Recorded := True;
9188 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
9189 and then (Data.Known_Order_Of_Source_Dirs
9191 The_Unit_Data.File_Names
9192 (Unit_Kind).Path.Name = Canonical_Path_Name)
9194 if Previous_Source = Nil_String then
9195 Data.Ada_Sources := Nil_String;
9197 In_Tree.String_Elements.Table (Previous_Source).Next :=
9199 String_Element_Table.Decrement_Last
9200 (In_Tree.String_Elements);
9203 Current_Source := Previous_Source;
9206 -- It is an error to have two units with the same name
9207 -- and the same kind (spec or body).
9209 if The_Location = No_Location then
9211 In_Tree.Projects.Table (Project).Location;
9214 Err_Vars.Error_Msg_Name_1 := Unit_Name;
9216 (Project, In_Tree, "duplicate unit %%", The_Location);
9218 Err_Vars.Error_Msg_Name_1 :=
9219 In_Tree.Projects.Table
9220 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
9221 Err_Vars.Error_Msg_File_1 :=
9223 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
9226 "\ project file %%, {", The_Location);
9228 Err_Vars.Error_Msg_Name_1 :=
9229 In_Tree.Projects.Table (Project).Name;
9230 Err_Vars.Error_Msg_File_1 :=
9231 File_Name_Type (Canonical_Path_Name);
9234 "\ project file %%, {", The_Location);
9237 -- It is a new unit, create a new record
9240 -- First, check if there is no other unit with this file
9241 -- name in another project. If it is, report error but note
9242 -- we do that only for the first unit in the source file.
9245 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
9247 if not File_Name_Recorded and then
9248 Unit_Prj /= No_Unit_Project
9250 Error_Msg_File_1 := File_Name;
9252 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9255 "{ is already a source of project %%",
9259 Unit_Table.Increment_Last (In_Tree.Units);
9260 The_Unit := Unit_Table.Last (In_Tree.Units);
9262 (In_Tree.Units_HT, Unit_Name, The_Unit);
9263 Unit_Prj := (Unit => The_Unit, Project => Project);
9266 Canonical_File_Name,
9268 The_Unit_Data.Name := Unit_Name;
9269 The_Unit_Data.File_Names (Unit_Kind) :=
9270 (Name => Canonical_File_Name,
9272 Display_Name => File_Name,
9273 Path => (Canonical_Path_Name, Path_Name),
9275 Needs_Pragma => Needs_Pragma);
9276 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9277 Source_Recorded := True;
9282 exit when Exception_Id = No_Ada_Naming_Exception;
9283 File_Name_Recorded := True;
9286 end Record_Ada_Source;
9292 procedure Remove_Source
9294 Replaced_By : Source_Id;
9295 Project : Project_Id;
9296 Data : in out Project_Data;
9297 In_Tree : Project_Tree_Ref)
9299 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9303 if Current_Verbosity = High then
9304 Write_Str ("Removing source #");
9305 Write_Line (Id'Img);
9308 if Replaced_By /= No_Source then
9309 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9310 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9311 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9314 -- Remove the source from the global source list
9316 Source := In_Tree.First_Source;
9319 In_Tree.First_Source := Src_Data.Next_In_Sources;
9322 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9323 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9326 In_Tree.Sources.Table (Source).Next_In_Sources :=
9327 Src_Data.Next_In_Sources;
9330 -- Remove the source from the project list
9332 if Src_Data.Project = Project then
9333 Source := Data.First_Source;
9336 Data.First_Source := Src_Data.Next_In_Project;
9338 if Src_Data.Next_In_Project = No_Source then
9339 Data.Last_Source := No_Source;
9343 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9344 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9347 In_Tree.Sources.Table (Source).Next_In_Project :=
9348 Src_Data.Next_In_Project;
9350 if Src_Data.Next_In_Project = No_Source then
9351 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9356 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9359 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9360 Src_Data.Next_In_Project;
9362 if Src_Data.Next_In_Project = No_Source then
9363 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9368 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9369 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9372 In_Tree.Sources.Table (Source).Next_In_Project :=
9373 Src_Data.Next_In_Project;
9375 if Src_Data.Next_In_Project = No_Source then
9376 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9381 -- Remove source from the language list
9383 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9386 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9387 Src_Data.Next_In_Lang;
9390 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9391 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9394 In_Tree.Sources.Table (Source).Next_In_Lang :=
9395 Src_Data.Next_In_Lang;
9399 -----------------------
9400 -- Report_No_Sources --
9401 -----------------------
9403 procedure Report_No_Sources
9404 (Project : Project_Id;
9406 In_Tree : Project_Tree_Ref;
9407 Location : Source_Ptr;
9408 Continuation : Boolean := False)
9411 case When_No_Sources is
9415 when Warning | Error =>
9417 Msg : constant String :=
9420 " sources in this project";
9423 Error_Msg_Warn := When_No_Sources = Warning;
9425 if Continuation then
9427 (Project, In_Tree, "\" & Msg, Location);
9431 (Project, In_Tree, Msg, Location);
9435 end Report_No_Sources;
9437 ----------------------
9438 -- Show_Source_Dirs --
9439 ----------------------
9441 procedure Show_Source_Dirs
9442 (Data : Project_Data;
9443 In_Tree : Project_Tree_Ref)
9445 Current : String_List_Id;
9446 Element : String_Element;
9449 Write_Line ("Source_Dirs:");
9451 Current := Data.Source_Dirs;
9452 while Current /= Nil_String loop
9453 Element := In_Tree.String_Elements.Table (Current);
9455 Write_Line (Get_Name_String (Element.Value));
9456 Current := Element.Next;
9459 Write_Line ("end Source_Dirs.");
9460 end Show_Source_Dirs;
9462 -------------------------
9463 -- Warn_If_Not_Sources --
9464 -------------------------
9466 -- comments needed in this body ???
9468 procedure Warn_If_Not_Sources
9469 (Project : Project_Id;
9470 In_Tree : Project_Tree_Ref;
9471 Conventions : Array_Element_Id;
9473 Extending : Boolean)
9475 Conv : Array_Element_Id;
9477 The_Unit_Id : Unit_Index;
9478 The_Unit_Data : Unit_Data;
9479 Location : Source_Ptr;
9482 Conv := Conventions;
9483 while Conv /= No_Array_Element loop
9484 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9485 Error_Msg_Name_1 := Unit;
9486 Get_Name_String (Unit);
9487 To_Lower (Name_Buffer (1 .. Name_Len));
9489 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9490 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9492 if The_Unit_Id = No_Unit_Index then
9493 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9496 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9498 In_Tree.Array_Elements.Table (Conv).Value.Value;
9501 if not Check_Project
9502 (The_Unit_Data.File_Names (Specification).Project,
9503 Project, In_Tree, Extending)
9507 "?source of spec of unit %% (%%)" &
9508 " cannot be found in this project",
9513 if not Check_Project
9514 (The_Unit_Data.File_Names (Body_Part).Project,
9515 Project, In_Tree, Extending)
9519 "?source of body of unit %% (%%)" &
9520 " cannot be found in this project",
9526 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9528 end Warn_If_Not_Sources;