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.
78 -- Except is set to True if source is a naming exception in the project.
80 No_Name_Location : constant Name_Location :=
82 Location => No_Location,
87 package Source_Names is new GNAT.HTable.Simple_HTable
88 (Header_Num => Header_Num,
89 Element => Name_Location,
90 No_Element => No_Name_Location,
91 Key => File_Name_Type,
94 -- Hash table to store file names found in string list attribute
95 -- Source_Files or in a source list file, stored in hash table
96 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
98 -- More documentation needed on what unit exceptions are about ???
100 type Unit_Exception is record
102 Spec : File_Name_Type;
103 Impl : File_Name_Type;
105 -- Record special naming schemes for Ada units (name of spec file and name
106 -- of implementation file).
108 No_Unit_Exception : constant Unit_Exception :=
113 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
114 (Header_Num => Header_Num,
115 Element => Unit_Exception,
116 No_Element => No_Unit_Exception,
120 -- Hash table to store the unit exceptions.
121 -- ??? Seems to be used only by the multi_lang mode
122 -- ??? Should not be a global array, but stored in the project_data
124 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
125 (Header_Num => Header_Num,
131 -- Hash table to store recursive source directories, to avoid looking
132 -- several times, and to avoid cycles that may be introduced by symbolic
135 type Ada_Naming_Exception_Id is new Nat;
136 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
138 type Unit_Info is record
141 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
145 package Ada_Naming_Exception_Table is new Table.Table
146 (Table_Component_Type => Unit_Info,
147 Table_Index_Type => Ada_Naming_Exception_Id,
148 Table_Low_Bound => 1,
150 Table_Increment => 100,
151 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
153 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
154 (Header_Num => Header_Num,
155 Element => Ada_Naming_Exception_Id,
156 No_Element => No_Ada_Naming_Exception,
157 Key => File_Name_Type,
160 -- A hash table to store naming exceptions for Ada. For each file name
161 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 -- ??? This is for ada_only mode, we should be able to merge with
163 -- Unit_Exceptions table, used by multi_lang mode.
165 package Object_File_Names is new GNAT.HTable.Simple_HTable
166 (Header_Num => Header_Num,
167 Element => File_Name_Type,
168 No_Element => No_File,
169 Key => File_Name_Type,
172 -- A hash table to store the object file names for a project, to check that
173 -- two different sources have different object file names.
175 type File_Found is record
176 File : File_Name_Type := No_File;
177 Found : Boolean := False;
178 Location : Source_Ptr := No_Location;
180 No_File_Found : constant File_Found := (No_File, False, No_Location);
181 -- Comments needed ???
183 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
184 (Header_Num => Header_Num,
185 Element => File_Found,
186 No_Element => No_File_Found,
187 Key => File_Name_Type,
190 -- A hash table to store the excluded files, if any. This is filled by
191 -- Find_Excluded_Sources below.
193 procedure Find_Excluded_Sources
194 (Project : Project_Id;
195 In_Tree : Project_Tree_Ref;
196 Data : Project_Data);
197 -- Find the list of files that should not be considered as source files
198 -- for this project. Sets the list in the Excluded_Sources_Htable.
200 function Hash (Unit : Unit_Info) return Header_Num;
202 type Name_And_Index is record
203 Name : Name_Id := No_Name;
206 No_Name_And_Index : constant Name_And_Index :=
207 (Name => No_Name, Index => 0);
209 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
210 (Header_Num => Header_Num,
211 Element => Name_And_Index,
212 No_Element => No_Name_And_Index,
216 -- A table to check if a unit with an exceptional name will hide a source
217 -- with a file name following the naming convention.
219 procedure Load_Naming_Exceptions
220 (Project : Project_Id;
221 In_Tree : Project_Tree_Ref);
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 In_Tree : Project_Tree_Ref;
229 Project : Project_Id;
230 Lang_Id : Language_Ptr;
232 File_Name : File_Name_Type;
233 Display_File : File_Name_Type;
234 Lang_Kind : Language_Kind;
235 Naming_Exception : Boolean := False;
236 Path : Path_Name_Type := No_Path;
237 Display_Path : Path_Name_Type := No_Path;
238 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
239 Other_Part : Source_Id := No_Source;
240 Unit : Name_Id := No_Name;
242 Source_To_Replace : Source_Id := No_Source);
243 -- Add a new source to the different lists: list of all sources in the
244 -- project tree, list of source of a project and list of sources of a
247 -- If Path is specified, the file is also added to Source_Paths_HT.
248 -- If Source_To_Replace is specified, it points to the source in the
249 -- extended project that the new file is overriding.
251 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
252 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
253 -- This alters Name_Buffer
255 function Suffix_Matches
257 Suffix : File_Name_Type) return Boolean;
258 -- True if the filename ends with the given suffix. It always returns False
259 -- if Suffix is No_Name
261 procedure Replace_Into_Name_Buffer
264 Replacement : Character);
265 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
266 -- converted to lower-case at the same time.
268 function ALI_File_Name (Source : String) return String;
269 -- Return the ALI file name corresponding to a source
271 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
272 -- Check that a name is a valid Ada unit name
274 procedure Check_Naming_Schemes
275 (Data : in out Project_Data;
276 Project : Project_Id;
277 In_Tree : Project_Tree_Ref);
278 -- Check the naming scheme part of Data
280 procedure Check_Configuration
281 (Project : Project_Id;
282 In_Tree : Project_Tree_Ref;
283 Data : in out Project_Data);
284 -- Check the configuration attributes for the project
286 procedure Check_If_Externally_Built
287 (Project : Project_Id;
288 In_Tree : Project_Tree_Ref;
289 Data : in out Project_Data);
290 -- Check attribute Externally_Built of project Project in project tree
291 -- In_Tree and modify its data Data if it has the value "true".
293 procedure Check_Interfaces
294 (Project : Project_Id;
295 In_Tree : Project_Tree_Ref;
296 Data : in out Project_Data);
297 -- If a list of sources is specified in attribute Interfaces, set
298 -- In_Interfaces only for the sources specified in the list.
300 procedure Check_Library_Attributes
301 (Project : Project_Id;
302 In_Tree : Project_Tree_Ref;
303 Current_Dir : String;
304 Data : in out Project_Data);
305 -- Check the library attributes of project Project in project tree In_Tree
306 -- and modify its data Data accordingly.
307 -- Current_Dir should represent the current directory, and is passed for
308 -- efficiency to avoid system calls to recompute it.
310 procedure Check_Package_Naming
311 (Project : Project_Id;
312 In_Tree : Project_Tree_Ref;
313 Data : in out Project_Data);
314 -- Check package Naming of project Project in project tree In_Tree and
315 -- modify its data Data accordingly.
317 procedure Check_Programming_Languages
318 (In_Tree : Project_Tree_Ref;
319 Project : Project_Id;
320 Data : in out Project_Data);
321 -- Check attribute Languages for the project with data Data in project
322 -- tree In_Tree and set the components of Data for all the programming
323 -- languages indicated in attribute Languages, if any.
325 function Check_Project
327 Root_Project : Project_Id;
328 In_Tree : Project_Tree_Ref;
329 Extending : Boolean) return Boolean;
330 -- Returns True if P is Root_Project or, if Extending is True, a project
331 -- extended by Root_Project.
333 procedure Check_Stand_Alone_Library
334 (Project : Project_Id;
335 In_Tree : Project_Tree_Ref;
336 Data : in out Project_Data;
337 Current_Dir : String;
338 Extending : Boolean);
339 -- Check if project Project in project tree In_Tree is a Stand-Alone
340 -- Library project, and modify its data Data accordingly if it is one.
341 -- Current_Dir should represent the current directory, and is passed for
342 -- efficiency to avoid system calls to recompute it.
344 procedure Check_And_Normalize_Unit_Names
345 (Project : Project_Id;
346 In_Tree : Project_Tree_Ref;
347 List : Array_Element_Id;
348 Debug_Name : String);
349 -- Check that a list of unit names contains only valid names. Casing
350 -- is normalized where appropriate.
351 -- Debug_Name is the name representing the list, and is used for debug
354 procedure Find_Ada_Sources
355 (Project : Project_Id;
356 In_Tree : Project_Tree_Ref;
357 Data : in out Project_Data;
358 Current_Dir : String;
359 Explicit_Sources_Only : Boolean);
360 -- Find all Ada sources by traversing all source directories.
361 -- If Explicit_Sources_Only is True, then the sources found must belong to
362 -- the list of sources specified explicitly in the project file.
363 -- If Explicit_Sources_Only is False, then all sources matching the naming
364 -- scheme are recorded.
366 function Compute_Directory_Last (Dir : String) return Natural;
367 -- Return the index of the last significant character in Dir. This is used
368 -- to avoid duplicate '/' (slash) characters at the end of directory names.
371 (Project : Project_Id;
372 In_Tree : Project_Tree_Ref;
374 Flag_Location : Source_Ptr);
375 -- Output an error message. If Error_Report is null, simply call
376 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
379 procedure Search_Directories
380 (Project : Project_Id;
381 In_Tree : Project_Tree_Ref;
382 Data : in out Project_Data;
383 For_All_Sources : Boolean);
384 -- Search the source directories to find the sources.
385 -- If For_All_Sources is True, check each regular file name against the
386 -- naming schemes of the different languages. Otherwise consider only the
387 -- file names in the hash table Source_Names.
390 (Project : Project_Id;
391 In_Tree : Project_Tree_Ref;
392 Data : in out Project_Data;
394 File_Name : File_Name_Type;
395 Display_File_Name : File_Name_Type;
396 Source_Directory : String;
397 For_All_Sources : Boolean);
398 -- Check if file File_Name is a valid source of the project. This is used
399 -- in multi-language mode only.
400 -- When the file matches one of the naming schemes, it is added to
401 -- various htables through Add_Source and to Source_Paths_Htable.
403 -- Name is the name of the candidate file. It hasn't been normalized yet
404 -- and is the direct result of readdir().
406 -- File_Name is the same as Name, but has been normalized.
407 -- Display_File_Name, however, has not been normalized.
409 -- Source_Directory is the directory in which the file
410 -- was found. It hasn't been normalized (nor has had links resolved).
411 -- It should not end with a directory separator, to avoid duplicates
414 -- If For_All_Sources is True, then all possible file names are analyzed
415 -- otherwise only those currently set in the Source_Names htable.
417 procedure Check_File_Naming_Schemes
418 (In_Tree : Project_Tree_Ref;
419 Data : in out Project_Data;
420 File_Name : File_Name_Type;
421 Alternate_Languages : out Alternate_Language_Id;
422 Language : out Language_Ptr;
423 Language_Name : out Name_Id;
424 Display_Language_Name : out Name_Id;
426 Lang_Kind : out Language_Kind;
427 Kind : out Source_Kind);
428 -- Check if the file name File_Name conforms to one of the naming
429 -- schemes of the project.
431 -- If the file does not match one of the naming schemes, set Language
432 -- to No_Language_Index.
434 -- Filename is the name of the file being investigated. It has been
435 -- normalized (case-folded). File_Name is the same value.
437 procedure Free_Ada_Naming_Exceptions;
438 -- Free the internal hash tables used for checking naming exceptions
440 procedure Get_Directories
441 (Project : Project_Id;
442 In_Tree : Project_Tree_Ref;
443 Current_Dir : String;
444 Data : in out Project_Data);
445 -- Get the object directory, the exec directory and the source directories
448 -- Current_Dir should represent the current directory, and is passed for
449 -- efficiency to avoid system calls to recompute it.
452 (Project : Project_Id;
453 In_Tree : Project_Tree_Ref;
454 Data : in out Project_Data);
455 -- Get the mains of a project from attribute Main, if it exists, and put
456 -- them in the project data.
458 procedure Get_Sources_From_File
460 Location : Source_Ptr;
461 Project : Project_Id;
462 In_Tree : Project_Tree_Ref);
463 -- Get the list of sources from a text file and put them in hash table
466 procedure Find_Sources
467 (Current_Dir : String;
468 Project : Project_Id;
469 In_Tree : Project_Tree_Ref;
470 Data : in out Project_Data);
471 -- Process the Source_Files and Source_List_File attributes, and store
472 -- the list of source files into the Source_Names htable.
473 -- When these attributes are not defined, find all files matching the
474 -- naming schemes in the source directories.
476 procedure Compute_Unit_Name
477 (File_Name : File_Name_Type;
478 Dot_Replacement : File_Name_Type;
479 Separate_Suffix : File_Name_Type;
480 Body_Suffix : File_Name_Type;
481 Spec_Suffix : File_Name_Type;
482 Casing : Casing_Type;
483 Kind : out Source_Kind;
485 In_Tree : Project_Tree_Ref);
486 -- Check whether the file matches the naming scheme. If it does,
487 -- compute its unit name. If Unit is set to No_Name on exit, none of the
488 -- other out parameters are relevant.
491 (In_Tree : Project_Tree_Ref;
492 Canonical_File_Name : File_Name_Type;
493 Naming : Naming_Data;
494 Exception_Id : out Ada_Naming_Exception_Id;
495 Unit_Name : out Name_Id;
496 Unit_Kind : out Spec_Or_Body;
497 Needs_Pragma : out Boolean);
498 -- Find out, from a file name, the unit name, the unit kind and if a
499 -- specific SFN pragma is needed. If the file name corresponds to no unit,
500 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
501 -- exception to the naming scheme, then Exception_Id is set to the unit or
502 -- units that the source contains.
504 function Is_Illegal_Suffix
505 (Suffix : File_Name_Type;
506 Dot_Replacement : File_Name_Type) return Boolean;
507 -- Returns True if the string Suffix cannot be used as a spec suffix, a
508 -- body suffix or a separate suffix.
510 procedure Locate_Directory
511 (Project : Project_Id;
512 In_Tree : Project_Tree_Ref;
513 Name : File_Name_Type;
514 Parent : Path_Name_Type;
515 Dir : out Path_Name_Type;
516 Display : out Path_Name_Type;
517 Create : String := "";
518 Current_Dir : String;
519 Location : Source_Ptr := No_Location;
520 Externally_Built : Boolean := False);
521 -- Locate a directory. Name is the directory name. Parent is the root
522 -- directory, if Name a relative path name. Dir is set to the canonical
523 -- case path name of the directory, and Display is the directory path name
524 -- for display purposes. If the directory does not exist and Setup_Projects
525 -- is True and Create is a non null string, an attempt is made to create
526 -- the directory. If the directory does not exist and Setup_Projects is
527 -- false, then Dir and Display are set to No_Name.
529 -- Current_Dir should represent the current directory, and is passed for
530 -- efficiency to avoid system calls to recompute it.
532 procedure Look_For_Sources
533 (Project : Project_Id;
534 In_Tree : Project_Tree_Ref;
535 Data : in out Project_Data;
536 Current_Dir : String);
537 -- Find all the sources of project Project in project tree In_Tree and
538 -- update its Data accordingly. This assumes that Data.First_Source has
539 -- been initialized with the list of excluded sources and special naming
542 -- Current_Dir should represent the current directory, and is passed for
543 -- efficiency to avoid system calls to recompute it.
545 function Path_Name_Of
546 (File_Name : File_Name_Type;
547 Directory : Path_Name_Type) return String;
548 -- Returns the path name of a (non project) file. Returns an empty string
549 -- if file cannot be found.
551 procedure Prepare_Ada_Naming_Exceptions
552 (List : Array_Element_Id;
553 In_Tree : Project_Tree_Ref;
554 Kind : Spec_Or_Body);
555 -- Prepare the internal hash tables used for checking naming exceptions
556 -- for Ada. Insert all elements of List in the tables.
558 procedure Record_Ada_Source
559 (File_Name : File_Name_Type;
560 Path_Name : Path_Name_Type;
561 Project : Project_Id;
562 In_Tree : Project_Tree_Ref;
563 Data : in out Project_Data;
564 Location : Source_Ptr;
565 Current_Source : in out String_List_Id;
566 Source_Recorded : in out Boolean;
567 Current_Dir : String);
568 -- Put a unit in the list of units of a project, if the file name
569 -- corresponds to a valid unit name.
571 -- Current_Dir should represent the current directory, and is passed for
572 -- efficiency to avoid system calls to recompute it.
574 procedure Remove_Source
576 Replaced_By : Source_Id);
579 procedure Report_No_Sources
580 (Project : Project_Id;
582 In_Tree : Project_Tree_Ref;
583 Location : Source_Ptr;
584 Continuation : Boolean := False);
585 -- Report an error or a warning depending on the value of When_No_Sources
586 -- when there are no sources for language Lang_Name.
588 procedure Show_Source_Dirs
589 (Data : Project_Data; In_Tree : Project_Tree_Ref);
590 -- List all the source directories of a project
592 procedure Warn_If_Not_Sources
593 (Project : Project_Id;
594 In_Tree : Project_Tree_Ref;
595 Conventions : Array_Element_Id;
597 Extending : Boolean);
598 -- Check that individual naming conventions apply to immediate sources of
599 -- the project. If not, issue a warning.
601 procedure Write_Attr (Name, Value : String);
602 -- Debug print a value for a specific property. Does nothing when not in
605 ------------------------------
606 -- Replace_Into_Name_Buffer --
607 ------------------------------
609 procedure Replace_Into_Name_Buffer
612 Replacement : Character)
614 Max : constant Integer := Str'Last - Pattern'Length + 1;
621 while J <= Str'Last loop
622 Name_Len := Name_Len + 1;
625 and then Str (J .. J + Pattern'Length - 1) = Pattern
627 Name_Buffer (Name_Len) := Replacement;
628 J := J + Pattern'Length;
631 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
635 end Replace_Into_Name_Buffer;
641 function Suffix_Matches
643 Suffix : File_Name_Type) return Boolean
646 if Suffix = No_File then
651 Suf : constant String := Get_Name_String (Suffix);
653 return Filename'Length > Suf'Length
655 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
663 procedure Write_Attr (Name, Value : String) is
665 if Current_Verbosity = High then
666 Write_Str (" " & Name & " = """);
679 In_Tree : Project_Tree_Ref;
680 Project : Project_Id;
681 Lang_Id : Language_Ptr;
683 File_Name : File_Name_Type;
684 Display_File : File_Name_Type;
685 Lang_Kind : Language_Kind;
686 Naming_Exception : Boolean := False;
687 Path : Path_Name_Type := No_Path;
688 Display_Path : Path_Name_Type := No_Path;
689 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
690 Other_Part : Source_Id := No_Source;
691 Unit : Name_Id := No_Name;
693 Source_To_Replace : Source_Id := No_Source)
695 Config : constant Language_Config := Lang_Id.Config;
698 Id := new Source_Data;
700 if Current_Verbosity = High then
701 Write_Str ("Adding source File: ");
702 Write_Str (Get_Name_String (File_Name));
704 if Lang_Kind = Unit_Based then
705 Write_Str (" Unit: ");
706 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
707 -- (see test extended_projects)
708 if Unit /= No_Name then
709 Write_Str (Get_Name_String (Unit));
711 Write_Str (" Kind: ");
712 Write_Str (Source_Kind'Image (Kind));
718 Id.Project := Project;
719 Id.Language := Lang_Id;
720 Id.Lang_Kind := Lang_Kind;
721 Id.Compiled := Lang_Id.Config.Compiler_Driver /=
724 Id.Alternate_Languages := Alternate_Languages;
725 Id.Other_Part := Other_Part;
727 Id.Object_Exists := Config.Object_Generated;
728 Id.Object_Linked := Config.Objects_Linked;
730 if Other_Part /= No_Source then
731 Other_Part.Other_Part := Id;
736 Id.File := File_Name;
737 Id.Display_File := Display_File;
738 Id.Dependency := Lang_Id.Config.Dependency_Kind;
739 Id.Dep_Name := Dependency_Name (File_Name, Id.Dependency);
740 Id.Naming_Exception := Naming_Exception;
742 if Id.Compiled and then Id.Object_Exists then
743 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
744 Id.Switches := Switches_Name (File_Name);
747 if Path /= No_Path then
748 Id.Path := (Path, Display_Path);
749 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
752 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
755 if Unit /= No_Name then
756 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
759 -- Add the source to the language list
761 Id.Next_In_Lang := Lang_Id.First_Source;
762 Lang_Id.First_Source := Id;
764 if Source_To_Replace /= No_Source then
765 Remove_Source (Source_To_Replace, Id);
773 function ALI_File_Name (Source : String) return String is
775 -- If the source name has an extension, then replace it with
778 for Index in reverse Source'First + 1 .. Source'Last loop
779 if Source (Index) = '.' then
780 return Source (Source'First .. Index - 1) & ALI_Suffix;
784 -- If there is no dot, or if it is the first character, just add the
787 return Source & ALI_Suffix;
790 ------------------------------
791 -- Canonical_Case_File_Name --
792 ------------------------------
794 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
796 if Osint.File_Names_Case_Sensitive then
797 return File_Name_Type (Name);
799 Get_Name_String (Name);
800 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
803 end Canonical_Case_File_Name;
810 (Project : Project_Id;
811 In_Tree : Project_Tree_Ref;
812 Report_Error : Put_Line_Access;
813 When_No_Sources : Error_Warning;
814 Current_Dir : String)
816 Data : Project_Data renames In_Tree.Projects.Table (Project);
817 Extending : Boolean := False;
820 Nmsc.When_No_Sources := When_No_Sources;
821 Error_Report := Report_Error;
823 Recursive_Dirs.Reset;
825 Check_If_Externally_Built (Project, In_Tree, Data);
827 -- Object, exec and source directories
829 Get_Directories (Project, In_Tree, Current_Dir, Data);
831 -- Get the programming languages
833 Check_Programming_Languages (In_Tree, Project, Data);
835 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
838 "an abstract project needs to have no language, no sources " &
839 "or no source directories",
843 -- Check configuration in multi language mode
845 if Must_Check_Configuration then
846 Check_Configuration (Project, In_Tree, Data);
849 -- Library attributes
851 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
853 if Current_Verbosity = High then
854 Show_Source_Dirs (Data, In_Tree);
857 Check_Package_Naming (Project, In_Tree, Data);
859 Extending := Data.Extends /= No_Project;
861 Check_Naming_Schemes (Data, Project, In_Tree);
863 if Get_Mode = Ada_Only then
864 Prepare_Ada_Naming_Exceptions
865 (Data.Naming.Bodies, In_Tree, Body_Part);
866 Prepare_Ada_Naming_Exceptions
867 (Data.Naming.Specs, In_Tree, Specification);
872 if Data.Source_Dirs /= Nil_String then
873 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
875 if Get_Mode = Ada_Only then
877 -- Check that all individual naming conventions apply to sources
878 -- of this project file.
881 (Project, In_Tree, Data.Naming.Bodies,
883 Extending => Extending);
885 (Project, In_Tree, Data.Naming.Specs,
887 Extending => Extending);
889 elsif Get_Mode = Multi_Language and then
890 (not Data.Externally_Built) and then
894 Language : Language_Ptr;
896 Alt_Lang : Alternate_Language_Id;
897 Alt_Lang_Data : Alternate_Language_Data;
898 Continuation : Boolean := False;
899 Iter : Source_Iterator;
902 Language := Data.Languages;
903 while Language /= No_Language_Index loop
905 -- If there are no sources for this language, check whether
906 -- there are sources for which this is an alternate
909 if Language.First_Source = No_Source then
910 Iter := For_Each_Source (In_Tree => In_Tree,
913 Source := Element (Iter);
914 exit Source_Loop when Source = No_Source
915 or else Source.Language = Language;
917 Alt_Lang := Source.Alternate_Languages;
920 while Alt_Lang /= No_Alternate_Language loop
921 Alt_Lang_Data := In_Tree.Alt_Langs.Table (Alt_Lang);
923 when Alt_Lang_Data.Language = Language;
924 Alt_Lang := Alt_Lang_Data.Next;
925 end loop Alternate_Loop;
928 end loop Source_Loop;
930 if Source = No_Source then
933 Get_Name_String (Language.Display_Name),
937 Continuation := True;
941 Language := Language.Next;
947 if Get_Mode = Multi_Language then
949 -- If a list of sources is specified in attribute Interfaces, set
950 -- In_Interfaces only for the sources specified in the list.
952 Check_Interfaces (Project, In_Tree, Data);
955 -- If it is a library project file, check if it is a standalone library
958 Check_Stand_Alone_Library
959 (Project, In_Tree, Data, Current_Dir, Extending);
962 -- Put the list of Mains, if any, in the project data
964 Get_Mains (Project, In_Tree, Data);
966 -- Update the project data in the Projects table
968 In_Tree.Projects.Table (Project) := Data;
970 Free_Ada_Naming_Exceptions;
977 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
978 The_Name : String := Name;
980 Need_Letter : Boolean := True;
981 Last_Underscore : Boolean := False;
982 OK : Boolean := The_Name'Length > 0;
985 function Is_Reserved (Name : Name_Id) return Boolean;
986 function Is_Reserved (S : String) return Boolean;
987 -- Check that the given name is not an Ada 95 reserved word. The reason
988 -- for the Ada 95 here is that we do not want to exclude the case of an
989 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
990 -- name would be rejected anyway by the compiler. That means there is no
991 -- requirement that the project file parser reject this.
997 function Is_Reserved (S : String) return Boolean is
1000 Add_Str_To_Name_Buffer (S);
1001 return Is_Reserved (Name_Find);
1008 function Is_Reserved (Name : Name_Id) return Boolean is
1010 if Get_Name_Table_Byte (Name) /= 0
1011 and then Name /= Name_Project
1012 and then Name /= Name_Extends
1013 and then Name /= Name_External
1014 and then Name not in Ada_2005_Reserved_Words
1018 if Current_Verbosity = High then
1019 Write_Str (The_Name);
1020 Write_Line (" is an Ada reserved word.");
1030 -- Start of processing for Check_Ada_Name
1033 To_Lower (The_Name);
1035 Name_Len := The_Name'Length;
1036 Name_Buffer (1 .. Name_Len) := The_Name;
1038 -- Special cases of children of packages A, G, I and S on VMS
1040 if OpenVMS_On_Target
1041 and then Name_Len > 3
1042 and then Name_Buffer (2 .. 3) = "__"
1044 ((Name_Buffer (1) = 'a') or else
1045 (Name_Buffer (1) = 'g') or else
1046 (Name_Buffer (1) = 'i') or else
1047 (Name_Buffer (1) = 's'))
1049 Name_Buffer (2) := '.';
1050 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1051 Name_Len := Name_Len - 1;
1054 Real_Name := Name_Find;
1056 if Is_Reserved (Real_Name) then
1060 First := The_Name'First;
1062 for Index in The_Name'Range loop
1065 -- We need a letter (at the beginning, and following a dot),
1066 -- but we don't have one.
1068 if Is_Letter (The_Name (Index)) then
1069 Need_Letter := False;
1074 if Current_Verbosity = High then
1075 Write_Int (Types.Int (Index));
1077 Write_Char (The_Name (Index));
1078 Write_Line ("' is not a letter.");
1084 elsif Last_Underscore
1085 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1087 -- Two underscores are illegal, and a dot cannot follow
1092 if Current_Verbosity = High then
1093 Write_Int (Types.Int (Index));
1095 Write_Char (The_Name (Index));
1096 Write_Line ("' is illegal here.");
1101 elsif The_Name (Index) = '.' then
1103 -- First, check if the name before the dot is not a reserved word
1104 if Is_Reserved (The_Name (First .. Index - 1)) then
1110 -- We need a letter after a dot
1112 Need_Letter := True;
1114 elsif The_Name (Index) = '_' then
1115 Last_Underscore := True;
1118 -- We need an letter or a digit
1120 Last_Underscore := False;
1122 if not Is_Alphanumeric (The_Name (Index)) then
1125 if Current_Verbosity = High then
1126 Write_Int (Types.Int (Index));
1128 Write_Char (The_Name (Index));
1129 Write_Line ("' is not alphanumeric.");
1137 -- Cannot end with an underscore or a dot
1139 OK := OK and then not Need_Letter and then not Last_Underscore;
1142 if First /= Name'First and then
1143 Is_Reserved (The_Name (First .. The_Name'Last))
1151 -- Signal a problem with No_Name
1157 -------------------------
1158 -- Check_Configuration --
1159 -------------------------
1161 procedure Check_Configuration
1162 (Project : Project_Id;
1163 In_Tree : Project_Tree_Ref;
1164 Data : in out Project_Data)
1166 Dot_Replacement : File_Name_Type := No_File;
1167 Casing : Casing_Type := All_Lower_Case;
1168 Separate_Suffix : File_Name_Type := No_File;
1170 Lang_Index : Language_Ptr := No_Language_Index;
1171 -- The index of the language data being checked
1173 Prev_Index : Language_Ptr := No_Language_Index;
1174 -- The index of the previous language
1176 Current_Language : Name_Id := No_Name;
1177 -- The name of the language
1179 procedure Get_Language_Index_Of (Language : Name_Id);
1180 -- Get the language index of Language, if Language is one of the
1181 -- languages of the project.
1183 procedure Process_Project_Level_Simple_Attributes;
1184 -- Process the simple attributes at the project level
1186 procedure Process_Project_Level_Array_Attributes;
1187 -- Process the associate array attributes at the project level
1189 procedure Process_Packages;
1190 -- Read the packages of the project
1192 ---------------------------
1193 -- Get_Language_Index_Of --
1194 ---------------------------
1196 procedure Get_Language_Index_Of (Language : Name_Id) is
1197 Real_Language : Name_Id;
1200 Get_Name_String (Language);
1201 To_Lower (Name_Buffer (1 .. Name_Len));
1202 Real_Language := Name_Find;
1204 -- Nothing to do if the language is the same as the current language
1206 if Current_Language /= Real_Language then
1207 Lang_Index := Data.Languages;
1208 while Lang_Index /= No_Language_Index loop
1209 exit when Lang_Index.Name = Real_Language;
1210 Lang_Index := Lang_Index.Next;
1213 if Lang_Index = No_Language_Index then
1214 Current_Language := No_Name;
1216 Current_Language := Real_Language;
1219 end Get_Language_Index_Of;
1221 ----------------------
1222 -- Process_Packages --
1223 ----------------------
1225 procedure Process_Packages is
1226 Packages : Package_Id;
1227 Element : Package_Element;
1229 procedure Process_Binder (Arrays : Array_Id);
1230 -- Process the associate array attributes of package Binder
1232 procedure Process_Builder (Attributes : Variable_Id);
1233 -- Process the simple attributes of package Builder
1235 procedure Process_Compiler (Arrays : Array_Id);
1236 -- Process the associate array attributes of package Compiler
1238 procedure Process_Naming (Attributes : Variable_Id);
1239 -- Process the simple attributes of package Naming
1241 procedure Process_Naming (Arrays : Array_Id);
1242 -- Process the associate array attributes of package Naming
1244 procedure Process_Linker (Attributes : Variable_Id);
1245 -- Process the simple attributes of package Linker of a
1246 -- configuration project.
1248 --------------------
1249 -- Process_Binder --
1250 --------------------
1252 procedure Process_Binder (Arrays : Array_Id) is
1253 Current_Array_Id : Array_Id;
1254 Current_Array : Array_Data;
1255 Element_Id : Array_Element_Id;
1256 Element : Array_Element;
1259 -- Process the associative array attribute of package Binder
1261 Current_Array_Id := Arrays;
1262 while Current_Array_Id /= No_Array loop
1263 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1265 Element_Id := Current_Array.Value;
1266 while Element_Id /= No_Array_Element loop
1267 Element := In_Tree.Array_Elements.Table (Element_Id);
1269 if Element.Index /= All_Other_Names then
1271 -- Get the name of the language
1273 Get_Language_Index_Of (Element.Index);
1275 if Lang_Index /= No_Language_Index then
1276 case Current_Array.Name is
1279 -- Attribute Driver (<language>)
1281 Lang_Index.Config.Binder_Driver :=
1282 File_Name_Type (Element.Value.Value);
1284 when Name_Required_Switches =>
1286 Lang_Index.Config.Binder_Required_Switches,
1287 From_List => Element.Value.Values,
1288 In_Tree => In_Tree);
1292 -- Attribute Prefix (<language>)
1294 Lang_Index.Config.Binder_Prefix :=
1295 Element.Value.Value;
1297 when Name_Objects_Path =>
1299 -- Attribute Objects_Path (<language>)
1301 Lang_Index.Config.Objects_Path :=
1302 Element.Value.Value;
1304 when Name_Objects_Path_File =>
1306 -- Attribute Objects_Path (<language>)
1308 Lang_Index.Config.Objects_Path_File :=
1309 Element.Value.Value;
1317 Element_Id := Element.Next;
1320 Current_Array_Id := Current_Array.Next;
1324 ---------------------
1325 -- Process_Builder --
1326 ---------------------
1328 procedure Process_Builder (Attributes : Variable_Id) is
1329 Attribute_Id : Variable_Id;
1330 Attribute : Variable;
1333 -- Process non associated array attribute from package Builder
1335 Attribute_Id := Attributes;
1336 while Attribute_Id /= No_Variable loop
1338 In_Tree.Variable_Elements.Table (Attribute_Id);
1340 if not Attribute.Value.Default then
1341 if Attribute.Name = Name_Executable_Suffix then
1343 -- Attribute Executable_Suffix: the suffix of the
1346 Data.Config.Executable_Suffix :=
1347 Attribute.Value.Value;
1351 Attribute_Id := Attribute.Next;
1353 end Process_Builder;
1355 ----------------------
1356 -- Process_Compiler --
1357 ----------------------
1359 procedure Process_Compiler (Arrays : Array_Id) is
1360 Current_Array_Id : Array_Id;
1361 Current_Array : Array_Data;
1362 Element_Id : Array_Element_Id;
1363 Element : Array_Element;
1364 List : String_List_Id;
1367 -- Process the associative array attribute of package Compiler
1369 Current_Array_Id := Arrays;
1370 while Current_Array_Id /= No_Array loop
1371 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1373 Element_Id := Current_Array.Value;
1374 while Element_Id /= No_Array_Element loop
1375 Element := In_Tree.Array_Elements.Table (Element_Id);
1377 if Element.Index /= All_Other_Names then
1379 -- Get the name of the language
1381 Get_Language_Index_Of (Element.Index);
1383 if Lang_Index /= No_Language_Index then
1384 case Current_Array.Name is
1385 when Name_Dependency_Switches =>
1387 -- Attribute Dependency_Switches (<language>)
1389 if Lang_Index.Config.Dependency_Kind = None then
1390 Lang_Index.Config.Dependency_Kind := Makefile;
1393 List := Element.Value.Values;
1395 if List /= Nil_String then
1397 Lang_Index.Config.Dependency_Option,
1399 In_Tree => In_Tree);
1402 when Name_Dependency_Driver =>
1404 -- Attribute Dependency_Driver (<language>)
1406 if Lang_Index.Config.Dependency_Kind = None then
1407 Lang_Index.Config.Dependency_Kind := Makefile;
1410 List := Element.Value.Values;
1412 if List /= Nil_String then
1414 Lang_Index.Config.Compute_Dependency,
1416 In_Tree => In_Tree);
1419 when Name_Include_Switches =>
1421 -- Attribute Include_Switches (<language>)
1423 List := Element.Value.Values;
1425 if List = Nil_String then
1429 "include option cannot be null",
1430 Element.Value.Location);
1434 Lang_Index.Config.Include_Option,
1436 In_Tree => In_Tree);
1438 when Name_Include_Path =>
1440 -- Attribute Include_Path (<language>)
1442 Lang_Index.Config.Include_Path :=
1443 Element.Value.Value;
1445 when Name_Include_Path_File =>
1447 -- Attribute Include_Path_File (<language>)
1449 Lang_Index.Config.Include_Path_File :=
1450 Element.Value.Value;
1454 -- Attribute Driver (<language>)
1456 Get_Name_String (Element.Value.Value);
1458 Lang_Index.Config.Compiler_Driver :=
1459 File_Name_Type (Element.Value.Value);
1461 when Name_Required_Switches =>
1463 Lang_Index.Config.Compiler_Required_Switches,
1464 From_List => Element.Value.Values,
1465 In_Tree => In_Tree);
1467 when Name_Path_Syntax =>
1469 Lang_Index.Config.Path_Syntax :=
1470 Path_Syntax_Kind'Value
1471 (Get_Name_String (Element.Value.Value));
1474 when Constraint_Error =>
1478 "invalid value for Path_Syntax",
1479 Element.Value.Location);
1482 when Name_Object_File_Suffix =>
1483 if Get_Name_String (Element.Value.Value) = "" then
1486 "object file suffix cannot be empty",
1487 Element.Value.Location);
1490 Lang_Index.Config.Object_File_Suffix :=
1491 Element.Value.Value;
1494 when Name_Pic_Option =>
1496 -- Attribute Compiler_Pic_Option (<language>)
1498 List := Element.Value.Values;
1500 if List = Nil_String then
1504 "compiler PIC option cannot be null",
1505 Element.Value.Location);
1509 Lang_Index.Config.Compilation_PIC_Option,
1511 In_Tree => In_Tree);
1513 when Name_Mapping_File_Switches =>
1515 -- Attribute Mapping_File_Switches (<language>)
1517 List := Element.Value.Values;
1519 if List = Nil_String then
1523 "mapping file switches cannot be null",
1524 Element.Value.Location);
1528 Lang_Index.Config.Mapping_File_Switches,
1530 In_Tree => In_Tree);
1532 when Name_Mapping_Spec_Suffix =>
1534 -- Attribute Mapping_Spec_Suffix (<language>)
1536 Lang_Index.Config.Mapping_Spec_Suffix :=
1537 File_Name_Type (Element.Value.Value);
1539 when Name_Mapping_Body_Suffix =>
1541 -- Attribute Mapping_Body_Suffix (<language>)
1543 Lang_Index.Config.Mapping_Body_Suffix :=
1544 File_Name_Type (Element.Value.Value);
1546 when Name_Config_File_Switches =>
1548 -- Attribute Config_File_Switches (<language>)
1550 List := Element.Value.Values;
1552 if List = Nil_String then
1556 "config file switches cannot be null",
1557 Element.Value.Location);
1561 Lang_Index.Config.Config_File_Switches,
1563 In_Tree => In_Tree);
1565 when Name_Objects_Path =>
1567 -- Attribute Objects_Path (<language>)
1569 Lang_Index.Config.Objects_Path :=
1570 Element.Value.Value;
1572 when Name_Objects_Path_File =>
1574 -- Attribute Objects_Path_File (<language>)
1576 Lang_Index.Config.Objects_Path_File :=
1577 Element.Value.Value;
1579 when Name_Config_Body_File_Name =>
1581 -- Attribute Config_Body_File_Name (<language>)
1583 Lang_Index.Config.Config_Body :=
1584 Element.Value.Value;
1586 when Name_Config_Body_File_Name_Pattern =>
1588 -- Attribute Config_Body_File_Name_Pattern
1591 Lang_Index.Config.Config_Body_Pattern :=
1592 Element.Value.Value;
1594 when Name_Config_Spec_File_Name =>
1596 -- Attribute Config_Spec_File_Name (<language>)
1598 Lang_Index.Config.Config_Spec :=
1599 Element.Value.Value;
1601 when Name_Config_Spec_File_Name_Pattern =>
1603 -- Attribute Config_Spec_File_Name_Pattern
1606 Lang_Index.Config.Config_Spec_Pattern :=
1607 Element.Value.Value;
1609 when Name_Config_File_Unique =>
1611 -- Attribute Config_File_Unique (<language>)
1614 Lang_Index.Config.Config_File_Unique :=
1616 (Get_Name_String (Element.Value.Value));
1618 when Constraint_Error =>
1622 "illegal value for Config_File_Unique",
1623 Element.Value.Location);
1632 Element_Id := Element.Next;
1635 Current_Array_Id := Current_Array.Next;
1637 end Process_Compiler;
1639 --------------------
1640 -- Process_Naming --
1641 --------------------
1643 procedure Process_Naming (Attributes : Variable_Id) is
1644 Attribute_Id : Variable_Id;
1645 Attribute : Variable;
1648 -- Process non associated array attribute from package Naming
1650 Attribute_Id := Attributes;
1651 while Attribute_Id /= No_Variable loop
1652 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1654 if not Attribute.Value.Default then
1655 if Attribute.Name = Name_Separate_Suffix then
1657 -- Attribute Separate_Suffix
1659 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1661 elsif Attribute.Name = Name_Casing then
1667 Value (Get_Name_String (Attribute.Value.Value));
1670 when Constraint_Error =>
1674 "invalid value for Casing",
1675 Attribute.Value.Location);
1678 elsif Attribute.Name = Name_Dot_Replacement then
1680 -- Attribute Dot_Replacement
1682 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1687 Attribute_Id := Attribute.Next;
1691 procedure Process_Naming (Arrays : Array_Id) is
1692 Current_Array_Id : Array_Id;
1693 Current_Array : Array_Data;
1694 Element_Id : Array_Element_Id;
1695 Element : Array_Element;
1697 -- Process the associative array attribute of package Naming
1699 Current_Array_Id := Arrays;
1700 while Current_Array_Id /= No_Array loop
1701 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1703 Element_Id := Current_Array.Value;
1704 while Element_Id /= No_Array_Element loop
1705 Element := In_Tree.Array_Elements.Table (Element_Id);
1707 -- Get the name of the language
1709 Get_Language_Index_Of (Element.Index);
1711 if Lang_Index /= No_Language_Index then
1712 case Current_Array.Name is
1713 when Name_Specification_Suffix | Name_Spec_Suffix =>
1715 -- Attribute Spec_Suffix (<language>)
1717 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1718 File_Name_Type (Element.Value.Value);
1720 when Name_Implementation_Suffix | Name_Body_Suffix =>
1722 -- Attribute Body_Suffix (<language>)
1724 Lang_Index.Config.Naming_Data.Body_Suffix :=
1725 File_Name_Type (Element.Value.Value);
1727 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1728 File_Name_Type (Element.Value.Value);
1735 Element_Id := Element.Next;
1738 Current_Array_Id := Current_Array.Next;
1742 --------------------
1743 -- Process_Linker --
1744 --------------------
1746 procedure Process_Linker (Attributes : Variable_Id) is
1747 Attribute_Id : Variable_Id;
1748 Attribute : Variable;
1751 -- Process non associated array attribute from package Linker
1753 Attribute_Id := Attributes;
1754 while Attribute_Id /= No_Variable loop
1756 In_Tree.Variable_Elements.Table (Attribute_Id);
1758 if not Attribute.Value.Default then
1759 if Attribute.Name = Name_Driver then
1761 -- Attribute Linker'Driver: the default linker to use
1763 Data.Config.Linker :=
1764 Path_Name_Type (Attribute.Value.Value);
1766 -- Linker'Driver is also used to link shared libraries
1767 -- if the obsolescent attribute Library_GCC has not been
1770 if Data.Config.Shared_Lib_Driver = No_File then
1771 Data.Config.Shared_Lib_Driver :=
1772 File_Name_Type (Attribute.Value.Value);
1775 elsif Attribute.Name = Name_Required_Switches then
1777 -- Attribute Required_Switches: the minimum
1778 -- options to use when invoking the linker
1781 Data.Config.Minimum_Linker_Options,
1782 From_List => Attribute.Value.Values,
1783 In_Tree => In_Tree);
1785 elsif Attribute.Name = Name_Map_File_Option then
1786 Data.Config.Map_File_Option := Attribute.Value.Value;
1788 elsif Attribute.Name = Name_Max_Command_Line_Length then
1790 Data.Config.Max_Command_Line_Length :=
1791 Natural'Value (Get_Name_String
1792 (Attribute.Value.Value));
1795 when Constraint_Error =>
1799 "value must be positive or equal to 0",
1800 Attribute.Value.Location);
1803 elsif Attribute.Name = Name_Response_File_Format then
1808 Get_Name_String (Attribute.Value.Value);
1809 To_Lower (Name_Buffer (1 .. Name_Len));
1812 if Name = Name_None then
1813 Data.Config.Resp_File_Format := None;
1815 elsif Name = Name_Gnu then
1816 Data.Config.Resp_File_Format := GNU;
1818 elsif Name = Name_Object_List then
1819 Data.Config.Resp_File_Format := Object_List;
1821 elsif Name = Name_Option_List then
1822 Data.Config.Resp_File_Format := Option_List;
1828 "illegal response file format",
1829 Attribute.Value.Location);
1833 elsif Attribute.Name = Name_Response_File_Switches then
1835 Data.Config.Resp_File_Options,
1836 From_List => Attribute.Value.Values,
1837 In_Tree => In_Tree);
1841 Attribute_Id := Attribute.Next;
1845 -- Start of processing for Process_Packages
1848 Packages := Data.Decl.Packages;
1849 while Packages /= No_Package loop
1850 Element := In_Tree.Packages.Table (Packages);
1852 case Element.Name is
1855 -- Process attributes of package Binder
1857 Process_Binder (Element.Decl.Arrays);
1859 when Name_Builder =>
1861 -- Process attributes of package Builder
1863 Process_Builder (Element.Decl.Attributes);
1865 when Name_Compiler =>
1867 -- Process attributes of package Compiler
1869 Process_Compiler (Element.Decl.Arrays);
1873 -- Process attributes of package Linker
1875 Process_Linker (Element.Decl.Attributes);
1879 -- Process attributes of package Naming
1881 Process_Naming (Element.Decl.Attributes);
1882 Process_Naming (Element.Decl.Arrays);
1888 Packages := Element.Next;
1890 end Process_Packages;
1892 ---------------------------------------------
1893 -- Process_Project_Level_Simple_Attributes --
1894 ---------------------------------------------
1896 procedure Process_Project_Level_Simple_Attributes is
1897 Attribute_Id : Variable_Id;
1898 Attribute : Variable;
1899 List : String_List_Id;
1902 -- Process non associated array attribute at project level
1904 Attribute_Id := Data.Decl.Attributes;
1905 while Attribute_Id /= No_Variable loop
1907 In_Tree.Variable_Elements.Table (Attribute_Id);
1909 if not Attribute.Value.Default then
1910 if Attribute.Name = Name_Target then
1912 -- Attribute Target: the target specified
1914 Data.Config.Target := Attribute.Value.Value;
1916 elsif Attribute.Name = Name_Library_Builder then
1918 -- Attribute Library_Builder: the application to invoke
1919 -- to build libraries.
1921 Data.Config.Library_Builder :=
1922 Path_Name_Type (Attribute.Value.Value);
1924 elsif Attribute.Name = Name_Archive_Builder then
1926 -- Attribute Archive_Builder: the archive builder
1927 -- (usually "ar") and its minimum options (usually "cr").
1929 List := Attribute.Value.Values;
1931 if List = Nil_String then
1935 "archive builder cannot be null",
1936 Attribute.Value.Location);
1939 Put (Into_List => Data.Config.Archive_Builder,
1941 In_Tree => In_Tree);
1943 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1945 -- Attribute Archive_Builder: the archive builder
1946 -- (usually "ar") and its minimum options (usually "cr").
1948 List := Attribute.Value.Values;
1950 if List /= Nil_String then
1952 (Into_List => Data.Config.Archive_Builder_Append_Option,
1954 In_Tree => In_Tree);
1957 elsif Attribute.Name = Name_Archive_Indexer then
1959 -- Attribute Archive_Indexer: the optional archive
1960 -- indexer (usually "ranlib") with its minimum options
1963 List := Attribute.Value.Values;
1965 if List = Nil_String then
1969 "archive indexer cannot be null",
1970 Attribute.Value.Location);
1973 Put (Into_List => Data.Config.Archive_Indexer,
1975 In_Tree => In_Tree);
1977 elsif Attribute.Name = Name_Library_Partial_Linker then
1979 -- Attribute Library_Partial_Linker: the optional linker
1980 -- driver with its minimum options, to partially link
1983 List := Attribute.Value.Values;
1985 if List = Nil_String then
1989 "partial linker cannot be null",
1990 Attribute.Value.Location);
1993 Put (Into_List => Data.Config.Lib_Partial_Linker,
1995 In_Tree => In_Tree);
1997 elsif Attribute.Name = Name_Library_GCC then
1998 Data.Config.Shared_Lib_Driver :=
1999 File_Name_Type (Attribute.Value.Value);
2003 "?Library_'G'C'C is an obsolescent attribute, " &
2004 "use Linker''Driver instead",
2005 Attribute.Value.Location);
2007 elsif Attribute.Name = Name_Archive_Suffix then
2008 Data.Config.Archive_Suffix :=
2009 File_Name_Type (Attribute.Value.Value);
2011 elsif Attribute.Name = Name_Linker_Executable_Option then
2013 -- Attribute Linker_Executable_Option: optional options
2014 -- to specify an executable name. Defaults to "-o".
2016 List := Attribute.Value.Values;
2018 if List = Nil_String then
2022 "linker executable option cannot be null",
2023 Attribute.Value.Location);
2026 Put (Into_List => Data.Config.Linker_Executable_Option,
2028 In_Tree => In_Tree);
2030 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2032 -- Attribute Linker_Lib_Dir_Option: optional options
2033 -- to specify a library search directory. Defaults to
2036 Get_Name_String (Attribute.Value.Value);
2038 if Name_Len = 0 then
2042 "linker library directory option cannot be empty",
2043 Attribute.Value.Location);
2046 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2048 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2050 -- Attribute Linker_Lib_Name_Option: optional options
2051 -- to specify the name of a library to be linked in.
2052 -- Defaults to "-l".
2054 Get_Name_String (Attribute.Value.Value);
2056 if Name_Len = 0 then
2060 "linker library name option cannot be empty",
2061 Attribute.Value.Location);
2064 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2066 elsif Attribute.Name = Name_Run_Path_Option then
2068 -- Attribute Run_Path_Option: optional options to
2069 -- specify a path for libraries.
2071 List := Attribute.Value.Values;
2073 if List /= Nil_String then
2074 Put (Into_List => Data.Config.Run_Path_Option,
2076 In_Tree => In_Tree);
2079 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2081 pragma Unsuppress (All_Checks);
2083 Data.Config.Separate_Run_Path_Options :=
2084 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2086 when Constraint_Error =>
2090 "invalid value """ &
2091 Get_Name_String (Attribute.Value.Value) &
2092 """ for Separate_Run_Path_Options",
2093 Attribute.Value.Location);
2096 elsif Attribute.Name = Name_Library_Support then
2098 pragma Unsuppress (All_Checks);
2100 Data.Config.Lib_Support :=
2101 Library_Support'Value (Get_Name_String
2102 (Attribute.Value.Value));
2104 when Constraint_Error =>
2108 "invalid value """ &
2109 Get_Name_String (Attribute.Value.Value) &
2110 """ for Library_Support",
2111 Attribute.Value.Location);
2114 elsif Attribute.Name = Name_Shared_Library_Prefix then
2115 Data.Config.Shared_Lib_Prefix :=
2116 File_Name_Type (Attribute.Value.Value);
2118 elsif Attribute.Name = Name_Shared_Library_Suffix then
2119 Data.Config.Shared_Lib_Suffix :=
2120 File_Name_Type (Attribute.Value.Value);
2122 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2124 pragma Unsuppress (All_Checks);
2126 Data.Config.Symbolic_Link_Supported :=
2127 Boolean'Value (Get_Name_String
2128 (Attribute.Value.Value));
2130 when Constraint_Error =>
2135 & Get_Name_String (Attribute.Value.Value)
2136 & """ for Symbolic_Link_Supported",
2137 Attribute.Value.Location);
2141 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2144 pragma Unsuppress (All_Checks);
2146 Data.Config.Lib_Maj_Min_Id_Supported :=
2147 Boolean'Value (Get_Name_String
2148 (Attribute.Value.Value));
2150 when Constraint_Error =>
2154 "invalid value """ &
2155 Get_Name_String (Attribute.Value.Value) &
2156 """ for Library_Major_Minor_Id_Supported",
2157 Attribute.Value.Location);
2160 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2162 pragma Unsuppress (All_Checks);
2164 Data.Config.Auto_Init_Supported :=
2165 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2167 when Constraint_Error =>
2172 & Get_Name_String (Attribute.Value.Value)
2173 & """ for Library_Auto_Init_Supported",
2174 Attribute.Value.Location);
2177 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2178 List := Attribute.Value.Values;
2180 if List /= Nil_String then
2181 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2183 In_Tree => In_Tree);
2186 elsif Attribute.Name = Name_Library_Version_Switches then
2187 List := Attribute.Value.Values;
2189 if List /= Nil_String then
2190 Put (Into_List => Data.Config.Lib_Version_Options,
2192 In_Tree => In_Tree);
2197 Attribute_Id := Attribute.Next;
2199 end Process_Project_Level_Simple_Attributes;
2201 --------------------------------------------
2202 -- Process_Project_Level_Array_Attributes --
2203 --------------------------------------------
2205 procedure Process_Project_Level_Array_Attributes is
2206 Current_Array_Id : Array_Id;
2207 Current_Array : Array_Data;
2208 Element_Id : Array_Element_Id;
2209 Element : Array_Element;
2210 List : String_List_Id;
2213 -- Process the associative array attributes at project level
2215 Current_Array_Id := Data.Decl.Arrays;
2216 while Current_Array_Id /= No_Array loop
2217 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2219 Element_Id := Current_Array.Value;
2220 while Element_Id /= No_Array_Element loop
2221 Element := In_Tree.Array_Elements.Table (Element_Id);
2223 -- Get the name of the language
2225 Get_Language_Index_Of (Element.Index);
2227 if Lang_Index /= No_Language_Index then
2228 case Current_Array.Name is
2229 when Name_Inherit_Source_Path =>
2230 List := Element.Value.Values;
2232 if List /= Nil_String then
2235 Lang_Index.Config.Include_Compatible_Languages,
2238 Lower_Case => True);
2241 when Name_Toolchain_Description =>
2243 -- Attribute Toolchain_Description (<language>)
2245 Lang_Index.Config.Toolchain_Description :=
2246 Element.Value.Value;
2248 when Name_Toolchain_Version =>
2250 -- Attribute Toolchain_Version (<language>)
2252 Lang_Index.Config.Toolchain_Version :=
2253 Element.Value.Value;
2255 when Name_Runtime_Library_Dir =>
2257 -- Attribute Runtime_Library_Dir (<language>)
2259 Lang_Index.Config.Runtime_Library_Dir :=
2260 Element.Value.Value;
2262 when Name_Runtime_Source_Dir =>
2264 -- Attribute Runtime_Library_Dir (<language>)
2266 Lang_Index.Config.Runtime_Source_Dir :=
2267 Element.Value.Value;
2269 when Name_Object_Generated =>
2271 pragma Unsuppress (All_Checks);
2277 (Get_Name_String (Element.Value.Value));
2279 Lang_Index.Config.Object_Generated := Value;
2281 -- If no object is generated, no object may be
2285 Lang_Index.Config.Objects_Linked := False;
2289 when Constraint_Error =>
2294 & Get_Name_String (Element.Value.Value)
2295 & """ for Object_Generated",
2296 Element.Value.Location);
2299 when Name_Objects_Linked =>
2301 pragma Unsuppress (All_Checks);
2307 (Get_Name_String (Element.Value.Value));
2309 -- No change if Object_Generated is False, as this
2310 -- forces Objects_Linked to be False too.
2312 if Lang_Index.Config.Object_Generated then
2313 Lang_Index.Config.Objects_Linked := Value;
2317 when Constraint_Error =>
2322 & Get_Name_String (Element.Value.Value)
2323 & """ for Objects_Linked",
2324 Element.Value.Location);
2331 Element_Id := Element.Next;
2334 Current_Array_Id := Current_Array.Next;
2336 end Process_Project_Level_Array_Attributes;
2339 Process_Project_Level_Simple_Attributes;
2340 Process_Project_Level_Array_Attributes;
2343 -- For unit based languages, set Casing, Dot_Replacement and
2344 -- Separate_Suffix in Naming_Data.
2346 Lang_Index := Data.Languages;
2347 while Lang_Index /= No_Language_Index loop
2348 if Lang_Index.Name = Name_Ada then
2349 Lang_Index.Config.Naming_Data.Casing := Casing;
2350 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2352 if Separate_Suffix /= No_File then
2353 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2360 Lang_Index := Lang_Index.Next;
2363 -- Give empty names to various prefixes/suffixes, if they have not
2364 -- been specified in the configuration.
2366 if Data.Config.Archive_Suffix = No_File then
2367 Data.Config.Archive_Suffix := Empty_File;
2370 if Data.Config.Shared_Lib_Prefix = No_File then
2371 Data.Config.Shared_Lib_Prefix := Empty_File;
2374 if Data.Config.Shared_Lib_Suffix = No_File then
2375 Data.Config.Shared_Lib_Suffix := Empty_File;
2378 Lang_Index := Data.Languages;
2379 while Lang_Index /= No_Language_Index loop
2380 Current_Language := Lang_Index.Display_Name;
2382 -- For all languages, Compiler_Driver needs to be specified
2384 if Lang_Index.Config.Compiler_Driver = No_File then
2385 Error_Msg_Name_1 := Current_Language;
2389 "?no compiler specified for language %%" &
2390 ", ignoring all its sources",
2393 if Lang_Index = Data.Languages then
2394 Data.Languages := Lang_Index.Next;
2396 Prev_Index.Next := Lang_Index.Next;
2399 elsif Lang_Index.Name = Name_Ada then
2400 Prev_Index := Lang_Index;
2402 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2403 -- Body_Suffix need to be specified.
2405 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2409 "Dot_Replacement not specified for Ada",
2413 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2417 "Spec_Suffix not specified for Ada",
2421 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2425 "Body_Suffix not specified for Ada",
2430 Prev_Index := Lang_Index;
2432 -- For file based languages, either Spec_Suffix or Body_Suffix
2433 -- need to be specified.
2435 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2436 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2438 Error_Msg_Name_1 := Current_Language;
2442 "no suffixes specified for %%",
2447 Lang_Index := Lang_Index.Next;
2449 end Check_Configuration;
2451 -------------------------------
2452 -- Check_If_Externally_Built --
2453 -------------------------------
2455 procedure Check_If_Externally_Built
2456 (Project : Project_Id;
2457 In_Tree : Project_Tree_Ref;
2458 Data : in out Project_Data)
2460 Externally_Built : constant Variable_Value :=
2462 (Name_Externally_Built,
2463 Data.Decl.Attributes, In_Tree);
2466 if not Externally_Built.Default then
2467 Get_Name_String (Externally_Built.Value);
2468 To_Lower (Name_Buffer (1 .. Name_Len));
2470 if Name_Buffer (1 .. Name_Len) = "true" then
2471 Data.Externally_Built := True;
2473 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2474 Error_Msg (Project, In_Tree,
2475 "Externally_Built may only be true or false",
2476 Externally_Built.Location);
2480 -- A virtual project extending an externally built project is itself
2481 -- externally built.
2483 if Data.Virtual and then Data.Extends /= No_Project then
2484 Data.Externally_Built :=
2485 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2488 if Current_Verbosity = High then
2489 Write_Str ("Project is ");
2491 if not Data.Externally_Built then
2495 Write_Line ("externally built.");
2497 end Check_If_Externally_Built;
2499 ----------------------
2500 -- Check_Interfaces --
2501 ----------------------
2503 procedure Check_Interfaces
2504 (Project : Project_Id;
2505 In_Tree : Project_Tree_Ref;
2506 Data : in out Project_Data)
2508 Interfaces : constant Prj.Variable_Value :=
2510 (Snames.Name_Interfaces,
2511 Data.Decl.Attributes,
2514 List : String_List_Id;
2515 Element : String_Element;
2516 Name : File_Name_Type;
2517 Iter : Source_Iterator;
2519 Project_2 : Project_Id;
2522 if not Interfaces.Default then
2524 -- Set In_Interfaces to False for all sources. It will be set to True
2525 -- later for the sources in the Interfaces list.
2527 Project_2 := Project;
2528 while Project_2 /= No_Project loop
2529 Iter := For_Each_Source (In_Tree, Project_2);
2532 Source := Prj.Element (Iter);
2533 exit when Source = No_Source;
2534 Source.In_Interfaces := False;
2538 Project_2 := In_Tree.Projects.Table (Project_2).Extends;
2541 List := Interfaces.Values;
2542 while List /= Nil_String loop
2543 Element := In_Tree.String_Elements.Table (List);
2544 Name := Canonical_Case_File_Name (Element.Value);
2546 Project_2 := Project;
2548 while Project_2 /= No_Project loop
2549 Iter := For_Each_Source (In_Tree, Project_2);
2552 Source := Prj.Element (Iter);
2553 exit when Source = No_Source;
2555 if Source.File = Name then
2556 if not Source.Locally_Removed then
2557 Source.In_Interfaces := True;
2558 Source.Declared_In_Interfaces := True;
2560 if Source.Other_Part /= No_Source then
2561 Source.Other_Part.In_Interfaces := True;
2562 Source.Other_Part.Declared_In_Interfaces := True;
2565 if Current_Verbosity = High then
2566 Write_Str (" interface: ");
2567 Write_Line (Get_Name_String (Source.Path.Name));
2577 Project_2 := In_Tree.Projects.Table (Project_2).Extends;
2580 if Source = No_Source then
2581 Error_Msg_File_1 := File_Name_Type (Element.Value);
2582 Error_Msg_Name_1 := Data.Name;
2587 "{ cannot be an interface of project %% "
2588 & "as it is not one of its sources",
2592 List := Element.Next;
2595 Data.Interfaces_Defined := True;
2597 elsif Data.Extends /= No_Project then
2598 Data.Interfaces_Defined :=
2599 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2601 if Data.Interfaces_Defined then
2602 Iter := For_Each_Source (In_Tree, Project);
2604 Source := Prj.Element (Iter);
2605 exit when Source = No_Source;
2607 if not Source.Declared_In_Interfaces then
2608 Source.In_Interfaces := False;
2615 end Check_Interfaces;
2617 ------------------------------------
2618 -- Check_And_Normalize_Unit_Names --
2619 ------------------------------------
2621 procedure Check_And_Normalize_Unit_Names
2622 (Project : Project_Id;
2623 In_Tree : Project_Tree_Ref;
2624 List : Array_Element_Id;
2625 Debug_Name : String)
2627 Current : Array_Element_Id;
2628 Element : Array_Element;
2629 Unit_Name : Name_Id;
2632 if Current_Verbosity = High then
2633 Write_Line (" Checking unit names in " & Debug_Name);
2637 while Current /= No_Array_Element loop
2638 Element := In_Tree.Array_Elements.Table (Current);
2639 Element.Value.Value :=
2640 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2642 -- Check that it contains a valid unit name
2644 Get_Name_String (Element.Index);
2645 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2647 if Unit_Name = No_Name then
2648 Err_Vars.Error_Msg_Name_1 := Element.Index;
2651 "%% is not a valid unit name.",
2652 Element.Value.Location);
2655 if Current_Verbosity = High then
2656 Write_Str (" for unit: ");
2657 Write_Line (Get_Name_String (Unit_Name));
2660 Element.Index := Unit_Name;
2661 In_Tree.Array_Elements.Table (Current) := Element;
2664 Current := Element.Next;
2666 end Check_And_Normalize_Unit_Names;
2668 --------------------------
2669 -- Check_Naming_Schemes --
2670 --------------------------
2672 procedure Check_Naming_Schemes
2673 (Data : in out Project_Data;
2674 Project : Project_Id;
2675 In_Tree : Project_Tree_Ref)
2677 Naming_Id : constant Package_Id :=
2678 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2679 Naming : Package_Element;
2681 procedure Check_Naming_Ada_Only;
2682 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2683 -- If there is a package Naming, puts in Data.Naming the contents of
2686 procedure Check_Naming_Multi_Lang;
2687 -- Does Check_Naming_Schemes processing for Multi_Language mode
2689 procedure Check_Common
2690 (Dot_Replacement : in out File_Name_Type;
2691 Casing : in out Casing_Type;
2692 Casing_Defined : out Boolean;
2693 Separate_Suffix : in out File_Name_Type;
2694 Sep_Suffix_Loc : out Source_Ptr);
2695 -- Check attributes common to Ada_Only and Multi_Lang modes
2697 procedure Process_Exceptions_File_Based
2698 (Lang_Id : Language_Ptr;
2699 Kind : Source_Kind);
2700 procedure Process_Exceptions_Unit_Based
2701 (Lang_Id : Language_Ptr;
2702 Kind : Source_Kind);
2703 -- In Multi_Lang mode, process the naming exceptions for the two types
2704 -- of languages we can have.
2710 procedure Check_Common
2711 (Dot_Replacement : in out File_Name_Type;
2712 Casing : in out Casing_Type;
2713 Casing_Defined : out Boolean;
2714 Separate_Suffix : in out File_Name_Type;
2715 Sep_Suffix_Loc : out Source_Ptr)
2717 Dot_Repl : constant Variable_Value :=
2719 (Name_Dot_Replacement,
2720 Naming.Decl.Attributes,
2722 Casing_String : constant Variable_Value :=
2725 Naming.Decl.Attributes,
2727 Sep_Suffix : constant Variable_Value :=
2729 (Name_Separate_Suffix,
2730 Naming.Decl.Attributes,
2732 Dot_Repl_Loc : Source_Ptr;
2735 Sep_Suffix_Loc := No_Location;
2737 if not Dot_Repl.Default then
2739 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2741 if Length_Of_Name (Dot_Repl.Value) = 0 then
2744 "Dot_Replacement cannot be empty",
2748 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2749 Dot_Repl_Loc := Dot_Repl.Location;
2752 Repl : constant String := Get_Name_String (Dot_Replacement);
2755 -- Dot_Replacement cannot
2757 -- - start or end with an alphanumeric
2758 -- - be a single '_'
2759 -- - start with an '_' followed by an alphanumeric
2760 -- - contain a '.' except if it is "."
2763 or else Is_Alphanumeric (Repl (Repl'First))
2764 or else Is_Alphanumeric (Repl (Repl'Last))
2765 or else (Repl (Repl'First) = '_'
2769 Is_Alphanumeric (Repl (Repl'First + 1))))
2770 or else (Repl'Length > 1
2772 Index (Source => Repl, Pattern => ".") /= 0)
2777 """ is illegal for Dot_Replacement.",
2783 if Dot_Replacement /= No_File then
2785 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2788 Casing_Defined := False;
2790 if not Casing_String.Default then
2792 (Casing_String.Kind = Single, "Casing is not a string");
2795 Casing_Image : constant String :=
2796 Get_Name_String (Casing_String.Value);
2798 if Casing_Image'Length = 0 then
2801 "Casing cannot be an empty string",
2802 Casing_String.Location);
2805 Casing := Value (Casing_Image);
2806 Casing_Defined := True;
2809 when Constraint_Error =>
2810 Name_Len := Casing_Image'Length;
2811 Name_Buffer (1 .. Name_Len) := Casing_Image;
2812 Err_Vars.Error_Msg_Name_1 := Name_Find;
2815 "%% is not a correct Casing",
2816 Casing_String.Location);
2820 Write_Attr ("Casing", Image (Casing));
2822 if not Sep_Suffix.Default then
2823 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2826 "Separate_Suffix cannot be empty",
2827 Sep_Suffix.Location);
2830 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2831 Sep_Suffix_Loc := Sep_Suffix.Location;
2833 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2834 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2837 "{ is illegal for Separate_Suffix",
2838 Sep_Suffix.Location);
2843 if Separate_Suffix /= No_File then
2845 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2849 -----------------------------------
2850 -- Process_Exceptions_File_Based --
2851 -----------------------------------
2853 procedure Process_Exceptions_File_Based
2854 (Lang_Id : Language_Ptr;
2857 Lang : constant Name_Id := Lang_Id.Name;
2858 Exceptions : Array_Element_Id;
2859 Exception_List : Variable_Value;
2860 Element_Id : String_List_Id;
2861 Element : String_Element;
2862 File_Name : File_Name_Type;
2864 Iter : Source_Iterator;
2871 (Name_Implementation_Exceptions,
2872 In_Arrays => Naming.Decl.Arrays,
2873 In_Tree => In_Tree);
2878 (Name_Specification_Exceptions,
2879 In_Arrays => Naming.Decl.Arrays,
2880 In_Tree => In_Tree);
2883 Exception_List := Value_Of
2885 In_Array => Exceptions,
2886 In_Tree => In_Tree);
2888 if Exception_List /= Nil_Variable_Value then
2889 Element_Id := Exception_List.Values;
2890 while Element_Id /= Nil_String loop
2891 Element := In_Tree.String_Elements.Table (Element_Id);
2892 File_Name := Canonical_Case_File_Name (Element.Value);
2894 Iter := For_Each_Source (In_Tree, Project);
2896 Source := Prj.Element (Iter);
2897 exit when Source = No_Source or else Source.File = File_Name;
2901 if Source = No_Source then
2908 File_Name => File_Name,
2909 Display_File => File_Name_Type (Element.Value),
2910 Naming_Exception => True,
2911 Lang_Kind => File_Based);
2914 -- Check if the file name is already recorded for another
2915 -- language or another kind.
2917 if Source.Language /= Lang_Id then
2921 "the same file cannot be a source of two languages",
2924 elsif Source.Kind /= Kind then
2928 "the same file cannot be a source and a template",
2932 -- If the file is already recorded for the same
2933 -- language and the same kind, it means that the file
2934 -- name appears several times in the *_Exceptions
2935 -- attribute; so there is nothing to do.
2938 Element_Id := Element.Next;
2941 end Process_Exceptions_File_Based;
2943 -----------------------------------
2944 -- Process_Exceptions_Unit_Based --
2945 -----------------------------------
2947 procedure Process_Exceptions_Unit_Based
2948 (Lang_Id : Language_Ptr;
2951 Lang : constant Name_Id := Lang_Id.Name;
2952 Exceptions : Array_Element_Id;
2953 Element : Array_Element;
2956 File_Name : File_Name_Type;
2958 Source_To_Replace : Source_Id := No_Source;
2959 Other_Project : Project_Id;
2960 Other_Part : Source_Id := No_Source;
2961 Iter : Source_Iterator;
2966 Exceptions := Value_Of
2968 In_Arrays => Naming.Decl.Arrays,
2969 In_Tree => In_Tree);
2971 if Exceptions = No_Array_Element then
2974 (Name_Implementation,
2975 In_Arrays => Naming.Decl.Arrays,
2976 In_Tree => In_Tree);
2983 In_Arrays => Naming.Decl.Arrays,
2984 In_Tree => In_Tree);
2986 if Exceptions = No_Array_Element then
2987 Exceptions := Value_Of
2988 (Name_Specification,
2989 In_Arrays => Naming.Decl.Arrays,
2990 In_Tree => In_Tree);
2994 while Exceptions /= No_Array_Element loop
2995 Element := In_Tree.Array_Elements.Table (Exceptions);
2996 File_Name := Canonical_Case_File_Name (Element.Value.Value);
2998 Get_Name_String (Element.Index);
2999 To_Lower (Name_Buffer (1 .. Name_Len));
3001 Index := Element.Value.Index;
3003 -- For Ada, check if it is a valid unit name
3005 if Lang = Name_Ada then
3006 Get_Name_String (Element.Index);
3007 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3009 if Unit = No_Name then
3010 Err_Vars.Error_Msg_Name_1 := Element.Index;
3013 "%% is not a valid unit name.",
3014 Element.Value.Location);
3018 if Unit /= No_Name then
3020 -- Check if the source already exists
3022 Source_To_Replace := No_Source;
3023 Iter := For_Each_Source (In_Tree);
3026 Source := Prj.Element (Iter);
3027 exit when Source = No_Source
3028 or else (Source.Unit = Unit and then Source.Index = Index);
3032 if Source /= No_Source then
3033 if Source.Kind /= Kind then
3034 Other_Part := Source;
3038 Source := Prj.Element (Iter);
3040 exit when Source = No_Source or else
3041 (Source.Unit = Unit and then Source.Index = Index);
3045 if Source /= No_Source then
3046 Other_Project := Source.Project;
3048 if Is_Extending (Project, Other_Project, In_Tree) then
3049 Other_Part := Source.Other_Part;
3051 -- Record the source to be removed
3053 Source_To_Replace := Source;
3054 Source := No_Source;
3057 Error_Msg_Name_1 := Unit;
3059 In_Tree.Projects.Table (Other_Project).Name;
3063 "%% is already a source of project %%",
3064 Element.Value.Location);
3069 if Source = No_Source then
3076 File_Name => File_Name,
3077 Display_File => File_Name_Type (Element.Value.Value),
3078 Lang_Kind => Unit_Based,
3079 Other_Part => Other_Part,
3082 Naming_Exception => True,
3083 Source_To_Replace => Source_To_Replace);
3087 Exceptions := Element.Next;
3089 end Process_Exceptions_Unit_Based;
3091 ---------------------------
3092 -- Check_Naming_Ada_Only --
3093 ---------------------------
3095 procedure Check_Naming_Ada_Only is
3096 Casing_Defined : Boolean;
3097 Spec_Suffix : File_Name_Type;
3098 Body_Suffix : File_Name_Type;
3099 Sep_Suffix_Loc : Source_Ptr;
3101 Ada_Spec_Suffix : constant Variable_Value :=
3105 In_Array => Data.Naming.Spec_Suffix,
3106 In_Tree => In_Tree);
3108 Ada_Body_Suffix : constant Variable_Value :=
3112 In_Array => Data.Naming.Body_Suffix,
3113 In_Tree => In_Tree);
3116 -- The default value of separate suffix should be the same as the
3117 -- body suffix, so we need to compute that first.
3119 if Ada_Body_Suffix.Kind = Single
3120 and then Length_Of_Name (Ada_Body_Suffix.Value) /= 0
3122 Body_Suffix := Canonical_Case_File_Name (Ada_Body_Suffix.Value);
3123 Data.Naming.Separate_Suffix := Body_Suffix;
3124 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Body_Suffix);
3127 Body_Suffix := Default_Ada_Body_Suffix;
3128 Data.Naming.Separate_Suffix := Body_Suffix;
3129 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Body_Suffix);
3132 Write_Attr ("Body_Suffix", Get_Name_String (Body_Suffix));
3134 -- We'll need the dot replacement below, so compute it now
3137 (Dot_Replacement => Data.Naming.Dot_Replacement,
3138 Casing => Data.Naming.Casing,
3139 Casing_Defined => Casing_Defined,
3140 Separate_Suffix => Data.Naming.Separate_Suffix,
3141 Sep_Suffix_Loc => Sep_Suffix_Loc);
3143 Data.Naming.Bodies :=
3144 Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3146 if Data.Naming.Bodies /= No_Array_Element then
3147 Check_And_Normalize_Unit_Names
3148 (Project, In_Tree, Data.Naming.Bodies, "Naming.Bodies");
3151 Data.Naming.Specs :=
3152 Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3154 if Data.Naming.Specs /= No_Array_Element then
3155 Check_And_Normalize_Unit_Names
3156 (Project, In_Tree, Data.Naming.Specs, "Naming.Specs");
3159 -- Check Spec_Suffix
3161 if Ada_Spec_Suffix.Kind = Single
3162 and then Length_Of_Name (Ada_Spec_Suffix.Value) /= 0
3164 Spec_Suffix := Canonical_Case_File_Name (Ada_Spec_Suffix.Value);
3165 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Spec_Suffix);
3167 if Is_Illegal_Suffix
3168 (Spec_Suffix, Data.Naming.Dot_Replacement)
3170 Err_Vars.Error_Msg_File_1 := Spec_Suffix;
3173 "{ is illegal for Spec_Suffix",
3174 Ada_Spec_Suffix.Location);
3178 Spec_Suffix := Default_Ada_Spec_Suffix;
3179 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Spec_Suffix);
3182 Write_Attr ("Spec_Suffix", Get_Name_String (Spec_Suffix));
3184 -- Check Body_Suffix
3186 if Is_Illegal_Suffix (Body_Suffix, Data.Naming.Dot_Replacement) then
3187 Err_Vars.Error_Msg_File_1 := Body_Suffix;
3190 "{ is illegal for Body_Suffix",
3191 Ada_Body_Suffix.Location);
3194 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3195 -- since that would cause a clear ambiguity. Note that we do allow a
3196 -- Spec_Suffix to have the same termination as one of these, which
3197 -- causes a potential ambiguity, but we resolve that my matching the
3198 -- longest possible suffix.
3200 if Spec_Suffix = Body_Suffix then
3204 Get_Name_String (Body_Suffix) &
3205 """) cannot be the same as Spec_Suffix.",
3206 Ada_Body_Suffix.Location);
3209 if Body_Suffix /= Data.Naming.Separate_Suffix
3210 and then Spec_Suffix = Data.Naming.Separate_Suffix
3214 "Separate_Suffix (""" &
3215 Get_Name_String (Data.Naming.Separate_Suffix) &
3216 """) cannot be the same as Spec_Suffix.",
3219 end Check_Naming_Ada_Only;
3221 -----------------------------
3222 -- Check_Naming_Multi_Lang --
3223 -----------------------------
3225 procedure Check_Naming_Multi_Lang is
3226 Dot_Replacement : File_Name_Type := No_File;
3227 Separate_Suffix : File_Name_Type := No_File;
3228 Casing : Casing_Type := All_Lower_Case;
3229 Casing_Defined : Boolean;
3230 Lang_Id : Language_Ptr;
3231 Sep_Suffix_Loc : Source_Ptr;
3232 Suffix : Variable_Value;
3237 (Dot_Replacement => Dot_Replacement,
3239 Casing_Defined => Casing_Defined,
3240 Separate_Suffix => Separate_Suffix,
3241 Sep_Suffix_Loc => Sep_Suffix_Loc);
3243 -- For all unit based languages, if any, set the specified
3244 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3245 -- systematically overwrite, since the defaults come from the
3246 -- configuration file
3248 if Dot_Replacement /= No_File
3249 or else Casing_Defined
3250 or else Separate_Suffix /= No_File
3252 Lang_Id := Data.Languages;
3253 while Lang_Id /= No_Language_Index loop
3254 if Lang_Id.Config.Kind = Unit_Based then
3255 if Dot_Replacement /= No_File then
3256 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3260 if Casing_Defined then
3261 Lang_Id.Config.Naming_Data.Casing := Casing;
3264 if Separate_Suffix /= No_File then
3265 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3270 Lang_Id := Lang_Id.Next;
3274 -- Next, get the spec and body suffixes
3276 Lang_Id := Data.Languages;
3277 while Lang_Id /= No_Language_Index loop
3278 Lang := Lang_Id.Name;
3284 Attribute_Or_Array_Name => Name_Spec_Suffix,
3285 In_Package => Naming_Id,
3286 In_Tree => In_Tree);
3288 if Suffix = Nil_Variable_Value then
3291 Attribute_Or_Array_Name => Name_Specification_Suffix,
3292 In_Package => Naming_Id,
3293 In_Tree => In_Tree);
3296 if Suffix /= Nil_Variable_Value then
3297 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3298 File_Name_Type (Suffix.Value);
3305 Attribute_Or_Array_Name => Name_Body_Suffix,
3306 In_Package => Naming_Id,
3307 In_Tree => In_Tree);
3309 if Suffix = Nil_Variable_Value then
3312 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3313 In_Package => Naming_Id,
3314 In_Tree => In_Tree);
3317 if Suffix /= Nil_Variable_Value then
3318 Lang_Id.Config.Naming_Data.Body_Suffix :=
3319 File_Name_Type (Suffix.Value);
3322 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3323 -- we do not check whether spec_suffix=body_suffix, which
3324 -- should be illegal. Best would be to share this code into
3325 -- Check_Common, but we access the attributes from the project
3326 -- files slightly differently apparently.
3328 Lang_Id := Lang_Id.Next;
3331 -- Get the naming exceptions for all languages
3333 for Kind in Spec .. Impl loop
3334 Lang_Id := Data.Languages;
3335 while Lang_Id /= No_Language_Index loop
3336 case Lang_Id.Config.Kind is
3338 Process_Exceptions_File_Based (Lang_Id, Kind);
3341 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3344 Lang_Id := Lang_Id.Next;
3347 end Check_Naming_Multi_Lang;
3349 -- Start of processing for Check_Naming_Schemes
3352 -- No Naming package or parsing a configuration file? nothing to do
3354 if Naming_Id /= No_Package and not In_Configuration then
3355 Naming := In_Tree.Packages.Table (Naming_Id);
3357 if Current_Verbosity = High then
3358 Write_Line ("Checking package Naming.");
3363 Check_Naming_Ada_Only;
3364 when Multi_Language =>
3365 Check_Naming_Multi_Lang;
3368 end Check_Naming_Schemes;
3370 ------------------------------
3371 -- Check_Library_Attributes --
3372 ------------------------------
3374 procedure Check_Library_Attributes
3375 (Project : Project_Id;
3376 In_Tree : Project_Tree_Ref;
3377 Current_Dir : String;
3378 Data : in out Project_Data)
3380 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3382 Lib_Dir : constant Prj.Variable_Value :=
3384 (Snames.Name_Library_Dir, Attributes, In_Tree);
3386 Lib_Name : constant Prj.Variable_Value :=
3388 (Snames.Name_Library_Name, Attributes, In_Tree);
3390 Lib_Version : constant Prj.Variable_Value :=
3392 (Snames.Name_Library_Version, Attributes, In_Tree);
3394 Lib_ALI_Dir : constant Prj.Variable_Value :=
3396 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3398 Lib_GCC : constant Prj.Variable_Value :=
3400 (Snames.Name_Library_GCC, Attributes, In_Tree);
3402 The_Lib_Kind : constant Prj.Variable_Value :=
3404 (Snames.Name_Library_Kind, Attributes, In_Tree);
3406 Imported_Project_List : Project_List := Empty_Project_List;
3408 Continuation : String_Access := No_Continuation_String'Access;
3410 Support_For_Libraries : Library_Support;
3412 Library_Directory_Present : Boolean;
3414 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3415 -- Check if an imported or extended project if also a library project
3421 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3422 Proj_Data : Project_Data;
3424 Iter : Source_Iterator;
3427 if Proj /= No_Project then
3428 Proj_Data := In_Tree.Projects.Table (Proj);
3430 if not Proj_Data.Library then
3432 -- The only not library projects that are OK are those that
3433 -- have no sources. However, header files from non-Ada
3434 -- languages are OK, as there is nothing to compile.
3436 Iter := For_Each_Source (In_Tree, Proj);
3438 Src_Id := Prj.Element (Iter);
3439 exit when Src_Id = No_Source
3440 or else Src_Id.Lang_Kind /= File_Based
3441 or else Src_Id.Kind /= Spec;
3445 if Src_Id /= No_Source then
3446 Error_Msg_Name_1 := Data.Name;
3447 Error_Msg_Name_2 := Proj_Data.Name;
3450 if Data.Library_Kind /= Static then
3454 "shared library project %% cannot extend " &
3455 "project %% that is not a library project",
3457 Continuation := Continuation_String'Access;
3460 elsif (not Unchecked_Shared_Lib_Imports)
3461 and then Data.Library_Kind /= Static
3466 "shared library project %% cannot import project %% " &
3467 "that is not a shared library project",
3469 Continuation := Continuation_String'Access;
3473 elsif Data.Library_Kind /= Static and then
3474 Proj_Data.Library_Kind = Static
3476 Error_Msg_Name_1 := Data.Name;
3477 Error_Msg_Name_2 := Proj_Data.Name;
3483 "shared library project %% cannot extend static " &
3484 "library project %%",
3486 Continuation := Continuation_String'Access;
3488 elsif not Unchecked_Shared_Lib_Imports then
3492 "shared library project %% cannot import static " &
3493 "library project %%",
3495 Continuation := Continuation_String'Access;
3502 -- Start of processing for Check_Library_Attributes
3505 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3507 -- Special case of extending project
3509 if Data.Extends /= No_Project then
3511 Extended_Data : constant Project_Data :=
3512 In_Tree.Projects.Table (Data.Extends);
3515 -- If the project extended is a library project, we inherit the
3516 -- library name, if it is not redefined; we check that the library
3517 -- directory is specified.
3519 if Extended_Data.Library then
3520 if Data.Qualifier = Standard then
3523 "a standard project cannot extend a library project",
3527 if Lib_Name.Default then
3528 Data.Library_Name := Extended_Data.Library_Name;
3531 if Lib_Dir.Default then
3532 if not Data.Virtual then
3535 "a project extending a library project must " &
3536 "specify an attribute Library_Dir",
3540 -- For a virtual project extending a library project,
3541 -- inherit library directory.
3543 Data.Library_Dir := Extended_Data.Library_Dir;
3544 Library_Directory_Present := True;
3552 pragma Assert (Lib_Name.Kind = Single);
3554 if Lib_Name.Value = Empty_String then
3555 if Current_Verbosity = High
3556 and then Data.Library_Name = No_Name
3558 Write_Line ("No library name");
3562 -- There is no restriction on the syntax of library names
3564 Data.Library_Name := Lib_Name.Value;
3567 if Data.Library_Name /= No_Name then
3568 if Current_Verbosity = High then
3569 Write_Attr ("Library name", Get_Name_String (Data.Library_Name));
3572 pragma Assert (Lib_Dir.Kind = Single);
3574 if not Library_Directory_Present then
3575 if Current_Verbosity = High then
3576 Write_Line ("No library directory");
3580 -- Find path name (unless inherited), check that it is a directory
3582 if Data.Library_Dir = No_Path_Information then
3586 File_Name_Type (Lib_Dir.Value),
3587 Data.Directory.Display_Name,
3588 Data.Library_Dir.Name,
3589 Data.Library_Dir.Display_Name,
3590 Create => "library",
3591 Current_Dir => Current_Dir,
3592 Location => Lib_Dir.Location,
3593 Externally_Built => Data.Externally_Built);
3596 if Data.Library_Dir = No_Path_Information then
3598 -- Get the absolute name of the library directory that
3599 -- does not exist, to report an error.
3602 Dir_Name : constant String :=
3603 Get_Name_String (Lib_Dir.Value);
3606 if Is_Absolute_Path (Dir_Name) then
3607 Err_Vars.Error_Msg_File_1 :=
3608 File_Name_Type (Lib_Dir.Value);
3611 Get_Name_String (Data.Directory.Display_Name);
3613 if Name_Buffer (Name_Len) /= Directory_Separator then
3614 Name_Len := Name_Len + 1;
3615 Name_Buffer (Name_Len) := Directory_Separator;
3619 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3621 Name_Len := Name_Len + Dir_Name'Length;
3622 Err_Vars.Error_Msg_File_1 := Name_Find;
3629 "library directory { does not exist",
3633 -- The library directory cannot be the same as the Object
3636 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3639 "library directory cannot be the same " &
3640 "as object directory",
3642 Data.Library_Dir := No_Path_Information;
3646 OK : Boolean := True;
3647 Dirs_Id : String_List_Id;
3648 Dir_Elem : String_Element;
3651 -- The library directory cannot be the same as a source
3652 -- directory of the current project.
3654 Dirs_Id := Data.Source_Dirs;
3655 while Dirs_Id /= Nil_String loop
3656 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3657 Dirs_Id := Dir_Elem.Next;
3660 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3662 Err_Vars.Error_Msg_File_1 :=
3663 File_Name_Type (Dir_Elem.Value);
3666 "library directory cannot be the same " &
3667 "as source directory {",
3676 -- The library directory cannot be the same as a source
3677 -- directory of another project either.
3680 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3681 if Pid /= Project then
3682 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3684 Dir_Loop : while Dirs_Id /= Nil_String loop
3686 In_Tree.String_Elements.Table (Dirs_Id);
3687 Dirs_Id := Dir_Elem.Next;
3689 if Data.Library_Dir.Name =
3690 Path_Name_Type (Dir_Elem.Value)
3692 Err_Vars.Error_Msg_File_1 :=
3693 File_Name_Type (Dir_Elem.Value);
3694 Err_Vars.Error_Msg_Name_1 :=
3695 In_Tree.Projects.Table (Pid).Name;
3699 "library directory cannot be the same " &
3700 "as source directory { of project %%",
3707 end loop Project_Loop;
3711 Data.Library_Dir := No_Path_Information;
3713 elsif Current_Verbosity = High then
3715 -- Display the Library directory in high verbosity
3718 ("Library directory",
3719 Get_Name_String (Data.Library_Dir.Display_Name));
3728 Data.Library_Dir /= No_Path_Information
3730 Data.Library_Name /= No_Name;
3732 if Data.Extends = No_Project then
3733 case Data.Qualifier is
3735 if Data.Library then
3738 "a standard project cannot be a library project",
3743 if not Data.Library then
3744 if Data.Library_Dir = No_Path_Information then
3747 "\attribute Library_Dir not declared",
3751 if Data.Library_Name = No_Name then
3754 "\attribute Library_Name not declared",
3765 if Data.Library then
3766 if Get_Mode = Multi_Language then
3767 Support_For_Libraries := Data.Config.Lib_Support;
3770 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3773 if Support_For_Libraries = Prj.None then
3776 "?libraries are not supported on this platform",
3778 Data.Library := False;
3781 if Lib_ALI_Dir.Value = Empty_String then
3782 if Current_Verbosity = High then
3783 Write_Line ("No library ALI directory specified");
3785 Data.Library_ALI_Dir := Data.Library_Dir;
3788 -- Find path name, check that it is a directory
3793 File_Name_Type (Lib_ALI_Dir.Value),
3794 Data.Directory.Display_Name,
3795 Data.Library_ALI_Dir.Name,
3796 Data.Library_ALI_Dir.Display_Name,
3797 Create => "library ALI",
3798 Current_Dir => Current_Dir,
3799 Location => Lib_ALI_Dir.Location,
3800 Externally_Built => Data.Externally_Built);
3802 if Data.Library_ALI_Dir = No_Path_Information then
3804 -- Get the absolute name of the library ALI directory that
3805 -- does not exist, to report an error.
3808 Dir_Name : constant String :=
3809 Get_Name_String (Lib_ALI_Dir.Value);
3812 if Is_Absolute_Path (Dir_Name) then
3813 Err_Vars.Error_Msg_File_1 :=
3814 File_Name_Type (Lib_Dir.Value);
3817 Get_Name_String (Data.Directory.Display_Name);
3819 if Name_Buffer (Name_Len) /= Directory_Separator then
3820 Name_Len := Name_Len + 1;
3821 Name_Buffer (Name_Len) := Directory_Separator;
3825 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3827 Name_Len := Name_Len + Dir_Name'Length;
3828 Err_Vars.Error_Msg_File_1 := Name_Find;
3835 "library 'A'L'I directory { does not exist",
3836 Lib_ALI_Dir.Location);
3840 if Data.Library_ALI_Dir /= Data.Library_Dir then
3842 -- The library ALI directory cannot be the same as the
3843 -- Object directory.
3845 if Data.Library_ALI_Dir = Data.Object_Directory then
3848 "library 'A'L'I directory cannot be the same " &
3849 "as object directory",
3850 Lib_ALI_Dir.Location);
3851 Data.Library_ALI_Dir := No_Path_Information;
3855 OK : Boolean := True;
3856 Dirs_Id : String_List_Id;
3857 Dir_Elem : String_Element;
3860 -- The library ALI directory cannot be the same as
3861 -- a source directory of the current project.
3863 Dirs_Id := Data.Source_Dirs;
3864 while Dirs_Id /= Nil_String loop
3865 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3866 Dirs_Id := Dir_Elem.Next;
3868 if Data.Library_ALI_Dir.Name =
3869 Path_Name_Type (Dir_Elem.Value)
3871 Err_Vars.Error_Msg_File_1 :=
3872 File_Name_Type (Dir_Elem.Value);
3875 "library 'A'L'I directory cannot be " &
3876 "the same as source directory {",
3877 Lib_ALI_Dir.Location);
3885 -- The library ALI directory cannot be the same as
3886 -- a source directory of another project either.
3890 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
3892 if Pid /= Project then
3894 In_Tree.Projects.Table (Pid).Source_Dirs;
3897 while Dirs_Id /= Nil_String loop
3899 In_Tree.String_Elements.Table (Dirs_Id);
3900 Dirs_Id := Dir_Elem.Next;
3902 if Data.Library_ALI_Dir.Name =
3903 Path_Name_Type (Dir_Elem.Value)
3905 Err_Vars.Error_Msg_File_1 :=
3906 File_Name_Type (Dir_Elem.Value);
3907 Err_Vars.Error_Msg_Name_1 :=
3908 In_Tree.Projects.Table (Pid).Name;
3912 "library 'A'L'I directory cannot " &
3913 "be the same as source directory " &
3915 Lib_ALI_Dir.Location);
3917 exit ALI_Project_Loop;
3919 end loop ALI_Dir_Loop;
3921 end loop ALI_Project_Loop;
3925 Data.Library_ALI_Dir := No_Path_Information;
3927 elsif Current_Verbosity = High then
3929 -- Display the Library ALI directory in high
3935 (Data.Library_ALI_Dir.Display_Name));
3942 pragma Assert (Lib_Version.Kind = Single);
3944 if Lib_Version.Value = Empty_String then
3945 if Current_Verbosity = High then
3946 Write_Line ("No library version specified");
3950 Data.Lib_Internal_Name := Lib_Version.Value;
3953 pragma Assert (The_Lib_Kind.Kind = Single);
3955 if The_Lib_Kind.Value = Empty_String then
3956 if Current_Verbosity = High then
3957 Write_Line ("No library kind specified");
3961 Get_Name_String (The_Lib_Kind.Value);
3964 Kind_Name : constant String :=
3965 To_Lower (Name_Buffer (1 .. Name_Len));
3967 OK : Boolean := True;
3970 if Kind_Name = "static" then
3971 Data.Library_Kind := Static;
3973 elsif Kind_Name = "dynamic" then
3974 Data.Library_Kind := Dynamic;
3976 elsif Kind_Name = "relocatable" then
3977 Data.Library_Kind := Relocatable;
3982 "illegal value for Library_Kind",
3983 The_Lib_Kind.Location);
3987 if Current_Verbosity = High and then OK then
3988 Write_Attr ("Library kind", Kind_Name);
3991 if Data.Library_Kind /= Static then
3992 if Support_For_Libraries = Prj.Static_Only then
3995 "only static libraries are supported " &
3997 The_Lib_Kind.Location);
3998 Data.Library := False;
4001 -- Check if (obsolescent) attribute Library_GCC or
4002 -- Linker'Driver is declared.
4004 if Lib_GCC.Value /= Empty_String then
4008 "?Library_'G'C'C is an obsolescent attribute, " &
4009 "use Linker''Driver instead",
4011 Data.Config.Shared_Lib_Driver :=
4012 File_Name_Type (Lib_GCC.Value);
4016 Linker : constant Package_Id :=
4021 Driver : constant Variable_Value :=
4024 Attribute_Or_Array_Name =>
4026 In_Package => Linker,
4031 if Driver /= Nil_Variable_Value
4032 and then Driver.Value /= Empty_String
4034 Data.Config.Shared_Lib_Driver :=
4035 File_Name_Type (Driver.Value);
4044 if Data.Library then
4045 if Current_Verbosity = High then
4046 Write_Line ("This is a library project file");
4049 if Get_Mode = Multi_Language then
4050 Check_Library (Data.Extends, Extends => True);
4052 Imported_Project_List := Data.Imported_Projects;
4053 while Imported_Project_List /= Empty_Project_List loop
4055 (In_Tree.Project_Lists.Table
4056 (Imported_Project_List).Project,
4058 Imported_Project_List :=
4059 In_Tree.Project_Lists.Table
4060 (Imported_Project_List).Next;
4068 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4069 -- Warn if they are declared, as it is a common error to think that
4070 -- library are "linked" with Linker switches.
4072 if Data.Library then
4074 Linker_Package_Id : constant Package_Id :=
4076 (Name_Linker, Data.Decl.Packages, In_Tree);
4077 Linker_Package : Package_Element;
4078 Switches : Array_Element_Id := No_Array_Element;
4081 if Linker_Package_Id /= No_Package then
4082 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4086 (Name => Name_Switches,
4087 In_Arrays => Linker_Package.Decl.Arrays,
4088 In_Tree => In_Tree);
4090 if Switches = No_Array_Element then
4093 (Name => Name_Default_Switches,
4094 In_Arrays => Linker_Package.Decl.Arrays,
4095 In_Tree => In_Tree);
4098 if Switches /= No_Array_Element then
4101 "?Linker switches not taken into account in library " &
4109 if Data.Extends /= No_Project then
4110 In_Tree.Projects.Table (Data.Extends).Library := False;
4112 end Check_Library_Attributes;
4114 --------------------------
4115 -- Check_Package_Naming --
4116 --------------------------
4118 procedure Check_Package_Naming
4119 (Project : Project_Id;
4120 In_Tree : Project_Tree_Ref;
4121 Data : in out Project_Data)
4123 Naming_Id : constant Package_Id :=
4124 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4126 Naming : Package_Element;
4129 -- If there is a package Naming, we will put in Data.Naming
4130 -- what is in this package Naming.
4132 if Naming_Id /= No_Package then
4133 Naming := In_Tree.Packages.Table (Naming_Id);
4135 if Current_Verbosity = High then
4136 Write_Line ("Checking ""Naming"".");
4139 -- Check Spec_Suffix
4142 Spec_Suffixs : Array_Element_Id :=
4148 Suffix : Array_Element_Id;
4149 Element : Array_Element;
4150 Suffix2 : Array_Element_Id;
4153 -- If some suffixes have been specified, we make sure that
4154 -- for each language for which a default suffix has been
4155 -- specified, there is a suffix specified, either the one
4156 -- in the project file or if there were none, the default.
4158 if Spec_Suffixs /= No_Array_Element then
4159 Suffix := Data.Naming.Spec_Suffix;
4161 while Suffix /= No_Array_Element loop
4163 In_Tree.Array_Elements.Table (Suffix);
4164 Suffix2 := Spec_Suffixs;
4166 while Suffix2 /= No_Array_Element loop
4167 exit when In_Tree.Array_Elements.Table
4168 (Suffix2).Index = Element.Index;
4169 Suffix2 := In_Tree.Array_Elements.Table
4173 -- There is a registered default suffix, but no
4174 -- suffix specified in the project file.
4175 -- Add the default to the array.
4177 if Suffix2 = No_Array_Element then
4178 Array_Element_Table.Increment_Last
4179 (In_Tree.Array_Elements);
4180 In_Tree.Array_Elements.Table
4181 (Array_Element_Table.Last
4182 (In_Tree.Array_Elements)) :=
4183 (Index => Element.Index,
4184 Src_Index => Element.Src_Index,
4185 Index_Case_Sensitive => False,
4186 Value => Element.Value,
4187 Next => Spec_Suffixs);
4188 Spec_Suffixs := Array_Element_Table.Last
4189 (In_Tree.Array_Elements);
4192 Suffix := Element.Next;
4195 -- Put the resulting array as the specification suffixes
4197 Data.Naming.Spec_Suffix := Spec_Suffixs;
4202 Current : Array_Element_Id;
4203 Element : Array_Element;
4206 Current := Data.Naming.Spec_Suffix;
4207 while Current /= No_Array_Element loop
4208 Element := In_Tree.Array_Elements.Table (Current);
4209 Get_Name_String (Element.Value.Value);
4211 if Name_Len = 0 then
4214 "Spec_Suffix cannot be empty",
4215 Element.Value.Location);
4218 In_Tree.Array_Elements.Table (Current) := Element;
4219 Current := Element.Next;
4223 -- Check Body_Suffix
4226 Impl_Suffixs : Array_Element_Id :=
4232 Suffix : Array_Element_Id;
4233 Element : Array_Element;
4234 Suffix2 : Array_Element_Id;
4237 -- If some suffixes have been specified, we make sure that
4238 -- for each language for which a default suffix has been
4239 -- specified, there is a suffix specified, either the one
4240 -- in the project file or if there were none, the default.
4242 if Impl_Suffixs /= No_Array_Element then
4243 Suffix := Data.Naming.Body_Suffix;
4244 while Suffix /= No_Array_Element loop
4246 In_Tree.Array_Elements.Table (Suffix);
4248 Suffix2 := Impl_Suffixs;
4249 while Suffix2 /= No_Array_Element loop
4250 exit when In_Tree.Array_Elements.Table
4251 (Suffix2).Index = Element.Index;
4252 Suffix2 := In_Tree.Array_Elements.Table
4256 -- There is a registered default suffix, but no suffix was
4257 -- specified in the project file. Add default to the array.
4259 if Suffix2 = No_Array_Element then
4260 Array_Element_Table.Increment_Last
4261 (In_Tree.Array_Elements);
4262 In_Tree.Array_Elements.Table
4263 (Array_Element_Table.Last
4264 (In_Tree.Array_Elements)) :=
4265 (Index => Element.Index,
4266 Src_Index => Element.Src_Index,
4267 Index_Case_Sensitive => False,
4268 Value => Element.Value,
4269 Next => Impl_Suffixs);
4270 Impl_Suffixs := Array_Element_Table.Last
4271 (In_Tree.Array_Elements);
4274 Suffix := Element.Next;
4277 -- Put the resulting array as the implementation suffixes
4279 Data.Naming.Body_Suffix := Impl_Suffixs;
4284 Current : Array_Element_Id;
4285 Element : Array_Element;
4288 Current := Data.Naming.Body_Suffix;
4289 while Current /= No_Array_Element loop
4290 Element := In_Tree.Array_Elements.Table (Current);
4291 Get_Name_String (Element.Value.Value);
4293 if Name_Len = 0 then
4296 "Body_Suffix cannot be empty",
4297 Element.Value.Location);
4300 In_Tree.Array_Elements.Table (Current) := Element;
4301 Current := Element.Next;
4305 -- Get the exceptions, if any
4307 Data.Naming.Specification_Exceptions :=
4309 (Name_Specification_Exceptions,
4310 In_Arrays => Naming.Decl.Arrays,
4311 In_Tree => In_Tree);
4313 Data.Naming.Implementation_Exceptions :=
4315 (Name_Implementation_Exceptions,
4316 In_Arrays => Naming.Decl.Arrays,
4317 In_Tree => In_Tree);
4319 end Check_Package_Naming;
4321 ---------------------------------
4322 -- Check_Programming_Languages --
4323 ---------------------------------
4325 procedure Check_Programming_Languages
4326 (In_Tree : Project_Tree_Ref;
4327 Project : Project_Id;
4328 Data : in out Project_Data)
4330 Languages : Variable_Value := Nil_Variable_Value;
4331 Def_Lang : Variable_Value := Nil_Variable_Value;
4332 Def_Lang_Id : Name_Id;
4335 Data.Languages := No_Language_Index;
4337 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4340 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4342 -- Shouldn't these be set to False by default, and only set to True when
4343 -- we actually find some source file???
4345 if Data.Source_Dirs /= Nil_String then
4347 -- Check if languages are specified in this project
4349 if Languages.Default then
4351 -- In Ada_Only mode, the default language is Ada
4353 if Get_Mode = Ada_Only then
4354 Def_Lang_Id := Name_Ada;
4357 -- Fail if there is no default language defined
4359 if Def_Lang.Default then
4360 if not Default_Language_Is_Ada then
4364 "no languages defined for this project",
4366 Def_Lang_Id := No_Name;
4368 Def_Lang_Id := Name_Ada;
4372 Get_Name_String (Def_Lang.Value);
4373 To_Lower (Name_Buffer (1 .. Name_Len));
4374 Def_Lang_Id := Name_Find;
4378 if Def_Lang_Id /= No_Name then
4380 new Language_Data'(No_Language_Data);
4381 Data.Languages.Name := Def_Lang_Id;
4382 Get_Name_String (Def_Lang_Id);
4383 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4384 Data.Languages.Display_Name := Name_Find;
4386 if Def_Lang_Id = Name_Ada then
4387 Data.Languages.Config.Kind := Unit_Based;
4388 Data.Languages.Config.Dependency_Kind :=
4391 Data.Languages.Config.Kind := File_Based;
4397 Current : String_List_Id := Languages.Values;
4398 Element : String_Element;
4399 Lang_Name : Name_Id;
4400 Index : Language_Ptr;
4401 NL_Id : Language_Ptr;
4404 -- If there are no languages declared, there are no sources
4406 if Current = Nil_String then
4407 Data.Source_Dirs := Nil_String;
4409 if Data.Qualifier = Standard then
4413 "a standard project cannot have no language declared",
4414 Languages.Location);
4418 -- Look through all the languages specified in attribute
4421 while Current /= Nil_String loop
4422 Element := In_Tree.String_Elements.Table (Current);
4423 Get_Name_String (Element.Value);
4424 To_Lower (Name_Buffer (1 .. Name_Len));
4425 Lang_Name := Name_Find;
4427 -- If the language was not already specified (duplicates
4428 -- are simply ignored).
4430 NL_Id := Data.Languages;
4431 while NL_Id /= No_Language_Index loop
4432 exit when Lang_Name = NL_Id.Name;
4433 NL_Id := NL_Id.Next;
4436 if NL_Id = No_Language_Index then
4437 Index := new Language_Data'(No_Language_Data);
4438 Index.Name := Lang_Name;
4439 Index.Display_Name := Element.Value;
4440 Index.Next := Data.Languages;
4442 if Lang_Name = Name_Ada then
4443 Index.Config.Kind := Unit_Based;
4444 Index.Config.Dependency_Kind := ALI_File;
4447 Index.Config.Kind := File_Based;
4448 Index.Config.Dependency_Kind := None;
4451 Data.Languages := Index;
4454 Current := Element.Next;
4460 end Check_Programming_Languages;
4466 function Check_Project
4468 Root_Project : Project_Id;
4469 In_Tree : Project_Tree_Ref;
4470 Extending : Boolean) return Boolean
4473 if P = Root_Project then
4476 elsif Extending then
4478 Data : Project_Data;
4481 Data := In_Tree.Projects.Table (Root_Project);
4482 while Data.Extends /= No_Project loop
4483 if P = Data.Extends then
4487 Data := In_Tree.Projects.Table (Data.Extends);
4495 -------------------------------
4496 -- Check_Stand_Alone_Library --
4497 -------------------------------
4499 procedure Check_Stand_Alone_Library
4500 (Project : Project_Id;
4501 In_Tree : Project_Tree_Ref;
4502 Data : in out Project_Data;
4503 Current_Dir : String;
4504 Extending : Boolean)
4506 Lib_Interfaces : constant Prj.Variable_Value :=
4508 (Snames.Name_Library_Interface,
4509 Data.Decl.Attributes,
4512 Lib_Auto_Init : constant Prj.Variable_Value :=
4514 (Snames.Name_Library_Auto_Init,
4515 Data.Decl.Attributes,
4518 Lib_Src_Dir : constant Prj.Variable_Value :=
4520 (Snames.Name_Library_Src_Dir,
4521 Data.Decl.Attributes,
4524 Lib_Symbol_File : constant Prj.Variable_Value :=
4526 (Snames.Name_Library_Symbol_File,
4527 Data.Decl.Attributes,
4530 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4532 (Snames.Name_Library_Symbol_Policy,
4533 Data.Decl.Attributes,
4536 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4538 (Snames.Name_Library_Reference_Symbol_File,
4539 Data.Decl.Attributes,
4542 Auto_Init_Supported : Boolean;
4543 OK : Boolean := True;
4545 Next_Proj : Project_Id;
4546 Iter : Source_Iterator;
4549 if Get_Mode = Multi_Language then
4550 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4552 Auto_Init_Supported :=
4553 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4556 pragma Assert (Lib_Interfaces.Kind = List);
4558 -- It is a stand-alone library project file if attribute
4559 -- Library_Interface is defined.
4561 if not Lib_Interfaces.Default then
4562 SAL_Library : declare
4563 Interfaces : String_List_Id := Lib_Interfaces.Values;
4564 Interface_ALIs : String_List_Id := Nil_String;
4566 The_Unit_Id : Unit_Index;
4567 The_Unit_Data : Unit_Data;
4569 procedure Add_ALI_For (Source : File_Name_Type);
4570 -- Add an ALI file name to the list of Interface ALIs
4576 procedure Add_ALI_For (Source : File_Name_Type) is
4578 Get_Name_String (Source);
4581 ALI : constant String :=
4582 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4583 ALI_Name_Id : Name_Id;
4586 Name_Len := ALI'Length;
4587 Name_Buffer (1 .. Name_Len) := ALI;
4588 ALI_Name_Id := Name_Find;
4590 String_Element_Table.Increment_Last
4591 (In_Tree.String_Elements);
4592 In_Tree.String_Elements.Table
4593 (String_Element_Table.Last
4594 (In_Tree.String_Elements)) :=
4595 (Value => ALI_Name_Id,
4597 Display_Value => ALI_Name_Id,
4599 In_Tree.String_Elements.Table
4600 (Interfaces).Location,
4602 Next => Interface_ALIs);
4603 Interface_ALIs := String_Element_Table.Last
4604 (In_Tree.String_Elements);
4608 -- Start of processing for SAL_Library
4611 Data.Standalone_Library := True;
4613 -- Library_Interface cannot be an empty list
4615 if Interfaces = Nil_String then
4618 "Library_Interface cannot be an empty list",
4619 Lib_Interfaces.Location);
4622 -- Process each unit name specified in the attribute
4623 -- Library_Interface.
4625 while Interfaces /= Nil_String loop
4627 (In_Tree.String_Elements.Table (Interfaces).Value);
4628 To_Lower (Name_Buffer (1 .. Name_Len));
4630 if Name_Len = 0 then
4633 "an interface cannot be an empty string",
4634 In_Tree.String_Elements.Table (Interfaces).Location);
4638 Error_Msg_Name_1 := Unit;
4640 if Get_Mode = Ada_Only then
4642 Units_Htable.Get (In_Tree.Units_HT, Unit);
4644 if The_Unit_Id = No_Unit_Index then
4648 In_Tree.String_Elements.Table
4649 (Interfaces).Location);
4652 -- Check that the unit is part of the project
4655 In_Tree.Units.Table (The_Unit_Id);
4657 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4658 and then The_Unit_Data.File_Names
4659 (Body_Part).Path.Name /= Slash
4662 (The_Unit_Data.File_Names (Body_Part).Project,
4663 Project, In_Tree, Extending)
4665 -- There is a body for this unit.
4666 -- If there is no spec, we need to check that it
4667 -- is not a subunit.
4669 if The_Unit_Data.File_Names
4670 (Specification).Name = No_File
4673 Src_Ind : Source_File_Index;
4676 Src_Ind := Sinput.P.Load_Project_File
4678 (The_Unit_Data.File_Names
4679 (Body_Part).Path.Name));
4681 if Sinput.P.Source_File_Is_Subunit
4686 "%% is a subunit; " &
4687 "it cannot be an interface",
4689 String_Elements.Table
4690 (Interfaces).Location);
4695 -- The unit is not a subunit, so we add the
4696 -- ALI file for its body to the Interface ALIs.
4699 (The_Unit_Data.File_Names (Body_Part).Name);
4704 "%% is not an unit of this project",
4705 In_Tree.String_Elements.Table
4706 (Interfaces).Location);
4709 elsif The_Unit_Data.File_Names
4710 (Specification).Name /= No_File
4711 and then The_Unit_Data.File_Names
4712 (Specification).Path.Name /= Slash
4713 and then Check_Project
4714 (The_Unit_Data.File_Names
4715 (Specification).Project,
4716 Project, In_Tree, Extending)
4719 -- The unit is part of the project, it has a spec,
4720 -- but no body. We add the ALI for its spec to the
4724 (The_Unit_Data.File_Names (Specification).Name);
4729 "%% is not an unit of this project",
4730 In_Tree.String_Elements.Table
4731 (Interfaces).Location);
4736 -- Multi_Language mode
4738 Next_Proj := Data.Extends;
4740 Iter := For_Each_Source (In_Tree, Project);
4743 while Prj.Element (Iter) /= No_Source and then
4744 Prj.Element (Iter).Unit /= Unit
4749 Source := Prj.Element (Iter);
4750 exit when Source /= No_Source or else
4751 Next_Proj = No_Project;
4753 Iter := For_Each_Source (In_Tree, Next_Proj);
4755 In_Tree.Projects.Table (Next_Proj).Extends;
4758 if Source /= No_Source then
4759 if Source.Kind = Sep then
4760 Source := No_Source;
4762 elsif Source.Kind = Spec
4763 and then Source.Other_Part /= No_Source
4765 Source := Source.Other_Part;
4769 if Source /= No_Source then
4770 if Source.Project /= Project
4772 not Is_Extending (Project, Source.Project, In_Tree)
4774 Source := No_Source;
4778 if Source = No_Source then
4781 "%% is not an unit of this project",
4782 In_Tree.String_Elements.Table
4783 (Interfaces).Location);
4786 if Source.Kind = Spec and then
4787 Source.Other_Part /= No_Source
4789 Source := Source.Other_Part;
4792 String_Element_Table.Increment_Last
4793 (In_Tree.String_Elements);
4794 In_Tree.String_Elements.Table
4795 (String_Element_Table.Last
4796 (In_Tree.String_Elements)) :=
4797 (Value => Name_Id (Source.Dep_Name),
4799 Display_Value => Name_Id (Source.Dep_Name),
4801 In_Tree.String_Elements.Table
4802 (Interfaces).Location,
4804 Next => Interface_ALIs);
4805 Interface_ALIs := String_Element_Table.Last
4806 (In_Tree.String_Elements);
4814 In_Tree.String_Elements.Table (Interfaces).Next;
4817 -- Put the list of Interface ALIs in the project data
4819 Data.Lib_Interface_ALIs := Interface_ALIs;
4821 -- Check value of attribute Library_Auto_Init and set
4822 -- Lib_Auto_Init accordingly.
4824 if Lib_Auto_Init.Default then
4826 -- If no attribute Library_Auto_Init is declared, then set auto
4827 -- init only if it is supported.
4829 Data.Lib_Auto_Init := Auto_Init_Supported;
4832 Get_Name_String (Lib_Auto_Init.Value);
4833 To_Lower (Name_Buffer (1 .. Name_Len));
4835 if Name_Buffer (1 .. Name_Len) = "false" then
4836 Data.Lib_Auto_Init := False;
4838 elsif Name_Buffer (1 .. Name_Len) = "true" then
4839 if Auto_Init_Supported then
4840 Data.Lib_Auto_Init := True;
4843 -- Library_Auto_Init cannot be "true" if auto init is not
4848 "library auto init not supported " &
4850 Lib_Auto_Init.Location);
4856 "invalid value for attribute Library_Auto_Init",
4857 Lib_Auto_Init.Location);
4862 -- If attribute Library_Src_Dir is defined and not the empty string,
4863 -- check if the directory exist and is not the object directory or
4864 -- one of the source directories. This is the directory where copies
4865 -- of the interface sources will be copied. Note that this directory
4866 -- may be the library directory.
4868 if Lib_Src_Dir.Value /= Empty_String then
4870 Dir_Id : constant File_Name_Type :=
4871 File_Name_Type (Lib_Src_Dir.Value);
4878 Data.Directory.Display_Name,
4879 Data.Library_Src_Dir.Name,
4880 Data.Library_Src_Dir.Display_Name,
4881 Create => "library source copy",
4882 Current_Dir => Current_Dir,
4883 Location => Lib_Src_Dir.Location,
4884 Externally_Built => Data.Externally_Built);
4886 -- If directory does not exist, report an error
4888 if Data.Library_Src_Dir = No_Path_Information then
4890 -- Get the absolute name of the library directory that does
4891 -- not exist, to report an error.
4894 Dir_Name : constant String :=
4895 Get_Name_String (Dir_Id);
4898 if Is_Absolute_Path (Dir_Name) then
4899 Err_Vars.Error_Msg_File_1 := Dir_Id;
4902 Get_Name_String (Data.Directory.Name);
4904 if Name_Buffer (Name_Len) /=
4907 Name_Len := Name_Len + 1;
4908 Name_Buffer (Name_Len) :=
4909 Directory_Separator;
4914 Name_Len + Dir_Name'Length) :=
4916 Name_Len := Name_Len + Dir_Name'Length;
4917 Err_Vars.Error_Msg_Name_1 := Name_Find;
4922 Error_Msg_File_1 := Dir_Id;
4925 "Directory { does not exist",
4926 Lib_Src_Dir.Location);
4929 -- Report error if it is the same as the object directory
4931 elsif Data.Library_Src_Dir = Data.Object_Directory then
4934 "directory to copy interfaces cannot be " &
4935 "the object directory",
4936 Lib_Src_Dir.Location);
4937 Data.Library_Src_Dir := No_Path_Information;
4941 Src_Dirs : String_List_Id;
4942 Src_Dir : String_Element;
4945 -- Interface copy directory cannot be one of the source
4946 -- directory of the current project.
4948 Src_Dirs := Data.Source_Dirs;
4949 while Src_Dirs /= Nil_String loop
4950 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4952 -- Report error if it is one of the source directories
4954 if Data.Library_Src_Dir.Name =
4955 Path_Name_Type (Src_Dir.Value)
4959 "directory to copy interfaces cannot " &
4960 "be one of the source directories",
4961 Lib_Src_Dir.Location);
4962 Data.Library_Src_Dir := No_Path_Information;
4966 Src_Dirs := Src_Dir.Next;
4969 if Data.Library_Src_Dir /= No_Path_Information then
4971 -- It cannot be a source directory of any other
4974 Project_Loop : for Pid in 1 ..
4975 Project_Table.Last (In_Tree.Projects)
4978 In_Tree.Projects.Table (Pid).Source_Dirs;
4979 Dir_Loop : while Src_Dirs /= Nil_String loop
4981 In_Tree.String_Elements.Table (Src_Dirs);
4983 -- Report error if it is one of the source
4986 if Data.Library_Src_Dir.Name =
4987 Path_Name_Type (Src_Dir.Value)
4990 File_Name_Type (Src_Dir.Value);
4992 In_Tree.Projects.Table (Pid).Name;
4995 "directory to copy interfaces cannot " &
4996 "be the same as source directory { of " &
4998 Lib_Src_Dir.Location);
4999 Data.Library_Src_Dir := No_Path_Information;
5003 Src_Dirs := Src_Dir.Next;
5005 end loop Project_Loop;
5009 -- In high verbosity, if there is a valid Library_Src_Dir,
5010 -- display its path name.
5012 if Data.Library_Src_Dir /= No_Path_Information
5013 and then Current_Verbosity = High
5016 ("Directory to copy interfaces",
5017 Get_Name_String (Data.Library_Src_Dir.Name));
5023 -- Check the symbol related attributes
5025 -- First, the symbol policy
5027 if not Lib_Symbol_Policy.Default then
5029 Value : constant String :=
5031 (Get_Name_String (Lib_Symbol_Policy.Value));
5034 -- Symbol policy must hove one of a limited number of values
5036 if Value = "autonomous" or else Value = "default" then
5037 Data.Symbol_Data.Symbol_Policy := Autonomous;
5039 elsif Value = "compliant" then
5040 Data.Symbol_Data.Symbol_Policy := Compliant;
5042 elsif Value = "controlled" then
5043 Data.Symbol_Data.Symbol_Policy := Controlled;
5045 elsif Value = "restricted" then
5046 Data.Symbol_Data.Symbol_Policy := Restricted;
5048 elsif Value = "direct" then
5049 Data.Symbol_Data.Symbol_Policy := Direct;
5054 "illegal value for Library_Symbol_Policy",
5055 Lib_Symbol_Policy.Location);
5060 -- If attribute Library_Symbol_File is not specified, symbol policy
5061 -- cannot be Restricted.
5063 if Lib_Symbol_File.Default then
5064 if Data.Symbol_Data.Symbol_Policy = Restricted then
5067 "Library_Symbol_File needs to be defined when " &
5068 "symbol policy is Restricted",
5069 Lib_Symbol_Policy.Location);
5073 -- Library_Symbol_File is defined
5075 Data.Symbol_Data.Symbol_File :=
5076 Path_Name_Type (Lib_Symbol_File.Value);
5078 Get_Name_String (Lib_Symbol_File.Value);
5080 if Name_Len = 0 then
5083 "symbol file name cannot be an empty string",
5084 Lib_Symbol_File.Location);
5087 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5090 for J in 1 .. Name_Len loop
5091 if Name_Buffer (J) = '/'
5092 or else Name_Buffer (J) = Directory_Separator
5101 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5104 "symbol file name { is illegal. " &
5105 "Name cannot include directory info.",
5106 Lib_Symbol_File.Location);
5111 -- If attribute Library_Reference_Symbol_File is not defined,
5112 -- symbol policy cannot be Compliant or Controlled.
5114 if Lib_Ref_Symbol_File.Default then
5115 if Data.Symbol_Data.Symbol_Policy = Compliant
5116 or else Data.Symbol_Data.Symbol_Policy = Controlled
5120 "a reference symbol file needs to be defined",
5121 Lib_Symbol_Policy.Location);
5125 -- Library_Reference_Symbol_File is defined, check file exists
5127 Data.Symbol_Data.Reference :=
5128 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5130 Get_Name_String (Lib_Ref_Symbol_File.Value);
5132 if Name_Len = 0 then
5135 "reference symbol file name cannot be an empty string",
5136 Lib_Symbol_File.Location);
5139 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5141 Add_Str_To_Name_Buffer
5142 (Get_Name_String (Data.Directory.Name));
5143 Add_Char_To_Name_Buffer (Directory_Separator);
5144 Add_Str_To_Name_Buffer
5145 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5146 Data.Symbol_Data.Reference := Name_Find;
5149 if not Is_Regular_File
5150 (Get_Name_String (Data.Symbol_Data.Reference))
5153 File_Name_Type (Lib_Ref_Symbol_File.Value);
5155 -- For controlled and direct symbol policies, it is an error
5156 -- if the reference symbol file does not exist. For other
5157 -- symbol policies, this is just a warning
5160 Data.Symbol_Data.Symbol_Policy /= Controlled
5161 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5165 "<library reference symbol file { does not exist",
5166 Lib_Ref_Symbol_File.Location);
5168 -- In addition in the non-controlled case, if symbol policy
5169 -- is Compliant, it is changed to Autonomous, because there
5170 -- is no reference to check against, and we don't want to
5171 -- fail in this case.
5173 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5174 if Data.Symbol_Data.Symbol_Policy = Compliant then
5175 Data.Symbol_Data.Symbol_Policy := Autonomous;
5180 -- If both the reference symbol file and the symbol file are
5181 -- defined, then check that they are not the same file.
5183 if Data.Symbol_Data.Symbol_File /= No_Path then
5184 Get_Name_String (Data.Symbol_Data.Symbol_File);
5186 if Name_Len > 0 then
5188 Symb_Path : constant String :=
5191 (Data.Object_Directory.Name) &
5192 Directory_Separator &
5193 Name_Buffer (1 .. Name_Len),
5194 Directory => Current_Dir,
5196 Opt.Follow_Links_For_Files);
5197 Ref_Path : constant String :=
5200 (Data.Symbol_Data.Reference),
5201 Directory => Current_Dir,
5203 Opt.Follow_Links_For_Files);
5205 if Symb_Path = Ref_Path then
5208 "library reference symbol file and library" &
5209 " symbol file cannot be the same file",
5210 Lib_Ref_Symbol_File.Location);
5218 end Check_Stand_Alone_Library;
5220 ----------------------------
5221 -- Compute_Directory_Last --
5222 ----------------------------
5224 function Compute_Directory_Last (Dir : String) return Natural is
5227 and then (Dir (Dir'Last - 1) = Directory_Separator
5228 or else Dir (Dir'Last - 1) = '/')
5230 return Dir'Last - 1;
5234 end Compute_Directory_Last;
5241 (Project : Project_Id;
5242 In_Tree : Project_Tree_Ref;
5244 Flag_Location : Source_Ptr)
5246 Real_Location : Source_Ptr := Flag_Location;
5247 Error_Buffer : String (1 .. 5_000);
5248 Error_Last : Natural := 0;
5249 Name_Number : Natural := 0;
5250 File_Number : Natural := 0;
5251 First : Positive := Msg'First;
5254 procedure Add (C : Character);
5255 -- Add a character to the buffer
5257 procedure Add (S : String);
5258 -- Add a string to the buffer
5261 -- Add a name to the buffer
5264 -- Add a file name to the buffer
5270 procedure Add (C : Character) is
5272 Error_Last := Error_Last + 1;
5273 Error_Buffer (Error_Last) := C;
5276 procedure Add (S : String) is
5278 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5279 Error_Last := Error_Last + S'Length;
5286 procedure Add_File is
5287 File : File_Name_Type;
5291 File_Number := File_Number + 1;
5295 File := Err_Vars.Error_Msg_File_1;
5297 File := Err_Vars.Error_Msg_File_2;
5299 File := Err_Vars.Error_Msg_File_3;
5304 Get_Name_String (File);
5305 Add (Name_Buffer (1 .. Name_Len));
5313 procedure Add_Name is
5318 Name_Number := Name_Number + 1;
5322 Name := Err_Vars.Error_Msg_Name_1;
5324 Name := Err_Vars.Error_Msg_Name_2;
5326 Name := Err_Vars.Error_Msg_Name_3;
5331 Get_Name_String (Name);
5332 Add (Name_Buffer (1 .. Name_Len));
5336 -- Start of processing for Error_Msg
5339 -- If location of error is unknown, use the location of the project
5341 if Real_Location = No_Location then
5342 Real_Location := In_Tree.Projects.Table (Project).Location;
5345 if Error_Report = null then
5346 Prj.Err.Error_Msg (Msg, Real_Location);
5350 -- Ignore continuation character
5352 if Msg (First) = '\' then
5356 -- Warning character is always the first one in this package
5357 -- this is an undocumented kludge???
5359 if Msg (First) = '?' then
5363 elsif Msg (First) = '<' then
5366 if Err_Vars.Error_Msg_Warn then
5372 while Index <= Msg'Last loop
5373 if Msg (Index) = '{' then
5376 elsif Msg (Index) = '%' then
5377 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5389 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5392 --------------------------------
5393 -- Free_Ada_Naming_Exceptions --
5394 --------------------------------
5396 procedure Free_Ada_Naming_Exceptions is
5398 Ada_Naming_Exception_Table.Set_Last (0);
5399 Ada_Naming_Exceptions.Reset;
5400 Reverse_Ada_Naming_Exceptions.Reset;
5401 end Free_Ada_Naming_Exceptions;
5403 ---------------------
5404 -- Get_Directories --
5405 ---------------------
5407 procedure Get_Directories
5408 (Project : Project_Id;
5409 In_Tree : Project_Tree_Ref;
5410 Current_Dir : String;
5411 Data : in out Project_Data)
5413 Object_Dir : constant Variable_Value :=
5415 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5417 Exec_Dir : constant Variable_Value :=
5419 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5421 Source_Dirs : constant Variable_Value :=
5423 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5425 Excluded_Source_Dirs : constant Variable_Value :=
5427 (Name_Excluded_Source_Dirs,
5428 Data.Decl.Attributes,
5431 Source_Files : constant Variable_Value :=
5433 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5435 Last_Source_Dir : String_List_Id := Nil_String;
5437 Languages : constant Variable_Value :=
5439 (Name_Languages, Data.Decl.Attributes, In_Tree);
5441 procedure Find_Source_Dirs
5442 (From : File_Name_Type;
5443 Location : Source_Ptr;
5444 Removed : Boolean := False);
5445 -- Find one or several source directories, and add (or remove, if
5446 -- Removed is True) them to list of source directories of the project.
5448 ----------------------
5449 -- Find_Source_Dirs --
5450 ----------------------
5452 procedure Find_Source_Dirs
5453 (From : File_Name_Type;
5454 Location : Source_Ptr;
5455 Removed : Boolean := False)
5457 Directory : constant String := Get_Name_String (From);
5458 Element : String_Element;
5460 procedure Recursive_Find_Dirs (Path : Name_Id);
5461 -- Find all the subdirectories (recursively) of Path and add them
5462 -- to the list of source directories of the project.
5464 -------------------------
5465 -- Recursive_Find_Dirs --
5466 -------------------------
5468 procedure Recursive_Find_Dirs (Path : Name_Id) is
5470 Name : String (1 .. 250);
5472 List : String_List_Id;
5473 Prev : String_List_Id;
5474 Element : String_Element;
5475 Found : Boolean := False;
5477 Non_Canonical_Path : Name_Id := No_Name;
5478 Canonical_Path : Name_Id := No_Name;
5480 The_Path : constant String :=
5482 (Get_Name_String (Path),
5483 Directory => Current_Dir,
5484 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5485 Directory_Separator;
5487 The_Path_Last : constant Natural :=
5488 Compute_Directory_Last (The_Path);
5491 Name_Len := The_Path_Last - The_Path'First + 1;
5492 Name_Buffer (1 .. Name_Len) :=
5493 The_Path (The_Path'First .. The_Path_Last);
5494 Non_Canonical_Path := Name_Find;
5496 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5498 -- To avoid processing the same directory several times, check
5499 -- if the directory is already in Recursive_Dirs. If it is, then
5500 -- there is nothing to do, just return. If it is not, put it there
5501 -- and continue recursive processing.
5504 if Recursive_Dirs.Get (Canonical_Path) then
5507 Recursive_Dirs.Set (Canonical_Path, True);
5511 -- Check if directory is already in list
5513 List := Data.Source_Dirs;
5515 while List /= Nil_String loop
5516 Element := In_Tree.String_Elements.Table (List);
5518 if Element.Value /= No_Name then
5519 Found := Element.Value = Canonical_Path;
5524 List := Element.Next;
5527 -- If directory is not already in list, put it there
5529 if (not Removed) and (not Found) then
5530 if Current_Verbosity = High then
5532 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5535 String_Element_Table.Increment_Last
5536 (In_Tree.String_Elements);
5538 (Value => Canonical_Path,
5539 Display_Value => Non_Canonical_Path,
5540 Location => No_Location,
5545 -- Case of first source directory
5547 if Last_Source_Dir = Nil_String then
5548 Data.Source_Dirs := String_Element_Table.Last
5549 (In_Tree.String_Elements);
5551 -- Here we already have source directories
5554 -- Link the previous last to the new one
5556 In_Tree.String_Elements.Table
5557 (Last_Source_Dir).Next :=
5558 String_Element_Table.Last
5559 (In_Tree.String_Elements);
5562 -- And register this source directory as the new last
5564 Last_Source_Dir := String_Element_Table.Last
5565 (In_Tree.String_Elements);
5566 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5569 elsif Removed and Found then
5570 if Prev = Nil_String then
5572 In_Tree.String_Elements.Table (List).Next;
5574 In_Tree.String_Elements.Table (Prev).Next :=
5575 In_Tree.String_Elements.Table (List).Next;
5579 -- Now look for subdirectories. We do that even when this
5580 -- directory is already in the list, because some of its
5581 -- subdirectories may not be in the list yet.
5583 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5586 Read (Dir, Name, Last);
5589 if Name (1 .. Last) /= "."
5590 and then Name (1 .. Last) /= ".."
5592 -- Avoid . and .. directories
5594 if Current_Verbosity = High then
5595 Write_Str (" Checking ");
5596 Write_Line (Name (1 .. Last));
5600 Path_Name : constant String :=
5602 (Name => Name (1 .. Last),
5604 The_Path (The_Path'First .. The_Path_Last),
5605 Resolve_Links => Opt.Follow_Links_For_Dirs,
5606 Case_Sensitive => True);
5609 if Is_Directory (Path_Name) then
5610 -- We have found a new subdirectory, call self
5612 Name_Len := Path_Name'Length;
5613 Name_Buffer (1 .. Name_Len) := Path_Name;
5614 Recursive_Find_Dirs (Name_Find);
5623 when Directory_Error =>
5625 end Recursive_Find_Dirs;
5627 -- Start of processing for Find_Source_Dirs
5630 if Current_Verbosity = High and then not Removed then
5631 Write_Str ("Find_Source_Dirs (""");
5632 Write_Str (Directory);
5636 -- First, check if we are looking for a directory tree, indicated
5637 -- by "/**" at the end.
5639 if Directory'Length >= 3
5640 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5641 and then (Directory (Directory'Last - 2) = '/'
5643 Directory (Directory'Last - 2) = Directory_Separator)
5646 Data.Known_Order_Of_Source_Dirs := False;
5649 Name_Len := Directory'Length - 3;
5651 if Name_Len = 0 then
5653 -- Case of "/**": all directories in file system
5656 Name_Buffer (1) := Directory (Directory'First);
5659 Name_Buffer (1 .. Name_Len) :=
5660 Directory (Directory'First .. Directory'Last - 3);
5663 if Current_Verbosity = High then
5664 Write_Str ("Looking for all subdirectories of """);
5665 Write_Str (Name_Buffer (1 .. Name_Len));
5670 Base_Dir : constant File_Name_Type := Name_Find;
5671 Root_Dir : constant String :=
5673 (Name => Get_Name_String (Base_Dir),
5675 Get_Name_String (Data.Directory.Display_Name),
5676 Resolve_Links => False,
5677 Case_Sensitive => True);
5680 if Root_Dir'Length = 0 then
5681 Err_Vars.Error_Msg_File_1 := Base_Dir;
5683 if Location = No_Location then
5686 "{ is not a valid directory.",
5691 "{ is not a valid directory.",
5696 -- We have an existing directory, we register it and all of
5697 -- its subdirectories.
5699 if Current_Verbosity = High then
5700 Write_Line ("Looking for source directories:");
5703 Name_Len := Root_Dir'Length;
5704 Name_Buffer (1 .. Name_Len) := Root_Dir;
5705 Recursive_Find_Dirs (Name_Find);
5707 if Current_Verbosity = High then
5708 Write_Line ("End of looking for source directories.");
5713 -- We have a single directory
5717 Path_Name : Path_Name_Type;
5718 Display_Path_Name : Path_Name_Type;
5719 List : String_List_Id;
5720 Prev : String_List_Id;
5724 (Project => Project,
5727 Parent => Data.Directory.Display_Name,
5729 Display => Display_Path_Name,
5730 Current_Dir => Current_Dir);
5732 if Path_Name = No_Path then
5733 Err_Vars.Error_Msg_File_1 := From;
5735 if Location = No_Location then
5738 "{ is not a valid directory",
5743 "{ is not a valid directory",
5749 Path : constant String :=
5750 Get_Name_String (Path_Name) &
5751 Directory_Separator;
5752 Last_Path : constant Natural :=
5753 Compute_Directory_Last (Path);
5755 Display_Path : constant String :=
5757 (Display_Path_Name) &
5758 Directory_Separator;
5759 Last_Display_Path : constant Natural :=
5760 Compute_Directory_Last
5762 Display_Path_Id : Name_Id;
5766 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5767 Path_Id := Name_Find;
5769 Add_Str_To_Name_Buffer
5771 (Display_Path'First .. Last_Display_Path));
5772 Display_Path_Id := Name_Find;
5776 -- As it is an existing directory, we add it to the
5777 -- list of directories.
5779 String_Element_Table.Increment_Last
5780 (In_Tree.String_Elements);
5784 Display_Value => Display_Path_Id,
5785 Location => No_Location,
5787 Next => Nil_String);
5789 if Last_Source_Dir = Nil_String then
5791 -- This is the first source directory
5793 Data.Source_Dirs := String_Element_Table.Last
5794 (In_Tree.String_Elements);
5797 -- We already have source directories, link the
5798 -- previous last to the new one.
5800 In_Tree.String_Elements.Table
5801 (Last_Source_Dir).Next :=
5802 String_Element_Table.Last
5803 (In_Tree.String_Elements);
5806 -- And register this source directory as the new last
5808 Last_Source_Dir := String_Element_Table.Last
5809 (In_Tree.String_Elements);
5810 In_Tree.String_Elements.Table
5811 (Last_Source_Dir) := Element;
5814 -- Remove source dir, if present
5816 List := Data.Source_Dirs;
5819 -- Look for source dir in current list
5821 while List /= Nil_String loop
5822 Element := In_Tree.String_Elements.Table (List);
5823 exit when Element.Value = Path_Id;
5825 List := Element.Next;
5828 if List /= Nil_String then
5829 -- Source dir was found, remove it from the list
5831 if Prev = Nil_String then
5833 In_Tree.String_Elements.Table (List).Next;
5836 In_Tree.String_Elements.Table (Prev).Next :=
5837 In_Tree.String_Elements.Table (List).Next;
5845 end Find_Source_Dirs;
5847 -- Start of processing for Get_Directories
5850 if Current_Verbosity = High then
5851 Write_Line ("Starting to look for directories");
5854 -- Set the object directory to its default which may be nil, if there
5855 -- is no sources in the project.
5857 if (((not Source_Files.Default)
5858 and then Source_Files.Values = Nil_String)
5860 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5862 ((not Languages.Default) and then Languages.Values = Nil_String))
5863 and then Data.Extends = No_Project
5865 Data.Object_Directory := No_Path_Information;
5868 Data.Object_Directory := Data.Directory;
5871 -- Check the object directory
5873 if Object_Dir.Value /= Empty_String then
5874 Get_Name_String (Object_Dir.Value);
5876 if Name_Len = 0 then
5879 "Object_Dir cannot be empty",
5880 Object_Dir.Location);
5883 -- We check that the specified object directory does exist
5888 File_Name_Type (Object_Dir.Value),
5889 Data.Directory.Display_Name,
5890 Data.Object_Directory.Name,
5891 Data.Object_Directory.Display_Name,
5893 Location => Object_Dir.Location,
5894 Current_Dir => Current_Dir,
5895 Externally_Built => Data.Externally_Built);
5897 if Data.Object_Directory = No_Path_Information then
5899 -- The object directory does not exist, report an error if the
5900 -- project is not externally built.
5902 if not Data.Externally_Built then
5903 Err_Vars.Error_Msg_File_1 :=
5904 File_Name_Type (Object_Dir.Value);
5907 "the object directory { cannot be found",
5911 -- Do not keep a nil Object_Directory. Set it to the specified
5912 -- (relative or absolute) path. This is for the benefit of
5913 -- tools that recover from errors; for example, these tools
5914 -- could create the non existent directory.
5916 Data.Object_Directory.Display_Name :=
5917 Path_Name_Type (Object_Dir.Value);
5918 Data.Object_Directory.Name :=
5919 Path_Name_Type (Canonical_Case_File_Name (Object_Dir.Value));
5923 elsif Data.Object_Directory /= No_Path_Information and then
5927 Name_Buffer (1) := '.';
5932 Data.Directory.Display_Name,
5933 Data.Object_Directory.Name,
5934 Data.Object_Directory.Display_Name,
5936 Location => Object_Dir.Location,
5937 Current_Dir => Current_Dir,
5938 Externally_Built => Data.Externally_Built);
5941 if Current_Verbosity = High then
5942 if Data.Object_Directory = No_Path_Information then
5943 Write_Line ("No object directory");
5946 ("Object directory",
5947 Get_Name_String (Data.Object_Directory.Display_Name));
5951 -- Check the exec directory
5953 -- We set the object directory to its default
5955 Data.Exec_Directory := Data.Object_Directory;
5957 if Exec_Dir.Value /= Empty_String then
5958 Get_Name_String (Exec_Dir.Value);
5960 if Name_Len = 0 then
5963 "Exec_Dir cannot be empty",
5967 -- We check that the specified exec directory does exist
5972 File_Name_Type (Exec_Dir.Value),
5973 Data.Directory.Display_Name,
5974 Data.Exec_Directory.Name,
5975 Data.Exec_Directory.Display_Name,
5977 Location => Exec_Dir.Location,
5978 Current_Dir => Current_Dir,
5979 Externally_Built => Data.Externally_Built);
5981 if Data.Exec_Directory = No_Path_Information then
5982 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5985 "the exec directory { cannot be found",
5991 if Current_Verbosity = High then
5992 if Data.Exec_Directory = No_Path_Information then
5993 Write_Line ("No exec directory");
5995 Write_Str ("Exec directory: """);
5996 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6001 -- Look for the source directories
6003 if Current_Verbosity = High then
6004 Write_Line ("Starting to look for source directories");
6007 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6009 if (not Source_Files.Default) and then
6010 Source_Files.Values = Nil_String
6012 Data.Source_Dirs := Nil_String;
6014 if Data.Qualifier = Standard then
6018 "a standard project cannot have no sources",
6019 Source_Files.Location);
6022 elsif Source_Dirs.Default then
6024 -- No Source_Dirs specified: the single source directory is the one
6025 -- containing the project file
6027 String_Element_Table.Increment_Last
6028 (In_Tree.String_Elements);
6029 Data.Source_Dirs := String_Element_Table.Last
6030 (In_Tree.String_Elements);
6031 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6032 (Value => Name_Id (Data.Directory.Name),
6033 Display_Value => Name_Id (Data.Directory.Display_Name),
6034 Location => No_Location,
6039 if Current_Verbosity = High then
6041 ("Single source directory",
6042 Get_Name_String (Data.Directory.Display_Name));
6045 elsif Source_Dirs.Values = Nil_String then
6046 if Data.Qualifier = Standard then
6050 "a standard project cannot have no source directories",
6051 Source_Dirs.Location);
6054 Data.Source_Dirs := Nil_String;
6058 Source_Dir : String_List_Id;
6059 Element : String_Element;
6062 -- Process the source directories for each element of the list
6064 Source_Dir := Source_Dirs.Values;
6065 while Source_Dir /= Nil_String loop
6066 Element := In_Tree.String_Elements.Table (Source_Dir);
6068 (File_Name_Type (Element.Value), Element.Location);
6069 Source_Dir := Element.Next;
6074 if not Excluded_Source_Dirs.Default
6075 and then Excluded_Source_Dirs.Values /= Nil_String
6078 Source_Dir : String_List_Id;
6079 Element : String_Element;
6082 -- Process the source directories for each element of the list
6084 Source_Dir := Excluded_Source_Dirs.Values;
6085 while Source_Dir /= Nil_String loop
6086 Element := In_Tree.String_Elements.Table (Source_Dir);
6088 (File_Name_Type (Element.Value),
6091 Source_Dir := Element.Next;
6096 if Current_Verbosity = High then
6097 Write_Line ("Putting source directories in canonical cases");
6101 Current : String_List_Id := Data.Source_Dirs;
6102 Element : String_Element;
6105 while Current /= Nil_String loop
6106 Element := In_Tree.String_Elements.Table (Current);
6107 if Element.Value /= No_Name then
6109 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
6110 In_Tree.String_Elements.Table (Current) := Element;
6113 Current := Element.Next;
6116 end Get_Directories;
6123 (Project : Project_Id;
6124 In_Tree : Project_Tree_Ref;
6125 Data : in out Project_Data)
6127 Mains : constant Variable_Value :=
6128 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6129 List : String_List_Id;
6130 Elem : String_Element;
6133 Data.Mains := Mains.Values;
6135 -- If no Mains were specified, and if we are an extending project,
6136 -- inherit the Mains from the project we are extending.
6138 if Mains.Default then
6139 if not Data.Library and then Data.Extends /= No_Project then
6141 In_Tree.Projects.Table (Data.Extends).Mains;
6144 -- In a library project file, Main cannot be specified
6146 elsif Data.Library then
6149 "a library project file cannot have Main specified",
6153 List := Mains.Values;
6154 while List /= Nil_String loop
6155 Elem := In_Tree.String_Elements.Table (List);
6157 if Length_Of_Name (Elem.Value) = 0 then
6160 "?a main cannot have an empty name",
6170 ---------------------------
6171 -- Get_Sources_From_File --
6172 ---------------------------
6174 procedure Get_Sources_From_File
6176 Location : Source_Ptr;
6177 Project : Project_Id;
6178 In_Tree : Project_Tree_Ref)
6180 File : Prj.Util.Text_File;
6181 Line : String (1 .. 250);
6183 Source_Name : File_Name_Type;
6184 Name_Loc : Name_Location;
6187 if Get_Mode = Ada_Only then
6191 if Current_Verbosity = High then
6192 Write_Str ("Opening """);
6199 Prj.Util.Open (File, Path);
6201 if not Prj.Util.Is_Valid (File) then
6202 Error_Msg (Project, In_Tree, "file does not exist", Location);
6205 -- Read the lines one by one
6207 while not Prj.Util.End_Of_File (File) loop
6208 Prj.Util.Get_Line (File, Line, Last);
6210 -- A non empty, non comment line should contain a file name
6213 and then (Last = 1 or else Line (1 .. 2) /= "--")
6216 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6217 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6218 Source_Name := Name_Find;
6220 -- Check that there is no directory information
6222 for J in 1 .. Last loop
6223 if Line (J) = '/' or else Line (J) = Directory_Separator then
6224 Error_Msg_File_1 := Source_Name;
6228 "file name cannot include directory information ({)",
6234 Name_Loc := Source_Names.Get (Source_Name);
6236 if Name_Loc = No_Name_Location then
6238 (Name => Source_Name,
6239 Location => Location,
6240 Source => No_Source,
6245 Source_Names.Set (Source_Name, Name_Loc);
6249 Prj.Util.Close (File);
6252 end Get_Sources_From_File;
6254 -----------------------
6255 -- Compute_Unit_Name --
6256 -----------------------
6258 procedure Compute_Unit_Name
6259 (File_Name : File_Name_Type;
6260 Dot_Replacement : File_Name_Type;
6261 Separate_Suffix : File_Name_Type;
6262 Body_Suffix : File_Name_Type;
6263 Spec_Suffix : File_Name_Type;
6264 Casing : Casing_Type;
6265 Kind : out Source_Kind;
6267 In_Tree : Project_Tree_Ref)
6269 Filename : constant String := Get_Name_String (File_Name);
6270 Last : Integer := Filename'Last;
6271 Sep_Len : constant Integer :=
6272 Integer (Length_Of_Name (Separate_Suffix));
6273 Body_Len : constant Integer :=
6274 Integer (Length_Of_Name (Body_Suffix));
6275 Spec_Len : constant Integer :=
6276 Integer (Length_Of_Name (Spec_Suffix));
6278 Standard_GNAT : constant Boolean :=
6279 Spec_Suffix = Default_Ada_Spec_Suffix
6281 Body_Suffix = Default_Ada_Body_Suffix;
6283 Unit_Except : Unit_Exception;
6284 Masked : Boolean := False;
6289 if Dot_Replacement = No_File then
6290 if Current_Verbosity = High then
6291 Write_Line (" No dot_replacement specified");
6296 -- Choose the longest suffix that matches. If there are several matches,
6297 -- give priority to specs, then bodies, then separates.
6299 if Separate_Suffix /= Body_Suffix
6300 and then Suffix_Matches (Filename, Separate_Suffix)
6302 Last := Filename'Last - Sep_Len;
6306 if Filename'Last - Body_Len <= Last
6307 and then Suffix_Matches (Filename, Body_Suffix)
6309 Last := Natural'Min (Last, Filename'Last - Body_Len);
6313 if Filename'Last - Spec_Len <= Last
6314 and then Suffix_Matches (Filename, Spec_Suffix)
6316 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6320 if Last = Filename'Last then
6321 if Current_Verbosity = High then
6322 Write_Line (" No matching suffix");
6327 -- Check that the casing matches
6329 if File_Names_Case_Sensitive then
6331 when All_Lower_Case =>
6332 for J in Filename'First .. Last loop
6333 if Is_Letter (Filename (J))
6334 and then not Is_Lower (Filename (J))
6336 if Current_Verbosity = High then
6337 Write_Line (" Invalid casing");
6343 when All_Upper_Case =>
6344 for J in Filename'First .. Last loop
6345 if Is_Letter (Filename (J))
6346 and then not Is_Upper (Filename (J))
6348 if Current_Verbosity = High then
6349 Write_Line (" Invalid casing");
6355 when Mixed_Case | Unknown =>
6360 -- If Dot_Replacement is not a single dot, then there should not
6361 -- be any dot in the name.
6364 Dot_Repl : constant String := Get_Name_String (Dot_Replacement);
6367 if Dot_Repl /= "." then
6368 for Index in Filename'First .. Last loop
6369 if Filename (Index) = '.' then
6370 if Current_Verbosity = High then
6371 Write_Line (" Invalid name, contains dot");
6377 Replace_Into_Name_Buffer
6378 (Filename (Filename'First .. Last), Dot_Repl, '.');
6380 Name_Len := Last - Filename'First + 1;
6381 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6383 (Source => Name_Buffer (1 .. Name_Len),
6384 Mapping => Lower_Case_Map);
6388 -- In the standard GNAT naming scheme, check for special cases: children
6389 -- or separates of A, G, I or S, and run time sources.
6391 if Standard_GNAT and then Name_Len >= 3 then
6393 S1 : constant Character := Name_Buffer (1);
6394 S2 : constant Character := Name_Buffer (2);
6395 S3 : constant Character := Name_Buffer (3);
6403 -- Children or separates of packages A, G, I or S. These names
6404 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6405 -- versions (x__... and x~...) are allowed in all platforms,
6406 -- because it is not possible to know the platform before
6407 -- processing of the project files.
6409 if S2 = '_' and then S3 = '_' then
6410 Name_Buffer (2) := '.';
6411 Name_Buffer (3 .. Name_Len - 1) :=
6412 Name_Buffer (4 .. Name_Len);
6413 Name_Len := Name_Len - 1;
6416 Name_Buffer (2) := '.';
6420 -- If it is potentially a run time source, disable filling
6421 -- of the mapping file to avoid warnings.
6423 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6429 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6430 -- that this is a valid unit name
6432 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6434 -- If there is a naming exception for the same unit, the file is not
6435 -- a source for the unit. Currently, this only applies in multi_lang
6436 -- mode, since Unit_Exceptions is no set in ada_only mode.
6438 if Unit /= No_Name then
6439 Unit_Except := Unit_Exceptions.Get (Unit);
6442 Masked := Unit_Except.Spec /= No_File
6444 Unit_Except.Spec /= File_Name;
6446 Masked := Unit_Except.Impl /= No_File
6448 Unit_Except.Impl /= File_Name;
6452 if Current_Verbosity = High then
6453 Write_Str (" """ & Filename & """ contains the ");
6456 Write_Str ("spec of a unit found in """);
6457 Write_Str (Get_Name_String (Unit_Except.Spec));
6459 Write_Str ("body of a unit found in """);
6460 Write_Str (Get_Name_String (Unit_Except.Impl));
6463 Write_Line (""" (ignored)");
6471 and then Current_Verbosity = High
6474 when Spec => Write_Str (" spec of ");
6475 when Impl => Write_Str (" body of ");
6476 when Sep => Write_Str (" sep of ");
6479 Write_Line (Get_Name_String (Unit));
6481 end Compute_Unit_Name;
6488 (In_Tree : Project_Tree_Ref;
6489 Canonical_File_Name : File_Name_Type;
6490 Naming : Naming_Data;
6491 Exception_Id : out Ada_Naming_Exception_Id;
6492 Unit_Name : out Name_Id;
6493 Unit_Kind : out Spec_Or_Body;
6494 Needs_Pragma : out Boolean)
6496 Info_Id : Ada_Naming_Exception_Id :=
6497 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6498 VMS_Name : File_Name_Type;
6502 if Info_Id = No_Ada_Naming_Exception
6503 and then Hostparm.OpenVMS
6505 VMS_Name := Canonical_File_Name;
6506 Get_Name_String (VMS_Name);
6508 if Name_Buffer (Name_Len) = '.' then
6509 Name_Len := Name_Len - 1;
6510 VMS_Name := Name_Find;
6513 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6516 if Info_Id /= No_Ada_Naming_Exception then
6517 Exception_Id := Info_Id;
6518 Unit_Name := No_Name;
6519 Unit_Kind := Specification;
6520 Needs_Pragma := True;
6522 Needs_Pragma := False;
6523 Exception_Id := No_Ada_Naming_Exception;
6525 (File_Name => Canonical_File_Name,
6526 Dot_Replacement => Naming.Dot_Replacement,
6527 Separate_Suffix => Naming.Separate_Suffix,
6528 Body_Suffix => Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6529 Spec_Suffix => Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6530 Casing => Naming.Casing,
6533 In_Tree => In_Tree);
6536 when Spec => Unit_Kind := Specification;
6537 when Impl | Sep => Unit_Kind := Body_Part;
6546 function Hash (Unit : Unit_Info) return Header_Num is
6548 return Header_Num (Unit.Unit mod 2048);
6551 -----------------------
6552 -- Is_Illegal_Suffix --
6553 -----------------------
6555 function Is_Illegal_Suffix
6556 (Suffix : File_Name_Type;
6557 Dot_Replacement : File_Name_Type) return Boolean
6559 Suffix_Str : constant String := Get_Name_String (Suffix);
6562 if Suffix_Str'Length = 0 or else Index (Suffix_Str, ".") = 0 then
6566 -- If dot replacement is a single dot, and first character of suffix is
6569 if Get_Name_String (Dot_Replacement) = "."
6570 and then Suffix_Str (Suffix_Str'First) = '.'
6572 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6574 -- If there is another dot
6576 if Suffix_Str (Index) = '.' then
6578 -- It is illegal to have a letter following the initial dot
6580 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6586 end Is_Illegal_Suffix;
6588 ----------------------
6589 -- Locate_Directory --
6590 ----------------------
6592 procedure Locate_Directory
6593 (Project : Project_Id;
6594 In_Tree : Project_Tree_Ref;
6595 Name : File_Name_Type;
6596 Parent : Path_Name_Type;
6597 Dir : out Path_Name_Type;
6598 Display : out Path_Name_Type;
6599 Create : String := "";
6600 Current_Dir : String;
6601 Location : Source_Ptr := No_Location;
6602 Externally_Built : Boolean := False)
6604 The_Parent : constant String :=
6605 Get_Name_String (Parent) & Directory_Separator;
6607 The_Parent_Last : constant Natural :=
6608 Compute_Directory_Last (The_Parent);
6610 Full_Name : File_Name_Type;
6612 The_Name : File_Name_Type;
6615 Get_Name_String (Name);
6617 -- Add Subdirs.all if it is a directory that may be created and
6618 -- Subdirs is not null;
6620 if Create /= "" and then Subdirs /= null then
6621 if Name_Buffer (Name_Len) /= Directory_Separator then
6622 Add_Char_To_Name_Buffer (Directory_Separator);
6625 Add_Str_To_Name_Buffer (Subdirs.all);
6628 -- Convert '/' to directory separator (for Windows)
6630 for J in 1 .. Name_Len loop
6631 if Name_Buffer (J) = '/' then
6632 Name_Buffer (J) := Directory_Separator;
6636 The_Name := Name_Find;
6638 if Current_Verbosity = High then
6639 Write_Str ("Locate_Directory (""");
6640 Write_Str (Get_Name_String (The_Name));
6641 Write_Str (""", """);
6642 Write_Str (The_Parent);
6649 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6650 Full_Name := The_Name;
6654 Add_Str_To_Name_Buffer
6655 (The_Parent (The_Parent'First .. The_Parent_Last));
6656 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6657 Full_Name := Name_Find;
6661 Full_Path_Name : String_Access :=
6662 new String'(Get_Name_String (Full_Name));
6665 if (Setup_Projects or else Subdirs /= null)
6666 and then Create'Length > 0
6668 if not Is_Directory (Full_Path_Name.all) then
6669 -- If project is externally built, do not create a subdir,
6670 -- use the specified directory, without the subdir.
6672 if Externally_Built then
6673 if Is_Absolute_Path (Get_Name_String (Name)) then
6674 Get_Name_String (Name);
6678 Add_Str_To_Name_Buffer
6679 (The_Parent (The_Parent'First .. The_Parent_Last));
6680 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6683 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6687 Create_Path (Full_Path_Name.all);
6689 if not Quiet_Output then
6691 Write_Str (" directory """);
6692 Write_Str (Full_Path_Name.all);
6693 Write_Line (""" created");
6700 "could not create " & Create &
6701 " directory " & Full_Path_Name.all,
6708 if Is_Directory (Full_Path_Name.all) then
6710 Normed : constant String :=
6712 (Full_Path_Name.all,
6713 Directory => Current_Dir,
6714 Resolve_Links => False,
6715 Case_Sensitive => True);
6717 Canonical_Path : constant String :=
6720 Directory => Current_Dir,
6722 Opt.Follow_Links_For_Dirs,
6723 Case_Sensitive => False);
6726 Name_Len := Normed'Length;
6727 Name_Buffer (1 .. Name_Len) := Normed;
6728 Display := Name_Find;
6730 Name_Len := Canonical_Path'Length;
6731 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6736 Free (Full_Path_Name);
6738 end Locate_Directory;
6740 ---------------------------
6741 -- Find_Excluded_Sources --
6742 ---------------------------
6744 procedure Find_Excluded_Sources
6745 (Project : Project_Id;
6746 In_Tree : Project_Tree_Ref;
6747 Data : Project_Data)
6749 Excluded_Source_List_File : constant Variable_Value :=
6751 (Name_Excluded_Source_List_File,
6752 Data.Decl.Attributes,
6755 Excluded_Sources : Variable_Value := Util.Value_Of
6756 (Name_Excluded_Source_Files,
6757 Data.Decl.Attributes,
6760 Current : String_List_Id;
6761 Element : String_Element;
6762 Location : Source_Ptr;
6763 Name : File_Name_Type;
6764 File : Prj.Util.Text_File;
6765 Line : String (1 .. 300);
6767 Locally_Removed : Boolean := False;
6770 -- If Excluded_Source_Files is not declared, check
6771 -- Locally_Removed_Files.
6773 if Excluded_Sources.Default then
6774 Locally_Removed := True;
6777 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
6780 Excluded_Sources_Htable.Reset;
6782 -- If there are excluded sources, put them in the table
6784 if not Excluded_Sources.Default then
6785 if not Excluded_Source_List_File.Default then
6786 if Locally_Removed then
6789 "?both attributes Locally_Removed_Files and " &
6790 "Excluded_Source_List_File are present",
6791 Excluded_Source_List_File.Location);
6795 "?both attributes Excluded_Source_Files and " &
6796 "Excluded_Source_List_File are present",
6797 Excluded_Source_List_File.Location);
6801 Current := Excluded_Sources.Values;
6802 while Current /= Nil_String loop
6803 Element := In_Tree.String_Elements.Table (Current);
6804 Name := Canonical_Case_File_Name (Element.Value);
6806 -- If the element has no location, then use the location
6807 -- of Excluded_Sources to report possible errors.
6809 if Element.Location = No_Location then
6810 Location := Excluded_Sources.Location;
6812 Location := Element.Location;
6815 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6816 Current := Element.Next;
6819 elsif not Excluded_Source_List_File.Default then
6820 Location := Excluded_Source_List_File.Location;
6823 Source_File_Path_Name : constant String :=
6826 (Excluded_Source_List_File.Value),
6827 Data.Directory.Name);
6830 if Source_File_Path_Name'Length = 0 then
6831 Err_Vars.Error_Msg_File_1 :=
6832 File_Name_Type (Excluded_Source_List_File.Value);
6835 "file with excluded sources { does not exist",
6836 Excluded_Source_List_File.Location);
6841 Prj.Util.Open (File, Source_File_Path_Name);
6843 if not Prj.Util.Is_Valid (File) then
6845 (Project, In_Tree, "file does not exist", Location);
6847 -- Read the lines one by one
6849 while not Prj.Util.End_Of_File (File) loop
6850 Prj.Util.Get_Line (File, Line, Last);
6852 -- A non empty, non comment line should contain a file
6856 and then (Last = 1 or else Line (1 .. 2) /= "--")
6859 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6860 Canonical_Case_File_Name
6861 (Name_Buffer (1 .. Name_Len));
6864 -- Check that there is no directory information
6866 for J in 1 .. Last loop
6868 or else Line (J) = Directory_Separator
6870 Error_Msg_File_1 := Name;
6874 "file name cannot include " &
6875 "directory information ({)",
6881 Excluded_Sources_Htable.Set
6882 (Name, (Name, False, Location));
6886 Prj.Util.Close (File);
6891 end Find_Excluded_Sources;
6897 procedure Find_Sources
6898 (Current_Dir : String;
6899 Project : Project_Id;
6900 In_Tree : Project_Tree_Ref;
6901 Data : in out Project_Data)
6903 Sources : constant Variable_Value :=
6906 Data.Decl.Attributes,
6908 Source_List_File : constant Variable_Value :=
6910 (Name_Source_List_File,
6911 Data.Decl.Attributes,
6913 Name_Loc : Name_Location;
6914 Has_Explicit_Sources : Boolean;
6917 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6919 (Source_List_File.Kind = Single,
6920 "Source_List_File is not a single string");
6922 -- If the user has specified a Sources attribute
6924 if not Sources.Default then
6925 if not Source_List_File.Default then
6928 "?both attributes source_files and " &
6929 "source_list_file are present",
6930 Source_List_File.Location);
6933 -- Sources is a list of file names
6936 Current : String_List_Id := Sources.Values;
6937 Element : String_Element;
6938 Location : Source_Ptr;
6939 Name : File_Name_Type;
6942 if Get_Mode = Multi_Language then
6943 if Current = Nil_String then
6944 Data.Languages := No_Language_Index;
6946 -- This project contains no source. For projects that
6947 -- don't extend other projects, this also means that
6948 -- there is no need for an object directory, if not
6951 if Data.Extends = No_Project
6952 and then Data.Object_Directory = Data.Directory
6954 Data.Object_Directory := No_Path_Information;
6959 while Current /= Nil_String loop
6960 Element := In_Tree.String_Elements.Table (Current);
6961 Name := Canonical_Case_File_Name (Element.Value);
6962 Get_Name_String (Element.Value);
6964 -- If the element has no location, then use the
6965 -- location of Sources to report possible errors.
6967 if Element.Location = No_Location then
6968 Location := Sources.Location;
6970 Location := Element.Location;
6973 -- Check that there is no directory information
6975 for J in 1 .. Name_Len loop
6976 if Name_Buffer (J) = '/'
6977 or else Name_Buffer (J) = Directory_Separator
6979 Error_Msg_File_1 := Name;
6983 "file name cannot include directory " &
6990 -- In Multi_Language mode, check whether the file is
6991 -- already there: the same file name may be in the list; if
6992 -- the source is missing, the error will be on the first
6993 -- mention of the source file name.
6997 Name_Loc := No_Name_Location;
6998 when Multi_Language =>
6999 Name_Loc := Source_Names.Get (Name);
7002 if Name_Loc = No_Name_Location then
7005 Location => Location,
7006 Source => No_Source,
7009 Source_Names.Set (Name, Name_Loc);
7012 Current := Element.Next;
7015 Has_Explicit_Sources := True;
7018 -- If we have no Source_Files attribute, check the Source_List_File
7021 elsif not Source_List_File.Default then
7023 -- Source_List_File is the name of the file
7024 -- that contains the source file names
7027 Source_File_Path_Name : constant String :=
7029 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7032 Has_Explicit_Sources := True;
7034 if Source_File_Path_Name'Length = 0 then
7035 Err_Vars.Error_Msg_File_1 :=
7036 File_Name_Type (Source_List_File.Value);
7039 "file with sources { does not exist",
7040 Source_List_File.Location);
7043 Get_Sources_From_File
7044 (Source_File_Path_Name, Source_List_File.Location,
7050 -- Neither Source_Files nor Source_List_File has been
7051 -- specified. Find all the files that satisfy the naming
7052 -- scheme in all the source directories.
7054 Has_Explicit_Sources := False;
7057 if Get_Mode = Ada_Only then
7059 (Project, In_Tree, Data, Current_Dir,
7060 Explicit_Sources_Only => Has_Explicit_Sources);
7064 (Project, In_Tree, Data,
7066 Sources.Default and then Source_List_File.Default);
7069 -- Check if all exceptions have been found.
7070 -- For Ada, it is an error if an exception is not found.
7071 -- For other language, the source is simply removed.
7075 Iter : Source_Iterator;
7078 Iter := For_Each_Source (In_Tree, Project);
7080 Source := Prj.Element (Iter);
7081 exit when Source = No_Source;
7083 if Source.Naming_Exception
7084 and then Source.Path = No_Path_Information
7086 if Source.Unit /= No_Name then
7087 Error_Msg_Name_1 := Name_Id (Source.Display_File);
7088 Error_Msg_Name_2 := Name_Id (Source.Unit);
7091 "source file %% for unit %% not found",
7095 Remove_Source (Source, No_Source);
7102 -- It is an error if a source file name in a source list or in a
7103 -- source list file is not found.
7105 if Has_Explicit_Sources then
7108 First_Error : Boolean := True;
7110 NL := Source_Names.Get_First;
7111 while NL /= No_Name_Location loop
7112 if not NL.Found then
7113 Err_Vars.Error_Msg_File_1 := NL.Name;
7118 "source file { cannot be found",
7120 First_Error := False;
7125 "\source file { cannot be found",
7130 NL := Source_Names.Get_Next;
7135 if Get_Mode = Ada_Only
7136 and then Data.Extends = No_Project
7138 -- We should have found at least one source, if not report an error
7140 if not Has_Ada_Sources (Data) then
7142 (Project, "Ada", In_Tree, Source_List_File.Location);
7147 ----------------------
7148 -- Find_Ada_Sources --
7149 ----------------------
7151 procedure Find_Ada_Sources
7152 (Project : Project_Id;
7153 In_Tree : Project_Tree_Ref;
7154 Data : in out Project_Data;
7155 Current_Dir : String;
7156 Explicit_Sources_Only : Boolean)
7158 Source_Dir : String_List_Id;
7159 Element : String_Element;
7161 Current_Source : String_List_Id := Nil_String;
7162 Dir_Has_Source : Boolean := False;
7166 if Current_Verbosity = High then
7167 Write_Line ("Looking for Ada sources:");
7170 -- We look in all source directories for the file names in the hash
7171 -- table Source_Names.
7173 Source_Dir := Data.Source_Dirs;
7174 while Source_Dir /= Nil_String loop
7175 Dir_Has_Source := False;
7176 Element := In_Tree.String_Elements.Table (Source_Dir);
7179 Dir_Path : constant String :=
7180 Get_Name_String (Element.Display_Value) & Directory_Separator;
7181 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
7183 if Current_Verbosity = High then
7184 Write_Line ("checking directory """ & Dir_Path & """");
7187 -- Look for all files in the current source directory
7189 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
7192 Read (Dir, Name_Buffer, Name_Len);
7193 exit when Name_Len = 0;
7195 if Current_Verbosity = High then
7196 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7200 Name : constant File_Name_Type := Name_Find;
7201 Canonical_Name : File_Name_Type;
7203 -- ??? We could probably optimize the following call:
7204 -- we need to resolve links only once for the
7205 -- directory itself, and then do a single call to
7206 -- readlink() for each file. Unfortunately that would
7207 -- require a change in Normalize_Pathname so that it
7208 -- has the option of not resolving links for its
7209 -- Directory parameter, only for Name.
7211 Path : constant String :=
7213 (Name => Name_Buffer (1 .. Name_Len),
7214 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7215 Resolve_Links => Opt.Follow_Links_For_Files,
7216 Case_Sensitive => True);
7218 Path_Name : Path_Name_Type;
7219 To_Record : Boolean := False;
7220 Location : Source_Ptr;
7223 -- If the file was listed in the explicit list of sources,
7224 -- mark it as such (since we'll need to report an error when
7225 -- an explicit source was not found)
7227 if Explicit_Sources_Only then
7228 Canonical_Name := Canonical_Case_File_Name
7230 NL := Source_Names.Get (Canonical_Name);
7231 To_Record := NL /= No_Name_Location and then not NL.Found;
7234 Location := NL.Location;
7235 Source_Names.Set (Canonical_Name, NL);
7240 Location := No_Location;
7244 Name_Len := Path'Length;
7245 Name_Buffer (1 .. Name_Len) := Path;
7246 Path_Name := Name_Find;
7248 if Current_Verbosity = High then
7249 Write_Line (" recording " & Get_Name_String (Name));
7252 -- Register the source if it is an Ada compilation unit
7256 Path_Name => Path_Name,
7260 Location => Location,
7261 Current_Source => Current_Source,
7262 Source_Recorded => Dir_Has_Source,
7263 Current_Dir => Current_Dir);
7276 if Dir_Has_Source then
7277 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7280 Source_Dir := Element.Next;
7283 if Current_Verbosity = High then
7284 Write_Line ("End looking for sources");
7286 end Find_Ada_Sources;
7288 -------------------------------
7289 -- Check_File_Naming_Schemes --
7290 -------------------------------
7292 procedure Check_File_Naming_Schemes
7293 (In_Tree : Project_Tree_Ref;
7294 Data : in out Project_Data;
7295 File_Name : File_Name_Type;
7296 Alternate_Languages : out Alternate_Language_Id;
7297 Language : out Language_Ptr;
7298 Language_Name : out Name_Id;
7299 Display_Language_Name : out Name_Id;
7301 Lang_Kind : out Language_Kind;
7302 Kind : out Source_Kind)
7304 Filename : constant String := Get_Name_String (File_Name);
7305 Config : Language_Config;
7306 Tmp_Lang : Language_Ptr;
7308 Header_File : Boolean := False;
7309 -- True if we found at least one language for which the file is a header
7310 -- In such a case, we search for all possible languages where this is
7311 -- also a header (C and C++ for instance), since the file might be used
7312 -- for several such languages.
7314 procedure Check_File_Based_Lang;
7315 -- Does the naming scheme test for file-based languages. For those,
7316 -- there is no Unit. Just check if the file name has the implementation
7317 -- or, if it is specified, the template suffix of the language.
7319 -- Returns True if the file belongs to the current language and we
7320 -- should stop searching for matching languages. Not that a given header
7321 -- file could belong to several languages (C and C++ for instance). Thus
7322 -- if we found a header we'll check whether it matches other languages
7324 ---------------------------
7325 -- Check_File_Based_Lang --
7326 ---------------------------
7328 procedure Check_File_Based_Lang is
7331 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7335 Language := Tmp_Lang;
7337 if Current_Verbosity = High then
7338 Write_Str (" implementation of language ");
7339 Write_Line (Get_Name_String (Display_Language_Name));
7342 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7343 if Current_Verbosity = High then
7344 Write_Str (" header of language ");
7345 Write_Line (Get_Name_String (Display_Language_Name));
7349 Alternate_Language_Table.Increment_Last (In_Tree.Alt_Langs);
7350 In_Tree.Alt_Langs.Table
7351 (Alternate_Language_Table.Last (In_Tree.Alt_Langs)) :=
7352 (Language => Language,
7353 Next => Alternate_Languages);
7354 Alternate_Languages :=
7355 Alternate_Language_Table.Last (In_Tree.Alt_Langs);
7358 Header_File := True;
7361 Language := Tmp_Lang;
7364 end Check_File_Based_Lang;
7366 -- Start of processing for Check_File_Naming_Schemes
7369 Language := No_Language_Index;
7370 Alternate_Languages := No_Alternate_Language;
7371 Display_Language_Name := No_Name;
7373 Lang_Kind := File_Based;
7376 Tmp_Lang := Data.Languages;
7377 while Tmp_Lang /= No_Language_Index loop
7378 Language_Name := Tmp_Lang.Name;
7380 if Current_Verbosity = High then
7382 (" Testing language "
7383 & Get_Name_String (Language_Name)
7384 & " Header_File=" & Header_File'Img);
7387 Display_Language_Name := Tmp_Lang.Display_Name;
7388 Config := Tmp_Lang.Config;
7389 Lang_Kind := Config.Kind;
7393 Check_File_Based_Lang;
7394 exit when Kind = Impl;
7398 -- We know it belongs to a least a file_based language, no
7399 -- need to check unit-based ones.
7401 if not Header_File then
7403 (File_Name => File_Name,
7404 Dot_Replacement => Config.Naming_Data.Dot_Replacement,
7405 Separate_Suffix => Config.Naming_Data.Separate_Suffix,
7406 Body_Suffix => Config.Naming_Data.Body_Suffix,
7407 Spec_Suffix => Config.Naming_Data.Spec_Suffix,
7408 Casing => Config.Naming_Data.Casing,
7411 In_Tree => In_Tree);
7413 if Unit /= No_Name then
7414 Language := Tmp_Lang;
7420 Tmp_Lang := Tmp_Lang.Next;
7423 if Language = No_Language_Index
7424 and then Current_Verbosity = High
7426 Write_Line (" not a source of any language");
7428 end Check_File_Naming_Schemes;
7434 procedure Check_File
7435 (Project : Project_Id;
7436 In_Tree : Project_Tree_Ref;
7437 Data : in out Project_Data;
7439 File_Name : File_Name_Type;
7440 Display_File_Name : File_Name_Type;
7441 Source_Directory : String;
7442 For_All_Sources : Boolean)
7444 Display_Path : constant String :=
7447 Directory => Source_Directory,
7448 Resolve_Links => Opt.Follow_Links_For_Files,
7449 Case_Sensitive => True);
7451 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7452 Path_Id : Path_Name_Type;
7453 Display_Path_Id : Path_Name_Type;
7454 Check_Name : Boolean := False;
7455 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
7456 Language : Language_Ptr;
7458 Other_Part : Source_Id;
7460 Src_Ind : Source_File_Index;
7462 Source_To_Replace : Source_Id := No_Source;
7464 Language_Name : Name_Id;
7465 Display_Language_Name : Name_Id;
7466 Lang_Kind : Language_Kind;
7467 Kind : Source_Kind := Spec;
7468 Iter : Source_Iterator;
7471 Name_Len := Display_Path'Length;
7472 Name_Buffer (1 .. Name_Len) := Display_Path;
7473 Display_Path_Id := Name_Find;
7475 if Osint.File_Names_Case_Sensitive then
7476 Path_Id := Display_Path_Id;
7478 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7479 Path_Id := Name_Find;
7482 if Name_Loc = No_Name_Location then
7483 Check_Name := For_All_Sources;
7486 if Name_Loc.Found then
7488 -- Check if it is OK to have the same file name in several
7489 -- source directories.
7491 if not Data.Known_Order_Of_Source_Dirs then
7492 Error_Msg_File_1 := File_Name;
7495 "{ is found in several source directories",
7500 Name_Loc.Found := True;
7502 Source_Names.Set (File_Name, Name_Loc);
7504 if Name_Loc.Source = No_Source then
7508 Name_Loc.Source.Path := (Path_Id, Display_Path_Id);
7510 Source_Paths_Htable.Set
7511 (In_Tree.Source_Paths_HT,
7515 -- Check if this is a subunit
7517 if Name_Loc.Source.Unit /= No_Name
7518 and then Name_Loc.Source.Kind = Impl
7520 Src_Ind := Sinput.P.Load_Project_File
7521 (Get_Name_String (Path_Id));
7523 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7524 Name_Loc.Source.Kind := Sep;
7532 Other_Part := No_Source;
7534 Check_File_Naming_Schemes
7535 (In_Tree => In_Tree,
7537 File_Name => File_Name,
7538 Alternate_Languages => Alternate_Languages,
7539 Language => Language,
7540 Language_Name => Language_Name,
7541 Display_Language_Name => Display_Language_Name,
7543 Lang_Kind => Lang_Kind,
7546 if Language = No_Language_Index then
7548 -- A file name in a list must be a source of a language
7550 if Name_Loc.Found then
7551 Error_Msg_File_1 := File_Name;
7555 "language unknown for {",
7560 -- Check if the same file name or unit is used in the prj tree
7562 Iter := For_Each_Source (In_Tree);
7565 Source := Prj.Element (Iter);
7566 exit when Source = No_Source;
7569 and then Source.Unit = Unit
7571 ((Source.Kind = Spec and then Kind = Impl)
7573 (Source.Kind = Impl and then Kind = Spec))
7575 Other_Part := Source;
7577 elsif (Unit /= No_Name
7578 and then Source.Unit = Unit
7582 (Source.Kind = Sep and then Kind = Impl)
7584 (Source.Kind = Impl and then Kind = Sep)))
7586 (Unit = No_Name and then Source.File = File_Name)
7588 -- Duplication of file/unit in same project is only
7589 -- allowed if order of source directories is known.
7591 if Project = Source.Project then
7592 if Data.Known_Order_Of_Source_Dirs then
7595 elsif Unit /= No_Name then
7596 Error_Msg_Name_1 := Unit;
7598 (Project, In_Tree, "duplicate unit %%",
7603 Error_Msg_File_1 := File_Name;
7605 (Project, In_Tree, "duplicate source file name {",
7610 -- Do not allow the same unit name in different
7611 -- projects, except if one is extending the other.
7613 -- For a file based language, the same file name
7614 -- replaces a file in a project being extended, but
7615 -- it is allowed to have the same file name in
7616 -- unrelated projects.
7619 (Project, Source.Project, In_Tree)
7621 Source_To_Replace := Source;
7623 elsif Unit /= No_Name
7624 and then not Source.Locally_Removed
7626 Error_Msg_Name_1 := Unit;
7629 "unit %% cannot belong to several projects",
7633 In_Tree.Projects.Table (Project).Name;
7634 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
7636 (Project, In_Tree, "\ project %%, %%", No_Location);
7639 In_Tree.Projects.Table (Source.Project).Name;
7640 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7642 (Project, In_Tree, "\ project %%, %%", No_Location);
7656 Lang_Id => Language,
7657 Lang_Kind => Lang_Kind,
7659 Alternate_Languages => Alternate_Languages,
7660 File_Name => File_Name,
7661 Display_File => Display_File_Name,
7662 Other_Part => Other_Part,
7665 Display_Path => Display_Path_Id,
7666 Source_To_Replace => Source_To_Replace);
7672 ------------------------
7673 -- Search_Directories --
7674 ------------------------
7676 procedure Search_Directories
7677 (Project : Project_Id;
7678 In_Tree : Project_Tree_Ref;
7679 Data : in out Project_Data;
7680 For_All_Sources : Boolean)
7682 Source_Dir : String_List_Id;
7683 Element : String_Element;
7685 Name : String (1 .. 1_000);
7687 File_Name : File_Name_Type;
7688 Display_File_Name : File_Name_Type;
7691 if Current_Verbosity = High then
7692 Write_Line ("Looking for sources:");
7695 -- Loop through subdirectories
7697 Source_Dir := Data.Source_Dirs;
7698 while Source_Dir /= Nil_String loop
7700 Element := In_Tree.String_Elements.Table (Source_Dir);
7701 if Element.Value /= No_Name then
7702 Get_Name_String (Element.Display_Value);
7705 Source_Directory : constant String :=
7706 Name_Buffer (1 .. Name_Len) &
7707 Directory_Separator;
7709 Dir_Last : constant Natural :=
7710 Compute_Directory_Last
7714 if Current_Verbosity = High then
7715 Write_Attr ("Source_Dir", Source_Directory);
7718 -- We look to every entry in the source directory
7720 Open (Dir, Source_Directory);
7723 Read (Dir, Name, Last);
7727 -- ??? Duplicate system call here, we just did a
7728 -- a similar one. Maybe Ada.Directories would be more
7732 (Source_Directory & Name (1 .. Last))
7734 if Current_Verbosity = High then
7735 Write_Str (" Checking ");
7736 Write_Line (Name (1 .. Last));
7740 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7741 Display_File_Name := Name_Find;
7743 if Osint.File_Names_Case_Sensitive then
7744 File_Name := Display_File_Name;
7746 Canonical_Case_File_Name
7747 (Name_Buffer (1 .. Name_Len));
7748 File_Name := Name_Find;
7753 Excluded_Sources_Htable.Get (File_Name);
7756 if FF /= No_File_Found then
7757 if not FF.Found then
7759 Excluded_Sources_Htable.Set
7762 if Current_Verbosity = High then
7763 Write_Str (" excluded source """);
7764 Write_Str (Get_Name_String (File_Name));
7771 (Project => Project,
7774 Name => Name (1 .. Last),
7775 File_Name => File_Name,
7776 Display_File_Name => Display_File_Name,
7777 Source_Directory => Source_Directory
7778 (Source_Directory'First .. Dir_Last),
7779 For_All_Sources => For_All_Sources);
7790 when Directory_Error =>
7794 Source_Dir := Element.Next;
7797 if Current_Verbosity = High then
7798 Write_Line ("end Looking for sources.");
7800 end Search_Directories;
7802 ----------------------------
7803 -- Load_Naming_Exceptions --
7804 ----------------------------
7806 procedure Load_Naming_Exceptions
7807 (Project : Project_Id;
7808 In_Tree : Project_Tree_Ref)
7811 Iter : Source_Iterator;
7814 Unit_Exceptions.Reset;
7816 Iter := For_Each_Source (In_Tree, Project);
7818 Source := Prj.Element (Iter);
7819 exit when Source = No_Source;
7821 -- An excluded file cannot also be an exception file name
7823 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7824 Error_Msg_File_1 := Source.File;
7827 "{ cannot be both excluded and an exception file name",
7831 if Current_Verbosity = High then
7832 Write_Str ("Naming exception: Putting source file ");
7833 Write_Str (Get_Name_String (Source.File));
7834 Write_Line (" in Source_Names");
7840 (Name => Source.File,
7841 Location => No_Location,
7843 Except => Source.Unit /= No_Name,
7846 -- If this is an Ada exception, record in table Unit_Exceptions
7848 if Source.Unit /= No_Name then
7850 Unit_Except : Unit_Exception :=
7851 Unit_Exceptions.Get (Source.Unit);
7854 Unit_Except.Name := Source.Unit;
7856 if Source.Kind = Spec then
7857 Unit_Except.Spec := Source.File;
7859 Unit_Except.Impl := Source.File;
7862 Unit_Exceptions.Set (Source.Unit, Unit_Except);
7868 end Load_Naming_Exceptions;
7870 ----------------------
7871 -- Look_For_Sources --
7872 ----------------------
7874 procedure Look_For_Sources
7875 (Project : Project_Id;
7876 In_Tree : Project_Tree_Ref;
7877 Data : in out Project_Data;
7878 Current_Dir : String)
7880 Iter : Source_Iterator;
7882 procedure Process_Sources_In_Multi_Language_Mode;
7883 -- Find all source files when in multi language mode
7885 procedure Mark_Excluded_Sources;
7886 -- Mark as such the sources that are declared as excluded
7888 ---------------------------
7889 -- Mark_Excluded_Sources --
7890 ---------------------------
7892 procedure Mark_Excluded_Sources is
7893 Source : Source_Id := No_Source;
7896 Excluded : File_Found := Excluded_Sources_Htable.Get_First;
7899 (Extended : Project_Id;
7901 Kind : Spec_Or_Body);
7902 -- If the current file (Excluded) belongs to the current project or
7903 -- one that the current project extends, then mark this file/unit as
7904 -- excluded. It is an error to locally remove a file from another
7912 (Extended : Project_Id;
7914 Kind : Spec_Or_Body)
7917 if Extended = Project
7918 or else Is_Extending (Project, Extended, In_Tree)
7922 if Index /= No_Unit_Index then
7923 Unit.File_Names (Kind).Path.Name := Slash;
7924 Unit.File_Names (Kind).Needs_Pragma := False;
7925 In_Tree.Units.Table (Index) := Unit;
7928 if Source /= No_Source then
7929 Source.Locally_Removed := True;
7930 Source.In_Interfaces := False;
7933 if Current_Verbosity = High then
7934 Write_Str ("Removing file ");
7935 Write_Line (Get_Name_String (Excluded.File));
7938 Add_Forbidden_File_Name (Excluded.File);
7943 "cannot remove a source from another project",
7948 -- Start of processing for Mark_Excluded_Sources
7951 while Excluded /= No_File_Found loop
7957 -- ??? This loop could be the same as for Multi_Language if
7958 -- we were setting In_Tree.First_Source when we search for
7959 -- Ada sources (basically once we have removed the use of
7960 -- Data.Ada_Sources).
7963 for Index in Unit_Table.First ..
7964 Unit_Table.Last (In_Tree.Units)
7966 Unit := In_Tree.Units.Table (Index);
7968 for Kind in Spec_Or_Body'Range loop
7969 if Unit.File_Names (Kind).Name = Excluded.File then
7970 Exclude (Unit.File_Names (Kind).Project, Index, Kind);
7974 end loop For_Each_Unit;
7976 when Multi_Language =>
7977 Iter := For_Each_Source (In_Tree);
7979 Source := Prj.Element (Iter);
7980 exit when Source = No_Source;
7982 if Source.File = Excluded.File then
7983 Exclude (Source.Project, No_Unit_Index, Specification);
7990 OK := OK or Excluded.Found;
7994 Err_Vars.Error_Msg_File_1 := Excluded.File;
7996 (Project, In_Tree, "unknown file {", Excluded.Location);
7999 Excluded := Excluded_Sources_Htable.Get_Next;
8001 end Mark_Excluded_Sources;
8003 --------------------------------------------
8004 -- Process_Sources_In_Multi_Language_Mode --
8005 --------------------------------------------
8007 procedure Process_Sources_In_Multi_Language_Mode is
8008 Iter : Source_Iterator;
8010 -- Check that two sources of this project do not have the same object
8013 Check_Object_File_Names : declare
8015 Source_Name : File_Name_Type;
8017 procedure Check_Object (Src : Source_Id);
8018 -- Check if object file name of the current source is already in
8019 -- hash table Object_File_Names. If it is, report an error. If it
8020 -- is not, put it there with the file name of the current source.
8026 procedure Check_Object (Src : Source_Id) is
8028 Source_Name := Object_File_Names.Get (Src.Object);
8030 if Source_Name /= No_File then
8031 Error_Msg_File_1 := Src.File;
8032 Error_Msg_File_2 := Source_Name;
8036 "{ and { have the same object file name",
8040 Object_File_Names.Set (Src.Object, Src.File);
8044 -- Start of processing for Check_Object_File_Names
8047 Object_File_Names.Reset;
8048 Iter := For_Each_Source (In_Tree);
8050 Src_Id := Prj.Element (Iter);
8051 exit when Src_Id = No_Source;
8053 if Src_Id.Compiled and then Src_Id.Object_Exists
8054 and then Is_Extending (Project, Src_Id.Project, In_Tree)
8056 if Src_Id.Unit = No_Name then
8057 if Src_Id.Kind = Impl then
8058 Check_Object (Src_Id);
8064 if Src_Id.Other_Part = No_Source then
8065 Check_Object (Src_Id);
8072 if Src_Id.Other_Part /= No_Source then
8073 Check_Object (Src_Id);
8076 -- Check if it is a subunit
8079 Src_Ind : constant Source_File_Index :=
8080 Sinput.P.Load_Project_File
8082 (Src_Id.Path.Name));
8084 if Sinput.P.Source_File_Is_Subunit
8089 Check_Object (Src_Id);
8099 end Check_Object_File_Names;
8100 end Process_Sources_In_Multi_Language_Mode;
8102 -- Start of processing for Look_For_Sources
8106 Find_Excluded_Sources (Project, In_Tree, Data);
8108 if (Get_Mode = Ada_Only and then Is_A_Language (Data, Name_Ada))
8109 or else (Get_Mode = Multi_Language
8110 and then Data.Languages /= No_Language_Index)
8112 if Get_Mode = Multi_Language then
8113 Load_Naming_Exceptions (Project, In_Tree);
8116 Find_Sources (Current_Dir, Project, In_Tree, Data);
8117 Mark_Excluded_Sources;
8119 if Get_Mode = Multi_Language then
8120 Process_Sources_In_Multi_Language_Mode;
8123 end Look_For_Sources;
8129 function Path_Name_Of
8130 (File_Name : File_Name_Type;
8131 Directory : Path_Name_Type) return String
8133 Result : String_Access;
8134 The_Directory : constant String := Get_Name_String (Directory);
8137 Get_Name_String (File_Name);
8140 (File_Name => Name_Buffer (1 .. Name_Len),
8141 Path => The_Directory);
8143 if Result = null then
8147 R : String := Result.all;
8150 Canonical_Case_File_Name (R);
8156 -----------------------------------
8157 -- Prepare_Ada_Naming_Exceptions --
8158 -----------------------------------
8160 procedure Prepare_Ada_Naming_Exceptions
8161 (List : Array_Element_Id;
8162 In_Tree : Project_Tree_Ref;
8163 Kind : Spec_Or_Body)
8165 Current : Array_Element_Id;
8166 Element : Array_Element;
8170 -- Traverse the list
8173 while Current /= No_Array_Element loop
8174 Element := In_Tree.Array_Elements.Table (Current);
8176 if Element.Index /= No_Name then
8179 Unit => Element.Index,
8180 Next => No_Ada_Naming_Exception);
8181 Reverse_Ada_Naming_Exceptions.Set
8182 (Unit, (Element.Value.Value, Element.Value.Index));
8184 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8185 Ada_Naming_Exception_Table.Increment_Last;
8186 Ada_Naming_Exception_Table.Table
8187 (Ada_Naming_Exception_Table.Last) := Unit;
8188 Ada_Naming_Exceptions.Set
8189 (File_Name_Type (Element.Value.Value),
8190 Ada_Naming_Exception_Table.Last);
8193 Current := Element.Next;
8195 end Prepare_Ada_Naming_Exceptions;
8197 -----------------------
8198 -- Record_Ada_Source --
8199 -----------------------
8201 procedure Record_Ada_Source
8202 (File_Name : File_Name_Type;
8203 Path_Name : Path_Name_Type;
8204 Project : Project_Id;
8205 In_Tree : Project_Tree_Ref;
8206 Data : in out Project_Data;
8207 Location : Source_Ptr;
8208 Current_Source : in out String_List_Id;
8209 Source_Recorded : in out Boolean;
8210 Current_Dir : String)
8212 Canonical_File_Name : File_Name_Type;
8213 Canonical_Path_Name : Path_Name_Type;
8215 Exception_Id : Ada_Naming_Exception_Id;
8216 Unit_Name : Name_Id;
8217 Unit_Kind : Spec_Or_Body;
8218 Unit_Ind : Int := 0;
8220 Name_Index : Name_And_Index;
8221 Needs_Pragma : Boolean;
8223 The_Location : Source_Ptr := Location;
8224 Previous_Source : constant String_List_Id := Current_Source;
8225 Except_Name : Name_And_Index := No_Name_And_Index;
8227 Unit_Prj : Unit_Project;
8229 File_Name_Recorded : Boolean := False;
8232 Canonical_File_Name := Canonical_Case_File_Name (Name_Id (File_Name));
8234 if Osint.File_Names_Case_Sensitive then
8235 Canonical_Path_Name := Path_Name;
8238 Canonical_Path : constant String :=
8240 (Get_Name_String (Path_Name),
8241 Directory => Current_Dir,
8242 Resolve_Links => Opt.Follow_Links_For_Files,
8243 Case_Sensitive => False);
8246 Add_Str_To_Name_Buffer (Canonical_Path);
8247 Canonical_Path_Name := Name_Find;
8251 -- Find out the unit name, the unit kind and if it needs
8252 -- a specific SFN pragma.
8255 (In_Tree => In_Tree,
8256 Canonical_File_Name => Canonical_File_Name,
8257 Naming => Data.Naming,
8258 Exception_Id => Exception_Id,
8259 Unit_Name => Unit_Name,
8260 Unit_Kind => Unit_Kind,
8261 Needs_Pragma => Needs_Pragma);
8263 if Exception_Id = No_Ada_Naming_Exception
8264 and then Unit_Name = No_Name
8266 if Current_Verbosity = High then
8268 Write_Str (Get_Name_String (Canonical_File_Name));
8269 Write_Line (""" is not a valid source file name (ignored).");
8273 -- Check to see if the source has been hidden by an exception,
8274 -- but only if it is not an exception.
8276 if not Needs_Pragma then
8278 Reverse_Ada_Naming_Exceptions.Get
8279 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8281 if Except_Name /= No_Name_And_Index then
8282 if Current_Verbosity = High then
8284 Write_Str (Get_Name_String (Canonical_File_Name));
8285 Write_Str (""" contains a unit that is found in """);
8286 Write_Str (Get_Name_String (Except_Name.Name));
8287 Write_Line (""" (ignored).");
8290 -- The file is not included in the source of the project since
8291 -- it is hidden by the exception. So, nothing else to do.
8298 if Exception_Id /= No_Ada_Naming_Exception then
8299 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8300 Exception_Id := Info.Next;
8301 Info.Next := No_Ada_Naming_Exception;
8302 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8304 Unit_Name := Info.Unit;
8305 Unit_Ind := Name_Index.Index;
8306 Unit_Kind := Info.Kind;
8309 -- Put the file name in the list of sources of the project
8311 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8312 In_Tree.String_Elements.Table
8313 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8314 (Value => Name_Id (Canonical_File_Name),
8315 Display_Value => Name_Id (File_Name),
8316 Location => No_Location,
8321 if Current_Source = Nil_String then
8323 String_Element_Table.Last (In_Tree.String_Elements);
8325 In_Tree.String_Elements.Table (Current_Source).Next :=
8326 String_Element_Table.Last (In_Tree.String_Elements);
8330 String_Element_Table.Last (In_Tree.String_Elements);
8332 -- Put the unit in unit list
8335 The_Unit : Unit_Index :=
8336 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8338 The_Unit_Data : Unit_Data;
8341 if Current_Verbosity = High then
8342 Write_Str (" Putting ");
8343 Write_Str (Get_Name_String (Unit_Name));
8344 Write_Line (" in the unit list.");
8347 -- The unit is already in the list, but may be it is
8348 -- only the other unit kind (spec or body), or what is
8349 -- in the unit list is a unit of a project we are extending.
8351 if The_Unit /= No_Unit_Index then
8352 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8354 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8357 The_Unit_Data.File_Names
8358 (Unit_Kind).Path.Name = Slash)
8359 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8360 or else Is_Extending
8362 The_Unit_Data.File_Names (Unit_Kind).Project,
8366 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
8368 Remove_Forbidden_File_Name
8369 (The_Unit_Data.File_Names (Unit_Kind).Name);
8372 -- Record the file name in the hash table Files_Htable
8374 Unit_Prj := (Unit => The_Unit, Project => Project);
8377 Canonical_File_Name,
8380 The_Unit_Data.File_Names (Unit_Kind) :=
8381 (Name => Canonical_File_Name,
8383 Display_Name => File_Name,
8384 Path => (Canonical_Path_Name, Path_Name),
8386 Needs_Pragma => Needs_Pragma);
8387 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8388 Source_Recorded := True;
8390 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8391 and then (Data.Known_Order_Of_Source_Dirs
8393 The_Unit_Data.File_Names
8394 (Unit_Kind).Path.Name = Canonical_Path_Name)
8396 if Previous_Source = Nil_String then
8397 Data.Ada_Sources := Nil_String;
8399 In_Tree.String_Elements.Table (Previous_Source).Next :=
8401 String_Element_Table.Decrement_Last
8402 (In_Tree.String_Elements);
8405 Current_Source := Previous_Source;
8408 -- It is an error to have two units with the same name
8409 -- and the same kind (spec or body).
8411 if The_Location = No_Location then
8413 In_Tree.Projects.Table (Project).Location;
8416 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8418 (Project, In_Tree, "duplicate unit %%", The_Location);
8420 Err_Vars.Error_Msg_Name_1 :=
8421 In_Tree.Projects.Table
8422 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
8423 Err_Vars.Error_Msg_File_1 :=
8425 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
8428 "\ project file %%, {", The_Location);
8430 Err_Vars.Error_Msg_Name_1 :=
8431 In_Tree.Projects.Table (Project).Name;
8432 Err_Vars.Error_Msg_File_1 :=
8433 File_Name_Type (Canonical_Path_Name);
8436 "\ project file %%, {", The_Location);
8439 -- It is a new unit, create a new record
8442 -- First, check if there is no other unit with this file
8443 -- name in another project. If it is, report error but note
8444 -- we do that only for the first unit in the source file.
8447 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
8449 if not File_Name_Recorded and then
8450 Unit_Prj /= No_Unit_Project
8452 Error_Msg_File_1 := File_Name;
8454 In_Tree.Projects.Table (Unit_Prj.Project).Name;
8457 "{ is already a source of project %%",
8461 Unit_Table.Increment_Last (In_Tree.Units);
8462 The_Unit := Unit_Table.Last (In_Tree.Units);
8464 (In_Tree.Units_HT, Unit_Name, The_Unit);
8465 Unit_Prj := (Unit => The_Unit, Project => Project);
8468 Canonical_File_Name,
8470 The_Unit_Data.Name := Unit_Name;
8471 The_Unit_Data.File_Names (Unit_Kind) :=
8472 (Name => Canonical_File_Name,
8474 Display_Name => File_Name,
8475 Path => (Canonical_Path_Name, Path_Name),
8477 Needs_Pragma => Needs_Pragma);
8478 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8479 Source_Recorded := True;
8484 exit when Exception_Id = No_Ada_Naming_Exception;
8485 File_Name_Recorded := True;
8488 end Record_Ada_Source;
8494 procedure Remove_Source
8496 Replaced_By : Source_Id)
8501 if Current_Verbosity = High then
8502 Write_Str ("Removing source ");
8503 Write_Line (Get_Name_String (Id.File));
8506 if Replaced_By /= No_Source then
8507 Id.Replaced_By := Replaced_By;
8508 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8511 Source := Id.Language.First_Source;
8514 Id.Language.First_Source := Id.Next_In_Lang;
8517 while Source.Next_In_Lang /= Id loop
8518 Source := Source.Next_In_Lang;
8521 Source.Next_In_Lang := Id.Next_In_Lang;
8525 -----------------------
8526 -- Report_No_Sources --
8527 -----------------------
8529 procedure Report_No_Sources
8530 (Project : Project_Id;
8532 In_Tree : Project_Tree_Ref;
8533 Location : Source_Ptr;
8534 Continuation : Boolean := False)
8537 case When_No_Sources is
8541 when Warning | Error =>
8543 Msg : constant String :=
8546 " sources in this project";
8549 Error_Msg_Warn := When_No_Sources = Warning;
8551 if Continuation then
8553 (Project, In_Tree, "\" & Msg, Location);
8557 (Project, In_Tree, Msg, Location);
8561 end Report_No_Sources;
8563 ----------------------
8564 -- Show_Source_Dirs --
8565 ----------------------
8567 procedure Show_Source_Dirs
8568 (Data : Project_Data;
8569 In_Tree : Project_Tree_Ref)
8571 Current : String_List_Id;
8572 Element : String_Element;
8575 Write_Line ("Source_Dirs:");
8577 Current := Data.Source_Dirs;
8578 while Current /= Nil_String loop
8579 Element := In_Tree.String_Elements.Table (Current);
8581 Write_Line (Get_Name_String (Element.Value));
8582 Current := Element.Next;
8585 Write_Line ("end Source_Dirs.");
8586 end Show_Source_Dirs;
8588 -------------------------
8589 -- Warn_If_Not_Sources --
8590 -------------------------
8592 -- comments needed in this body ???
8594 procedure Warn_If_Not_Sources
8595 (Project : Project_Id;
8596 In_Tree : Project_Tree_Ref;
8597 Conventions : Array_Element_Id;
8599 Extending : Boolean)
8601 Conv : Array_Element_Id;
8603 The_Unit_Id : Unit_Index;
8604 The_Unit_Data : Unit_Data;
8605 Location : Source_Ptr;
8608 Conv := Conventions;
8609 while Conv /= No_Array_Element loop
8610 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8611 Error_Msg_Name_1 := Unit;
8612 Get_Name_String (Unit);
8613 To_Lower (Name_Buffer (1 .. Name_Len));
8615 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
8616 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8618 if The_Unit_Id = No_Unit_Index then
8619 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8622 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
8624 In_Tree.Array_Elements.Table (Conv).Value.Value;
8627 if not Check_Project
8628 (The_Unit_Data.File_Names (Specification).Project,
8629 Project, In_Tree, Extending)
8633 "?source of spec of unit %% (%%)" &
8634 " cannot be found in this project",
8639 if not Check_Project
8640 (The_Unit_Data.File_Names (Body_Part).Project,
8641 Project, In_Tree, Extending)
8645 "?source of body of unit %% (%%)" &
8646 " cannot be found in this project",
8652 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8654 end Warn_If_Not_Sources;