1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
30 with Err_Vars; use Err_Vars;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
39 with Prj.Util; use Prj.Util;
41 with Snames; use Snames;
42 with Table; use Table;
43 with Targparm; use Targparm;
45 with Ada.Characters.Handling; use Ada.Characters.Handling;
46 with Ada.Directories; use Ada.Directories;
47 with Ada.Strings; use Ada.Strings;
48 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
49 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
51 package body Prj.Nmsc is
53 No_Continuation_String : aliased String := "";
54 Continuation_String : aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
68 type Name_Location is record
69 Name : File_Name_Type;
70 Location : Source_Ptr;
71 Source : Source_Id := No_Source;
72 Except : Boolean := False;
73 Found : Boolean := False;
75 -- Information about file names found in string list attribute
76 -- Source_Files or in a source list file, stored in hash table
77 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
79 No_Name_Location : constant Name_Location :=
81 Location => No_Location,
86 package Source_Names is new GNAT.HTable.Simple_HTable
87 (Header_Num => Header_Num,
88 Element => Name_Location,
89 No_Element => No_Name_Location,
90 Key => File_Name_Type,
93 -- Hash table to store file names found in string list attribute
94 -- Source_Files or in a source list file, stored in hash table
95 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97 -- More documentation needed on what unit exceptions are about ???
99 type Unit_Exception is record
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
104 -- Record special naming schemes for Ada units (name of spec file and name
105 -- of implementation file).
107 No_Unit_Exception : constant Unit_Exception :=
112 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
113 (Header_Num => Header_Num,
114 Element => Unit_Exception,
115 No_Element => No_Unit_Exception,
119 -- Hash table to store the unit exceptions.
120 -- ??? Seems to be used only by the multi_lang mode
121 -- ??? Should not be a global array, but stored in the project_data
123 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
124 (Header_Num => Header_Num,
130 -- Hash table to store recursive source directories, to avoid looking
131 -- several times, and to avoid cycles that may be introduced by symbolic
134 type Ada_Naming_Exception_Id is new Nat;
135 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
137 type Unit_Info is record
140 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
149 Table_Increment => 100,
150 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
152 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
153 (Header_Num => Header_Num,
154 Element => Ada_Naming_Exception_Id,
155 No_Element => No_Ada_Naming_Exception,
156 Key => File_Name_Type,
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
161 -- ??? This is for ada_only mode, we should be able to merge with
162 -- Unit_Exceptions table, used by multi_lang mode.
164 package Object_File_Names is new GNAT.HTable.Simple_HTable
165 (Header_Num => Header_Num,
166 Element => File_Name_Type,
167 No_Element => No_File,
168 Key => File_Name_Type,
171 -- A hash table to store the object file names for a project, to check that
172 -- two different sources have different object file names.
174 type File_Found is record
175 File : File_Name_Type := No_File;
176 Found : Boolean := False;
177 Location : Source_Ptr := No_Location;
179 No_File_Found : constant File_Found := (No_File, False, No_Location);
180 -- Comments needed ???
182 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
183 (Header_Num => Header_Num,
184 Element => File_Found,
185 No_Element => No_File_Found,
186 Key => File_Name_Type,
189 -- A hash table to store the excluded files, if any. This is filled by
190 -- Find_Excluded_Sources below.
192 procedure Find_Excluded_Sources
193 (Project : Project_Id;
194 In_Tree : Project_Tree_Ref;
195 Data : Project_Data);
196 -- Find the list of files that should not be considered as source files
197 -- for this project. Sets the list in the Excluded_Sources_Htable.
199 function Hash (Unit : Unit_Info) return Header_Num;
201 type Name_And_Index is record
202 Name : Name_Id := No_Name;
205 No_Name_And_Index : constant Name_And_Index :=
206 (Name => No_Name, Index => 0);
208 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
209 (Header_Num => Header_Num,
210 Element => Name_And_Index,
211 No_Element => No_Name_And_Index,
215 -- A table to check if a unit with an exceptional name will hide a source
216 -- with a file name following the naming convention.
218 procedure Load_Naming_Exceptions
219 (Project : Project_Id;
220 In_Tree : Project_Tree_Ref;
221 Data : in out Project_Data);
222 -- All source files in Data.First_Source are considered as naming
223 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
228 Data : in out Project_Data;
229 In_Tree : Project_Tree_Ref;
230 Project : Project_Id;
232 Lang_Id : Language_Index;
234 File_Name : File_Name_Type;
235 Display_File : File_Name_Type;
236 Lang_Kind : Language_Kind;
237 Naming_Exception : Boolean := False;
238 Path : Path_Name_Type := No_Path;
239 Display_Path : Path_Name_Type := No_Path;
240 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
241 Other_Part : Source_Id := No_Source;
242 Unit : Name_Id := No_Name;
244 Source_To_Replace : Source_Id := No_Source);
245 -- Add a new source to the different lists: list of all sources in the
246 -- project tree, list of source of a project and list of sources of a
249 -- If Path is specified, the file is also added to Source_Paths_HT.
250 -- If Source_To_Replace is specified, it points to the source in the
251 -- extended project that the new file is overriding.
253 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
254 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
255 -- This alters Name_Buffer
257 function Suffix_Matches
259 Suffix : File_Name_Type) return Boolean;
260 -- True if the filename ends with the given suffix. It always returns False
261 -- if Suffix is No_Name
263 procedure Replace_Into_Name_Buffer
266 Replacement : Character);
267 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
268 -- converted to lower-case at the same time.
270 function ALI_File_Name (Source : String) return String;
271 -- Return the ALI file name corresponding to a source
273 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
274 -- Check that a name is a valid Ada unit name
276 procedure Check_Naming_Schemes
277 (Data : in out Project_Data;
278 Project : Project_Id;
279 In_Tree : Project_Tree_Ref);
280 -- Check the naming scheme part of Data
282 procedure Check_Configuration
283 (Project : Project_Id;
284 In_Tree : Project_Tree_Ref;
285 Data : in out Project_Data);
286 -- Check the configuration attributes for the project
288 procedure Check_If_Externally_Built
289 (Project : Project_Id;
290 In_Tree : Project_Tree_Ref;
291 Data : in out Project_Data);
292 -- Check attribute Externally_Built of project Project in project tree
293 -- In_Tree and modify its data Data if it has the value "true".
295 procedure Check_Interfaces
296 (Project : Project_Id;
297 In_Tree : Project_Tree_Ref;
298 Data : in out Project_Data);
299 -- If a list of sources is specified in attribute Interfaces, set
300 -- In_Interfaces only for the sources specified in the list.
302 procedure Check_Library_Attributes
303 (Project : Project_Id;
304 In_Tree : Project_Tree_Ref;
305 Current_Dir : String;
306 Data : in out Project_Data);
307 -- Check the library attributes of project Project in project tree In_Tree
308 -- and modify its data Data accordingly.
309 -- Current_Dir should represent the current directory, and is passed for
310 -- efficiency to avoid system calls to recompute it.
312 procedure Check_Package_Naming
313 (Project : Project_Id;
314 In_Tree : Project_Tree_Ref;
315 Data : in out Project_Data);
316 -- Check package Naming of project Project in project tree In_Tree and
317 -- modify its data Data accordingly.
319 procedure Check_Programming_Languages
320 (In_Tree : Project_Tree_Ref;
321 Project : Project_Id;
322 Data : in out Project_Data);
323 -- Check attribute Languages for the project with data Data in project
324 -- tree In_Tree and set the components of Data for all the programming
325 -- languages indicated in attribute Languages, if any.
327 function Check_Project
329 Root_Project : Project_Id;
330 In_Tree : Project_Tree_Ref;
331 Extending : Boolean) return Boolean;
332 -- Returns True if P is Root_Project or, if Extending is True, a project
333 -- extended by Root_Project.
335 procedure Check_Stand_Alone_Library
336 (Project : Project_Id;
337 In_Tree : Project_Tree_Ref;
338 Data : in out Project_Data;
339 Current_Dir : String;
340 Extending : Boolean);
341 -- Check if project Project in project tree In_Tree is a Stand-Alone
342 -- Library project, and modify its data Data accordingly if it is one.
343 -- Current_Dir should represent the current directory, and is passed for
344 -- efficiency to avoid system calls to recompute it.
346 procedure Check_And_Normalize_Unit_Names
347 (Project : Project_Id;
348 In_Tree : Project_Tree_Ref;
349 List : Array_Element_Id;
350 Debug_Name : String);
351 -- Check that a list of unit names contains only valid names. Casing
352 -- is normalized where appropriate.
353 -- Debug_Name is the name representing the list, and is used for debug
356 procedure Get_Path_Names_And_Record_Ada_Sources
357 (Project : Project_Id;
358 In_Tree : Project_Tree_Ref;
359 Data : in out Project_Data;
360 Current_Dir : String);
361 -- Find the path names of the source files in the Source_Names table
362 -- in the source directories and record those that are Ada sources.
364 function Get_Language_Processing_From_Lang
365 (In_Tree : Project_Tree_Ref;
367 Lang : Name_List_Index) return Language_Index;
368 -- Return the language_processing description associated for the given
371 function Compute_Directory_Last (Dir : String) return Natural;
372 -- Return the index of the last significant character in Dir. This is used
373 -- to avoid duplicate '/' (slash) characters at the end of directory names.
376 (Project : Project_Id;
377 In_Tree : Project_Tree_Ref;
379 Flag_Location : Source_Ptr);
380 -- Output an error message. If Error_Report is null, simply call
381 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
384 procedure Find_Ada_Sources
385 (Project : Project_Id;
386 In_Tree : Project_Tree_Ref;
387 Data : in out Project_Data;
388 Current_Dir : String);
389 -- Find all the Ada sources in all of the source directories of a project
390 -- Current_Dir should represent the current directory, and is passed for
391 -- efficiency to avoid system calls to recompute it.
393 procedure Search_Directories
394 (Project : Project_Id;
395 In_Tree : Project_Tree_Ref;
396 Data : in out Project_Data;
397 For_All_Sources : Boolean);
398 -- Search the source directories to find the sources.
399 -- If For_All_Sources is True, check each regular file name against the
400 -- naming schemes of the different languages. Otherwise consider only the
401 -- file names in the hash table Source_Names.
404 (Project : Project_Id;
405 In_Tree : Project_Tree_Ref;
406 Data : in out Project_Data;
408 File_Name : File_Name_Type;
409 Display_File_Name : File_Name_Type;
410 Source_Directory : String;
411 For_All_Sources : Boolean);
412 -- Check if file File_Name is a valid source of the project. This is used
413 -- in multi-language mode only.
414 -- When the file matches one of the naming schemes, it is added to
415 -- various htables through Add_Source and to Source_Paths_Htable.
417 -- Name is the name of the candidate file. It hasn't been normalized yet
418 -- and is the direct result of readdir().
420 -- File_Name is the same as Name, but has been normalized.
421 -- Display_File_Name, however, has not been normalized.
423 -- Source_Directory is the directory in which the file
424 -- was found. It hasn't been normalized (nor has had links resolved).
425 -- It should not end with a directory separator, to avoid duplicates
428 -- If For_All_Sources is True, then all possible file names are analyzed
429 -- otherwise only those currently set in the Source_Names htable.
431 procedure Check_File_Naming_Schemes
432 (In_Tree : Project_Tree_Ref;
433 Data : in out Project_Data;
434 File_Name : File_Name_Type;
435 Alternate_Languages : out Alternate_Language_Id;
436 Language : out Language_Index;
437 Language_Name : out Name_Id;
438 Display_Language_Name : out Name_Id;
440 Lang_Kind : out Language_Kind;
441 Kind : out Source_Kind);
442 -- Check if the file name File_Name conforms to one of the naming
443 -- schemes of the project.
445 -- If the file does not match one of the naming schemes, set Language
446 -- to No_Language_Index.
448 -- Filename is the name of the file being investigated. It has been
449 -- normalized (case-folded). File_Name is the same value.
451 procedure Free_Ada_Naming_Exceptions;
452 -- Free the internal hash tables used for checking naming exceptions
454 procedure Get_Directories
455 (Project : Project_Id;
456 In_Tree : Project_Tree_Ref;
457 Current_Dir : String;
458 Data : in out Project_Data);
459 -- Get the object directory, the exec directory and the source directories
462 -- Current_Dir should represent the current directory, and is passed for
463 -- efficiency to avoid system calls to recompute it.
466 (Project : Project_Id;
467 In_Tree : Project_Tree_Ref;
468 Data : in out Project_Data);
469 -- Get the mains of a project from attribute Main, if it exists, and put
470 -- them in the project data.
472 procedure Get_Sources_From_File
474 Location : Source_Ptr;
475 Project : Project_Id;
476 In_Tree : Project_Tree_Ref);
477 -- Get the list of sources from a text file and put them in hash table
480 procedure Find_Explicit_Sources
481 (Current_Dir : String;
482 Project : Project_Id;
483 In_Tree : Project_Tree_Ref;
484 Data : in out Project_Data);
485 -- Process the Source_Files and Source_List_File attributes, and store
486 -- the list of source files into the Source_Names htable.
488 -- Lang indicates which language is being processed when in Ada_Only mode
489 -- (all languages are processed anyway when in Multi_Language mode).
491 procedure Compute_Unit_Name
492 (File_Name : File_Name_Type;
493 Dot_Replacement : File_Name_Type;
494 Separate_Suffix : File_Name_Type;
495 Body_Suffix : File_Name_Type;
496 Spec_Suffix : File_Name_Type;
497 Casing : Casing_Type;
498 Kind : out Source_Kind;
500 -- Check whether the file matches the naming scheme. If it does,
501 -- compute its unit name. If Unit is set to No_Name on exit, none of the
502 -- other out parameters are relevant.
505 (In_Tree : Project_Tree_Ref;
506 Canonical_File_Name : File_Name_Type;
507 Naming : Naming_Data;
508 Exception_Id : out Ada_Naming_Exception_Id;
509 Unit_Name : out Name_Id;
510 Unit_Kind : out Spec_Or_Body;
511 Needs_Pragma : out Boolean);
512 -- Find out, from a file name, the unit name, the unit kind and if a
513 -- specific SFN pragma is needed. If the file name corresponds to no unit,
514 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
515 -- exception to the naming scheme, then Exception_Id is set to the unit or
516 -- units that the source contains.
518 function Is_Illegal_Suffix
519 (Suffix : File_Name_Type;
520 Dot_Replacement : File_Name_Type) return Boolean;
521 -- Returns True if the string Suffix cannot be used as a spec suffix, a
522 -- body suffix or a separate suffix.
524 procedure Locate_Directory
525 (Project : Project_Id;
526 In_Tree : Project_Tree_Ref;
527 Name : File_Name_Type;
528 Parent : Path_Name_Type;
529 Dir : out Path_Name_Type;
530 Display : out Path_Name_Type;
531 Create : String := "";
532 Current_Dir : String;
533 Location : Source_Ptr := No_Location;
534 Externally_Built : Boolean := False);
535 -- Locate a directory. Name is the directory name. Parent is the root
536 -- directory, if Name a relative path name. Dir is set to the canonical
537 -- case path name of the directory, and Display is the directory path name
538 -- for display purposes. If the directory does not exist and Setup_Projects
539 -- is True and Create is a non null string, an attempt is made to create
540 -- the directory. If the directory does not exist and Setup_Projects is
541 -- false, then Dir and Display are set to No_Name.
543 -- Current_Dir should represent the current directory, and is passed for
544 -- efficiency to avoid system calls to recompute it.
546 procedure Look_For_Sources
547 (Project : Project_Id;
548 In_Tree : Project_Tree_Ref;
549 Data : in out Project_Data;
550 Current_Dir : String);
551 -- Find all the sources of project Project in project tree In_Tree and
552 -- update its Data accordingly. This assumes that Data.First_Source has
553 -- been initialized with the list of excluded sources and special naming
556 -- Current_Dir should represent the current directory, and is passed for
557 -- efficiency to avoid system calls to recompute it.
559 function Path_Name_Of
560 (File_Name : File_Name_Type;
561 Directory : Path_Name_Type) return String;
562 -- Returns the path name of a (non project) file. Returns an empty string
563 -- if file cannot be found.
565 procedure Prepare_Ada_Naming_Exceptions
566 (List : Array_Element_Id;
567 In_Tree : Project_Tree_Ref;
568 Kind : Spec_Or_Body);
569 -- Prepare the internal hash tables used for checking naming exceptions
570 -- for Ada. Insert all elements of List in the tables.
572 procedure Record_Ada_Source
573 (File_Name : File_Name_Type;
574 Path_Name : Path_Name_Type;
575 Project : Project_Id;
576 In_Tree : Project_Tree_Ref;
577 Data : in out Project_Data;
578 Location : Source_Ptr;
579 Current_Source : in out String_List_Id;
580 Source_Recorded : in out Boolean;
581 Current_Dir : String);
582 -- Put a unit in the list of units of a project, if the file name
583 -- corresponds to a valid unit name.
585 -- Current_Dir should represent the current directory, and is passed for
586 -- efficiency to avoid system calls to recompute it.
588 procedure Remove_Source
590 Replaced_By : Source_Id;
591 Project : Project_Id;
592 Data : in out Project_Data;
593 In_Tree : Project_Tree_Ref);
596 procedure Report_No_Sources
597 (Project : Project_Id;
599 In_Tree : Project_Tree_Ref;
600 Location : Source_Ptr;
601 Continuation : Boolean := False);
602 -- Report an error or a warning depending on the value of When_No_Sources
603 -- when there are no sources for language Lang_Name.
605 procedure Show_Source_Dirs
606 (Data : Project_Data; In_Tree : Project_Tree_Ref);
607 -- List all the source directories of a project
609 procedure Warn_If_Not_Sources
610 (Project : Project_Id;
611 In_Tree : Project_Tree_Ref;
612 Conventions : Array_Element_Id;
614 Extending : Boolean);
615 -- Check that individual naming conventions apply to immediate sources of
616 -- the project. If not, issue a warning.
618 procedure Write_Attr (Name, Value : String);
619 -- Debug print a value for a specific property. Does nothing when not in
622 ------------------------------
623 -- Replace_Into_Name_Buffer --
624 ------------------------------
626 procedure Replace_Into_Name_Buffer
629 Replacement : Character)
631 Max : constant Integer := Str'Last - Pattern'Length + 1;
638 while J <= Str'Last loop
639 Name_Len := Name_Len + 1;
642 and then Str (J .. J + Pattern'Length - 1) = Pattern
644 Name_Buffer (Name_Len) := Replacement;
645 J := J + Pattern'Length;
648 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
652 end Replace_Into_Name_Buffer;
658 function Suffix_Matches
660 Suffix : File_Name_Type) return Boolean
663 if Suffix = No_File then
668 Suf : constant String := Get_Name_String (Suffix);
670 return Filename'Length > Suf'Length
672 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
680 procedure Write_Attr (Name, Value : String) is
682 if Current_Verbosity = High then
683 Write_Str (" " & Name & " = """);
696 Data : in out Project_Data;
697 In_Tree : Project_Tree_Ref;
698 Project : Project_Id;
700 Lang_Id : Language_Index;
702 File_Name : File_Name_Type;
703 Display_File : File_Name_Type;
704 Lang_Kind : Language_Kind;
705 Naming_Exception : Boolean := False;
706 Path : Path_Name_Type := No_Path;
707 Display_Path : Path_Name_Type := No_Path;
708 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
709 Other_Part : Source_Id := No_Source;
710 Unit : Name_Id := No_Name;
712 Source_To_Replace : Source_Id := No_Source)
714 Source : constant Source_Id := Data.Last_Source;
715 Src_Data : Source_Data := No_Source_Data;
716 Config : constant Language_Config :=
717 In_Tree.Languages_Data.Table (Lang_Id).Config;
720 -- This is a new source so create an entry for it in the Sources table
722 Source_Data_Table.Increment_Last (In_Tree.Sources);
723 Id := Source_Data_Table.Last (In_Tree.Sources);
725 if Current_Verbosity = High then
726 Write_Str ("Adding source #");
728 Write_Str (", File : ");
729 Write_Str (Get_Name_String (File_Name));
731 if Lang_Kind = Unit_Based then
732 Write_Str (", Unit : ");
733 Write_Str (Get_Name_String (Unit));
739 Src_Data.Project := Project;
740 Src_Data.Language := Lang_Id;
741 Src_Data.Lang_Kind := Lang_Kind;
742 Src_Data.Compiled := In_Tree.Languages_Data.Table
743 (Lang_Id).Config.Compiler_Driver /=
745 Src_Data.Kind := Kind;
746 Src_Data.Alternate_Languages := Alternate_Languages;
747 Src_Data.Other_Part := Other_Part;
749 Src_Data.Object_Exists := Config.Object_Generated;
750 Src_Data.Object_Linked := Config.Objects_Linked;
752 if Other_Part /= No_Source then
753 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
756 Src_Data.Unit := Unit;
757 Src_Data.Index := Index;
758 Src_Data.File := File_Name;
759 Src_Data.Display_File := Display_File;
760 Src_Data.Dependency := In_Tree.Languages_Data.Table
761 (Lang_Id).Config.Dependency_Kind;
762 Src_Data.Dep_Name := Dependency_Name
763 (File_Name, Src_Data.Dependency);
764 Src_Data.Naming_Exception := Naming_Exception;
766 if Src_Data.Compiled and then Src_Data.Object_Exists then
768 Object_Name (File_Name, Config.Object_File_Suffix);
769 Src_Data.Switches := Switches_Name (File_Name);
772 if Path /= No_Path then
773 Src_Data.Path := (Path, Display_Path);
774 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
777 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
780 if Unit /= No_Name then
781 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
784 -- Add the source to the global list
786 Src_Data.Next_In_Sources := In_Tree.First_Source;
787 In_Tree.First_Source := Id;
789 -- Add the source to the project list
791 if Source = No_Source then
792 Data.First_Source := Id;
794 In_Tree.Sources.Table (Source).Next_In_Project := Id;
797 Data.Last_Source := Id;
799 -- Add the source to the language list
801 Src_Data.Next_In_Lang :=
802 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
803 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
805 In_Tree.Sources.Table (Id) := Src_Data;
807 if Source_To_Replace /= No_Source then
808 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
816 function ALI_File_Name (Source : String) return String is
818 -- If the source name has an extension, then replace it with
821 for Index in reverse Source'First + 1 .. Source'Last loop
822 if Source (Index) = '.' then
823 return Source (Source'First .. Index - 1) & ALI_Suffix;
827 -- If there is no dot, or if it is the first character, just add the
830 return Source & ALI_Suffix;
833 ------------------------------
834 -- Canonical_Case_File_Name --
835 ------------------------------
837 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
839 if Osint.File_Names_Case_Sensitive then
840 return File_Name_Type (Name);
842 Get_Name_String (Name);
843 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
846 end Canonical_Case_File_Name;
853 (Project : Project_Id;
854 In_Tree : Project_Tree_Ref;
855 Report_Error : Put_Line_Access;
856 When_No_Sources : Error_Warning;
857 Current_Dir : String)
859 Data : Project_Data := In_Tree.Projects.Table (Project);
860 Extending : Boolean := False;
863 Nmsc.When_No_Sources := When_No_Sources;
864 Error_Report := Report_Error;
866 Recursive_Dirs.Reset;
868 Check_If_Externally_Built (Project, In_Tree, Data);
870 -- Object, exec and source directories
872 Get_Directories (Project, In_Tree, Current_Dir, Data);
874 -- Get the programming languages
876 Check_Programming_Languages (In_Tree, Project, Data);
878 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
881 "an abstract project needs to have no language, no sources " &
882 "or no source directories",
886 -- Check configuration in multi language mode
888 if Must_Check_Configuration then
889 Check_Configuration (Project, In_Tree, Data);
892 -- Library attributes
894 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
896 if Current_Verbosity = High then
897 Show_Source_Dirs (Data, In_Tree);
900 Check_Package_Naming (Project, In_Tree, Data);
902 Extending := Data.Extends /= No_Project;
904 Check_Naming_Schemes (Data, Project, In_Tree);
906 if Get_Mode = Ada_Only then
907 Prepare_Ada_Naming_Exceptions
908 (Data.Naming.Bodies, In_Tree, Body_Part);
909 Prepare_Ada_Naming_Exceptions
910 (Data.Naming.Specs, In_Tree, Specification);
915 if Data.Source_Dirs /= Nil_String then
916 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
918 if Get_Mode = Ada_Only then
920 -- Check that all individual naming conventions apply to sources
921 -- of this project file.
924 (Project, In_Tree, Data.Naming.Bodies,
926 Extending => Extending);
928 (Project, In_Tree, Data.Naming.Specs,
930 Extending => Extending);
932 elsif Get_Mode = Multi_Language and then
933 (not Data.Externally_Built) and then
937 Language : Language_Index;
939 Alt_Lang : Alternate_Language_Id;
940 Alt_Lang_Data : Alternate_Language_Data;
941 Continuation : Boolean := False;
944 Language := Data.First_Language_Processing;
945 while Language /= No_Language_Index loop
946 Source := Data.First_Source;
947 Source_Loop : while Source /= No_Source loop
949 Src_Data : Source_Data renames
950 In_Tree.Sources.Table (Source);
953 exit Source_Loop when Src_Data.Language = Language;
955 Alt_Lang := Src_Data.Alternate_Languages;
958 while Alt_Lang /= No_Alternate_Language loop
960 In_Tree.Alt_Langs.Table (Alt_Lang);
962 when Alt_Lang_Data.Language = Language;
963 Alt_Lang := Alt_Lang_Data.Next;
964 end loop Alternate_Loop;
966 Source := Src_Data.Next_In_Project;
968 end loop Source_Loop;
970 if Source = No_Source then
974 (In_Tree.Languages_Data.Table
975 (Language).Display_Name),
979 Continuation := True;
982 Language := In_Tree.Languages_Data.Table (Language).Next;
988 if Get_Mode = Multi_Language then
990 -- If a list of sources is specified in attribute Interfaces, set
991 -- In_Interfaces only for the sources specified in the list.
993 Check_Interfaces (Project, In_Tree, Data);
996 -- If it is a library project file, check if it is a standalone library
999 Check_Stand_Alone_Library
1000 (Project, In_Tree, Data, Current_Dir, Extending);
1003 -- Put the list of Mains, if any, in the project data
1005 Get_Mains (Project, In_Tree, Data);
1007 -- Update the project data in the Projects table
1009 In_Tree.Projects.Table (Project) := Data;
1011 Free_Ada_Naming_Exceptions;
1014 --------------------
1015 -- Check_Ada_Name --
1016 --------------------
1018 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1019 The_Name : String := Name;
1020 Real_Name : Name_Id;
1021 Need_Letter : Boolean := True;
1022 Last_Underscore : Boolean := False;
1023 OK : Boolean := The_Name'Length > 0;
1026 function Is_Reserved (Name : Name_Id) return Boolean;
1027 function Is_Reserved (S : String) return Boolean;
1028 -- Check that the given name is not an Ada 95 reserved word. The reason
1029 -- for the Ada 95 here is that we do not want to exclude the case of an
1030 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1031 -- name would be rejected anyway by the compiler. That means there is no
1032 -- requirement that the project file parser reject this.
1038 function Is_Reserved (S : String) return Boolean is
1041 Add_Str_To_Name_Buffer (S);
1042 return Is_Reserved (Name_Find);
1049 function Is_Reserved (Name : Name_Id) return Boolean is
1051 if Get_Name_Table_Byte (Name) /= 0
1052 and then Name /= Name_Project
1053 and then Name /= Name_Extends
1054 and then Name /= Name_External
1055 and then Name not in Ada_2005_Reserved_Words
1059 if Current_Verbosity = High then
1060 Write_Str (The_Name);
1061 Write_Line (" is an Ada reserved word.");
1071 -- Start of processing for Check_Ada_Name
1074 To_Lower (The_Name);
1076 Name_Len := The_Name'Length;
1077 Name_Buffer (1 .. Name_Len) := The_Name;
1079 -- Special cases of children of packages A, G, I and S on VMS
1081 if OpenVMS_On_Target
1082 and then Name_Len > 3
1083 and then Name_Buffer (2 .. 3) = "__"
1085 ((Name_Buffer (1) = 'a') or else
1086 (Name_Buffer (1) = 'g') or else
1087 (Name_Buffer (1) = 'i') or else
1088 (Name_Buffer (1) = 's'))
1090 Name_Buffer (2) := '.';
1091 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1092 Name_Len := Name_Len - 1;
1095 Real_Name := Name_Find;
1097 if Is_Reserved (Real_Name) then
1101 First := The_Name'First;
1103 for Index in The_Name'Range loop
1106 -- We need a letter (at the beginning, and following a dot),
1107 -- but we don't have one.
1109 if Is_Letter (The_Name (Index)) then
1110 Need_Letter := False;
1115 if Current_Verbosity = High then
1116 Write_Int (Types.Int (Index));
1118 Write_Char (The_Name (Index));
1119 Write_Line ("' is not a letter.");
1125 elsif Last_Underscore
1126 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1128 -- Two underscores are illegal, and a dot cannot follow
1133 if Current_Verbosity = High then
1134 Write_Int (Types.Int (Index));
1136 Write_Char (The_Name (Index));
1137 Write_Line ("' is illegal here.");
1142 elsif The_Name (Index) = '.' then
1144 -- First, check if the name before the dot is not a reserved word
1145 if Is_Reserved (The_Name (First .. Index - 1)) then
1151 -- We need a letter after a dot
1153 Need_Letter := True;
1155 elsif The_Name (Index) = '_' then
1156 Last_Underscore := True;
1159 -- We need an letter or a digit
1161 Last_Underscore := False;
1163 if not Is_Alphanumeric (The_Name (Index)) then
1166 if Current_Verbosity = High then
1167 Write_Int (Types.Int (Index));
1169 Write_Char (The_Name (Index));
1170 Write_Line ("' is not alphanumeric.");
1178 -- Cannot end with an underscore or a dot
1180 OK := OK and then not Need_Letter and then not Last_Underscore;
1183 if First /= Name'First and then
1184 Is_Reserved (The_Name (First .. The_Name'Last))
1192 -- Signal a problem with No_Name
1198 -------------------------
1199 -- Check_Configuration --
1200 -------------------------
1202 procedure Check_Configuration
1203 (Project : Project_Id;
1204 In_Tree : Project_Tree_Ref;
1205 Data : in out Project_Data)
1207 Dot_Replacement : File_Name_Type := No_File;
1208 Casing : Casing_Type := All_Lower_Case;
1209 Separate_Suffix : File_Name_Type := No_File;
1211 Lang_Index : Language_Index := No_Language_Index;
1212 -- The index of the language data being checked
1214 Prev_Index : Language_Index := No_Language_Index;
1215 -- The index of the previous language
1217 Current_Language : Name_Id := No_Name;
1218 -- The name of the language
1220 Lang_Data : Language_Data;
1221 -- The data of the language being checked
1223 procedure Get_Language_Index_Of (Language : Name_Id);
1224 -- Get the language index of Language, if Language is one of the
1225 -- languages of the project.
1227 procedure Process_Project_Level_Simple_Attributes;
1228 -- Process the simple attributes at the project level
1230 procedure Process_Project_Level_Array_Attributes;
1231 -- Process the associate array attributes at the project level
1233 procedure Process_Packages;
1234 -- Read the packages of the project
1236 ---------------------------
1237 -- Get_Language_Index_Of --
1238 ---------------------------
1240 procedure Get_Language_Index_Of (Language : Name_Id) is
1241 Real_Language : Name_Id;
1244 Get_Name_String (Language);
1245 To_Lower (Name_Buffer (1 .. Name_Len));
1246 Real_Language := Name_Find;
1248 -- Nothing to do if the language is the same as the current language
1250 if Current_Language /= Real_Language then
1251 Lang_Index := Data.First_Language_Processing;
1252 while Lang_Index /= No_Language_Index loop
1253 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1256 In_Tree.Languages_Data.Table (Lang_Index).Next;
1259 if Lang_Index = No_Language_Index then
1260 Current_Language := No_Name;
1262 Current_Language := Real_Language;
1265 end Get_Language_Index_Of;
1267 ----------------------
1268 -- Process_Packages --
1269 ----------------------
1271 procedure Process_Packages is
1272 Packages : Package_Id;
1273 Element : Package_Element;
1275 procedure Process_Binder (Arrays : Array_Id);
1276 -- Process the associate array attributes of package Binder
1278 procedure Process_Builder (Attributes : Variable_Id);
1279 -- Process the simple attributes of package Builder
1281 procedure Process_Compiler (Arrays : Array_Id);
1282 -- Process the associate array attributes of package Compiler
1284 procedure Process_Naming (Attributes : Variable_Id);
1285 -- Process the simple attributes of package Naming
1287 procedure Process_Naming (Arrays : Array_Id);
1288 -- Process the associate array attributes of package Naming
1290 procedure Process_Linker (Attributes : Variable_Id);
1291 -- Process the simple attributes of package Linker of a
1292 -- configuration project.
1294 --------------------
1295 -- Process_Binder --
1296 --------------------
1298 procedure Process_Binder (Arrays : Array_Id) is
1299 Current_Array_Id : Array_Id;
1300 Current_Array : Array_Data;
1301 Element_Id : Array_Element_Id;
1302 Element : Array_Element;
1305 -- Process the associative array attribute of package Binder
1307 Current_Array_Id := Arrays;
1308 while Current_Array_Id /= No_Array loop
1309 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1311 Element_Id := Current_Array.Value;
1312 while Element_Id /= No_Array_Element loop
1313 Element := In_Tree.Array_Elements.Table (Element_Id);
1315 if Element.Index /= All_Other_Names then
1317 -- Get the name of the language
1319 Get_Language_Index_Of (Element.Index);
1321 if Lang_Index /= No_Language_Index then
1322 case Current_Array.Name is
1325 -- Attribute Driver (<language>)
1327 In_Tree.Languages_Data.Table
1328 (Lang_Index).Config.Binder_Driver :=
1329 File_Name_Type (Element.Value.Value);
1331 when Name_Required_Switches =>
1333 In_Tree.Languages_Data.Table
1334 (Lang_Index).Config.Binder_Required_Switches,
1335 From_List => Element.Value.Values,
1336 In_Tree => In_Tree);
1340 -- Attribute Prefix (<language>)
1342 In_Tree.Languages_Data.Table
1343 (Lang_Index).Config.Binder_Prefix :=
1344 Element.Value.Value;
1346 when Name_Objects_Path =>
1348 -- Attribute Objects_Path (<language>)
1350 In_Tree.Languages_Data.Table
1351 (Lang_Index).Config.Objects_Path :=
1352 Element.Value.Value;
1354 when Name_Objects_Path_File =>
1356 -- Attribute Objects_Path (<language>)
1358 In_Tree.Languages_Data.Table
1359 (Lang_Index).Config.Objects_Path_File :=
1360 Element.Value.Value;
1368 Element_Id := Element.Next;
1371 Current_Array_Id := Current_Array.Next;
1375 ---------------------
1376 -- Process_Builder --
1377 ---------------------
1379 procedure Process_Builder (Attributes : Variable_Id) is
1380 Attribute_Id : Variable_Id;
1381 Attribute : Variable;
1384 -- Process non associated array attribute from package Builder
1386 Attribute_Id := Attributes;
1387 while Attribute_Id /= No_Variable loop
1389 In_Tree.Variable_Elements.Table (Attribute_Id);
1391 if not Attribute.Value.Default then
1392 if Attribute.Name = Name_Executable_Suffix then
1394 -- Attribute Executable_Suffix: the suffix of the
1397 Data.Config.Executable_Suffix :=
1398 Attribute.Value.Value;
1402 Attribute_Id := Attribute.Next;
1404 end Process_Builder;
1406 ----------------------
1407 -- Process_Compiler --
1408 ----------------------
1410 procedure Process_Compiler (Arrays : Array_Id) is
1411 Current_Array_Id : Array_Id;
1412 Current_Array : Array_Data;
1413 Element_Id : Array_Element_Id;
1414 Element : Array_Element;
1415 List : String_List_Id;
1418 -- Process the associative array attribute of package Compiler
1420 Current_Array_Id := Arrays;
1421 while Current_Array_Id /= No_Array loop
1422 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1424 Element_Id := Current_Array.Value;
1425 while Element_Id /= No_Array_Element loop
1426 Element := In_Tree.Array_Elements.Table (Element_Id);
1428 if Element.Index /= All_Other_Names then
1430 -- Get the name of the language
1432 Get_Language_Index_Of (Element.Index);
1434 if Lang_Index /= No_Language_Index then
1435 case Current_Array.Name is
1436 when Name_Dependency_Switches =>
1438 -- Attribute Dependency_Switches (<language>)
1440 if In_Tree.Languages_Data.Table
1441 (Lang_Index).Config.Dependency_Kind = None
1443 In_Tree.Languages_Data.Table
1444 (Lang_Index).Config.Dependency_Kind :=
1448 List := Element.Value.Values;
1450 if List /= Nil_String then
1452 In_Tree.Languages_Data.Table
1453 (Lang_Index).Config.Dependency_Option,
1455 In_Tree => In_Tree);
1458 when Name_Dependency_Driver =>
1460 -- Attribute Dependency_Driver (<language>)
1462 if In_Tree.Languages_Data.Table
1463 (Lang_Index).Config.Dependency_Kind = None
1465 In_Tree.Languages_Data.Table
1466 (Lang_Index).Config.Dependency_Kind :=
1470 List := Element.Value.Values;
1472 if List /= Nil_String then
1474 In_Tree.Languages_Data.Table
1475 (Lang_Index).Config.Compute_Dependency,
1477 In_Tree => In_Tree);
1480 when Name_Include_Switches =>
1482 -- Attribute Include_Switches (<language>)
1484 List := Element.Value.Values;
1486 if List = Nil_String then
1490 "include option cannot be null",
1491 Element.Value.Location);
1495 In_Tree.Languages_Data.Table
1496 (Lang_Index).Config.Include_Option,
1498 In_Tree => In_Tree);
1500 when Name_Include_Path =>
1502 -- Attribute Include_Path (<language>)
1504 In_Tree.Languages_Data.Table
1505 (Lang_Index).Config.Include_Path :=
1506 Element.Value.Value;
1508 when Name_Include_Path_File =>
1510 -- Attribute Include_Path_File (<language>)
1512 In_Tree.Languages_Data.Table
1513 (Lang_Index).Config.Include_Path_File :=
1514 Element.Value.Value;
1518 -- Attribute Driver (<language>)
1520 Get_Name_String (Element.Value.Value);
1522 In_Tree.Languages_Data.Table
1523 (Lang_Index).Config.Compiler_Driver :=
1524 File_Name_Type (Element.Value.Value);
1526 when Name_Required_Switches =>
1528 In_Tree.Languages_Data.Table
1529 (Lang_Index).Config.
1530 Compiler_Required_Switches,
1531 From_List => Element.Value.Values,
1532 In_Tree => In_Tree);
1534 when Name_Path_Syntax =>
1536 In_Tree.Languages_Data.Table
1537 (Lang_Index).Config.Path_Syntax :=
1538 Path_Syntax_Kind'Value
1539 (Get_Name_String (Element.Value.Value));
1542 when Constraint_Error =>
1546 "invalid value for Path_Syntax",
1547 Element.Value.Location);
1550 when Name_Object_File_Suffix =>
1551 if Get_Name_String (Element.Value.Value) = "" then
1554 "object file suffix cannot be empty",
1555 Element.Value.Location);
1558 In_Tree.Languages_Data.Table
1559 (Lang_Index).Config.Object_File_Suffix :=
1560 Element.Value.Value;
1563 when Name_Pic_Option =>
1565 -- Attribute Compiler_Pic_Option (<language>)
1567 List := Element.Value.Values;
1569 if List = Nil_String then
1573 "compiler PIC option cannot be null",
1574 Element.Value.Location);
1578 In_Tree.Languages_Data.Table
1579 (Lang_Index).Config.Compilation_PIC_Option,
1581 In_Tree => In_Tree);
1583 when Name_Mapping_File_Switches =>
1585 -- Attribute Mapping_File_Switches (<language>)
1587 List := Element.Value.Values;
1589 if List = Nil_String then
1593 "mapping file switches cannot be null",
1594 Element.Value.Location);
1598 In_Tree.Languages_Data.Table
1599 (Lang_Index).Config.Mapping_File_Switches,
1601 In_Tree => In_Tree);
1603 when Name_Mapping_Spec_Suffix =>
1605 -- Attribute Mapping_Spec_Suffix (<language>)
1607 In_Tree.Languages_Data.Table
1608 (Lang_Index).Config.Mapping_Spec_Suffix :=
1609 File_Name_Type (Element.Value.Value);
1611 when Name_Mapping_Body_Suffix =>
1613 -- Attribute Mapping_Body_Suffix (<language>)
1615 In_Tree.Languages_Data.Table
1616 (Lang_Index).Config.Mapping_Body_Suffix :=
1617 File_Name_Type (Element.Value.Value);
1619 when Name_Config_File_Switches =>
1621 -- Attribute Config_File_Switches (<language>)
1623 List := Element.Value.Values;
1625 if List = Nil_String then
1629 "config file switches cannot be null",
1630 Element.Value.Location);
1634 In_Tree.Languages_Data.Table
1635 (Lang_Index).Config.Config_File_Switches,
1637 In_Tree => In_Tree);
1639 when Name_Objects_Path =>
1641 -- Attribute Objects_Path (<language>)
1643 In_Tree.Languages_Data.Table
1644 (Lang_Index).Config.Objects_Path :=
1645 Element.Value.Value;
1647 when Name_Objects_Path_File =>
1649 -- Attribute Objects_Path_File (<language>)
1651 In_Tree.Languages_Data.Table
1652 (Lang_Index).Config.Objects_Path_File :=
1653 Element.Value.Value;
1655 when Name_Config_Body_File_Name =>
1657 -- Attribute Config_Body_File_Name (<language>)
1659 In_Tree.Languages_Data.Table
1660 (Lang_Index).Config.Config_Body :=
1661 Element.Value.Value;
1663 when Name_Config_Body_File_Name_Pattern =>
1665 -- Attribute Config_Body_File_Name_Pattern
1668 In_Tree.Languages_Data.Table
1669 (Lang_Index).Config.Config_Body_Pattern :=
1670 Element.Value.Value;
1672 when Name_Config_Spec_File_Name =>
1674 -- Attribute Config_Spec_File_Name (<language>)
1676 In_Tree.Languages_Data.Table
1677 (Lang_Index).Config.Config_Spec :=
1678 Element.Value.Value;
1680 when Name_Config_Spec_File_Name_Pattern =>
1682 -- Attribute Config_Spec_File_Name_Pattern
1685 In_Tree.Languages_Data.Table
1686 (Lang_Index).Config.Config_Spec_Pattern :=
1687 Element.Value.Value;
1689 when Name_Config_File_Unique =>
1691 -- Attribute Config_File_Unique (<language>)
1694 In_Tree.Languages_Data.Table
1695 (Lang_Index).Config.Config_File_Unique :=
1697 (Get_Name_String (Element.Value.Value));
1699 when Constraint_Error =>
1703 "illegal value for Config_File_Unique",
1704 Element.Value.Location);
1713 Element_Id := Element.Next;
1716 Current_Array_Id := Current_Array.Next;
1718 end Process_Compiler;
1720 --------------------
1721 -- Process_Naming --
1722 --------------------
1724 procedure Process_Naming (Attributes : Variable_Id) is
1725 Attribute_Id : Variable_Id;
1726 Attribute : Variable;
1729 -- Process non associated array attribute from package Naming
1731 Attribute_Id := Attributes;
1732 while Attribute_Id /= No_Variable loop
1733 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1735 if not Attribute.Value.Default then
1736 if Attribute.Name = Name_Separate_Suffix then
1738 -- Attribute Separate_Suffix
1740 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1742 elsif Attribute.Name = Name_Casing then
1748 Value (Get_Name_String (Attribute.Value.Value));
1751 when Constraint_Error =>
1755 "invalid value for Casing",
1756 Attribute.Value.Location);
1759 elsif Attribute.Name = Name_Dot_Replacement then
1761 -- Attribute Dot_Replacement
1763 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1768 Attribute_Id := Attribute.Next;
1772 procedure Process_Naming (Arrays : Array_Id) is
1773 Current_Array_Id : Array_Id;
1774 Current_Array : Array_Data;
1775 Element_Id : Array_Element_Id;
1776 Element : Array_Element;
1778 -- Process the associative array attribute of package Naming
1780 Current_Array_Id := Arrays;
1781 while Current_Array_Id /= No_Array loop
1782 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1784 Element_Id := Current_Array.Value;
1785 while Element_Id /= No_Array_Element loop
1786 Element := In_Tree.Array_Elements.Table (Element_Id);
1788 -- Get the name of the language
1790 Get_Language_Index_Of (Element.Index);
1792 if Lang_Index /= No_Language_Index then
1793 case Current_Array.Name is
1794 when Name_Specification_Suffix | Name_Spec_Suffix =>
1796 -- Attribute Spec_Suffix (<language>)
1798 In_Tree.Languages_Data.Table
1799 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1800 File_Name_Type (Element.Value.Value);
1802 when Name_Implementation_Suffix | Name_Body_Suffix =>
1804 -- Attribute Body_Suffix (<language>)
1806 In_Tree.Languages_Data.Table
1807 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1808 File_Name_Type (Element.Value.Value);
1810 In_Tree.Languages_Data.Table
1811 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1812 File_Name_Type (Element.Value.Value);
1819 Element_Id := Element.Next;
1822 Current_Array_Id := Current_Array.Next;
1826 --------------------
1827 -- Process_Linker --
1828 --------------------
1830 procedure Process_Linker (Attributes : Variable_Id) is
1831 Attribute_Id : Variable_Id;
1832 Attribute : Variable;
1835 -- Process non associated array attribute from package Linker
1837 Attribute_Id := Attributes;
1838 while Attribute_Id /= No_Variable loop
1840 In_Tree.Variable_Elements.Table (Attribute_Id);
1842 if not Attribute.Value.Default then
1843 if Attribute.Name = Name_Driver then
1845 -- Attribute Linker'Driver: the default linker to use
1847 Data.Config.Linker :=
1848 Path_Name_Type (Attribute.Value.Value);
1850 -- Linker'Driver is also used to link shared libraries
1851 -- if the obsolescent attribute Library_GCC has not been
1854 if Data.Config.Shared_Lib_Driver = No_File then
1855 Data.Config.Shared_Lib_Driver :=
1856 File_Name_Type (Attribute.Value.Value);
1859 elsif Attribute.Name = Name_Required_Switches then
1861 -- Attribute Required_Switches: the minimum
1862 -- options to use when invoking the linker
1865 Data.Config.Minimum_Linker_Options,
1866 From_List => Attribute.Value.Values,
1867 In_Tree => In_Tree);
1869 elsif Attribute.Name = Name_Map_File_Option then
1870 Data.Config.Map_File_Option := Attribute.Value.Value;
1872 elsif Attribute.Name = Name_Max_Command_Line_Length then
1874 Data.Config.Max_Command_Line_Length :=
1875 Natural'Value (Get_Name_String
1876 (Attribute.Value.Value));
1879 when Constraint_Error =>
1883 "value must be positive or equal to 0",
1884 Attribute.Value.Location);
1887 elsif Attribute.Name = Name_Response_File_Format then
1892 Get_Name_String (Attribute.Value.Value);
1893 To_Lower (Name_Buffer (1 .. Name_Len));
1896 if Name = Name_None then
1897 Data.Config.Resp_File_Format := None;
1899 elsif Name = Name_Gnu then
1900 Data.Config.Resp_File_Format := GNU;
1902 elsif Name = Name_Object_List then
1903 Data.Config.Resp_File_Format := Object_List;
1905 elsif Name = Name_Option_List then
1906 Data.Config.Resp_File_Format := Option_List;
1912 "illegal response file format",
1913 Attribute.Value.Location);
1917 elsif Attribute.Name = Name_Response_File_Switches then
1919 Data.Config.Resp_File_Options,
1920 From_List => Attribute.Value.Values,
1921 In_Tree => In_Tree);
1925 Attribute_Id := Attribute.Next;
1929 -- Start of processing for Process_Packages
1932 Packages := Data.Decl.Packages;
1933 while Packages /= No_Package loop
1934 Element := In_Tree.Packages.Table (Packages);
1936 case Element.Name is
1939 -- Process attributes of package Binder
1941 Process_Binder (Element.Decl.Arrays);
1943 when Name_Builder =>
1945 -- Process attributes of package Builder
1947 Process_Builder (Element.Decl.Attributes);
1949 when Name_Compiler =>
1951 -- Process attributes of package Compiler
1953 Process_Compiler (Element.Decl.Arrays);
1957 -- Process attributes of package Linker
1959 Process_Linker (Element.Decl.Attributes);
1963 -- Process attributes of package Naming
1965 Process_Naming (Element.Decl.Attributes);
1966 Process_Naming (Element.Decl.Arrays);
1972 Packages := Element.Next;
1974 end Process_Packages;
1976 ---------------------------------------------
1977 -- Process_Project_Level_Simple_Attributes --
1978 ---------------------------------------------
1980 procedure Process_Project_Level_Simple_Attributes is
1981 Attribute_Id : Variable_Id;
1982 Attribute : Variable;
1983 List : String_List_Id;
1986 -- Process non associated array attribute at project level
1988 Attribute_Id := Data.Decl.Attributes;
1989 while Attribute_Id /= No_Variable loop
1991 In_Tree.Variable_Elements.Table (Attribute_Id);
1993 if not Attribute.Value.Default then
1994 if Attribute.Name = Name_Target then
1996 -- Attribute Target: the target specified
1998 Data.Config.Target := Attribute.Value.Value;
2000 elsif Attribute.Name = Name_Library_Builder then
2002 -- Attribute Library_Builder: the application to invoke
2003 -- to build libraries.
2005 Data.Config.Library_Builder :=
2006 Path_Name_Type (Attribute.Value.Value);
2008 elsif Attribute.Name = Name_Archive_Builder then
2010 -- Attribute Archive_Builder: the archive builder
2011 -- (usually "ar") and its minimum options (usually "cr").
2013 List := Attribute.Value.Values;
2015 if List = Nil_String then
2019 "archive builder cannot be null",
2020 Attribute.Value.Location);
2023 Put (Into_List => Data.Config.Archive_Builder,
2025 In_Tree => In_Tree);
2027 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
2029 -- Attribute Archive_Builder: the archive builder
2030 -- (usually "ar") and its minimum options (usually "cr").
2032 List := Attribute.Value.Values;
2034 if List /= Nil_String then
2036 (Into_List => Data.Config.Archive_Builder_Append_Option,
2038 In_Tree => In_Tree);
2041 elsif Attribute.Name = Name_Archive_Indexer then
2043 -- Attribute Archive_Indexer: the optional archive
2044 -- indexer (usually "ranlib") with its minimum options
2047 List := Attribute.Value.Values;
2049 if List = Nil_String then
2053 "archive indexer cannot be null",
2054 Attribute.Value.Location);
2057 Put (Into_List => Data.Config.Archive_Indexer,
2059 In_Tree => In_Tree);
2061 elsif Attribute.Name = Name_Library_Partial_Linker then
2063 -- Attribute Library_Partial_Linker: the optional linker
2064 -- driver with its minimum options, to partially link
2067 List := Attribute.Value.Values;
2069 if List = Nil_String then
2073 "partial linker cannot be null",
2074 Attribute.Value.Location);
2077 Put (Into_List => Data.Config.Lib_Partial_Linker,
2079 In_Tree => In_Tree);
2081 elsif Attribute.Name = Name_Library_GCC then
2082 Data.Config.Shared_Lib_Driver :=
2083 File_Name_Type (Attribute.Value.Value);
2087 "?Library_'G'C'C is an obsolescent attribute, " &
2088 "use Linker''Driver instead",
2089 Attribute.Value.Location);
2091 elsif Attribute.Name = Name_Archive_Suffix then
2092 Data.Config.Archive_Suffix :=
2093 File_Name_Type (Attribute.Value.Value);
2095 elsif Attribute.Name = Name_Linker_Executable_Option then
2097 -- Attribute Linker_Executable_Option: optional options
2098 -- to specify an executable name. Defaults to "-o".
2100 List := Attribute.Value.Values;
2102 if List = Nil_String then
2106 "linker executable option cannot be null",
2107 Attribute.Value.Location);
2110 Put (Into_List => Data.Config.Linker_Executable_Option,
2112 In_Tree => In_Tree);
2114 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2116 -- Attribute Linker_Lib_Dir_Option: optional options
2117 -- to specify a library search directory. Defaults to
2120 Get_Name_String (Attribute.Value.Value);
2122 if Name_Len = 0 then
2126 "linker library directory option cannot be empty",
2127 Attribute.Value.Location);
2130 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2132 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2134 -- Attribute Linker_Lib_Name_Option: optional options
2135 -- to specify the name of a library to be linked in.
2136 -- Defaults to "-l".
2138 Get_Name_String (Attribute.Value.Value);
2140 if Name_Len = 0 then
2144 "linker library name option cannot be empty",
2145 Attribute.Value.Location);
2148 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2150 elsif Attribute.Name = Name_Run_Path_Option then
2152 -- Attribute Run_Path_Option: optional options to
2153 -- specify a path for libraries.
2155 List := Attribute.Value.Values;
2157 if List /= Nil_String then
2158 Put (Into_List => Data.Config.Run_Path_Option,
2160 In_Tree => In_Tree);
2163 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2165 pragma Unsuppress (All_Checks);
2167 Data.Config.Separate_Run_Path_Options :=
2168 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2170 when Constraint_Error =>
2174 "invalid value """ &
2175 Get_Name_String (Attribute.Value.Value) &
2176 """ for Separate_Run_Path_Options",
2177 Attribute.Value.Location);
2180 elsif Attribute.Name = Name_Library_Support then
2182 pragma Unsuppress (All_Checks);
2184 Data.Config.Lib_Support :=
2185 Library_Support'Value (Get_Name_String
2186 (Attribute.Value.Value));
2188 when Constraint_Error =>
2192 "invalid value """ &
2193 Get_Name_String (Attribute.Value.Value) &
2194 """ for Library_Support",
2195 Attribute.Value.Location);
2198 elsif Attribute.Name = Name_Shared_Library_Prefix then
2199 Data.Config.Shared_Lib_Prefix :=
2200 File_Name_Type (Attribute.Value.Value);
2202 elsif Attribute.Name = Name_Shared_Library_Suffix then
2203 Data.Config.Shared_Lib_Suffix :=
2204 File_Name_Type (Attribute.Value.Value);
2206 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2208 pragma Unsuppress (All_Checks);
2210 Data.Config.Symbolic_Link_Supported :=
2211 Boolean'Value (Get_Name_String
2212 (Attribute.Value.Value));
2214 when Constraint_Error =>
2219 & Get_Name_String (Attribute.Value.Value)
2220 & """ for Symbolic_Link_Supported",
2221 Attribute.Value.Location);
2225 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2228 pragma Unsuppress (All_Checks);
2230 Data.Config.Lib_Maj_Min_Id_Supported :=
2231 Boolean'Value (Get_Name_String
2232 (Attribute.Value.Value));
2234 when Constraint_Error =>
2238 "invalid value """ &
2239 Get_Name_String (Attribute.Value.Value) &
2240 """ for Library_Major_Minor_Id_Supported",
2241 Attribute.Value.Location);
2244 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2246 pragma Unsuppress (All_Checks);
2248 Data.Config.Auto_Init_Supported :=
2249 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2251 when Constraint_Error =>
2256 & Get_Name_String (Attribute.Value.Value)
2257 & """ for Library_Auto_Init_Supported",
2258 Attribute.Value.Location);
2261 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2262 List := Attribute.Value.Values;
2264 if List /= Nil_String then
2265 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2267 In_Tree => In_Tree);
2270 elsif Attribute.Name = Name_Library_Version_Switches then
2271 List := Attribute.Value.Values;
2273 if List /= Nil_String then
2274 Put (Into_List => Data.Config.Lib_Version_Options,
2276 In_Tree => In_Tree);
2281 Attribute_Id := Attribute.Next;
2283 end Process_Project_Level_Simple_Attributes;
2285 --------------------------------------------
2286 -- Process_Project_Level_Array_Attributes --
2287 --------------------------------------------
2289 procedure Process_Project_Level_Array_Attributes is
2290 Current_Array_Id : Array_Id;
2291 Current_Array : Array_Data;
2292 Element_Id : Array_Element_Id;
2293 Element : Array_Element;
2294 List : String_List_Id;
2297 -- Process the associative array attributes at project level
2299 Current_Array_Id := Data.Decl.Arrays;
2300 while Current_Array_Id /= No_Array loop
2301 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2303 Element_Id := Current_Array.Value;
2304 while Element_Id /= No_Array_Element loop
2305 Element := In_Tree.Array_Elements.Table (Element_Id);
2307 -- Get the name of the language
2309 Get_Language_Index_Of (Element.Index);
2311 if Lang_Index /= No_Language_Index then
2312 case Current_Array.Name is
2313 when Name_Inherit_Source_Path =>
2314 List := Element.Value.Values;
2316 if List /= Nil_String then
2319 In_Tree.Languages_Data.Table (Lang_Index).
2320 Config.Include_Compatible_Languages,
2323 Lower_Case => True);
2326 when Name_Toolchain_Description =>
2328 -- Attribute Toolchain_Description (<language>)
2330 In_Tree.Languages_Data.Table
2331 (Lang_Index).Config.Toolchain_Description :=
2332 Element.Value.Value;
2334 when Name_Toolchain_Version =>
2336 -- Attribute Toolchain_Version (<language>)
2338 In_Tree.Languages_Data.Table
2339 (Lang_Index).Config.Toolchain_Version :=
2340 Element.Value.Value;
2342 when Name_Runtime_Library_Dir =>
2344 -- Attribute Runtime_Library_Dir (<language>)
2346 In_Tree.Languages_Data.Table
2347 (Lang_Index).Config.Runtime_Library_Dir :=
2348 Element.Value.Value;
2350 when Name_Runtime_Source_Dir =>
2352 -- Attribute Runtime_Library_Dir (<language>)
2354 In_Tree.Languages_Data.Table
2355 (Lang_Index).Config.Runtime_Source_Dir :=
2356 Element.Value.Value;
2358 when Name_Object_Generated =>
2360 pragma Unsuppress (All_Checks);
2366 (Get_Name_String (Element.Value.Value));
2368 In_Tree.Languages_Data.Table
2369 (Lang_Index).Config.Object_Generated := Value;
2371 -- If no object is generated, no object may be
2375 In_Tree.Languages_Data.Table
2376 (Lang_Index).Config.Objects_Linked := False;
2380 when Constraint_Error =>
2385 & Get_Name_String (Element.Value.Value)
2386 & """ for Object_Generated",
2387 Element.Value.Location);
2390 when Name_Objects_Linked =>
2392 pragma Unsuppress (All_Checks);
2398 (Get_Name_String (Element.Value.Value));
2400 -- No change if Object_Generated is False, as this
2401 -- forces Objects_Linked to be False too.
2403 if In_Tree.Languages_Data.Table
2404 (Lang_Index).Config.Object_Generated
2406 In_Tree.Languages_Data.Table
2407 (Lang_Index).Config.Objects_Linked :=
2412 when Constraint_Error =>
2417 & Get_Name_String (Element.Value.Value)
2418 & """ for Objects_Linked",
2419 Element.Value.Location);
2426 Element_Id := Element.Next;
2429 Current_Array_Id := Current_Array.Next;
2431 end Process_Project_Level_Array_Attributes;
2434 Process_Project_Level_Simple_Attributes;
2435 Process_Project_Level_Array_Attributes;
2438 -- For unit based languages, set Casing, Dot_Replacement and
2439 -- Separate_Suffix in Naming_Data.
2441 Lang_Index := Data.First_Language_Processing;
2442 while Lang_Index /= No_Language_Index loop
2443 if In_Tree.Languages_Data.Table
2444 (Lang_Index).Name = Name_Ada
2446 In_Tree.Languages_Data.Table
2447 (Lang_Index).Config.Naming_Data.Casing := Casing;
2448 In_Tree.Languages_Data.Table
2449 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2452 if Separate_Suffix /= No_File then
2453 In_Tree.Languages_Data.Table
2454 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2461 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2464 -- Give empty names to various prefixes/suffixes, if they have not
2465 -- been specified in the configuration.
2467 if Data.Config.Archive_Suffix = No_File then
2468 Data.Config.Archive_Suffix := Empty_File;
2471 if Data.Config.Shared_Lib_Prefix = No_File then
2472 Data.Config.Shared_Lib_Prefix := Empty_File;
2475 if Data.Config.Shared_Lib_Suffix = No_File then
2476 Data.Config.Shared_Lib_Suffix := Empty_File;
2479 Lang_Index := Data.First_Language_Processing;
2480 while Lang_Index /= No_Language_Index loop
2481 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2483 Current_Language := Lang_Data.Display_Name;
2485 -- For all languages, Compiler_Driver needs to be specified
2487 if Lang_Data.Config.Compiler_Driver = No_File then
2488 Error_Msg_Name_1 := Current_Language;
2492 "?no compiler specified for language %%" &
2493 ", ignoring all its sources",
2496 if Lang_Index = Data.First_Language_Processing then
2497 Data.First_Language_Processing :=
2500 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2504 elsif Lang_Data.Name = Name_Ada then
2505 Prev_Index := Lang_Index;
2507 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2508 -- Body_Suffix need to be specified.
2510 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2514 "Dot_Replacement not specified for Ada",
2518 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2522 "Spec_Suffix not specified for Ada",
2526 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2530 "Body_Suffix not specified for Ada",
2535 Prev_Index := Lang_Index;
2537 -- For file based languages, either Spec_Suffix or Body_Suffix
2538 -- need to be specified.
2540 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2541 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2543 Error_Msg_Name_1 := Current_Language;
2547 "no suffixes specified for %%",
2552 Lang_Index := Lang_Data.Next;
2554 end Check_Configuration;
2556 -------------------------------
2557 -- Check_If_Externally_Built --
2558 -------------------------------
2560 procedure Check_If_Externally_Built
2561 (Project : Project_Id;
2562 In_Tree : Project_Tree_Ref;
2563 Data : in out Project_Data)
2565 Externally_Built : constant Variable_Value :=
2567 (Name_Externally_Built,
2568 Data.Decl.Attributes, In_Tree);
2571 if not Externally_Built.Default then
2572 Get_Name_String (Externally_Built.Value);
2573 To_Lower (Name_Buffer (1 .. Name_Len));
2575 if Name_Buffer (1 .. Name_Len) = "true" then
2576 Data.Externally_Built := True;
2578 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2579 Error_Msg (Project, In_Tree,
2580 "Externally_Built may only be true or false",
2581 Externally_Built.Location);
2585 -- A virtual project extending an externally built project is itself
2586 -- externally built.
2588 if Data.Virtual and then Data.Extends /= No_Project then
2589 Data.Externally_Built :=
2590 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2593 if Current_Verbosity = High then
2594 Write_Str ("Project is ");
2596 if not Data.Externally_Built then
2600 Write_Line ("externally built.");
2602 end Check_If_Externally_Built;
2604 ----------------------
2605 -- Check_Interfaces --
2606 ----------------------
2608 procedure Check_Interfaces
2609 (Project : Project_Id;
2610 In_Tree : Project_Tree_Ref;
2611 Data : in out Project_Data)
2613 Interfaces : constant Prj.Variable_Value :=
2615 (Snames.Name_Interfaces,
2616 Data.Decl.Attributes,
2619 List : String_List_Id;
2620 Element : String_Element;
2621 Name : File_Name_Type;
2625 Project_2 : Project_Id;
2626 Data_2 : Project_Data;
2629 if not Interfaces.Default then
2631 -- Set In_Interfaces to False for all sources. It will be set to True
2632 -- later for the sources in the Interfaces list.
2634 Project_2 := Project;
2637 Source := Data_2.First_Source;
2638 while Source /= No_Source loop
2640 Src_Data : Source_Data renames
2641 In_Tree.Sources.Table (Source);
2643 Src_Data.In_Interfaces := False;
2644 Source := Src_Data.Next_In_Project;
2648 Project_2 := Data_2.Extends;
2650 exit when Project_2 = No_Project;
2652 Data_2 := In_Tree.Projects.Table (Project_2);
2655 List := Interfaces.Values;
2656 while List /= Nil_String loop
2657 Element := In_Tree.String_Elements.Table (List);
2658 Name := Canonical_Case_File_Name (Element.Value);
2660 Project_2 := Project;
2664 Source := Data_2.First_Source;
2665 while Source /= No_Source loop
2667 Src_Data : Source_Data renames
2668 In_Tree.Sources.Table (Source);
2671 if Src_Data.File = Name then
2672 if not Src_Data.Locally_Removed then
2673 Src_Data.In_Interfaces := True;
2674 Src_Data.Declared_In_Interfaces := True;
2676 if Src_Data.Other_Part /= No_Source then
2677 In_Tree.Sources.Table
2678 (Src_Data.Other_Part).In_Interfaces := True;
2679 In_Tree.Sources.Table
2680 (Src_Data.Other_Part).Declared_In_Interfaces :=
2684 if Current_Verbosity = High then
2685 Write_Str (" interface: ");
2687 (Get_Name_String (Src_Data.Path.Name));
2694 Source := Src_Data.Next_In_Project;
2698 Project_2 := Data_2.Extends;
2700 exit Big_Loop when Project_2 = No_Project;
2702 Data_2 := In_Tree.Projects.Table (Project_2);
2705 if Source = No_Source then
2706 Error_Msg_File_1 := File_Name_Type (Element.Value);
2707 Error_Msg_Name_1 := Data.Name;
2712 "{ cannot be an interface of project %% "
2713 & "as it is not one of its sources",
2717 List := Element.Next;
2720 Data.Interfaces_Defined := True;
2722 elsif Data.Extends /= No_Project then
2723 Data.Interfaces_Defined :=
2724 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2726 if Data.Interfaces_Defined then
2727 Source := Data.First_Source;
2728 while Source /= No_Source loop
2730 Src_Data : Source_Data renames
2731 In_Tree.Sources.Table (Source);
2734 if not Src_Data.Declared_In_Interfaces then
2735 Src_Data.In_Interfaces := False;
2738 Source := Src_Data.Next_In_Project;
2743 end Check_Interfaces;
2745 ------------------------------------
2746 -- Check_And_Normalize_Unit_Names --
2747 ------------------------------------
2749 procedure Check_And_Normalize_Unit_Names
2750 (Project : Project_Id;
2751 In_Tree : Project_Tree_Ref;
2752 List : Array_Element_Id;
2753 Debug_Name : String)
2755 Current : Array_Element_Id;
2756 Element : Array_Element;
2757 Unit_Name : Name_Id;
2760 if Current_Verbosity = High then
2761 Write_Line (" Checking unit names in " & Debug_Name);
2765 while Current /= No_Array_Element loop
2766 Element := In_Tree.Array_Elements.Table (Current);
2767 Element.Value.Value :=
2768 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2770 -- Check that it contains a valid unit name
2772 Get_Name_String (Element.Index);
2773 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2775 if Unit_Name = No_Name then
2776 Err_Vars.Error_Msg_Name_1 := Element.Index;
2779 "%% is not a valid unit name.",
2780 Element.Value.Location);
2783 if Current_Verbosity = High then
2784 Write_Str (" for unit: ");
2785 Write_Line (Get_Name_String (Unit_Name));
2788 Element.Index := Unit_Name;
2789 In_Tree.Array_Elements.Table (Current) := Element;
2792 Current := Element.Next;
2794 end Check_And_Normalize_Unit_Names;
2796 --------------------------
2797 -- Check_Naming_Schemes --
2798 --------------------------
2800 procedure Check_Naming_Schemes
2801 (Data : in out Project_Data;
2802 Project : Project_Id;
2803 In_Tree : Project_Tree_Ref)
2805 Naming_Id : constant Package_Id :=
2806 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2807 Naming : Package_Element;
2809 procedure Check_Naming_Ada_Only;
2810 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2811 -- If there is a package Naming, puts in Data.Naming the contents of
2814 procedure Check_Naming_Multi_Lang;
2815 -- Does Check_Naming_Schemes processing for Multi_Language mode
2817 procedure Check_Common
2818 (Dot_Replacement : in out File_Name_Type;
2819 Casing : in out Casing_Type;
2820 Casing_Defined : out Boolean;
2821 Separate_Suffix : in out File_Name_Type;
2822 Sep_Suffix_Loc : out Source_Ptr);
2823 -- Check attributes common to Ada_Only and Multi_Lang modes
2825 procedure Process_Exceptions_File_Based
2826 (Lang_Id : Language_Index;
2827 Kind : Source_Kind);
2828 procedure Process_Exceptions_Unit_Based
2829 (Lang_Id : Language_Index;
2830 Kind : Source_Kind);
2831 -- In Multi_Lang mode, process the naming exceptions for the two types
2832 -- of languages we can have.
2838 procedure Check_Common
2839 (Dot_Replacement : in out File_Name_Type;
2840 Casing : in out Casing_Type;
2841 Casing_Defined : out Boolean;
2842 Separate_Suffix : in out File_Name_Type;
2843 Sep_Suffix_Loc : out Source_Ptr)
2845 Dot_Repl : constant Variable_Value :=
2847 (Name_Dot_Replacement,
2848 Naming.Decl.Attributes,
2850 Casing_String : constant Variable_Value :=
2853 Naming.Decl.Attributes,
2855 Sep_Suffix : constant Variable_Value :=
2857 (Name_Separate_Suffix,
2858 Naming.Decl.Attributes,
2860 Dot_Repl_Loc : Source_Ptr;
2863 Sep_Suffix_Loc := No_Location;
2865 if not Dot_Repl.Default then
2867 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2869 if Length_Of_Name (Dot_Repl.Value) = 0 then
2872 "Dot_Replacement cannot be empty",
2876 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2877 Dot_Repl_Loc := Dot_Repl.Location;
2880 Repl : constant String := Get_Name_String (Dot_Replacement);
2883 -- Dot_Replacement cannot
2885 -- - start or end with an alphanumeric
2886 -- - be a single '_'
2887 -- - start with an '_' followed by an alphanumeric
2888 -- - contain a '.' except if it is "."
2891 or else Is_Alphanumeric (Repl (Repl'First))
2892 or else Is_Alphanumeric (Repl (Repl'Last))
2893 or else (Repl (Repl'First) = '_'
2897 Is_Alphanumeric (Repl (Repl'First + 1))))
2898 or else (Repl'Length > 1
2900 Index (Source => Repl, Pattern => ".") /= 0)
2905 """ is illegal for Dot_Replacement.",
2912 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2914 Casing_Defined := False;
2916 if not Casing_String.Default then
2918 (Casing_String.Kind = Single, "Casing is not a string");
2921 Casing_Image : constant String :=
2922 Get_Name_String (Casing_String.Value);
2924 if Casing_Image'Length = 0 then
2927 "Casing cannot be an empty string",
2928 Casing_String.Location);
2931 Casing := Value (Casing_Image);
2932 Casing_Defined := True;
2935 when Constraint_Error =>
2936 Name_Len := Casing_Image'Length;
2937 Name_Buffer (1 .. Name_Len) := Casing_Image;
2938 Err_Vars.Error_Msg_Name_1 := Name_Find;
2941 "%% is not a correct Casing",
2942 Casing_String.Location);
2946 Write_Attr ("Casing", Image (Casing));
2948 if not Sep_Suffix.Default then
2949 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2952 "Separate_Suffix cannot be empty",
2953 Sep_Suffix.Location);
2956 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2957 Sep_Suffix_Loc := Sep_Suffix.Location;
2959 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2960 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2963 "{ is illegal for Separate_Suffix",
2964 Sep_Suffix.Location);
2969 if Separate_Suffix /= No_File then
2971 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2975 -----------------------------------
2976 -- Process_Exceptions_File_Based --
2977 -----------------------------------
2979 procedure Process_Exceptions_File_Based
2980 (Lang_Id : Language_Index;
2983 Lang : constant Name_Id :=
2984 In_Tree.Languages_Data.Table (Lang_Id).Name;
2985 Exceptions : Array_Element_Id;
2986 Exception_List : Variable_Value;
2987 Element_Id : String_List_Id;
2988 Element : String_Element;
2989 File_Name : File_Name_Type;
2997 (Name_Implementation_Exceptions,
2998 In_Arrays => Naming.Decl.Arrays,
2999 In_Tree => In_Tree);
3004 (Name_Specification_Exceptions,
3005 In_Arrays => Naming.Decl.Arrays,
3006 In_Tree => In_Tree);
3009 Exception_List := Value_Of
3011 In_Array => Exceptions,
3012 In_Tree => In_Tree);
3014 if Exception_List /= Nil_Variable_Value then
3015 Element_Id := Exception_List.Values;
3016 while Element_Id /= Nil_String loop
3017 Element := In_Tree.String_Elements.Table (Element_Id);
3018 File_Name := Canonical_Case_File_Name (Element.Value);
3020 Source := Data.First_Source;
3021 while Source /= No_Source
3022 and then In_Tree.Sources.Table (Source).File /= File_Name
3024 Source := In_Tree.Sources.Table (Source).Next_In_Project;
3027 if Source = No_Source then
3036 File_Name => File_Name,
3037 Display_File => File_Name_Type (Element.Value),
3038 Naming_Exception => True,
3039 Lang_Kind => File_Based);
3042 -- Check if the file name is already recorded for another
3043 -- language or another kind.
3045 if In_Tree.Sources.Table (Source).Language /= Lang_Id then
3049 "the same file cannot be a source of two languages",
3052 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
3056 "the same file cannot be a source and a template",
3060 -- If the file is already recorded for the same
3061 -- language and the same kind, it means that the file
3062 -- name appears several times in the *_Exceptions
3063 -- attribute; so there is nothing to do.
3066 Element_Id := Element.Next;
3069 end Process_Exceptions_File_Based;
3071 -----------------------------------
3072 -- Process_Exceptions_Unit_Based --
3073 -----------------------------------
3075 procedure Process_Exceptions_Unit_Based
3076 (Lang_Id : Language_Index;
3079 Lang : constant Name_Id :=
3080 In_Tree.Languages_Data.Table (Lang_Id).Name;
3081 Exceptions : Array_Element_Id;
3082 Element : Array_Element;
3085 File_Name : File_Name_Type;
3087 Source_To_Replace : Source_Id := No_Source;
3088 Other_Project : Project_Id;
3089 Other_Part : Source_Id := No_Source;
3094 Exceptions := Value_Of
3096 In_Arrays => Naming.Decl.Arrays,
3097 In_Tree => In_Tree);
3099 if Exceptions = No_Array_Element then
3102 (Name_Implementation,
3103 In_Arrays => Naming.Decl.Arrays,
3104 In_Tree => In_Tree);
3111 In_Arrays => Naming.Decl.Arrays,
3112 In_Tree => In_Tree);
3114 if Exceptions = No_Array_Element then
3115 Exceptions := Value_Of
3116 (Name_Specification,
3117 In_Arrays => Naming.Decl.Arrays,
3118 In_Tree => In_Tree);
3122 while Exceptions /= No_Array_Element loop
3123 Element := In_Tree.Array_Elements.Table (Exceptions);
3124 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3126 Get_Name_String (Element.Index);
3127 To_Lower (Name_Buffer (1 .. Name_Len));
3129 Index := Element.Value.Index;
3131 -- For Ada, check if it is a valid unit name
3133 if Lang = Name_Ada then
3134 Get_Name_String (Element.Index);
3135 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3137 if Unit = No_Name then
3138 Err_Vars.Error_Msg_Name_1 := Element.Index;
3141 "%% is not a valid unit name.",
3142 Element.Value.Location);
3146 if Unit /= No_Name then
3148 -- Check if the source already exists
3150 Source := In_Tree.First_Source;
3151 Source_To_Replace := No_Source;
3153 while Source /= No_Source and then
3154 (In_Tree.Sources.Table (Source).Unit /= Unit or else
3155 In_Tree.Sources.Table (Source).Index /= Index)
3157 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
3160 if Source /= No_Source then
3161 if In_Tree.Sources.Table (Source).Kind /= Kind then
3162 Other_Part := Source;
3166 In_Tree.Sources.Table (Source).Next_In_Sources;
3168 exit when Source = No_Source or else
3169 (In_Tree.Sources.Table (Source).Unit = Unit
3171 In_Tree.Sources.Table (Source).Index = Index);
3175 if Source /= No_Source then
3176 Other_Project := In_Tree.Sources.Table (Source).Project;
3178 if Is_Extending (Project, Other_Project, In_Tree) then
3180 In_Tree.Sources.Table (Source).Other_Part;
3182 -- Record the source to be removed
3184 Source_To_Replace := Source;
3185 Source := No_Source;
3188 Error_Msg_Name_1 := Unit;
3190 In_Tree.Projects.Table (Other_Project).Name;
3194 "%% is already a source of project %%",
3195 Element.Value.Location);
3200 if Source = No_Source then
3209 File_Name => File_Name,
3210 Display_File => File_Name_Type (Element.Value.Value),
3211 Lang_Kind => Unit_Based,
3212 Other_Part => Other_Part,
3215 Naming_Exception => True,
3216 Source_To_Replace => Source_To_Replace);
3220 Exceptions := Element.Next;
3222 end Process_Exceptions_Unit_Based;
3224 ---------------------------
3225 -- Check_Naming_Ada_Only --
3226 ---------------------------
3228 procedure Check_Naming_Ada_Only is
3229 Casing_Defined : Boolean;
3230 Spec_Suffix : File_Name_Type;
3231 Body_Suffix : File_Name_Type;
3232 Sep_Suffix_Loc : Source_Ptr;
3234 Ada_Spec_Suffix : constant Variable_Value :=
3238 In_Array => Data.Naming.Spec_Suffix,
3239 In_Tree => In_Tree);
3241 Ada_Body_Suffix : constant Variable_Value :=
3245 In_Array => Data.Naming.Body_Suffix,
3246 In_Tree => In_Tree);
3249 -- The default value of separate suffix should be the same as the
3250 -- body suffix, so we need to compute that first.
3252 if Ada_Body_Suffix.Kind = Single
3253 and then Length_Of_Name (Ada_Body_Suffix.Value) /= 0
3255 Body_Suffix := Canonical_Case_File_Name (Ada_Body_Suffix.Value);
3256 Data.Naming.Separate_Suffix := Body_Suffix;
3257 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Body_Suffix);
3260 Body_Suffix := Default_Ada_Body_Suffix;
3261 Data.Naming.Separate_Suffix := Body_Suffix;
3262 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Body_Suffix);
3265 Write_Attr ("Body_Suffix", Get_Name_String (Body_Suffix));
3267 -- We'll need the dot replacement below, so compute it now.
3270 (Dot_Replacement => Data.Naming.Dot_Replacement,
3271 Casing => Data.Naming.Casing,
3272 Casing_Defined => Casing_Defined,
3273 Separate_Suffix => Data.Naming.Separate_Suffix,
3274 Sep_Suffix_Loc => Sep_Suffix_Loc);
3276 Data.Naming.Bodies :=
3277 Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3279 if Data.Naming.Bodies /= No_Array_Element then
3280 Check_And_Normalize_Unit_Names
3281 (Project, In_Tree, Data.Naming.Bodies, "Naming.Bodies");
3284 Data.Naming.Specs :=
3285 Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3287 if Data.Naming.Specs /= No_Array_Element then
3288 Check_And_Normalize_Unit_Names
3289 (Project, In_Tree, Data.Naming.Specs, "Naming.Specs");
3292 -- Check Spec_Suffix
3294 if Ada_Spec_Suffix.Kind = Single
3295 and then Length_Of_Name (Ada_Spec_Suffix.Value) /= 0
3297 Spec_Suffix := Canonical_Case_File_Name (Ada_Spec_Suffix.Value);
3298 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Spec_Suffix);
3300 if Is_Illegal_Suffix
3301 (Spec_Suffix, Data.Naming.Dot_Replacement)
3303 Err_Vars.Error_Msg_File_1 := Spec_Suffix;
3306 "{ is illegal for Spec_Suffix",
3307 Ada_Spec_Suffix.Location);
3311 Spec_Suffix := Default_Ada_Spec_Suffix;
3312 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Spec_Suffix);
3315 Write_Attr ("Spec_Suffix", Get_Name_String (Spec_Suffix));
3317 -- Check Body_Suffix
3319 if Is_Illegal_Suffix (Body_Suffix, Data.Naming.Dot_Replacement) then
3320 Err_Vars.Error_Msg_File_1 := Body_Suffix;
3323 "{ is illegal for Body_Suffix",
3324 Ada_Body_Suffix.Location);
3327 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3328 -- since that would cause a clear ambiguity. Note that we do allow a
3329 -- Spec_Suffix to have the same termination as one of these, which
3330 -- causes a potential ambiguity, but we resolve that my matching the
3331 -- longest possible suffix.
3333 if Spec_Suffix = Body_Suffix then
3337 Get_Name_String (Body_Suffix) &
3338 """) cannot be the same as Spec_Suffix.",
3339 Ada_Body_Suffix.Location);
3342 if Body_Suffix /= Data.Naming.Separate_Suffix
3343 and then Spec_Suffix = Data.Naming.Separate_Suffix
3347 "Separate_Suffix (""" &
3348 Get_Name_String (Data.Naming.Separate_Suffix) &
3349 """) cannot be the same as Spec_Suffix.",
3352 end Check_Naming_Ada_Only;
3354 -----------------------------
3355 -- Check_Naming_Multi_Lang --
3356 -----------------------------
3358 procedure Check_Naming_Multi_Lang is
3359 Dot_Replacement : File_Name_Type := No_File;
3360 Separate_Suffix : File_Name_Type := No_File;
3361 Casing : Casing_Type := All_Lower_Case;
3362 Casing_Defined : Boolean;
3363 Lang_Id : Language_Index;
3364 Sep_Suffix_Loc : Source_Ptr;
3365 Suffix : Variable_Value;
3370 (Dot_Replacement => Dot_Replacement,
3372 Casing_Defined => Casing_Defined,
3373 Separate_Suffix => Separate_Suffix,
3374 Sep_Suffix_Loc => Sep_Suffix_Loc);
3376 -- For all unit based languages, if any, set the specified
3377 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3378 -- systematically overwrite, since the defaults come from the
3379 -- configuration file
3381 if Dot_Replacement /= No_File
3382 or else Casing_Defined
3383 or else Separate_Suffix /= No_File
3385 Lang_Id := Data.First_Language_Processing;
3386 while Lang_Id /= No_Language_Index loop
3387 if In_Tree.Languages_Data.
3388 Table (Lang_Id).Config.Kind = Unit_Based
3390 if Dot_Replacement /= No_File then
3391 In_Tree.Languages_Data.Table
3392 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3396 if Casing_Defined then
3397 In_Tree.Languages_Data.Table
3398 (Lang_Id).Config.Naming_Data.Casing := Casing;
3401 if Separate_Suffix /= No_File then
3402 In_Tree.Languages_Data.Table
3403 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3408 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3412 -- Next, get the spec and body suffixes
3414 Lang_Id := Data.First_Language_Processing;
3415 while Lang_Id /= No_Language_Index loop
3416 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3422 Attribute_Or_Array_Name => Name_Spec_Suffix,
3423 In_Package => Naming_Id,
3424 In_Tree => In_Tree);
3426 if Suffix = Nil_Variable_Value then
3429 Attribute_Or_Array_Name => Name_Specification_Suffix,
3430 In_Package => Naming_Id,
3431 In_Tree => In_Tree);
3434 if Suffix /= Nil_Variable_Value then
3435 In_Tree.Languages_Data.Table (Lang_Id).
3436 Config.Naming_Data.Spec_Suffix :=
3437 File_Name_Type (Suffix.Value);
3444 Attribute_Or_Array_Name => Name_Body_Suffix,
3445 In_Package => Naming_Id,
3446 In_Tree => In_Tree);
3448 if Suffix = Nil_Variable_Value then
3451 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3452 In_Package => Naming_Id,
3453 In_Tree => In_Tree);
3456 if Suffix /= Nil_Variable_Value then
3457 In_Tree.Languages_Data.Table (Lang_Id).
3458 Config.Naming_Data.Body_Suffix :=
3459 File_Name_Type (Suffix.Value);
3462 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3463 -- we do not check whether spec_suffix=body_suffix, which
3464 -- should be illegal. Best would be to share this code into
3465 -- Check_Common, but we access the attributes from the project
3466 -- files slightly differently apparently.
3468 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3471 -- Get the naming exceptions for all languages
3473 for Kind in Spec .. Impl loop
3474 Lang_Id := Data.First_Language_Processing;
3475 while Lang_Id /= No_Language_Index loop
3476 case In_Tree.Languages_Data.Table (Lang_Id).Config.Kind is
3478 Process_Exceptions_File_Based (Lang_Id, Kind);
3481 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3484 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3487 end Check_Naming_Multi_Lang;
3489 -- Start of processing for Check_Naming_Schemes
3492 -- No Naming package or parsing a configuration file? nothing to do
3494 if Naming_Id /= No_Package and not In_Configuration then
3495 Naming := In_Tree.Packages.Table (Naming_Id);
3497 if Current_Verbosity = High then
3498 Write_Line ("Checking package Naming.");
3503 Check_Naming_Ada_Only;
3504 when Multi_Language =>
3505 Check_Naming_Multi_Lang;
3508 end Check_Naming_Schemes;
3510 ------------------------------
3511 -- Check_Library_Attributes --
3512 ------------------------------
3514 procedure Check_Library_Attributes
3515 (Project : Project_Id;
3516 In_Tree : Project_Tree_Ref;
3517 Current_Dir : String;
3518 Data : in out Project_Data)
3520 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3522 Lib_Dir : constant Prj.Variable_Value :=
3524 (Snames.Name_Library_Dir, Attributes, In_Tree);
3526 Lib_Name : constant Prj.Variable_Value :=
3528 (Snames.Name_Library_Name, Attributes, In_Tree);
3530 Lib_Version : constant Prj.Variable_Value :=
3532 (Snames.Name_Library_Version, Attributes, In_Tree);
3534 Lib_ALI_Dir : constant Prj.Variable_Value :=
3536 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3538 Lib_GCC : constant Prj.Variable_Value :=
3540 (Snames.Name_Library_GCC, Attributes, In_Tree);
3542 The_Lib_Kind : constant Prj.Variable_Value :=
3544 (Snames.Name_Library_Kind, Attributes, In_Tree);
3546 Imported_Project_List : Project_List := Empty_Project_List;
3548 Continuation : String_Access := No_Continuation_String'Access;
3550 Support_For_Libraries : Library_Support;
3552 Library_Directory_Present : Boolean;
3554 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3555 -- Check if an imported or extended project if also a library project
3561 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3562 Proj_Data : Project_Data;
3566 if Proj /= No_Project then
3567 Proj_Data := In_Tree.Projects.Table (Proj);
3569 if not Proj_Data.Library then
3571 -- The only not library projects that are OK are those that
3572 -- have no sources. However, header files from non-Ada
3573 -- languages are OK, as there is nothing to compile.
3575 Src_Id := Proj_Data.First_Source;
3576 while Src_Id /= No_Source loop
3578 Src : Source_Data renames In_Tree.Sources.Table (Src_Id);
3580 exit when Src.Lang_Kind /= File_Based
3581 or else Src.Kind /= Spec;
3582 Src_Id := Src.Next_In_Project;
3586 if Src_Id /= No_Source then
3587 Error_Msg_Name_1 := Data.Name;
3588 Error_Msg_Name_2 := Proj_Data.Name;
3591 if Data.Library_Kind /= Static then
3595 "shared library project %% cannot extend " &
3596 "project %% that is not a library project",
3598 Continuation := Continuation_String'Access;
3601 elsif Data.Library_Kind /= Static then
3605 "shared library project %% cannot import project %% " &
3606 "that is not a shared library project",
3608 Continuation := Continuation_String'Access;
3612 elsif Data.Library_Kind /= Static and then
3613 Proj_Data.Library_Kind = Static
3615 Error_Msg_Name_1 := Data.Name;
3616 Error_Msg_Name_2 := Proj_Data.Name;
3622 "shared library project %% cannot extend static " &
3623 "library project %%",
3630 "shared library project %% cannot import static " &
3631 "library project %%",
3635 Continuation := Continuation_String'Access;
3640 -- Start of processing for Check_Library_Attributes
3643 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3645 -- Special case of extending project
3647 if Data.Extends /= No_Project then
3649 Extended_Data : constant Project_Data :=
3650 In_Tree.Projects.Table (Data.Extends);
3653 -- If the project extended is a library project, we inherit the
3654 -- library name, if it is not redefined; we check that the library
3655 -- directory is specified.
3657 if Extended_Data.Library then
3658 if Data.Qualifier = Standard then
3661 "a standard project cannot extend a library project",
3665 if Lib_Name.Default then
3666 Data.Library_Name := Extended_Data.Library_Name;
3669 if Lib_Dir.Default then
3670 if not Data.Virtual then
3673 "a project extending a library project must " &
3674 "specify an attribute Library_Dir",
3678 -- For a virtual project extending a library project,
3679 -- inherit library directory.
3681 Data.Library_Dir := Extended_Data.Library_Dir;
3682 Library_Directory_Present := True;
3690 pragma Assert (Lib_Name.Kind = Single);
3692 if Lib_Name.Value = Empty_String then
3693 if Current_Verbosity = High
3694 and then Data.Library_Name = No_Name
3696 Write_Line ("No library name");
3700 -- There is no restriction on the syntax of library names
3702 Data.Library_Name := Lib_Name.Value;
3705 if Data.Library_Name /= No_Name then
3706 if Current_Verbosity = High then
3707 Write_Attr ("Library name", Get_Name_String (Data.Library_Name));
3710 pragma Assert (Lib_Dir.Kind = Single);
3712 if not Library_Directory_Present then
3713 if Current_Verbosity = High then
3714 Write_Line ("No library directory");
3718 -- Find path name (unless inherited), check that it is a directory
3720 if Data.Library_Dir = No_Path_Information then
3724 File_Name_Type (Lib_Dir.Value),
3725 Data.Directory.Display_Name,
3726 Data.Library_Dir.Name,
3727 Data.Library_Dir.Display_Name,
3728 Create => "library",
3729 Current_Dir => Current_Dir,
3730 Location => Lib_Dir.Location,
3731 Externally_Built => Data.Externally_Built);
3734 if Data.Library_Dir = No_Path_Information then
3736 -- Get the absolute name of the library directory that
3737 -- does not exist, to report an error.
3740 Dir_Name : constant String :=
3741 Get_Name_String (Lib_Dir.Value);
3744 if Is_Absolute_Path (Dir_Name) then
3745 Err_Vars.Error_Msg_File_1 :=
3746 File_Name_Type (Lib_Dir.Value);
3749 Get_Name_String (Data.Directory.Display_Name);
3751 if Name_Buffer (Name_Len) /= Directory_Separator then
3752 Name_Len := Name_Len + 1;
3753 Name_Buffer (Name_Len) := Directory_Separator;
3757 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3759 Name_Len := Name_Len + Dir_Name'Length;
3760 Err_Vars.Error_Msg_File_1 := Name_Find;
3767 "library directory { does not exist",
3771 -- The library directory cannot be the same as the Object
3774 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3777 "library directory cannot be the same " &
3778 "as object directory",
3780 Data.Library_Dir := No_Path_Information;
3784 OK : Boolean := True;
3785 Dirs_Id : String_List_Id;
3786 Dir_Elem : String_Element;
3789 -- The library directory cannot be the same as a source
3790 -- directory of the current project.
3792 Dirs_Id := Data.Source_Dirs;
3793 while Dirs_Id /= Nil_String loop
3794 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3795 Dirs_Id := Dir_Elem.Next;
3798 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3800 Err_Vars.Error_Msg_File_1 :=
3801 File_Name_Type (Dir_Elem.Value);
3804 "library directory cannot be the same " &
3805 "as source directory {",
3814 -- The library directory cannot be the same as a source
3815 -- directory of another project either.
3818 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3819 if Pid /= Project then
3820 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3822 Dir_Loop : while Dirs_Id /= Nil_String loop
3824 In_Tree.String_Elements.Table (Dirs_Id);
3825 Dirs_Id := Dir_Elem.Next;
3827 if Data.Library_Dir.Name =
3828 Path_Name_Type (Dir_Elem.Value)
3830 Err_Vars.Error_Msg_File_1 :=
3831 File_Name_Type (Dir_Elem.Value);
3832 Err_Vars.Error_Msg_Name_1 :=
3833 In_Tree.Projects.Table (Pid).Name;
3837 "library directory cannot be the same " &
3838 "as source directory { of project %%",
3845 end loop Project_Loop;
3849 Data.Library_Dir := No_Path_Information;
3851 elsif Current_Verbosity = High then
3853 -- Display the Library directory in high verbosity
3856 ("Library directory",
3857 Get_Name_String (Data.Library_Dir.Display_Name));
3866 Data.Library_Dir /= No_Path_Information
3868 Data.Library_Name /= No_Name;
3870 if Data.Extends = No_Project then
3871 case Data.Qualifier is
3873 if Data.Library then
3876 "a standard project cannot be a library project",
3881 if not Data.Library then
3882 if Data.Library_Dir = No_Path_Information then
3885 "\attribute Library_Dir not declared",
3889 if Data.Library_Name = No_Name then
3892 "\attribute Library_Name not declared",
3903 if Data.Library then
3904 if Get_Mode = Multi_Language then
3905 Support_For_Libraries := Data.Config.Lib_Support;
3908 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3911 if Support_For_Libraries = Prj.None then
3914 "?libraries are not supported on this platform",
3916 Data.Library := False;
3919 if Lib_ALI_Dir.Value = Empty_String then
3920 if Current_Verbosity = High then
3921 Write_Line ("No library ALI directory specified");
3923 Data.Library_ALI_Dir := Data.Library_Dir;
3926 -- Find path name, check that it is a directory
3931 File_Name_Type (Lib_ALI_Dir.Value),
3932 Data.Directory.Display_Name,
3933 Data.Library_ALI_Dir.Name,
3934 Data.Library_ALI_Dir.Display_Name,
3935 Create => "library ALI",
3936 Current_Dir => Current_Dir,
3937 Location => Lib_ALI_Dir.Location,
3938 Externally_Built => Data.Externally_Built);
3940 if Data.Library_ALI_Dir = No_Path_Information then
3942 -- Get the absolute name of the library ALI directory that
3943 -- does not exist, to report an error.
3946 Dir_Name : constant String :=
3947 Get_Name_String (Lib_ALI_Dir.Value);
3950 if Is_Absolute_Path (Dir_Name) then
3951 Err_Vars.Error_Msg_File_1 :=
3952 File_Name_Type (Lib_Dir.Value);
3955 Get_Name_String (Data.Directory.Display_Name);
3957 if Name_Buffer (Name_Len) /= Directory_Separator then
3958 Name_Len := Name_Len + 1;
3959 Name_Buffer (Name_Len) := Directory_Separator;
3963 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3965 Name_Len := Name_Len + Dir_Name'Length;
3966 Err_Vars.Error_Msg_File_1 := Name_Find;
3973 "library 'A'L'I directory { does not exist",
3974 Lib_ALI_Dir.Location);
3978 if Data.Library_ALI_Dir /= Data.Library_Dir then
3980 -- The library ALI directory cannot be the same as the
3981 -- Object directory.
3983 if Data.Library_ALI_Dir = Data.Object_Directory then
3986 "library 'A'L'I directory cannot be the same " &
3987 "as object directory",
3988 Lib_ALI_Dir.Location);
3989 Data.Library_ALI_Dir := No_Path_Information;
3993 OK : Boolean := True;
3994 Dirs_Id : String_List_Id;
3995 Dir_Elem : String_Element;
3998 -- The library ALI directory cannot be the same as
3999 -- a source directory of the current project.
4001 Dirs_Id := Data.Source_Dirs;
4002 while Dirs_Id /= Nil_String loop
4003 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
4004 Dirs_Id := Dir_Elem.Next;
4006 if Data.Library_ALI_Dir.Name =
4007 Path_Name_Type (Dir_Elem.Value)
4009 Err_Vars.Error_Msg_File_1 :=
4010 File_Name_Type (Dir_Elem.Value);
4013 "library 'A'L'I directory cannot be " &
4014 "the same as source directory {",
4015 Lib_ALI_Dir.Location);
4023 -- The library ALI directory cannot be the same as
4024 -- a source directory of another project either.
4028 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
4030 if Pid /= Project then
4032 In_Tree.Projects.Table (Pid).Source_Dirs;
4035 while Dirs_Id /= Nil_String loop
4037 In_Tree.String_Elements.Table (Dirs_Id);
4038 Dirs_Id := Dir_Elem.Next;
4040 if Data.Library_ALI_Dir.Name =
4041 Path_Name_Type (Dir_Elem.Value)
4043 Err_Vars.Error_Msg_File_1 :=
4044 File_Name_Type (Dir_Elem.Value);
4045 Err_Vars.Error_Msg_Name_1 :=
4046 In_Tree.Projects.Table (Pid).Name;
4050 "library 'A'L'I directory cannot " &
4051 "be the same as source directory " &
4053 Lib_ALI_Dir.Location);
4055 exit ALI_Project_Loop;
4057 end loop ALI_Dir_Loop;
4059 end loop ALI_Project_Loop;
4063 Data.Library_ALI_Dir := No_Path_Information;
4065 elsif Current_Verbosity = High then
4067 -- Display the Library ALI directory in high
4073 (Data.Library_ALI_Dir.Display_Name));
4080 pragma Assert (Lib_Version.Kind = Single);
4082 if Lib_Version.Value = Empty_String then
4083 if Current_Verbosity = High then
4084 Write_Line ("No library version specified");
4088 Data.Lib_Internal_Name := Lib_Version.Value;
4091 pragma Assert (The_Lib_Kind.Kind = Single);
4093 if The_Lib_Kind.Value = Empty_String then
4094 if Current_Verbosity = High then
4095 Write_Line ("No library kind specified");
4099 Get_Name_String (The_Lib_Kind.Value);
4102 Kind_Name : constant String :=
4103 To_Lower (Name_Buffer (1 .. Name_Len));
4105 OK : Boolean := True;
4108 if Kind_Name = "static" then
4109 Data.Library_Kind := Static;
4111 elsif Kind_Name = "dynamic" then
4112 Data.Library_Kind := Dynamic;
4114 elsif Kind_Name = "relocatable" then
4115 Data.Library_Kind := Relocatable;
4120 "illegal value for Library_Kind",
4121 The_Lib_Kind.Location);
4125 if Current_Verbosity = High and then OK then
4126 Write_Attr ("Library kind", Kind_Name);
4129 if Data.Library_Kind /= Static then
4130 if Support_For_Libraries = Prj.Static_Only then
4133 "only static libraries are supported " &
4135 The_Lib_Kind.Location);
4136 Data.Library := False;
4139 -- Check if (obsolescent) attribute Library_GCC or
4140 -- Linker'Driver is declared.
4142 if Lib_GCC.Value /= Empty_String then
4146 "?Library_'G'C'C is an obsolescent attribute, " &
4147 "use Linker''Driver instead",
4149 Data.Config.Shared_Lib_Driver :=
4150 File_Name_Type (Lib_GCC.Value);
4154 Linker : constant Package_Id :=
4159 Driver : constant Variable_Value :=
4162 Attribute_Or_Array_Name =>
4164 In_Package => Linker,
4169 if Driver /= Nil_Variable_Value
4170 and then Driver.Value /= Empty_String
4172 Data.Config.Shared_Lib_Driver :=
4173 File_Name_Type (Driver.Value);
4182 if Data.Library then
4183 if Current_Verbosity = High then
4184 Write_Line ("This is a library project file");
4187 if Get_Mode = Multi_Language then
4188 Check_Library (Data.Extends, Extends => True);
4190 Imported_Project_List := Data.Imported_Projects;
4191 while Imported_Project_List /= Empty_Project_List loop
4193 (In_Tree.Project_Lists.Table
4194 (Imported_Project_List).Project,
4196 Imported_Project_List :=
4197 In_Tree.Project_Lists.Table
4198 (Imported_Project_List).Next;
4206 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4207 -- Warn if they are declared, as it is a common error to think that
4208 -- library are "linked" with Linker switches.
4210 if Data.Library then
4212 Linker_Package_Id : constant Package_Id :=
4214 (Name_Linker, Data.Decl.Packages, In_Tree);
4215 Linker_Package : Package_Element;
4216 Switches : Array_Element_Id := No_Array_Element;
4219 if Linker_Package_Id /= No_Package then
4220 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4224 (Name => Name_Switches,
4225 In_Arrays => Linker_Package.Decl.Arrays,
4226 In_Tree => In_Tree);
4228 if Switches = No_Array_Element then
4231 (Name => Name_Default_Switches,
4232 In_Arrays => Linker_Package.Decl.Arrays,
4233 In_Tree => In_Tree);
4236 if Switches /= No_Array_Element then
4239 "?Linker switches not taken into account in library " &
4247 if Data.Extends /= No_Project then
4248 In_Tree.Projects.Table (Data.Extends).Library := False;
4250 end Check_Library_Attributes;
4252 --------------------------
4253 -- Check_Package_Naming --
4254 --------------------------
4256 procedure Check_Package_Naming
4257 (Project : Project_Id;
4258 In_Tree : Project_Tree_Ref;
4259 Data : in out Project_Data)
4261 Naming_Id : constant Package_Id :=
4262 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4264 Naming : Package_Element;
4267 -- If there is a package Naming, we will put in Data.Naming
4268 -- what is in this package Naming.
4270 if Naming_Id /= No_Package then
4271 Naming := In_Tree.Packages.Table (Naming_Id);
4273 if Current_Verbosity = High then
4274 Write_Line ("Checking ""Naming"".");
4277 -- Check Spec_Suffix
4280 Spec_Suffixs : Array_Element_Id :=
4286 Suffix : Array_Element_Id;
4287 Element : Array_Element;
4288 Suffix2 : Array_Element_Id;
4291 -- If some suffixes have been specified, we make sure that
4292 -- for each language for which a default suffix has been
4293 -- specified, there is a suffix specified, either the one
4294 -- in the project file or if there were none, the default.
4296 if Spec_Suffixs /= No_Array_Element then
4297 Suffix := Data.Naming.Spec_Suffix;
4299 while Suffix /= No_Array_Element loop
4301 In_Tree.Array_Elements.Table (Suffix);
4302 Suffix2 := Spec_Suffixs;
4304 while Suffix2 /= No_Array_Element loop
4305 exit when In_Tree.Array_Elements.Table
4306 (Suffix2).Index = Element.Index;
4307 Suffix2 := In_Tree.Array_Elements.Table
4311 -- There is a registered default suffix, but no
4312 -- suffix specified in the project file.
4313 -- Add the default to the array.
4315 if Suffix2 = No_Array_Element then
4316 Array_Element_Table.Increment_Last
4317 (In_Tree.Array_Elements);
4318 In_Tree.Array_Elements.Table
4319 (Array_Element_Table.Last
4320 (In_Tree.Array_Elements)) :=
4321 (Index => Element.Index,
4322 Src_Index => Element.Src_Index,
4323 Index_Case_Sensitive => False,
4324 Value => Element.Value,
4325 Next => Spec_Suffixs);
4326 Spec_Suffixs := Array_Element_Table.Last
4327 (In_Tree.Array_Elements);
4330 Suffix := Element.Next;
4333 -- Put the resulting array as the specification suffixes
4335 Data.Naming.Spec_Suffix := Spec_Suffixs;
4340 Current : Array_Element_Id;
4341 Element : Array_Element;
4344 Current := Data.Naming.Spec_Suffix;
4345 while Current /= No_Array_Element loop
4346 Element := In_Tree.Array_Elements.Table (Current);
4347 Get_Name_String (Element.Value.Value);
4349 if Name_Len = 0 then
4352 "Spec_Suffix cannot be empty",
4353 Element.Value.Location);
4356 In_Tree.Array_Elements.Table (Current) := Element;
4357 Current := Element.Next;
4361 -- Check Body_Suffix
4364 Impl_Suffixs : Array_Element_Id :=
4370 Suffix : Array_Element_Id;
4371 Element : Array_Element;
4372 Suffix2 : Array_Element_Id;
4375 -- If some suffixes have been specified, we make sure that
4376 -- for each language for which a default suffix has been
4377 -- specified, there is a suffix specified, either the one
4378 -- in the project file or if there were none, the default.
4380 if Impl_Suffixs /= No_Array_Element then
4381 Suffix := Data.Naming.Body_Suffix;
4382 while Suffix /= No_Array_Element loop
4384 In_Tree.Array_Elements.Table (Suffix);
4386 Suffix2 := Impl_Suffixs;
4387 while Suffix2 /= No_Array_Element loop
4388 exit when In_Tree.Array_Elements.Table
4389 (Suffix2).Index = Element.Index;
4390 Suffix2 := In_Tree.Array_Elements.Table
4394 -- There is a registered default suffix, but no suffix was
4395 -- specified in the project file. Add default to the array.
4397 if Suffix2 = No_Array_Element then
4398 Array_Element_Table.Increment_Last
4399 (In_Tree.Array_Elements);
4400 In_Tree.Array_Elements.Table
4401 (Array_Element_Table.Last
4402 (In_Tree.Array_Elements)) :=
4403 (Index => Element.Index,
4404 Src_Index => Element.Src_Index,
4405 Index_Case_Sensitive => False,
4406 Value => Element.Value,
4407 Next => Impl_Suffixs);
4408 Impl_Suffixs := Array_Element_Table.Last
4409 (In_Tree.Array_Elements);
4412 Suffix := Element.Next;
4415 -- Put the resulting array as the implementation suffixes
4417 Data.Naming.Body_Suffix := Impl_Suffixs;
4422 Current : Array_Element_Id;
4423 Element : Array_Element;
4426 Current := Data.Naming.Body_Suffix;
4427 while Current /= No_Array_Element loop
4428 Element := In_Tree.Array_Elements.Table (Current);
4429 Get_Name_String (Element.Value.Value);
4431 if Name_Len = 0 then
4434 "Body_Suffix cannot be empty",
4435 Element.Value.Location);
4438 In_Tree.Array_Elements.Table (Current) := Element;
4439 Current := Element.Next;
4443 -- Get the exceptions, if any
4445 Data.Naming.Specification_Exceptions :=
4447 (Name_Specification_Exceptions,
4448 In_Arrays => Naming.Decl.Arrays,
4449 In_Tree => In_Tree);
4451 Data.Naming.Implementation_Exceptions :=
4453 (Name_Implementation_Exceptions,
4454 In_Arrays => Naming.Decl.Arrays,
4455 In_Tree => In_Tree);
4457 end Check_Package_Naming;
4459 ---------------------------------
4460 -- Check_Programming_Languages --
4461 ---------------------------------
4463 procedure Check_Programming_Languages
4464 (In_Tree : Project_Tree_Ref;
4465 Project : Project_Id;
4466 Data : in out Project_Data)
4468 Languages : Variable_Value := Nil_Variable_Value;
4469 Def_Lang : Variable_Value := Nil_Variable_Value;
4470 Def_Lang_Id : Name_Id;
4473 Data.First_Language_Processing := No_Language_Index;
4475 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4478 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4479 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4480 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4482 if Data.Source_Dirs /= Nil_String then
4484 -- Check if languages are specified in this project
4486 if Languages.Default then
4488 -- Attribute Languages is not specified. So, it defaults to
4489 -- a project of the default language only.
4491 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4492 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4494 -- In Ada_Only mode, the default language is Ada
4496 if Get_Mode = Ada_Only then
4497 In_Tree.Name_Lists.Table (Data.Languages) :=
4498 (Name => Name_Ada, Next => No_Name_List);
4500 -- Attribute Languages is not specified. So, it defaults to
4501 -- a project of language Ada only. No sources of languages
4504 Data.Other_Sources_Present := False;
4507 -- Fail if there is no default language defined
4509 if Def_Lang.Default then
4510 if not Default_Language_Is_Ada then
4514 "no languages defined for this project",
4516 Def_Lang_Id := No_Name;
4518 Def_Lang_Id := Name_Ada;
4522 Get_Name_String (Def_Lang.Value);
4523 To_Lower (Name_Buffer (1 .. Name_Len));
4524 Def_Lang_Id := Name_Find;
4527 if Def_Lang_Id /= No_Name then
4528 In_Tree.Name_Lists.Table (Data.Languages) :=
4529 (Name => Def_Lang_Id, Next => No_Name_List);
4531 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4533 Data.First_Language_Processing :=
4534 Language_Data_Table.Last (In_Tree.Languages_Data);
4535 In_Tree.Languages_Data.Table
4536 (Data.First_Language_Processing) := No_Language_Data;
4537 In_Tree.Languages_Data.Table
4538 (Data.First_Language_Processing).Name := Def_Lang_Id;
4539 Get_Name_String (Def_Lang_Id);
4540 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4541 In_Tree.Languages_Data.Table
4542 (Data.First_Language_Processing).Display_Name := Name_Find;
4544 if Def_Lang_Id = Name_Ada then
4545 In_Tree.Languages_Data.Table
4546 (Data.First_Language_Processing).Config.Kind :=
4548 In_Tree.Languages_Data.Table
4549 (Data.First_Language_Processing).Config.
4550 Dependency_Kind := ALI_File;
4553 In_Tree.Languages_Data.Table
4554 (Data.First_Language_Processing).Config.Kind :=
4562 Current : String_List_Id := Languages.Values;
4563 Element : String_Element;
4564 Lang_Name : Name_Id;
4565 Index : Language_Index;
4566 Lang_Data : Language_Data;
4567 NL_Id : Name_List_Index := No_Name_List;
4570 -- Assume there are no language declared
4572 Data.Ada_Sources_Present := False;
4573 Data.Other_Sources_Present := False;
4575 -- If there are no languages declared, there are no sources
4577 if Current = Nil_String then
4578 Data.Source_Dirs := Nil_String;
4580 if Data.Qualifier = Standard then
4584 "a standard project cannot have no language declared",
4585 Languages.Location);
4589 -- Look through all the languages specified in attribute
4592 while Current /= Nil_String loop
4594 In_Tree.String_Elements.Table (Current);
4595 Get_Name_String (Element.Value);
4596 To_Lower (Name_Buffer (1 .. Name_Len));
4597 Lang_Name := Name_Find;
4599 NL_Id := Data.Languages;
4600 while NL_Id /= No_Name_List loop
4602 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4603 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4606 if NL_Id = No_Name_List then
4607 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4609 if Data.Languages = No_Name_List then
4611 Name_List_Table.Last (In_Tree.Name_Lists);
4614 NL_Id := Data.Languages;
4615 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4618 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4621 In_Tree.Name_Lists.Table (NL_Id).Next :=
4622 Name_List_Table.Last (In_Tree.Name_Lists);
4625 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4626 In_Tree.Name_Lists.Table (NL_Id) :=
4627 (Lang_Name, No_Name_List);
4629 if Get_Mode = Ada_Only then
4630 -- Check for language Ada
4632 if Lang_Name = Name_Ada then
4633 Data.Ada_Sources_Present := True;
4636 Data.Other_Sources_Present := True;
4640 Language_Data_Table.Increment_Last
4641 (In_Tree.Languages_Data);
4643 Language_Data_Table.Last (In_Tree.Languages_Data);
4644 Lang_Data.Name := Lang_Name;
4645 Lang_Data.Display_Name := Element.Value;
4646 Lang_Data.Next := Data.First_Language_Processing;
4648 if Lang_Name = Name_Ada then
4649 Lang_Data.Config.Kind := Unit_Based;
4650 Lang_Data.Config.Dependency_Kind := ALI_File;
4652 Lang_Data.Config.Kind := File_Based;
4653 Lang_Data.Config.Dependency_Kind := None;
4656 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4657 Data.First_Language_Processing := Index;
4661 Current := Element.Next;
4667 end Check_Programming_Languages;
4673 function Check_Project
4675 Root_Project : Project_Id;
4676 In_Tree : Project_Tree_Ref;
4677 Extending : Boolean) return Boolean
4680 if P = Root_Project then
4683 elsif Extending then
4685 Data : Project_Data;
4688 Data := In_Tree.Projects.Table (Root_Project);
4689 while Data.Extends /= No_Project loop
4690 if P = Data.Extends then
4694 Data := In_Tree.Projects.Table (Data.Extends);
4702 -------------------------------
4703 -- Check_Stand_Alone_Library --
4704 -------------------------------
4706 procedure Check_Stand_Alone_Library
4707 (Project : Project_Id;
4708 In_Tree : Project_Tree_Ref;
4709 Data : in out Project_Data;
4710 Current_Dir : String;
4711 Extending : Boolean)
4713 Lib_Interfaces : constant Prj.Variable_Value :=
4715 (Snames.Name_Library_Interface,
4716 Data.Decl.Attributes,
4719 Lib_Auto_Init : constant Prj.Variable_Value :=
4721 (Snames.Name_Library_Auto_Init,
4722 Data.Decl.Attributes,
4725 Lib_Src_Dir : constant Prj.Variable_Value :=
4727 (Snames.Name_Library_Src_Dir,
4728 Data.Decl.Attributes,
4731 Lib_Symbol_File : constant Prj.Variable_Value :=
4733 (Snames.Name_Library_Symbol_File,
4734 Data.Decl.Attributes,
4737 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4739 (Snames.Name_Library_Symbol_Policy,
4740 Data.Decl.Attributes,
4743 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4745 (Snames.Name_Library_Reference_Symbol_File,
4746 Data.Decl.Attributes,
4749 Auto_Init_Supported : Boolean;
4750 OK : Boolean := True;
4752 Next_Proj : Project_Id;
4755 if Get_Mode = Multi_Language then
4756 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4758 Auto_Init_Supported :=
4759 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4762 pragma Assert (Lib_Interfaces.Kind = List);
4764 -- It is a stand-alone library project file if attribute
4765 -- Library_Interface is defined.
4767 if not Lib_Interfaces.Default then
4768 SAL_Library : declare
4769 Interfaces : String_List_Id := Lib_Interfaces.Values;
4770 Interface_ALIs : String_List_Id := Nil_String;
4772 The_Unit_Id : Unit_Index;
4773 The_Unit_Data : Unit_Data;
4775 procedure Add_ALI_For (Source : File_Name_Type);
4776 -- Add an ALI file name to the list of Interface ALIs
4782 procedure Add_ALI_For (Source : File_Name_Type) is
4784 Get_Name_String (Source);
4787 ALI : constant String :=
4788 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4789 ALI_Name_Id : Name_Id;
4792 Name_Len := ALI'Length;
4793 Name_Buffer (1 .. Name_Len) := ALI;
4794 ALI_Name_Id := Name_Find;
4796 String_Element_Table.Increment_Last
4797 (In_Tree.String_Elements);
4798 In_Tree.String_Elements.Table
4799 (String_Element_Table.Last
4800 (In_Tree.String_Elements)) :=
4801 (Value => ALI_Name_Id,
4803 Display_Value => ALI_Name_Id,
4805 In_Tree.String_Elements.Table
4806 (Interfaces).Location,
4808 Next => Interface_ALIs);
4809 Interface_ALIs := String_Element_Table.Last
4810 (In_Tree.String_Elements);
4814 -- Start of processing for SAL_Library
4817 Data.Standalone_Library := True;
4819 -- Library_Interface cannot be an empty list
4821 if Interfaces = Nil_String then
4824 "Library_Interface cannot be an empty list",
4825 Lib_Interfaces.Location);
4828 -- Process each unit name specified in the attribute
4829 -- Library_Interface.
4831 while Interfaces /= Nil_String loop
4833 (In_Tree.String_Elements.Table (Interfaces).Value);
4834 To_Lower (Name_Buffer (1 .. Name_Len));
4836 if Name_Len = 0 then
4839 "an interface cannot be an empty string",
4840 In_Tree.String_Elements.Table (Interfaces).Location);
4844 Error_Msg_Name_1 := Unit;
4846 if Get_Mode = Ada_Only then
4848 Units_Htable.Get (In_Tree.Units_HT, Unit);
4850 if The_Unit_Id = No_Unit_Index then
4854 In_Tree.String_Elements.Table
4855 (Interfaces).Location);
4858 -- Check that the unit is part of the project
4861 In_Tree.Units.Table (The_Unit_Id);
4863 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4864 and then The_Unit_Data.File_Names
4865 (Body_Part).Path.Name /= Slash
4868 (The_Unit_Data.File_Names (Body_Part).Project,
4869 Project, In_Tree, Extending)
4871 -- There is a body for this unit.
4872 -- If there is no spec, we need to check
4873 -- that it is not a subunit.
4875 if The_Unit_Data.File_Names
4876 (Specification).Name = No_File
4879 Src_Ind : Source_File_Index;
4882 Src_Ind := Sinput.P.Load_Project_File
4884 (The_Unit_Data.File_Names
4885 (Body_Part).Path.Name));
4887 if Sinput.P.Source_File_Is_Subunit
4892 "%% is a subunit; " &
4893 "it cannot be an interface",
4895 String_Elements.Table
4896 (Interfaces).Location);
4901 -- The unit is not a subunit, so we add
4902 -- to the Interface ALIs the ALI file
4903 -- corresponding to the body.
4906 (The_Unit_Data.File_Names (Body_Part).Name);
4911 "%% is not an unit of this project",
4912 In_Tree.String_Elements.Table
4913 (Interfaces).Location);
4916 elsif The_Unit_Data.File_Names
4917 (Specification).Name /= No_File
4918 and then The_Unit_Data.File_Names
4919 (Specification).Path.Name /= Slash
4920 and then Check_Project
4921 (The_Unit_Data.File_Names
4922 (Specification).Project,
4923 Project, In_Tree, Extending)
4926 -- The unit is part of the project, it has
4927 -- a spec, but no body. We add to the Interface
4928 -- ALIs the ALI file corresponding to the spec.
4931 (The_Unit_Data.File_Names (Specification).Name);
4936 "%% is not an unit of this project",
4937 In_Tree.String_Elements.Table
4938 (Interfaces).Location);
4943 -- Multi_Language mode
4945 Next_Proj := Data.Extends;
4946 Source := Data.First_Source;
4949 while Source /= No_Source and then
4950 In_Tree.Sources.Table (Source).Unit /= Unit
4953 In_Tree.Sources.Table (Source).Next_In_Project;
4956 exit when Source /= No_Source or else
4957 Next_Proj = No_Project;
4960 In_Tree.Projects.Table (Next_Proj).First_Source;
4962 In_Tree.Projects.Table (Next_Proj).Extends;
4965 if Source /= No_Source then
4966 if In_Tree.Sources.Table (Source).Kind = Sep then
4967 Source := No_Source;
4969 elsif In_Tree.Sources.Table (Source).Kind = Spec
4971 In_Tree.Sources.Table (Source).Other_Part /=
4974 Source := In_Tree.Sources.Table (Source).Other_Part;
4978 if Source /= No_Source then
4979 if In_Tree.Sources.Table (Source).Project /= Project
4983 In_Tree.Sources.Table (Source).Project,
4986 Source := No_Source;
4990 if Source = No_Source then
4993 "%% is not an unit of this project",
4994 In_Tree.String_Elements.Table
4995 (Interfaces).Location);
4998 if In_Tree.Sources.Table (Source).Kind = Spec and then
4999 In_Tree.Sources.Table (Source).Other_Part /=
5002 Source := In_Tree.Sources.Table (Source).Other_Part;
5005 String_Element_Table.Increment_Last
5006 (In_Tree.String_Elements);
5007 In_Tree.String_Elements.Table
5008 (String_Element_Table.Last
5009 (In_Tree.String_Elements)) :=
5011 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5014 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
5016 In_Tree.String_Elements.Table
5017 (Interfaces).Location,
5019 Next => Interface_ALIs);
5020 Interface_ALIs := String_Element_Table.Last
5021 (In_Tree.String_Elements);
5029 In_Tree.String_Elements.Table (Interfaces).Next;
5032 -- Put the list of Interface ALIs in the project data
5034 Data.Lib_Interface_ALIs := Interface_ALIs;
5036 -- Check value of attribute Library_Auto_Init and set
5037 -- Lib_Auto_Init accordingly.
5039 if Lib_Auto_Init.Default then
5041 -- If no attribute Library_Auto_Init is declared, then set auto
5042 -- init only if it is supported.
5044 Data.Lib_Auto_Init := Auto_Init_Supported;
5047 Get_Name_String (Lib_Auto_Init.Value);
5048 To_Lower (Name_Buffer (1 .. Name_Len));
5050 if Name_Buffer (1 .. Name_Len) = "false" then
5051 Data.Lib_Auto_Init := False;
5053 elsif Name_Buffer (1 .. Name_Len) = "true" then
5054 if Auto_Init_Supported then
5055 Data.Lib_Auto_Init := True;
5058 -- Library_Auto_Init cannot be "true" if auto init is not
5063 "library auto init not supported " &
5065 Lib_Auto_Init.Location);
5071 "invalid value for attribute Library_Auto_Init",
5072 Lib_Auto_Init.Location);
5077 -- If attribute Library_Src_Dir is defined and not the empty string,
5078 -- check if the directory exist and is not the object directory or
5079 -- one of the source directories. This is the directory where copies
5080 -- of the interface sources will be copied. Note that this directory
5081 -- may be the library directory.
5083 if Lib_Src_Dir.Value /= Empty_String then
5085 Dir_Id : constant File_Name_Type :=
5086 File_Name_Type (Lib_Src_Dir.Value);
5093 Data.Directory.Display_Name,
5094 Data.Library_Src_Dir.Name,
5095 Data.Library_Src_Dir.Display_Name,
5096 Create => "library source copy",
5097 Current_Dir => Current_Dir,
5098 Location => Lib_Src_Dir.Location,
5099 Externally_Built => Data.Externally_Built);
5101 -- If directory does not exist, report an error
5103 if Data.Library_Src_Dir = No_Path_Information then
5105 -- Get the absolute name of the library directory that does
5106 -- not exist, to report an error.
5109 Dir_Name : constant String :=
5110 Get_Name_String (Dir_Id);
5113 if Is_Absolute_Path (Dir_Name) then
5114 Err_Vars.Error_Msg_File_1 := Dir_Id;
5117 Get_Name_String (Data.Directory.Name);
5119 if Name_Buffer (Name_Len) /=
5122 Name_Len := Name_Len + 1;
5123 Name_Buffer (Name_Len) :=
5124 Directory_Separator;
5129 Name_Len + Dir_Name'Length) :=
5131 Name_Len := Name_Len + Dir_Name'Length;
5132 Err_Vars.Error_Msg_Name_1 := Name_Find;
5137 Error_Msg_File_1 := Dir_Id;
5140 "Directory { does not exist",
5141 Lib_Src_Dir.Location);
5144 -- Report error if it is the same as the object directory
5146 elsif Data.Library_Src_Dir = Data.Object_Directory then
5149 "directory to copy interfaces cannot be " &
5150 "the object directory",
5151 Lib_Src_Dir.Location);
5152 Data.Library_Src_Dir := No_Path_Information;
5156 Src_Dirs : String_List_Id;
5157 Src_Dir : String_Element;
5160 -- Interface copy directory cannot be one of the source
5161 -- directory of the current project.
5163 Src_Dirs := Data.Source_Dirs;
5164 while Src_Dirs /= Nil_String loop
5165 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5167 -- Report error if it is one of the source directories
5169 if Data.Library_Src_Dir.Name =
5170 Path_Name_Type (Src_Dir.Value)
5174 "directory to copy interfaces cannot " &
5175 "be one of the source directories",
5176 Lib_Src_Dir.Location);
5177 Data.Library_Src_Dir := No_Path_Information;
5181 Src_Dirs := Src_Dir.Next;
5184 if Data.Library_Src_Dir /= No_Path_Information then
5186 -- It cannot be a source directory of any other
5189 Project_Loop : for Pid in 1 ..
5190 Project_Table.Last (In_Tree.Projects)
5193 In_Tree.Projects.Table (Pid).Source_Dirs;
5194 Dir_Loop : while Src_Dirs /= Nil_String loop
5196 In_Tree.String_Elements.Table (Src_Dirs);
5198 -- Report error if it is one of the source
5201 if Data.Library_Src_Dir.Name =
5202 Path_Name_Type (Src_Dir.Value)
5205 File_Name_Type (Src_Dir.Value);
5207 In_Tree.Projects.Table (Pid).Name;
5210 "directory to copy interfaces cannot " &
5211 "be the same as source directory { of " &
5213 Lib_Src_Dir.Location);
5214 Data.Library_Src_Dir := No_Path_Information;
5218 Src_Dirs := Src_Dir.Next;
5220 end loop Project_Loop;
5224 -- In high verbosity, if there is a valid Library_Src_Dir,
5225 -- display its path name.
5227 if Data.Library_Src_Dir /= No_Path_Information
5228 and then Current_Verbosity = High
5231 ("Directory to copy interfaces",
5232 Get_Name_String (Data.Library_Src_Dir.Name));
5238 -- Check the symbol related attributes
5240 -- First, the symbol policy
5242 if not Lib_Symbol_Policy.Default then
5244 Value : constant String :=
5246 (Get_Name_String (Lib_Symbol_Policy.Value));
5249 -- Symbol policy must hove one of a limited number of values
5251 if Value = "autonomous" or else Value = "default" then
5252 Data.Symbol_Data.Symbol_Policy := Autonomous;
5254 elsif Value = "compliant" then
5255 Data.Symbol_Data.Symbol_Policy := Compliant;
5257 elsif Value = "controlled" then
5258 Data.Symbol_Data.Symbol_Policy := Controlled;
5260 elsif Value = "restricted" then
5261 Data.Symbol_Data.Symbol_Policy := Restricted;
5263 elsif Value = "direct" then
5264 Data.Symbol_Data.Symbol_Policy := Direct;
5269 "illegal value for Library_Symbol_Policy",
5270 Lib_Symbol_Policy.Location);
5275 -- If attribute Library_Symbol_File is not specified, symbol policy
5276 -- cannot be Restricted.
5278 if Lib_Symbol_File.Default then
5279 if Data.Symbol_Data.Symbol_Policy = Restricted then
5282 "Library_Symbol_File needs to be defined when " &
5283 "symbol policy is Restricted",
5284 Lib_Symbol_Policy.Location);
5288 -- Library_Symbol_File is defined
5290 Data.Symbol_Data.Symbol_File :=
5291 Path_Name_Type (Lib_Symbol_File.Value);
5293 Get_Name_String (Lib_Symbol_File.Value);
5295 if Name_Len = 0 then
5298 "symbol file name cannot be an empty string",
5299 Lib_Symbol_File.Location);
5302 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5305 for J in 1 .. Name_Len loop
5306 if Name_Buffer (J) = '/'
5307 or else Name_Buffer (J) = Directory_Separator
5316 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5319 "symbol file name { is illegal. " &
5320 "Name cannot include directory info.",
5321 Lib_Symbol_File.Location);
5326 -- If attribute Library_Reference_Symbol_File is not defined,
5327 -- symbol policy cannot be Compliant or Controlled.
5329 if Lib_Ref_Symbol_File.Default then
5330 if Data.Symbol_Data.Symbol_Policy = Compliant
5331 or else Data.Symbol_Data.Symbol_Policy = Controlled
5335 "a reference symbol file needs to be defined",
5336 Lib_Symbol_Policy.Location);
5340 -- Library_Reference_Symbol_File is defined, check file exists
5342 Data.Symbol_Data.Reference :=
5343 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5345 Get_Name_String (Lib_Ref_Symbol_File.Value);
5347 if Name_Len = 0 then
5350 "reference symbol file name cannot be an empty string",
5351 Lib_Symbol_File.Location);
5354 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5356 Add_Str_To_Name_Buffer
5357 (Get_Name_String (Data.Directory.Name));
5358 Add_Char_To_Name_Buffer (Directory_Separator);
5359 Add_Str_To_Name_Buffer
5360 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5361 Data.Symbol_Data.Reference := Name_Find;
5364 if not Is_Regular_File
5365 (Get_Name_String (Data.Symbol_Data.Reference))
5368 File_Name_Type (Lib_Ref_Symbol_File.Value);
5370 -- For controlled and direct symbol policies, it is an error
5371 -- if the reference symbol file does not exist. For other
5372 -- symbol policies, this is just a warning
5375 Data.Symbol_Data.Symbol_Policy /= Controlled
5376 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5380 "<library reference symbol file { does not exist",
5381 Lib_Ref_Symbol_File.Location);
5383 -- In addition in the non-controlled case, if symbol policy
5384 -- is Compliant, it is changed to Autonomous, because there
5385 -- is no reference to check against, and we don't want to
5386 -- fail in this case.
5388 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5389 if Data.Symbol_Data.Symbol_Policy = Compliant then
5390 Data.Symbol_Data.Symbol_Policy := Autonomous;
5395 -- If both the reference symbol file and the symbol file are
5396 -- defined, then check that they are not the same file.
5398 if Data.Symbol_Data.Symbol_File /= No_Path then
5399 Get_Name_String (Data.Symbol_Data.Symbol_File);
5401 if Name_Len > 0 then
5403 Symb_Path : constant String :=
5406 (Data.Object_Directory.Name) &
5407 Directory_Separator &
5408 Name_Buffer (1 .. Name_Len),
5409 Directory => Current_Dir,
5411 Opt.Follow_Links_For_Files);
5412 Ref_Path : constant String :=
5415 (Data.Symbol_Data.Reference),
5416 Directory => Current_Dir,
5418 Opt.Follow_Links_For_Files);
5420 if Symb_Path = Ref_Path then
5423 "library reference symbol file and library" &
5424 " symbol file cannot be the same file",
5425 Lib_Ref_Symbol_File.Location);
5433 end Check_Stand_Alone_Library;
5435 ----------------------------
5436 -- Compute_Directory_Last --
5437 ----------------------------
5439 function Compute_Directory_Last (Dir : String) return Natural is
5442 and then (Dir (Dir'Last - 1) = Directory_Separator
5443 or else Dir (Dir'Last - 1) = '/')
5445 return Dir'Last - 1;
5449 end Compute_Directory_Last;
5456 (Project : Project_Id;
5457 In_Tree : Project_Tree_Ref;
5459 Flag_Location : Source_Ptr)
5461 Real_Location : Source_Ptr := Flag_Location;
5462 Error_Buffer : String (1 .. 5_000);
5463 Error_Last : Natural := 0;
5464 Name_Number : Natural := 0;
5465 File_Number : Natural := 0;
5466 First : Positive := Msg'First;
5469 procedure Add (C : Character);
5470 -- Add a character to the buffer
5472 procedure Add (S : String);
5473 -- Add a string to the buffer
5476 -- Add a name to the buffer
5479 -- Add a file name to the buffer
5485 procedure Add (C : Character) is
5487 Error_Last := Error_Last + 1;
5488 Error_Buffer (Error_Last) := C;
5491 procedure Add (S : String) is
5493 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5494 Error_Last := Error_Last + S'Length;
5501 procedure Add_File is
5502 File : File_Name_Type;
5506 File_Number := File_Number + 1;
5510 File := Err_Vars.Error_Msg_File_1;
5512 File := Err_Vars.Error_Msg_File_2;
5514 File := Err_Vars.Error_Msg_File_3;
5519 Get_Name_String (File);
5520 Add (Name_Buffer (1 .. Name_Len));
5528 procedure Add_Name is
5533 Name_Number := Name_Number + 1;
5537 Name := Err_Vars.Error_Msg_Name_1;
5539 Name := Err_Vars.Error_Msg_Name_2;
5541 Name := Err_Vars.Error_Msg_Name_3;
5546 Get_Name_String (Name);
5547 Add (Name_Buffer (1 .. Name_Len));
5551 -- Start of processing for Error_Msg
5554 -- If location of error is unknown, use the location of the project
5556 if Real_Location = No_Location then
5557 Real_Location := In_Tree.Projects.Table (Project).Location;
5560 if Error_Report = null then
5561 Prj.Err.Error_Msg (Msg, Real_Location);
5565 -- Ignore continuation character
5567 if Msg (First) = '\' then
5571 -- Warning character is always the first one in this package
5572 -- this is an undocumented kludge???
5574 if Msg (First) = '?' then
5578 elsif Msg (First) = '<' then
5581 if Err_Vars.Error_Msg_Warn then
5587 while Index <= Msg'Last loop
5588 if Msg (Index) = '{' then
5591 elsif Msg (Index) = '%' then
5592 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5604 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5607 ----------------------
5608 -- Find_Ada_Sources --
5609 ----------------------
5611 procedure Find_Ada_Sources
5612 (Project : Project_Id;
5613 In_Tree : Project_Tree_Ref;
5614 Data : in out Project_Data;
5615 Current_Dir : String)
5617 Source_Dir : String_List_Id := Data.Source_Dirs;
5618 Element : String_Element;
5620 Current_Source : String_List_Id := Nil_String;
5621 Source_Recorded : Boolean := False;
5624 if Current_Verbosity = High then
5625 Write_Line ("Looking for sources:");
5628 -- For each subdirectory
5630 while Source_Dir /= Nil_String loop
5632 Source_Recorded := False;
5633 Element := In_Tree.String_Elements.Table (Source_Dir);
5634 if Element.Value /= No_Name then
5635 Get_Name_String (Element.Display_Value);
5638 Source_Directory : constant String :=
5639 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5640 Dir_Last : constant Natural :=
5641 Compute_Directory_Last (Source_Directory);
5644 if Current_Verbosity = High then
5645 Write_Attr ("Source_Dir", Source_Directory);
5648 -- We look at every entry in the source directory
5651 Source_Directory (Source_Directory'First .. Dir_Last));
5654 Read (Dir, Name_Buffer, Name_Len);
5656 if Current_Verbosity = High then
5657 Write_Str (" Checking ");
5658 Write_Line (Name_Buffer (1 .. Name_Len));
5661 exit when Name_Len = 0;
5664 File_Name : constant File_Name_Type := Name_Find;
5666 -- ??? We could probably optimize the following call:
5667 -- we need to resolve links only once for the
5668 -- directory itself, and then do a single call to
5669 -- readlink() for each file. Unfortunately that would
5670 -- require a change in Normalize_Pathname so that it
5671 -- has the option of not resolving links for its
5672 -- Directory parameter, only for Name.
5674 Path : constant String :=
5676 (Name => Name_Buffer (1 .. Name_Len),
5679 (Source_Directory'First .. Dir_Last),
5681 Opt.Follow_Links_For_Files,
5682 Case_Sensitive => True);
5684 Path_Name : Path_Name_Type;
5687 Name_Len := Path'Length;
5688 Name_Buffer (1 .. Name_Len) := Path;
5689 Path_Name := Name_Find;
5691 -- We attempt to register it as a source. However,
5692 -- there is no error if the file does not contain a
5693 -- valid source. But there is an error if we have a
5694 -- duplicate unit name.
5697 (File_Name => File_Name,
5698 Path_Name => Path_Name,
5702 Location => No_Location,
5703 Current_Source => Current_Source,
5704 Source_Recorded => Source_Recorded,
5705 Current_Dir => Current_Dir);
5714 when Directory_Error =>
5718 if Source_Recorded then
5719 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5723 Source_Dir := Element.Next;
5726 if Current_Verbosity = High then
5727 Write_Line ("end Looking for sources.");
5730 end Find_Ada_Sources;
5732 --------------------------------
5733 -- Free_Ada_Naming_Exceptions --
5734 --------------------------------
5736 procedure Free_Ada_Naming_Exceptions is
5738 Ada_Naming_Exception_Table.Set_Last (0);
5739 Ada_Naming_Exceptions.Reset;
5740 Reverse_Ada_Naming_Exceptions.Reset;
5741 end Free_Ada_Naming_Exceptions;
5743 ---------------------
5744 -- Get_Directories --
5745 ---------------------
5747 procedure Get_Directories
5748 (Project : Project_Id;
5749 In_Tree : Project_Tree_Ref;
5750 Current_Dir : String;
5751 Data : in out Project_Data)
5753 Object_Dir : constant Variable_Value :=
5755 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5757 Exec_Dir : constant Variable_Value :=
5759 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5761 Source_Dirs : constant Variable_Value :=
5763 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5765 Excluded_Source_Dirs : constant Variable_Value :=
5767 (Name_Excluded_Source_Dirs,
5768 Data.Decl.Attributes,
5771 Source_Files : constant Variable_Value :=
5773 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5775 Last_Source_Dir : String_List_Id := Nil_String;
5777 Languages : constant Variable_Value :=
5779 (Name_Languages, Data.Decl.Attributes, In_Tree);
5781 procedure Find_Source_Dirs
5782 (From : File_Name_Type;
5783 Location : Source_Ptr;
5784 Removed : Boolean := False);
5785 -- Find one or several source directories, and add (or remove, if
5786 -- Removed is True) them to list of source directories of the project.
5788 ----------------------
5789 -- Find_Source_Dirs --
5790 ----------------------
5792 procedure Find_Source_Dirs
5793 (From : File_Name_Type;
5794 Location : Source_Ptr;
5795 Removed : Boolean := False)
5797 Directory : constant String := Get_Name_String (From);
5798 Element : String_Element;
5800 procedure Recursive_Find_Dirs (Path : Name_Id);
5801 -- Find all the subdirectories (recursively) of Path and add them
5802 -- to the list of source directories of the project.
5804 -------------------------
5805 -- Recursive_Find_Dirs --
5806 -------------------------
5808 procedure Recursive_Find_Dirs (Path : Name_Id) is
5810 Name : String (1 .. 250);
5812 List : String_List_Id;
5813 Prev : String_List_Id;
5814 Element : String_Element;
5815 Found : Boolean := False;
5817 Non_Canonical_Path : Name_Id := No_Name;
5818 Canonical_Path : Name_Id := No_Name;
5820 The_Path : constant String :=
5822 (Get_Name_String (Path),
5823 Directory => Current_Dir,
5824 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5825 Directory_Separator;
5827 The_Path_Last : constant Natural :=
5828 Compute_Directory_Last (The_Path);
5831 Name_Len := The_Path_Last - The_Path'First + 1;
5832 Name_Buffer (1 .. Name_Len) :=
5833 The_Path (The_Path'First .. The_Path_Last);
5834 Non_Canonical_Path := Name_Find;
5836 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5838 -- To avoid processing the same directory several times, check
5839 -- if the directory is already in Recursive_Dirs. If it is, then
5840 -- there is nothing to do, just return. If it is not, put it there
5841 -- and continue recursive processing.
5844 if Recursive_Dirs.Get (Canonical_Path) then
5847 Recursive_Dirs.Set (Canonical_Path, True);
5851 -- Check if directory is already in list
5853 List := Data.Source_Dirs;
5855 while List /= Nil_String loop
5856 Element := In_Tree.String_Elements.Table (List);
5858 if Element.Value /= No_Name then
5859 Found := Element.Value = Canonical_Path;
5864 List := Element.Next;
5867 -- If directory is not already in list, put it there
5869 if (not Removed) and (not Found) then
5870 if Current_Verbosity = High then
5872 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5875 String_Element_Table.Increment_Last
5876 (In_Tree.String_Elements);
5878 (Value => Canonical_Path,
5879 Display_Value => Non_Canonical_Path,
5880 Location => No_Location,
5885 -- Case of first source directory
5887 if Last_Source_Dir = Nil_String then
5888 Data.Source_Dirs := String_Element_Table.Last
5889 (In_Tree.String_Elements);
5891 -- Here we already have source directories
5894 -- Link the previous last to the new one
5896 In_Tree.String_Elements.Table
5897 (Last_Source_Dir).Next :=
5898 String_Element_Table.Last
5899 (In_Tree.String_Elements);
5902 -- And register this source directory as the new last
5904 Last_Source_Dir := String_Element_Table.Last
5905 (In_Tree.String_Elements);
5906 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5909 elsif Removed and Found then
5910 if Prev = Nil_String then
5912 In_Tree.String_Elements.Table (List).Next;
5914 In_Tree.String_Elements.Table (Prev).Next :=
5915 In_Tree.String_Elements.Table (List).Next;
5919 -- Now look for subdirectories. We do that even when this
5920 -- directory is already in the list, because some of its
5921 -- subdirectories may not be in the list yet.
5923 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5926 Read (Dir, Name, Last);
5929 if Name (1 .. Last) /= "."
5930 and then Name (1 .. Last) /= ".."
5932 -- Avoid . and .. directories
5934 if Current_Verbosity = High then
5935 Write_Str (" Checking ");
5936 Write_Line (Name (1 .. Last));
5940 Path_Name : constant String :=
5942 (Name => Name (1 .. Last),
5944 The_Path (The_Path'First .. The_Path_Last),
5945 Resolve_Links => Opt.Follow_Links_For_Dirs,
5946 Case_Sensitive => True);
5949 if Is_Directory (Path_Name) then
5950 -- We have found a new subdirectory, call self
5952 Name_Len := Path_Name'Length;
5953 Name_Buffer (1 .. Name_Len) := Path_Name;
5954 Recursive_Find_Dirs (Name_Find);
5963 when Directory_Error =>
5965 end Recursive_Find_Dirs;
5967 -- Start of processing for Find_Source_Dirs
5970 if Current_Verbosity = High and then not Removed then
5971 Write_Str ("Find_Source_Dirs (""");
5972 Write_Str (Directory);
5976 -- First, check if we are looking for a directory tree, indicated
5977 -- by "/**" at the end.
5979 if Directory'Length >= 3
5980 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5981 and then (Directory (Directory'Last - 2) = '/'
5983 Directory (Directory'Last - 2) = Directory_Separator)
5986 Data.Known_Order_Of_Source_Dirs := False;
5989 Name_Len := Directory'Length - 3;
5991 if Name_Len = 0 then
5993 -- Case of "/**": all directories in file system
5996 Name_Buffer (1) := Directory (Directory'First);
5999 Name_Buffer (1 .. Name_Len) :=
6000 Directory (Directory'First .. Directory'Last - 3);
6003 if Current_Verbosity = High then
6004 Write_Str ("Looking for all subdirectories of """);
6005 Write_Str (Name_Buffer (1 .. Name_Len));
6010 Base_Dir : constant File_Name_Type := Name_Find;
6011 Root_Dir : constant String :=
6013 (Name => Get_Name_String (Base_Dir),
6015 Get_Name_String (Data.Directory.Display_Name),
6016 Resolve_Links => False,
6017 Case_Sensitive => True);
6020 if Root_Dir'Length = 0 then
6021 Err_Vars.Error_Msg_File_1 := Base_Dir;
6023 if Location = No_Location then
6026 "{ is not a valid directory.",
6031 "{ is not a valid directory.",
6036 -- We have an existing directory, we register it and all of
6037 -- its subdirectories.
6039 if Current_Verbosity = High then
6040 Write_Line ("Looking for source directories:");
6043 Name_Len := Root_Dir'Length;
6044 Name_Buffer (1 .. Name_Len) := Root_Dir;
6045 Recursive_Find_Dirs (Name_Find);
6047 if Current_Verbosity = High then
6048 Write_Line ("End of looking for source directories.");
6053 -- We have a single directory
6057 Path_Name : Path_Name_Type;
6058 Display_Path_Name : Path_Name_Type;
6059 List : String_List_Id;
6060 Prev : String_List_Id;
6064 (Project => Project,
6067 Parent => Data.Directory.Display_Name,
6069 Display => Display_Path_Name,
6070 Current_Dir => Current_Dir);
6072 if Path_Name = No_Path then
6073 Err_Vars.Error_Msg_File_1 := From;
6075 if Location = No_Location then
6078 "{ is not a valid directory",
6083 "{ is not a valid directory",
6089 Path : constant String :=
6090 Get_Name_String (Path_Name) &
6091 Directory_Separator;
6092 Last_Path : constant Natural :=
6093 Compute_Directory_Last (Path);
6095 Display_Path : constant String :=
6097 (Display_Path_Name) &
6098 Directory_Separator;
6099 Last_Display_Path : constant Natural :=
6100 Compute_Directory_Last
6102 Display_Path_Id : Name_Id;
6106 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6107 Path_Id := Name_Find;
6109 Add_Str_To_Name_Buffer
6111 (Display_Path'First .. Last_Display_Path));
6112 Display_Path_Id := Name_Find;
6116 -- As it is an existing directory, we add it to the
6117 -- list of directories.
6119 String_Element_Table.Increment_Last
6120 (In_Tree.String_Elements);
6124 Display_Value => Display_Path_Id,
6125 Location => No_Location,
6127 Next => Nil_String);
6129 if Last_Source_Dir = Nil_String then
6131 -- This is the first source directory
6133 Data.Source_Dirs := String_Element_Table.Last
6134 (In_Tree.String_Elements);
6137 -- We already have source directories, link the
6138 -- previous last to the new one.
6140 In_Tree.String_Elements.Table
6141 (Last_Source_Dir).Next :=
6142 String_Element_Table.Last
6143 (In_Tree.String_Elements);
6146 -- And register this source directory as the new last
6148 Last_Source_Dir := String_Element_Table.Last
6149 (In_Tree.String_Elements);
6150 In_Tree.String_Elements.Table
6151 (Last_Source_Dir) := Element;
6154 -- Remove source dir, if present
6156 List := Data.Source_Dirs;
6159 -- Look for source dir in current list
6161 while List /= Nil_String loop
6162 Element := In_Tree.String_Elements.Table (List);
6163 exit when Element.Value = Path_Id;
6165 List := Element.Next;
6168 if List /= Nil_String then
6169 -- Source dir was found, remove it from the list
6171 if Prev = Nil_String then
6173 In_Tree.String_Elements.Table (List).Next;
6176 In_Tree.String_Elements.Table (Prev).Next :=
6177 In_Tree.String_Elements.Table (List).Next;
6185 end Find_Source_Dirs;
6187 -- Start of processing for Get_Directories
6190 if Current_Verbosity = High then
6191 Write_Line ("Starting to look for directories");
6194 -- Set the object directory to its default which may be nil, if there
6195 -- is no sources in the project.
6197 if (((not Source_Files.Default)
6198 and then Source_Files.Values = Nil_String)
6200 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
6202 ((not Languages.Default) and then Languages.Values = Nil_String))
6203 and then Data.Extends = No_Project
6205 Data.Object_Directory := No_Path_Information;
6208 Data.Object_Directory := Data.Directory;
6211 -- Check the object directory
6213 if Object_Dir.Value /= Empty_String then
6214 Get_Name_String (Object_Dir.Value);
6216 if Name_Len = 0 then
6219 "Object_Dir cannot be empty",
6220 Object_Dir.Location);
6223 -- We check that the specified object directory does exist
6228 File_Name_Type (Object_Dir.Value),
6229 Data.Directory.Display_Name,
6230 Data.Object_Directory.Name,
6231 Data.Object_Directory.Display_Name,
6233 Location => Object_Dir.Location,
6234 Current_Dir => Current_Dir,
6235 Externally_Built => Data.Externally_Built);
6237 if Data.Object_Directory = No_Path_Information then
6239 -- The object directory does not exist, report an error if the
6240 -- project is not externally built.
6242 if not Data.Externally_Built then
6243 Err_Vars.Error_Msg_File_1 :=
6244 File_Name_Type (Object_Dir.Value);
6247 "the object directory { cannot be found",
6251 -- Do not keep a nil Object_Directory. Set it to the specified
6252 -- (relative or absolute) path. This is for the benefit of
6253 -- tools that recover from errors; for example, these tools
6254 -- could create the non existent directory.
6256 Data.Object_Directory.Display_Name :=
6257 Path_Name_Type (Object_Dir.Value);
6258 Data.Object_Directory.Name :=
6259 Path_Name_Type (Canonical_Case_File_Name (Object_Dir.Value));
6263 elsif Data.Object_Directory /= No_Path_Information and then
6267 Name_Buffer (1) := '.';
6272 Data.Directory.Display_Name,
6273 Data.Object_Directory.Name,
6274 Data.Object_Directory.Display_Name,
6276 Location => Object_Dir.Location,
6277 Current_Dir => Current_Dir,
6278 Externally_Built => Data.Externally_Built);
6281 if Current_Verbosity = High then
6282 if Data.Object_Directory = No_Path_Information then
6283 Write_Line ("No object directory");
6286 ("Object directory",
6287 Get_Name_String (Data.Object_Directory.Display_Name));
6291 -- Check the exec directory
6293 -- We set the object directory to its default
6295 Data.Exec_Directory := Data.Object_Directory;
6297 if Exec_Dir.Value /= Empty_String then
6298 Get_Name_String (Exec_Dir.Value);
6300 if Name_Len = 0 then
6303 "Exec_Dir cannot be empty",
6307 -- We check that the specified exec directory does exist
6312 File_Name_Type (Exec_Dir.Value),
6313 Data.Directory.Display_Name,
6314 Data.Exec_Directory.Name,
6315 Data.Exec_Directory.Display_Name,
6317 Location => Exec_Dir.Location,
6318 Current_Dir => Current_Dir,
6319 Externally_Built => Data.Externally_Built);
6321 if Data.Exec_Directory = No_Path_Information then
6322 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6325 "the exec directory { cannot be found",
6331 if Current_Verbosity = High then
6332 if Data.Exec_Directory = No_Path_Information then
6333 Write_Line ("No exec directory");
6335 Write_Str ("Exec directory: """);
6336 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6341 -- Look for the source directories
6343 if Current_Verbosity = High then
6344 Write_Line ("Starting to look for source directories");
6347 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6349 if (not Source_Files.Default) and then
6350 Source_Files.Values = Nil_String
6352 Data.Source_Dirs := Nil_String;
6354 if Data.Qualifier = Standard then
6358 "a standard project cannot have no sources",
6359 Source_Files.Location);
6362 elsif Source_Dirs.Default then
6364 -- No Source_Dirs specified: the single source directory is the one
6365 -- containing the project file
6367 String_Element_Table.Increment_Last
6368 (In_Tree.String_Elements);
6369 Data.Source_Dirs := String_Element_Table.Last
6370 (In_Tree.String_Elements);
6371 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6372 (Value => Name_Id (Data.Directory.Name),
6373 Display_Value => Name_Id (Data.Directory.Display_Name),
6374 Location => No_Location,
6379 if Current_Verbosity = High then
6381 ("Single source directory",
6382 Get_Name_String (Data.Directory.Display_Name));
6385 elsif Source_Dirs.Values = Nil_String then
6386 if Data.Qualifier = Standard then
6390 "a standard project cannot have no source directories",
6391 Source_Dirs.Location);
6394 Data.Source_Dirs := Nil_String;
6398 Source_Dir : String_List_Id;
6399 Element : String_Element;
6402 -- Process the source directories for each element of the list
6404 Source_Dir := Source_Dirs.Values;
6405 while Source_Dir /= Nil_String loop
6406 Element := In_Tree.String_Elements.Table (Source_Dir);
6408 (File_Name_Type (Element.Value), Element.Location);
6409 Source_Dir := Element.Next;
6414 if not Excluded_Source_Dirs.Default
6415 and then Excluded_Source_Dirs.Values /= Nil_String
6418 Source_Dir : String_List_Id;
6419 Element : String_Element;
6422 -- Process the source directories for each element of the list
6424 Source_Dir := Excluded_Source_Dirs.Values;
6425 while Source_Dir /= Nil_String loop
6426 Element := In_Tree.String_Elements.Table (Source_Dir);
6428 (File_Name_Type (Element.Value),
6431 Source_Dir := Element.Next;
6436 if Current_Verbosity = High then
6437 Write_Line ("Putting source directories in canonical cases");
6441 Current : String_List_Id := Data.Source_Dirs;
6442 Element : String_Element;
6445 while Current /= Nil_String loop
6446 Element := In_Tree.String_Elements.Table (Current);
6447 if Element.Value /= No_Name then
6449 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
6450 In_Tree.String_Elements.Table (Current) := Element;
6453 Current := Element.Next;
6456 end Get_Directories;
6463 (Project : Project_Id;
6464 In_Tree : Project_Tree_Ref;
6465 Data : in out Project_Data)
6467 Mains : constant Variable_Value :=
6468 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6469 List : String_List_Id;
6470 Elem : String_Element;
6473 Data.Mains := Mains.Values;
6475 -- If no Mains were specified, and if we are an extending project,
6476 -- inherit the Mains from the project we are extending.
6478 if Mains.Default then
6479 if not Data.Library and then Data.Extends /= No_Project then
6481 In_Tree.Projects.Table (Data.Extends).Mains;
6484 -- In a library project file, Main cannot be specified
6486 elsif Data.Library then
6489 "a library project file cannot have Main specified",
6493 List := Mains.Values;
6494 while List /= Nil_String loop
6495 Elem := In_Tree.String_Elements.Table (List);
6497 if Length_Of_Name (Elem.Value) = 0 then
6500 "?a main cannot have an empty name",
6510 ---------------------------
6511 -- Get_Sources_From_File --
6512 ---------------------------
6514 procedure Get_Sources_From_File
6516 Location : Source_Ptr;
6517 Project : Project_Id;
6518 In_Tree : Project_Tree_Ref)
6520 File : Prj.Util.Text_File;
6521 Line : String (1 .. 250);
6523 Source_Name : File_Name_Type;
6524 Name_Loc : Name_Location;
6527 if Get_Mode = Ada_Only then
6531 if Current_Verbosity = High then
6532 Write_Str ("Opening """);
6539 Prj.Util.Open (File, Path);
6541 if not Prj.Util.Is_Valid (File) then
6542 Error_Msg (Project, In_Tree, "file does not exist", Location);
6545 -- Read the lines one by one
6547 while not Prj.Util.End_Of_File (File) loop
6548 Prj.Util.Get_Line (File, Line, Last);
6550 -- A non empty, non comment line should contain a file name
6553 and then (Last = 1 or else Line (1 .. 2) /= "--")
6556 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6557 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6558 Source_Name := Name_Find;
6560 -- Check that there is no directory information
6562 for J in 1 .. Last loop
6563 if Line (J) = '/' or else Line (J) = Directory_Separator then
6564 Error_Msg_File_1 := Source_Name;
6568 "file name cannot include directory information ({)",
6574 Name_Loc := Source_Names.Get (Source_Name);
6576 if Name_Loc = No_Name_Location then
6578 (Name => Source_Name,
6579 Location => Location,
6580 Source => No_Source,
6585 Source_Names.Set (Source_Name, Name_Loc);
6589 Prj.Util.Close (File);
6592 end Get_Sources_From_File;
6594 -----------------------
6595 -- Compute_Unit_Name --
6596 -----------------------
6598 procedure Compute_Unit_Name
6599 (File_Name : File_Name_Type;
6600 Dot_Replacement : File_Name_Type;
6601 Separate_Suffix : File_Name_Type;
6602 Body_Suffix : File_Name_Type;
6603 Spec_Suffix : File_Name_Type;
6604 Casing : Casing_Type;
6605 Kind : out Source_Kind;
6608 Filename : constant String := Get_Name_String (File_Name);
6609 Last : Integer := Filename'Last;
6610 Sep_Len : constant Integer :=
6611 Integer (Length_Of_Name (Separate_Suffix));
6612 Body_Len : constant Integer :=
6613 Integer (Length_Of_Name (Body_Suffix));
6614 Spec_Len : constant Integer :=
6615 Integer (Length_Of_Name (Spec_Suffix));
6617 Standard_GNAT : constant Boolean :=
6618 Spec_Suffix = Default_Ada_Spec_Suffix
6620 Body_Suffix = Default_Ada_Body_Suffix;
6622 Unit_Except : Unit_Exception;
6623 Masked : Boolean := False;
6628 if Dot_Replacement = No_File then
6629 if Current_Verbosity = High then
6630 Write_Line (" No dot_replacement specified");
6635 -- Choose the longest suffix that matches. If there are several matches,
6636 -- give priority to specs, then bodies, then separates.
6638 if Separate_Suffix /= Body_Suffix
6639 and then Suffix_Matches (Filename, Separate_Suffix)
6641 Last := Filename'Last - Sep_Len;
6645 if Filename'Last - Body_Len <= Last
6646 and then Suffix_Matches (Filename, Body_Suffix)
6648 Last := Natural'Min (Last, Filename'Last - Body_Len);
6652 if Filename'Last - Spec_Len <= Last
6653 and then Suffix_Matches (Filename, Spec_Suffix)
6655 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6659 if Last = Filename'Last then
6660 if Current_Verbosity = High then
6661 Write_Line (" No matching suffix");
6666 -- Check that the casing matches
6668 if File_Names_Case_Sensitive then
6670 when All_Lower_Case =>
6671 for J in Filename'First .. Last loop
6672 if Is_Letter (Filename (J))
6673 and then not Is_Lower (Filename (J))
6675 if Current_Verbosity = High then
6676 Write_Line (" Invalid casing");
6682 when All_Upper_Case =>
6683 for J in Filename'First .. Last loop
6684 if Is_Letter (Filename (J))
6685 and then not Is_Upper (Filename (J))
6687 if Current_Verbosity = High then
6688 Write_Line (" Invalid casing");
6694 when Mixed_Case | Unknown =>
6699 -- If Dot_Replacement is not a single dot, then there should not
6700 -- be any dot in the name.
6703 Dot_Repl : constant String := Get_Name_String (Dot_Replacement);
6706 if Dot_Repl /= "." then
6707 for Index in Filename'First .. Last loop
6708 if Filename (Index) = '.' then
6709 if Current_Verbosity = High then
6710 Write_Line (" Invalid name, contains dot");
6716 Replace_Into_Name_Buffer
6717 (Filename (Filename'First .. Last), Dot_Repl, '.');
6719 Name_Len := Last - Filename'First + 1;
6720 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6722 (Source => Name_Buffer (1 .. Name_Len),
6723 Mapping => Lower_Case_Map);
6727 -- In the standard GNAT naming scheme, check for special cases: children
6728 -- or separates of A, G, I or S, and run time sources.
6730 if Standard_GNAT and then Name_Len >= 3 then
6732 S1 : constant Character := Name_Buffer (1);
6733 S2 : constant Character := Name_Buffer (2);
6734 S3 : constant Character := Name_Buffer (3);
6742 -- Children or separates of packages A, G, I or S. These names
6743 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6744 -- versions (x__... and x~...) are allowed in all platforms,
6745 -- because it is not possible to know the platform before
6746 -- processing of the project files.
6748 if S2 = '_' and then S3 = '_' then
6749 Name_Buffer (2) := '.';
6750 Name_Buffer (3 .. Name_Len - 1) :=
6751 Name_Buffer (4 .. Name_Len);
6752 Name_Len := Name_Len - 1;
6755 Name_Buffer (2) := '.';
6759 -- If it is potentially a run time source, disable filling
6760 -- of the mapping file to avoid warnings.
6762 Set_Mapping_File_Initial_State_To_Empty;
6768 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6769 -- that this is a valid unit name
6771 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6773 -- If there is a naming exception for the same unit, the file is not
6774 -- a source for the unit. Currently, this only applies in multi_lang
6775 -- mode, since Unit_Exceptions is no set in ada_only mode.
6777 if Unit /= No_Name then
6778 Unit_Except := Unit_Exceptions.Get (Unit);
6781 Masked := Unit_Except.Spec /= No_File
6783 Unit_Except.Spec /= File_Name;
6785 Masked := Unit_Except.Impl /= No_File
6787 Unit_Except.Impl /= File_Name;
6791 if Current_Verbosity = High then
6792 Write_Str (" """ & Filename & """ contains the ");
6795 Write_Str ("spec of a unit found in """);
6796 Write_Str (Get_Name_String (Unit_Except.Spec));
6798 Write_Str ("body of a unit found in """);
6799 Write_Str (Get_Name_String (Unit_Except.Impl));
6802 Write_Line (""" (ignored)");
6810 and then Current_Verbosity = High
6813 when Spec => Write_Str (" spec of ");
6814 when Impl => Write_Str (" body of ");
6815 when Sep => Write_Str (" sep of ");
6818 Write_Line (Get_Name_String (Unit));
6820 end Compute_Unit_Name;
6827 (In_Tree : Project_Tree_Ref;
6828 Canonical_File_Name : File_Name_Type;
6829 Naming : Naming_Data;
6830 Exception_Id : out Ada_Naming_Exception_Id;
6831 Unit_Name : out Name_Id;
6832 Unit_Kind : out Spec_Or_Body;
6833 Needs_Pragma : out Boolean)
6835 Info_Id : Ada_Naming_Exception_Id :=
6836 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6837 VMS_Name : File_Name_Type;
6841 if Info_Id = No_Ada_Naming_Exception
6842 and then Hostparm.OpenVMS
6844 VMS_Name := Canonical_File_Name;
6845 Get_Name_String (VMS_Name);
6847 if Name_Buffer (Name_Len) = '.' then
6848 Name_Len := Name_Len - 1;
6849 VMS_Name := Name_Find;
6852 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6855 if Info_Id /= No_Ada_Naming_Exception then
6856 Exception_Id := Info_Id;
6857 Unit_Name := No_Name;
6858 Unit_Kind := Specification;
6859 Needs_Pragma := True;
6861 Needs_Pragma := False;
6862 Exception_Id := No_Ada_Naming_Exception;
6864 (File_Name => Canonical_File_Name,
6865 Dot_Replacement => Naming.Dot_Replacement,
6866 Separate_Suffix => Naming.Separate_Suffix,
6867 Body_Suffix => Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6868 Spec_Suffix => Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6869 Casing => Naming.Casing,
6874 when Spec => Unit_Kind := Specification;
6875 when Impl | Sep => Unit_Kind := Body_Part;
6884 function Hash (Unit : Unit_Info) return Header_Num is
6886 return Header_Num (Unit.Unit mod 2048);
6889 -----------------------
6890 -- Is_Illegal_Suffix --
6891 -----------------------
6893 function Is_Illegal_Suffix
6894 (Suffix : File_Name_Type;
6895 Dot_Replacement : File_Name_Type) return Boolean
6897 Suffix_Str : constant String := Get_Name_String (Suffix);
6900 if Suffix_Str'Length = 0 or else Index (Suffix_Str, ".") = 0 then
6904 -- If dot replacement is a single dot, and first character of suffix is
6907 if Get_Name_String (Dot_Replacement) = "."
6908 and then Suffix_Str (Suffix_Str'First) = '.'
6910 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6912 -- If there is another dot
6914 if Suffix_Str (Index) = '.' then
6916 -- It is illegal to have a letter following the initial dot
6918 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6924 end Is_Illegal_Suffix;
6926 ----------------------
6927 -- Locate_Directory --
6928 ----------------------
6930 procedure Locate_Directory
6931 (Project : Project_Id;
6932 In_Tree : Project_Tree_Ref;
6933 Name : File_Name_Type;
6934 Parent : Path_Name_Type;
6935 Dir : out Path_Name_Type;
6936 Display : out Path_Name_Type;
6937 Create : String := "";
6938 Current_Dir : String;
6939 Location : Source_Ptr := No_Location;
6940 Externally_Built : Boolean := False)
6942 The_Parent : constant String :=
6943 Get_Name_String (Parent) & Directory_Separator;
6945 The_Parent_Last : constant Natural :=
6946 Compute_Directory_Last (The_Parent);
6948 Full_Name : File_Name_Type;
6950 The_Name : File_Name_Type;
6953 Get_Name_String (Name);
6955 -- Add Subdirs.all if it is a directory that may be created and
6956 -- Subdirs is not null;
6958 if Create /= "" and then Subdirs /= null then
6959 if Name_Buffer (Name_Len) /= Directory_Separator then
6960 Add_Char_To_Name_Buffer (Directory_Separator);
6963 Add_Str_To_Name_Buffer (Subdirs.all);
6966 -- Convert '/' to directory separator (for Windows)
6968 for J in 1 .. Name_Len loop
6969 if Name_Buffer (J) = '/' then
6970 Name_Buffer (J) := Directory_Separator;
6974 The_Name := Name_Find;
6976 if Current_Verbosity = High then
6977 Write_Str ("Locate_Directory (""");
6978 Write_Str (Get_Name_String (The_Name));
6979 Write_Str (""", """);
6980 Write_Str (The_Parent);
6987 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6988 Full_Name := The_Name;
6992 Add_Str_To_Name_Buffer
6993 (The_Parent (The_Parent'First .. The_Parent_Last));
6994 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6995 Full_Name := Name_Find;
6999 Full_Path_Name : String_Access :=
7000 new String'(Get_Name_String (Full_Name));
7003 if (Setup_Projects or else Subdirs /= null)
7004 and then Create'Length > 0
7006 if not Is_Directory (Full_Path_Name.all) then
7007 -- If project is externally built, do not create a subdir,
7008 -- use the specified directory, without the subdir.
7010 if Externally_Built then
7011 if Is_Absolute_Path (Get_Name_String (Name)) then
7012 Get_Name_String (Name);
7016 Add_Str_To_Name_Buffer
7017 (The_Parent (The_Parent'First .. The_Parent_Last));
7018 Add_Str_To_Name_Buffer (Get_Name_String (Name));
7021 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
7025 Create_Path (Full_Path_Name.all);
7027 if not Quiet_Output then
7029 Write_Str (" directory """);
7030 Write_Str (Full_Path_Name.all);
7031 Write_Line (""" created");
7038 "could not create " & Create &
7039 " directory " & Full_Path_Name.all,
7046 if Is_Directory (Full_Path_Name.all) then
7048 Normed : constant String :=
7050 (Full_Path_Name.all,
7051 Directory => Current_Dir,
7052 Resolve_Links => False,
7053 Case_Sensitive => True);
7055 Canonical_Path : constant String :=
7058 Directory => Current_Dir,
7060 Opt.Follow_Links_For_Dirs,
7061 Case_Sensitive => False);
7064 Name_Len := Normed'Length;
7065 Name_Buffer (1 .. Name_Len) := Normed;
7066 Display := Name_Find;
7068 Name_Len := Canonical_Path'Length;
7069 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7074 Free (Full_Path_Name);
7076 end Locate_Directory;
7078 ---------------------------
7079 -- Find_Excluded_Sources --
7080 ---------------------------
7082 procedure Find_Excluded_Sources
7083 (Project : Project_Id;
7084 In_Tree : Project_Tree_Ref;
7085 Data : Project_Data)
7087 Excluded_Source_List_File : constant Variable_Value :=
7089 (Name_Excluded_Source_List_File,
7090 Data.Decl.Attributes,
7093 Excluded_Sources : Variable_Value := Util.Value_Of
7094 (Name_Excluded_Source_Files,
7095 Data.Decl.Attributes,
7098 Current : String_List_Id;
7099 Element : String_Element;
7100 Location : Source_Ptr;
7101 Name : File_Name_Type;
7102 File : Prj.Util.Text_File;
7103 Line : String (1 .. 300);
7105 Locally_Removed : Boolean := False;
7108 -- If Excluded_Source_Files is not declared, check
7109 -- Locally_Removed_Files.
7111 if Excluded_Sources.Default then
7112 Locally_Removed := True;
7115 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7118 Excluded_Sources_Htable.Reset;
7120 -- If there are excluded sources, put them in the table
7122 if not Excluded_Sources.Default then
7123 if not Excluded_Source_List_File.Default then
7124 if Locally_Removed then
7127 "?both attributes Locally_Removed_Files and " &
7128 "Excluded_Source_List_File are present",
7129 Excluded_Source_List_File.Location);
7133 "?both attributes Excluded_Source_Files and " &
7134 "Excluded_Source_List_File are present",
7135 Excluded_Source_List_File.Location);
7139 Current := Excluded_Sources.Values;
7140 while Current /= Nil_String loop
7141 Element := In_Tree.String_Elements.Table (Current);
7142 Name := Canonical_Case_File_Name (Element.Value);
7144 -- If the element has no location, then use the location
7145 -- of Excluded_Sources to report possible errors.
7147 if Element.Location = No_Location then
7148 Location := Excluded_Sources.Location;
7150 Location := Element.Location;
7153 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7154 Current := Element.Next;
7157 elsif not Excluded_Source_List_File.Default then
7158 Location := Excluded_Source_List_File.Location;
7161 Source_File_Path_Name : constant String :=
7164 (Excluded_Source_List_File.Value),
7165 Data.Directory.Name);
7168 if Source_File_Path_Name'Length = 0 then
7169 Err_Vars.Error_Msg_File_1 :=
7170 File_Name_Type (Excluded_Source_List_File.Value);
7173 "file with excluded sources { does not exist",
7174 Excluded_Source_List_File.Location);
7179 Prj.Util.Open (File, Source_File_Path_Name);
7181 if not Prj.Util.Is_Valid (File) then
7183 (Project, In_Tree, "file does not exist", Location);
7185 -- Read the lines one by one
7187 while not Prj.Util.End_Of_File (File) loop
7188 Prj.Util.Get_Line (File, Line, Last);
7190 -- A non empty, non comment line should contain a file
7194 and then (Last = 1 or else Line (1 .. 2) /= "--")
7197 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7198 Canonical_Case_File_Name
7199 (Name_Buffer (1 .. Name_Len));
7202 -- Check that there is no directory information
7204 for J in 1 .. Last loop
7206 or else Line (J) = Directory_Separator
7208 Error_Msg_File_1 := Name;
7212 "file name cannot include " &
7213 "directory information ({)",
7219 Excluded_Sources_Htable.Set
7220 (Name, (Name, False, Location));
7224 Prj.Util.Close (File);
7229 end Find_Excluded_Sources;
7231 ---------------------------
7232 -- Find_Explicit_Sources --
7233 ---------------------------
7235 procedure Find_Explicit_Sources
7236 (Current_Dir : String;
7237 Project : Project_Id;
7238 In_Tree : Project_Tree_Ref;
7239 Data : in out Project_Data)
7241 Sources : constant Variable_Value :=
7244 Data.Decl.Attributes,
7246 Source_List_File : constant Variable_Value :=
7248 (Name_Source_List_File,
7249 Data.Decl.Attributes,
7251 Name_Loc : Name_Location;
7254 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7256 (Source_List_File.Kind = Single,
7257 "Source_List_File is not a single string");
7259 -- If the user has specified a Sources attribute
7261 if not Sources.Default then
7262 if not Source_List_File.Default then
7265 "?both attributes source_files and " &
7266 "source_list_file are present",
7267 Source_List_File.Location);
7270 -- Sources is a list of file names
7273 Current : String_List_Id := Sources.Values;
7274 Element : String_Element;
7275 Location : Source_Ptr;
7276 Name : File_Name_Type;
7279 if Get_Mode = Ada_Only then
7280 Data.Ada_Sources_Present := Current /= Nil_String;
7283 if Get_Mode = Multi_Language then
7284 if Current = Nil_String then
7285 Data.First_Language_Processing := No_Language_Index;
7287 -- This project contains no source. For projects that
7288 -- don't extend other projects, this also means that
7289 -- there is no need for an object directory, if not
7292 if Data.Extends = No_Project
7293 and then Data.Object_Directory = Data.Directory
7295 Data.Object_Directory := No_Path_Information;
7300 while Current /= Nil_String loop
7301 Element := In_Tree.String_Elements.Table (Current);
7302 Name := Canonical_Case_File_Name (Element.Value);
7303 Get_Name_String (Element.Value);
7305 -- If the element has no location, then use the
7306 -- location of Sources to report possible errors.
7308 if Element.Location = No_Location then
7309 Location := Sources.Location;
7311 Location := Element.Location;
7314 -- Check that there is no directory information
7316 for J in 1 .. Name_Len loop
7317 if Name_Buffer (J) = '/'
7318 or else Name_Buffer (J) = Directory_Separator
7320 Error_Msg_File_1 := Name;
7324 "file name cannot include directory " &
7331 -- In Multi_Language mode, check whether the file is
7332 -- already there: the same file name may be in the list; if
7333 -- the source is missing, the error will be on the first
7334 -- mention of the source file name.
7338 Name_Loc := No_Name_Location;
7339 when Multi_Language =>
7340 Name_Loc := Source_Names.Get (Name);
7343 if Name_Loc = No_Name_Location then
7346 Location => Location,
7347 Source => No_Source,
7350 Source_Names.Set (Name, Name_Loc);
7353 Current := Element.Next;
7356 if Get_Mode = Ada_Only then
7357 Get_Path_Names_And_Record_Ada_Sources
7358 (Project, In_Tree, Data, Current_Dir);
7362 -- If we have no Source_Files attribute, check the Source_List_File
7365 elsif not Source_List_File.Default then
7367 -- Source_List_File is the name of the file
7368 -- that contains the source file names
7371 Source_File_Path_Name : constant String :=
7373 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7376 if Source_File_Path_Name'Length = 0 then
7377 Err_Vars.Error_Msg_File_1 :=
7378 File_Name_Type (Source_List_File.Value);
7381 "file with sources { does not exist",
7382 Source_List_File.Location);
7385 Get_Sources_From_File
7386 (Source_File_Path_Name, Source_List_File.Location,
7389 if Get_Mode = Ada_Only then
7390 -- Look in the source directories to find those sources
7392 Get_Path_Names_And_Record_Ada_Sources
7393 (Project, In_Tree, Data, Current_Dir);
7399 -- Neither Source_Files nor Source_List_File has been
7400 -- specified. Find all the files that satisfy the naming
7401 -- scheme in all the source directories.
7403 if Get_Mode = Ada_Only then
7404 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7408 if Get_Mode = Multi_Language then
7410 (Project, In_Tree, Data,
7412 Sources.Default and then Source_List_File.Default);
7414 -- Check if all exceptions have been found.
7415 -- For Ada, it is an error if an exception is not found.
7416 -- For other language, the source is simply removed.
7422 Source := Data.First_Source;
7423 while Source /= No_Source loop
7425 Src_Data : Source_Data renames
7426 In_Tree.Sources.Table (Source);
7429 if Src_Data.Naming_Exception
7430 and then Src_Data.Path = No_Path_Information
7432 if Src_Data.Unit /= No_Name then
7433 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7434 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7437 "source file %% for unit %% not found",
7441 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7444 Source := Src_Data.Next_In_Project;
7449 -- Check that all sources in Source_Files or the file
7450 -- Source_List_File has been found.
7453 Name_Loc : Name_Location;
7456 Name_Loc := Source_Names.Get_First;
7457 while Name_Loc /= No_Name_Location loop
7458 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7459 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7463 "file %% not found",
7467 Name_Loc := Source_Names.Get_Next;
7472 if Get_Mode = Ada_Only
7473 and then Data.Extends = No_Project
7475 -- We should have found at least one source, if not report an error
7477 if Data.Ada_Sources = Nil_String then
7479 (Project, "Ada", In_Tree, Source_List_File.Location);
7483 end Find_Explicit_Sources;
7485 -------------------------------------------
7486 -- Get_Path_Names_And_Record_Ada_Sources --
7487 -------------------------------------------
7489 procedure Get_Path_Names_And_Record_Ada_Sources
7490 (Project : Project_Id;
7491 In_Tree : Project_Tree_Ref;
7492 Data : in out Project_Data;
7493 Current_Dir : String)
7495 Source_Dir : String_List_Id;
7496 Element : String_Element;
7497 Path : Path_Name_Type;
7499 Name : File_Name_Type;
7500 Canonical_Name : File_Name_Type;
7501 Name_Str : String (1 .. 1_024);
7502 Last : Natural := 0;
7504 Current_Source : String_List_Id := Nil_String;
7505 First_Error : Boolean := True;
7506 Source_Recorded : Boolean := False;
7509 -- We look in all source directories for the file names in the hash
7510 -- table Source_Names.
7512 Source_Dir := Data.Source_Dirs;
7513 while Source_Dir /= Nil_String loop
7514 Source_Recorded := False;
7515 Element := In_Tree.String_Elements.Table (Source_Dir);
7518 Dir_Path : constant String :=
7519 Get_Name_String (Element.Display_Value);
7521 if Current_Verbosity = High then
7522 Write_Str ("checking directory """);
7523 Write_Str (Dir_Path);
7527 Open (Dir, Dir_Path);
7530 Read (Dir, Name_Str, Last);
7534 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7537 if Osint.File_Names_Case_Sensitive then
7538 Canonical_Name := Name;
7540 Canonical_Case_File_Name (Name_Str (1 .. Last));
7541 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7542 Canonical_Name := Name_Find;
7545 NL := Source_Names.Get (Canonical_Name);
7547 if NL /= No_Name_Location and then not NL.Found then
7549 Source_Names.Set (Canonical_Name, NL);
7550 Name_Len := Dir_Path'Length;
7551 Name_Buffer (1 .. Name_Len) := Dir_Path;
7553 if Name_Buffer (Name_Len) /= Directory_Separator then
7554 Add_Char_To_Name_Buffer (Directory_Separator);
7557 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7560 if Current_Verbosity = High then
7561 Write_Str (" found ");
7562 Write_Line (Get_Name_String (Name));
7565 -- Register the source if it is an Ada compilation unit
7573 Location => NL.Location,
7574 Current_Source => Current_Source,
7575 Source_Recorded => Source_Recorded,
7576 Current_Dir => Current_Dir);
7583 if Source_Recorded then
7584 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7588 Source_Dir := Element.Next;
7591 -- It is an error if a source file name in a source list or
7592 -- in a source list file is not found.
7594 NL := Source_Names.Get_First;
7595 while NL /= No_Name_Location loop
7596 if not NL.Found then
7597 Err_Vars.Error_Msg_File_1 := NL.Name;
7602 "source file { cannot be found",
7604 First_Error := False;
7609 "\source file { cannot be found",
7614 NL := Source_Names.Get_Next;
7616 end Get_Path_Names_And_Record_Ada_Sources;
7618 ---------------------------------------
7619 -- Get_Language_Processing_From_Lang --
7620 ---------------------------------------
7622 function Get_Language_Processing_From_Lang
7623 (In_Tree : Project_Tree_Ref;
7624 Data : Project_Data;
7625 Lang : Name_List_Index) return Language_Index
7627 Name : constant Name_Id := In_Tree.Name_Lists.Table (Lang).Name;
7628 Language : Language_Index;
7631 Language := Data.First_Language_Processing;
7632 while Language /= No_Language_Index loop
7633 if In_Tree.Languages_Data.Table (Language).Name = Name then
7637 Language := In_Tree.Languages_Data.Table (Language).Next;
7640 return No_Language_Index;
7641 end Get_Language_Processing_From_Lang;
7643 -------------------------------
7644 -- Check_File_Naming_Schemes --
7645 -------------------------------
7647 procedure Check_File_Naming_Schemes
7648 (In_Tree : Project_Tree_Ref;
7649 Data : in out Project_Data;
7650 File_Name : File_Name_Type;
7651 Alternate_Languages : out Alternate_Language_Id;
7652 Language : out Language_Index;
7653 Language_Name : out Name_Id;
7654 Display_Language_Name : out Name_Id;
7656 Lang_Kind : out Language_Kind;
7657 Kind : out Source_Kind)
7659 Filename : constant String := Get_Name_String (File_Name);
7660 Config : Language_Config;
7661 Lang : Name_List_Index;
7662 Tmp_Lang : Language_Index;
7664 Header_File : Boolean := False;
7665 -- True if we found at least one language for which the file is a header
7666 -- In such a case, we search for all possible languages where this is
7667 -- also a header (C and C++ for instance), since the file might be used
7668 -- for several such languages.
7670 procedure Check_File_Based_Lang;
7671 -- Does the naming scheme test for file-based languages. For those,
7672 -- there is no Unit. Just check if the file name has the implementation
7673 -- or, if it is specified, the template suffix of the language.
7675 -- Returns True if the file belongs to the current language and we
7676 -- should stop searching for matching languages. Not that a given header
7677 -- file could belong to several languages (C and C++ for instance). Thus
7678 -- if we found a header we'll check whether it matches other languages
7680 ---------------------------
7681 -- Check_File_Based_Lang --
7682 ---------------------------
7684 procedure Check_File_Based_Lang is
7687 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7691 Language := Tmp_Lang;
7693 if Current_Verbosity = High then
7694 Write_Str (" implementation of language ");
7695 Write_Line (Get_Name_String (Display_Language_Name));
7698 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7699 if Current_Verbosity = High then
7700 Write_Str (" header of language ");
7701 Write_Line (Get_Name_String (Display_Language_Name));
7705 Alternate_Language_Table.Increment_Last (In_Tree.Alt_Langs);
7706 In_Tree.Alt_Langs.Table
7707 (Alternate_Language_Table.Last (In_Tree.Alt_Langs)) :=
7708 (Language => Language,
7709 Next => Alternate_Languages);
7710 Alternate_Languages :=
7711 Alternate_Language_Table.Last (In_Tree.Alt_Langs);
7714 Header_File := True;
7717 Language := Tmp_Lang;
7720 end Check_File_Based_Lang;
7722 -- Start of processing for Check_File_Naming_Schemes
7725 Language := No_Language_Index;
7726 Alternate_Languages := No_Alternate_Language;
7727 Display_Language_Name := No_Name;
7729 Lang_Kind := File_Based;
7732 Lang := Data.Languages;
7733 while Lang /= No_Name_List loop
7734 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7735 Tmp_Lang := Get_Language_Processing_From_Lang (In_Tree, Data, Lang);
7737 if Current_Verbosity = High then
7739 (" Testing language "
7740 & Get_Name_String (Language_Name)
7741 & " Header_File=" & Header_File'Img);
7744 if Tmp_Lang /= No_Language_Index then
7745 Display_Language_Name :=
7746 In_Tree.Languages_Data.Table (Tmp_Lang).Display_Name;
7747 Config := In_Tree.Languages_Data.Table (Tmp_Lang).Config;
7748 Lang_Kind := Config.Kind;
7752 Check_File_Based_Lang;
7753 exit when Kind = Impl;
7757 -- We know it belongs to a least a file_based language, no
7758 -- need to check unit-based ones.
7760 if not Header_File then
7762 (File_Name => File_Name,
7763 Dot_Replacement => Config.Naming_Data.Dot_Replacement,
7764 Separate_Suffix => Config.Naming_Data.Separate_Suffix,
7765 Body_Suffix => Config.Naming_Data.Body_Suffix,
7766 Spec_Suffix => Config.Naming_Data.Spec_Suffix,
7767 Casing => Config.Naming_Data.Casing,
7771 if Unit /= No_Name then
7772 Language := Tmp_Lang;
7779 Lang := In_Tree.Name_Lists.Table (Lang).Next;
7782 if Language = No_Language_Index
7783 and then Current_Verbosity = High
7785 Write_Line (" not a source of any language");
7787 end Check_File_Naming_Schemes;
7793 procedure Check_File
7794 (Project : Project_Id;
7795 In_Tree : Project_Tree_Ref;
7796 Data : in out Project_Data;
7798 File_Name : File_Name_Type;
7799 Display_File_Name : File_Name_Type;
7800 Source_Directory : String;
7801 For_All_Sources : Boolean)
7803 Display_Path : constant String :=
7806 Directory => Source_Directory,
7807 Resolve_Links => Opt.Follow_Links_For_Files,
7808 Case_Sensitive => True);
7810 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7811 Path_Id : Path_Name_Type;
7812 Display_Path_Id : Path_Name_Type;
7813 Check_Name : Boolean := False;
7814 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
7815 Language : Language_Index;
7817 Other_Part : Source_Id;
7819 Src_Ind : Source_File_Index;
7821 Source_To_Replace : Source_Id := No_Source;
7823 Language_Name : Name_Id;
7824 Display_Language_Name : Name_Id;
7825 Lang_Kind : Language_Kind;
7826 Kind : Source_Kind := Spec;
7829 Name_Len := Display_Path'Length;
7830 Name_Buffer (1 .. Name_Len) := Display_Path;
7831 Display_Path_Id := Name_Find;
7833 if Osint.File_Names_Case_Sensitive then
7834 Path_Id := Display_Path_Id;
7836 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7837 Path_Id := Name_Find;
7840 if Name_Loc = No_Name_Location then
7841 Check_Name := For_All_Sources;
7844 if Name_Loc.Found then
7846 -- Check if it is OK to have the same file name in several
7847 -- source directories.
7849 if not Data.Known_Order_Of_Source_Dirs then
7850 Error_Msg_File_1 := File_Name;
7853 "{ is found in several source directories",
7858 Name_Loc.Found := True;
7860 Source_Names.Set (File_Name, Name_Loc);
7862 if Name_Loc.Source = No_Source then
7866 In_Tree.Sources.Table (Name_Loc.Source).Path :=
7867 (Path_Id, Display_Path_Id);
7869 Source_Paths_Htable.Set
7870 (In_Tree.Source_Paths_HT,
7874 -- Check if this is a subunit
7876 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
7878 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
7880 Src_Ind := Sinput.P.Load_Project_File
7881 (Get_Name_String (Path_Id));
7883 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7884 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
7892 Other_Part := No_Source;
7894 Check_File_Naming_Schemes
7895 (In_Tree => In_Tree,
7897 File_Name => File_Name,
7898 Alternate_Languages => Alternate_Languages,
7899 Language => Language,
7900 Language_Name => Language_Name,
7901 Display_Language_Name => Display_Language_Name,
7903 Lang_Kind => Lang_Kind,
7906 if Language = No_Language_Index then
7908 -- A file name in a list must be a source of a language
7910 if Name_Loc.Found then
7911 Error_Msg_File_1 := File_Name;
7915 "language unknown for {",
7920 -- Check if the same file name or unit is used in the prj tree
7922 Source := In_Tree.First_Source;
7924 while Source /= No_Source loop
7926 Src_Data : Source_Data renames
7927 In_Tree.Sources.Table (Source);
7931 and then Src_Data.Unit = Unit
7933 ((Src_Data.Kind = Spec and then Kind = Impl)
7935 (Src_Data.Kind = Impl and then Kind = Spec))
7937 Other_Part := Source;
7939 elsif (Unit /= No_Name
7940 and then Src_Data.Unit = Unit
7942 (Src_Data.Kind = Kind
7944 (Src_Data.Kind = Sep and then Kind = Impl)
7946 (Src_Data.Kind = Impl and then Kind = Sep)))
7948 (Unit = No_Name and then Src_Data.File = File_Name)
7950 -- Duplication of file/unit in same project is only
7951 -- allowed if order of source directories is known.
7953 if Project = Src_Data.Project then
7954 if Data.Known_Order_Of_Source_Dirs then
7957 elsif Unit /= No_Name then
7958 Error_Msg_Name_1 := Unit;
7960 (Project, In_Tree, "duplicate unit %%",
7965 Error_Msg_File_1 := File_Name;
7967 (Project, In_Tree, "duplicate source file name {",
7972 -- Do not allow the same unit name in different
7973 -- projects, except if one is extending the other.
7975 -- For a file based language, the same file name
7976 -- replaces a file in a project being extended, but
7977 -- it is allowed to have the same file name in
7978 -- unrelated projects.
7981 (Project, Src_Data.Project, In_Tree)
7983 Source_To_Replace := Source;
7985 elsif Unit /= No_Name
7986 and then not Src_Data.Locally_Removed
7988 Error_Msg_Name_1 := Unit;
7991 "unit %% cannot belong to several projects",
7995 In_Tree.Projects.Table (Project).Name;
7996 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
7998 (Project, In_Tree, "\ project %%, %%", No_Location);
8001 In_Tree.Projects.Table (Src_Data.Project).Name;
8003 Name_Id (Src_Data.Path.Display_Name);
8005 (Project, In_Tree, "\ project %%, %%", No_Location);
8011 Source := Src_Data.Next_In_Sources;
8021 Lang => Language_Name,
8022 Lang_Id => Language,
8023 Lang_Kind => Lang_Kind,
8025 Alternate_Languages => Alternate_Languages,
8026 File_Name => File_Name,
8027 Display_File => Display_File_Name,
8028 Other_Part => Other_Part,
8031 Display_Path => Display_Path_Id,
8032 Source_To_Replace => Source_To_Replace);
8038 ------------------------
8039 -- Search_Directories --
8040 ------------------------
8042 procedure Search_Directories
8043 (Project : Project_Id;
8044 In_Tree : Project_Tree_Ref;
8045 Data : in out Project_Data;
8046 For_All_Sources : Boolean)
8048 Source_Dir : String_List_Id;
8049 Element : String_Element;
8051 Name : String (1 .. 1_000);
8053 File_Name : File_Name_Type;
8054 Display_File_Name : File_Name_Type;
8057 if Current_Verbosity = High then
8058 Write_Line ("Looking for sources:");
8061 -- Loop through subdirectories
8063 Source_Dir := Data.Source_Dirs;
8064 while Source_Dir /= Nil_String loop
8066 Element := In_Tree.String_Elements.Table (Source_Dir);
8067 if Element.Value /= No_Name then
8068 Get_Name_String (Element.Display_Value);
8071 Source_Directory : constant String :=
8072 Name_Buffer (1 .. Name_Len) &
8073 Directory_Separator;
8075 Dir_Last : constant Natural :=
8076 Compute_Directory_Last
8080 if Current_Verbosity = High then
8081 Write_Attr ("Source_Dir", Source_Directory);
8084 -- We look to every entry in the source directory
8086 Open (Dir, Source_Directory);
8089 Read (Dir, Name, Last);
8093 -- ??? Duplicate system call here, we just did a
8094 -- a similar one. Maybe Ada.Directories would be more
8098 (Source_Directory & Name (1 .. Last))
8100 if Current_Verbosity = High then
8101 Write_Str (" Checking ");
8102 Write_Line (Name (1 .. Last));
8106 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8107 Display_File_Name := Name_Find;
8109 if Osint.File_Names_Case_Sensitive then
8110 File_Name := Display_File_Name;
8112 Canonical_Case_File_Name
8113 (Name_Buffer (1 .. Name_Len));
8114 File_Name := Name_Find;
8119 Excluded_Sources_Htable.Get (File_Name);
8122 if FF /= No_File_Found then
8123 if not FF.Found then
8125 Excluded_Sources_Htable.Set
8128 if Current_Verbosity = High then
8129 Write_Str (" excluded source """);
8130 Write_Str (Get_Name_String (File_Name));
8137 (Project => Project,
8140 Name => Name (1 .. Last),
8141 File_Name => File_Name,
8142 Display_File_Name => Display_File_Name,
8143 Source_Directory => Source_Directory
8144 (Source_Directory'First .. Dir_Last),
8145 For_All_Sources => For_All_Sources);
8156 when Directory_Error =>
8160 Source_Dir := Element.Next;
8163 if Current_Verbosity = High then
8164 Write_Line ("end Looking for sources.");
8166 end Search_Directories;
8168 ----------------------------
8169 -- Load_Naming_Exceptions --
8170 ----------------------------
8172 procedure Load_Naming_Exceptions
8173 (Project : Project_Id;
8174 In_Tree : Project_Tree_Ref;
8175 Data : in out Project_Data)
8178 File : File_Name_Type;
8182 Unit_Exceptions.Reset;
8184 Source := Data.First_Source;
8185 while Source /= No_Source loop
8186 File := In_Tree.Sources.Table (Source).File;
8187 Unit := In_Tree.Sources.Table (Source).Unit;
8189 -- An excluded file cannot also be an exception file name
8191 if Excluded_Sources_Htable.Get (File) /= No_File_Found then
8192 Error_Msg_File_1 := File;
8195 "{ cannot be both excluded and an exception file name",
8199 if Current_Verbosity = High then
8200 Write_Str ("Naming exception: Putting source #");
8201 Write_Str (Source'Img);
8202 Write_Str (", file ");
8203 Write_Str (Get_Name_String (File));
8204 Write_Line (" in Source_Names");
8211 Location => No_Location,
8213 Except => Unit /= No_Name,
8216 -- If this is an Ada exception, record in table Unit_Exceptions
8218 if Unit /= No_Name then
8220 Unit_Except : Unit_Exception := Unit_Exceptions.Get (Unit);
8223 Unit_Except.Name := Unit;
8225 if In_Tree.Sources.Table (Source).Kind = Spec then
8226 Unit_Except.Spec := File;
8228 Unit_Except.Impl := File;
8231 Unit_Exceptions.Set (Unit, Unit_Except);
8235 Source := In_Tree.Sources.Table (Source).Next_In_Project;
8237 end Load_Naming_Exceptions;
8239 ----------------------
8240 -- Look_For_Sources --
8241 ----------------------
8243 procedure Look_For_Sources
8244 (Project : Project_Id;
8245 In_Tree : Project_Tree_Ref;
8246 Data : in out Project_Data;
8247 Current_Dir : String)
8249 procedure Process_Sources_In_Multi_Language_Mode;
8250 -- Find all source files when in multi language mode
8252 procedure Mark_Excluded_Sources;
8253 -- Mark as such the sources that are declared as excluded
8255 ---------------------------
8256 -- Mark_Excluded_Sources --
8257 ---------------------------
8259 procedure Mark_Excluded_Sources is
8260 Source : Source_Id := No_Source;
8263 Excluded : File_Found := Excluded_Sources_Htable.Get_First;
8266 (Extended : Project_Id;
8268 Kind : Spec_Or_Body);
8269 -- If the current file (Excluded) belongs to the current project or
8270 -- one that the current project extends, then mark this file/unit as
8271 -- excluded. It is an error to locally remove a file from another
8279 (Extended : Project_Id;
8281 Kind : Spec_Or_Body)
8284 if Extended = Project
8285 or else Is_Extending (Project, Extended, In_Tree)
8289 if Index /= No_Unit_Index then
8290 Unit.File_Names (Kind).Path.Name := Slash;
8291 Unit.File_Names (Kind).Needs_Pragma := False;
8292 In_Tree.Units.Table (Index) := Unit;
8295 if Source /= No_Source then
8296 In_Tree.Sources.Table (Source).Locally_Removed := True;
8297 In_Tree.Sources.Table (Source).In_Interfaces := False;
8300 if Current_Verbosity = High then
8301 Write_Str ("Removing file ");
8302 Write_Line (Get_Name_String (Excluded.File));
8305 Add_Forbidden_File_Name (Excluded.File);
8310 "cannot remove a source from another project",
8315 -- Start of processing for Mark_Excluded_Sources
8318 while Excluded /= No_File_Found loop
8324 -- ??? This loop could be the same as for Multi_Language if
8325 -- we were setting In_Tree.First_Source when we search for
8326 -- Ada sources (basically once we have removed the use of
8327 -- Data.Ada_Sources).
8330 for Index in Unit_Table.First ..
8331 Unit_Table.Last (In_Tree.Units)
8333 Unit := In_Tree.Units.Table (Index);
8335 for Kind in Spec_Or_Body'Range loop
8336 if Unit.File_Names (Kind).Name = Excluded.File then
8337 Exclude (Unit.File_Names (Kind).Project, Index, Kind);
8341 end loop For_Each_Unit;
8343 when Multi_Language =>
8344 Source := In_Tree.First_Source;
8345 while Source /= No_Source loop
8346 if In_Tree.Sources.Table (Source).File = Excluded.File then
8348 (In_Tree.Sources.Table (Source).Project,
8349 No_Unit_Index, Specification);
8353 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
8356 OK := OK or Excluded.Found;
8360 Err_Vars.Error_Msg_File_1 := Excluded.File;
8362 (Project, In_Tree, "unknown file {", Excluded.Location);
8365 Excluded := Excluded_Sources_Htable.Get_Next;
8367 end Mark_Excluded_Sources;
8369 --------------------------------------------
8370 -- Process_Sources_In_Multi_Language_Mode --
8371 --------------------------------------------
8373 procedure Process_Sources_In_Multi_Language_Mode is
8375 -- Check that two sources of this project do not have the same object
8378 Check_Object_File_Names : declare
8380 Source_Name : File_Name_Type;
8382 procedure Check_Object (Src_Data : Source_Data);
8383 -- Check if object file name of the current source is already in
8384 -- hash table Object_File_Names. If it is, report an error. If it
8385 -- is not, put it there with the file name of the current source.
8391 procedure Check_Object (Src_Data : Source_Data) is
8393 Source_Name := Object_File_Names.Get (Src_Data.Object);
8395 if Source_Name /= No_File then
8396 Error_Msg_File_1 := Src_Data.File;
8397 Error_Msg_File_2 := Source_Name;
8401 "{ and { have the same object file name",
8405 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8409 -- Start of processing for Check_Object_File_Names
8412 Object_File_Names.Reset;
8413 Src_Id := In_Tree.First_Source;
8414 while Src_Id /= No_Source loop
8416 Src_Data : Source_Data renames
8417 In_Tree.Sources.Table (Src_Id);
8420 if Src_Data.Compiled and then Src_Data.Object_Exists
8421 and then Is_Extending (Project, Src_Data.Project, In_Tree)
8423 if Src_Data.Unit = No_Name then
8424 if Src_Data.Kind = Impl then
8425 Check_Object (Src_Data);
8429 case Src_Data.Kind is
8431 if Src_Data.Other_Part = No_Source then
8432 Check_Object (Src_Data);
8439 if Src_Data.Other_Part /= No_Source then
8440 Check_Object (Src_Data);
8443 -- Check if it is a subunit
8446 Src_Ind : constant Source_File_Index :=
8447 Sinput.P.Load_Project_File
8449 (Src_Data.Path.Name));
8451 if Sinput.P.Source_File_Is_Subunit
8454 In_Tree.Sources.Table (Src_Id).Kind :=
8457 Check_Object (Src_Data);
8465 Src_Id := Src_Data.Next_In_Sources;
8468 end Check_Object_File_Names;
8469 end Process_Sources_In_Multi_Language_Mode;
8471 -- Start of processing for Look_For_Sources
8475 Find_Excluded_Sources (Project, In_Tree, Data);
8477 if (Get_Mode = Ada_Only and then Is_A_Language (In_Tree, Data, Name_Ada))
8478 or else (Get_Mode = Multi_Language
8479 and then Data.First_Language_Processing /= No_Language_Index)
8481 if Get_Mode = Multi_Language then
8482 Load_Naming_Exceptions (Project, In_Tree, Data);
8485 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8486 Mark_Excluded_Sources;
8488 if Get_Mode = Multi_Language then
8489 Process_Sources_In_Multi_Language_Mode;
8492 end Look_For_Sources;
8498 function Path_Name_Of
8499 (File_Name : File_Name_Type;
8500 Directory : Path_Name_Type) return String
8502 Result : String_Access;
8503 The_Directory : constant String := Get_Name_String (Directory);
8506 Get_Name_String (File_Name);
8509 (File_Name => Name_Buffer (1 .. Name_Len),
8510 Path => The_Directory);
8512 if Result = null then
8516 R : String := Result.all;
8519 Canonical_Case_File_Name (R);
8525 -----------------------------------
8526 -- Prepare_Ada_Naming_Exceptions --
8527 -----------------------------------
8529 procedure Prepare_Ada_Naming_Exceptions
8530 (List : Array_Element_Id;
8531 In_Tree : Project_Tree_Ref;
8532 Kind : Spec_Or_Body)
8534 Current : Array_Element_Id;
8535 Element : Array_Element;
8539 -- Traverse the list
8542 while Current /= No_Array_Element loop
8543 Element := In_Tree.Array_Elements.Table (Current);
8545 if Element.Index /= No_Name then
8548 Unit => Element.Index,
8549 Next => No_Ada_Naming_Exception);
8550 Reverse_Ada_Naming_Exceptions.Set
8551 (Unit, (Element.Value.Value, Element.Value.Index));
8553 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8554 Ada_Naming_Exception_Table.Increment_Last;
8555 Ada_Naming_Exception_Table.Table
8556 (Ada_Naming_Exception_Table.Last) := Unit;
8557 Ada_Naming_Exceptions.Set
8558 (File_Name_Type (Element.Value.Value),
8559 Ada_Naming_Exception_Table.Last);
8562 Current := Element.Next;
8564 end Prepare_Ada_Naming_Exceptions;
8566 -----------------------
8567 -- Record_Ada_Source --
8568 -----------------------
8570 procedure Record_Ada_Source
8571 (File_Name : File_Name_Type;
8572 Path_Name : Path_Name_Type;
8573 Project : Project_Id;
8574 In_Tree : Project_Tree_Ref;
8575 Data : in out Project_Data;
8576 Location : Source_Ptr;
8577 Current_Source : in out String_List_Id;
8578 Source_Recorded : in out Boolean;
8579 Current_Dir : String)
8581 Canonical_File_Name : File_Name_Type;
8582 Canonical_Path_Name : Path_Name_Type;
8584 Exception_Id : Ada_Naming_Exception_Id;
8585 Unit_Name : Name_Id;
8586 Unit_Kind : Spec_Or_Body;
8587 Unit_Ind : Int := 0;
8589 Name_Index : Name_And_Index;
8590 Needs_Pragma : Boolean;
8592 The_Location : Source_Ptr := Location;
8593 Previous_Source : constant String_List_Id := Current_Source;
8594 Except_Name : Name_And_Index := No_Name_And_Index;
8596 Unit_Prj : Unit_Project;
8598 File_Name_Recorded : Boolean := False;
8601 Canonical_File_Name := Canonical_Case_File_Name (Name_Id (File_Name));
8603 if Osint.File_Names_Case_Sensitive then
8604 Canonical_Path_Name := Path_Name;
8607 Canonical_Path : constant String :=
8609 (Get_Name_String (Path_Name),
8610 Directory => Current_Dir,
8611 Resolve_Links => Opt.Follow_Links_For_Files,
8612 Case_Sensitive => False);
8615 Add_Str_To_Name_Buffer (Canonical_Path);
8616 Canonical_Path_Name := Name_Find;
8620 -- Find out the unit name, the unit kind and if it needs
8621 -- a specific SFN pragma.
8624 (In_Tree => In_Tree,
8625 Canonical_File_Name => Canonical_File_Name,
8626 Naming => Data.Naming,
8627 Exception_Id => Exception_Id,
8628 Unit_Name => Unit_Name,
8629 Unit_Kind => Unit_Kind,
8630 Needs_Pragma => Needs_Pragma);
8632 if Exception_Id = No_Ada_Naming_Exception
8633 and then Unit_Name = No_Name
8635 if Current_Verbosity = High then
8637 Write_Str (Get_Name_String (Canonical_File_Name));
8638 Write_Line (""" is not a valid source file name (ignored).");
8642 -- Check to see if the source has been hidden by an exception,
8643 -- but only if it is not an exception.
8645 if not Needs_Pragma then
8647 Reverse_Ada_Naming_Exceptions.Get
8648 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8650 if Except_Name /= No_Name_And_Index then
8651 if Current_Verbosity = High then
8653 Write_Str (Get_Name_String (Canonical_File_Name));
8654 Write_Str (""" contains a unit that is found in """);
8655 Write_Str (Get_Name_String (Except_Name.Name));
8656 Write_Line (""" (ignored).");
8659 -- The file is not included in the source of the project since
8660 -- it is hidden by the exception. So, nothing else to do.
8667 if Exception_Id /= No_Ada_Naming_Exception then
8668 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8669 Exception_Id := Info.Next;
8670 Info.Next := No_Ada_Naming_Exception;
8671 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8673 Unit_Name := Info.Unit;
8674 Unit_Ind := Name_Index.Index;
8675 Unit_Kind := Info.Kind;
8678 -- Put the file name in the list of sources of the project
8680 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8681 In_Tree.String_Elements.Table
8682 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8683 (Value => Name_Id (Canonical_File_Name),
8684 Display_Value => Name_Id (File_Name),
8685 Location => No_Location,
8690 if Current_Source = Nil_String then
8692 String_Element_Table.Last (In_Tree.String_Elements);
8694 In_Tree.String_Elements.Table (Current_Source).Next :=
8695 String_Element_Table.Last (In_Tree.String_Elements);
8699 String_Element_Table.Last (In_Tree.String_Elements);
8701 -- Put the unit in unit list
8704 The_Unit : Unit_Index :=
8705 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8707 The_Unit_Data : Unit_Data;
8710 if Current_Verbosity = High then
8711 Write_Str ("Putting ");
8712 Write_Str (Get_Name_String (Unit_Name));
8713 Write_Line (" in the unit list.");
8716 -- The unit is already in the list, but may be it is
8717 -- only the other unit kind (spec or body), or what is
8718 -- in the unit list is a unit of a project we are extending.
8720 if The_Unit /= No_Unit_Index then
8721 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8723 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8726 The_Unit_Data.File_Names
8727 (Unit_Kind).Path.Name = Slash)
8728 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8729 or else Is_Extending
8731 The_Unit_Data.File_Names (Unit_Kind).Project,
8735 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
8737 Remove_Forbidden_File_Name
8738 (The_Unit_Data.File_Names (Unit_Kind).Name);
8741 -- Record the file name in the hash table Files_Htable
8743 Unit_Prj := (Unit => The_Unit, Project => Project);
8746 Canonical_File_Name,
8749 The_Unit_Data.File_Names (Unit_Kind) :=
8750 (Name => Canonical_File_Name,
8752 Display_Name => File_Name,
8753 Path => (Canonical_Path_Name, Path_Name),
8755 Needs_Pragma => Needs_Pragma);
8756 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8757 Source_Recorded := True;
8759 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8760 and then (Data.Known_Order_Of_Source_Dirs
8762 The_Unit_Data.File_Names
8763 (Unit_Kind).Path.Name = Canonical_Path_Name)
8765 if Previous_Source = Nil_String then
8766 Data.Ada_Sources := Nil_String;
8768 In_Tree.String_Elements.Table (Previous_Source).Next :=
8770 String_Element_Table.Decrement_Last
8771 (In_Tree.String_Elements);
8774 Current_Source := Previous_Source;
8777 -- It is an error to have two units with the same name
8778 -- and the same kind (spec or body).
8780 if The_Location = No_Location then
8782 In_Tree.Projects.Table (Project).Location;
8785 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8787 (Project, In_Tree, "duplicate unit %%", The_Location);
8789 Err_Vars.Error_Msg_Name_1 :=
8790 In_Tree.Projects.Table
8791 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
8792 Err_Vars.Error_Msg_File_1 :=
8794 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
8797 "\ project file %%, {", The_Location);
8799 Err_Vars.Error_Msg_Name_1 :=
8800 In_Tree.Projects.Table (Project).Name;
8801 Err_Vars.Error_Msg_File_1 :=
8802 File_Name_Type (Canonical_Path_Name);
8805 "\ project file %%, {", The_Location);
8808 -- It is a new unit, create a new record
8811 -- First, check if there is no other unit with this file
8812 -- name in another project. If it is, report error but note
8813 -- we do that only for the first unit in the source file.
8816 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
8818 if not File_Name_Recorded and then
8819 Unit_Prj /= No_Unit_Project
8821 Error_Msg_File_1 := File_Name;
8823 In_Tree.Projects.Table (Unit_Prj.Project).Name;
8826 "{ is already a source of project %%",
8830 Unit_Table.Increment_Last (In_Tree.Units);
8831 The_Unit := Unit_Table.Last (In_Tree.Units);
8833 (In_Tree.Units_HT, Unit_Name, The_Unit);
8834 Unit_Prj := (Unit => The_Unit, Project => Project);
8837 Canonical_File_Name,
8839 The_Unit_Data.Name := Unit_Name;
8840 The_Unit_Data.File_Names (Unit_Kind) :=
8841 (Name => Canonical_File_Name,
8843 Display_Name => File_Name,
8844 Path => (Canonical_Path_Name, Path_Name),
8846 Needs_Pragma => Needs_Pragma);
8847 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8848 Source_Recorded := True;
8853 exit when Exception_Id = No_Ada_Naming_Exception;
8854 File_Name_Recorded := True;
8857 end Record_Ada_Source;
8863 procedure Remove_Source
8865 Replaced_By : Source_Id;
8866 Project : Project_Id;
8867 Data : in out Project_Data;
8868 In_Tree : Project_Tree_Ref)
8870 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
8874 if Current_Verbosity = High then
8875 Write_Str ("Removing source #");
8876 Write_Line (Id'Img);
8879 if Replaced_By /= No_Source then
8880 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
8881 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
8882 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
8885 -- Remove the source from the global source list
8887 Source := In_Tree.First_Source;
8890 In_Tree.First_Source := Src_Data.Next_In_Sources;
8893 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
8894 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
8897 In_Tree.Sources.Table (Source).Next_In_Sources :=
8898 Src_Data.Next_In_Sources;
8901 -- Remove the source from the project list
8903 if Src_Data.Project = Project then
8904 Source := Data.First_Source;
8907 Data.First_Source := Src_Data.Next_In_Project;
8909 if Src_Data.Next_In_Project = No_Source then
8910 Data.Last_Source := No_Source;
8914 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
8915 Source := In_Tree.Sources.Table (Source).Next_In_Project;
8918 In_Tree.Sources.Table (Source).Next_In_Project :=
8919 Src_Data.Next_In_Project;
8921 if Src_Data.Next_In_Project = No_Source then
8922 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
8927 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
8930 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
8931 Src_Data.Next_In_Project;
8933 if Src_Data.Next_In_Project = No_Source then
8934 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
8939 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
8940 Source := In_Tree.Sources.Table (Source).Next_In_Project;
8943 In_Tree.Sources.Table (Source).Next_In_Project :=
8944 Src_Data.Next_In_Project;
8946 if Src_Data.Next_In_Project = No_Source then
8947 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
8952 -- Remove source from the language list
8954 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
8957 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
8958 Src_Data.Next_In_Lang;
8961 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
8962 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
8965 In_Tree.Sources.Table (Source).Next_In_Lang :=
8966 Src_Data.Next_In_Lang;
8970 -----------------------
8971 -- Report_No_Sources --
8972 -----------------------
8974 procedure Report_No_Sources
8975 (Project : Project_Id;
8977 In_Tree : Project_Tree_Ref;
8978 Location : Source_Ptr;
8979 Continuation : Boolean := False)
8982 case When_No_Sources is
8986 when Warning | Error =>
8988 Msg : constant String :=
8991 " sources in this project";
8994 Error_Msg_Warn := When_No_Sources = Warning;
8996 if Continuation then
8998 (Project, In_Tree, "\" & Msg, Location);
9002 (Project, In_Tree, Msg, Location);
9006 end Report_No_Sources;
9008 ----------------------
9009 -- Show_Source_Dirs --
9010 ----------------------
9012 procedure Show_Source_Dirs
9013 (Data : Project_Data;
9014 In_Tree : Project_Tree_Ref)
9016 Current : String_List_Id;
9017 Element : String_Element;
9020 Write_Line ("Source_Dirs:");
9022 Current := Data.Source_Dirs;
9023 while Current /= Nil_String loop
9024 Element := In_Tree.String_Elements.Table (Current);
9026 Write_Line (Get_Name_String (Element.Value));
9027 Current := Element.Next;
9030 Write_Line ("end Source_Dirs.");
9031 end Show_Source_Dirs;
9033 -------------------------
9034 -- Warn_If_Not_Sources --
9035 -------------------------
9037 -- comments needed in this body ???
9039 procedure Warn_If_Not_Sources
9040 (Project : Project_Id;
9041 In_Tree : Project_Tree_Ref;
9042 Conventions : Array_Element_Id;
9044 Extending : Boolean)
9046 Conv : Array_Element_Id;
9048 The_Unit_Id : Unit_Index;
9049 The_Unit_Data : Unit_Data;
9050 Location : Source_Ptr;
9053 Conv := Conventions;
9054 while Conv /= No_Array_Element loop
9055 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9056 Error_Msg_Name_1 := Unit;
9057 Get_Name_String (Unit);
9058 To_Lower (Name_Buffer (1 .. Name_Len));
9060 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9061 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9063 if The_Unit_Id = No_Unit_Index then
9064 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9067 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9069 In_Tree.Array_Elements.Table (Conv).Value.Value;
9072 if not Check_Project
9073 (The_Unit_Data.File_Names (Specification).Project,
9074 Project, In_Tree, Extending)
9078 "?source of spec of unit %% (%%)" &
9079 " cannot be found in this project",
9084 if not Check_Project
9085 (The_Unit_Data.File_Names (Body_Part).Project,
9086 Project, In_Tree, Extending)
9090 "?source of body of unit %% (%%)" &
9091 " cannot be found in this project",
9097 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9099 end Warn_If_Not_Sources;