merge with trunk @ 139506
[official-gcc.git] / gcc / ada / prj-nmsc.adb
blobdb6a70cd7b019cc2700db2dcaf2e4024202a3674
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . N M S C --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2000-2008, Free Software Foundation, Inc. --
10 -- --
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. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
28 with GNAT.HTable;
30 with Err_Vars; use Err_Vars;
31 with Fmap; use Fmap;
32 with Hostparm;
33 with MLib.Tgt;
34 with Opt; use Opt;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
38 with Prj.Err;
39 with Prj.Util; use Prj.Util;
40 with Sinput.P;
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
56 -- location.
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;
74 end record;
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 :=
80 (Name => No_File,
81 Location => No_Location,
82 Source => No_Source,
83 Except => False,
84 Found => False);
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,
91 Hash => Hash,
92 Equal => "=");
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
100 Name : Name_Id;
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
103 end record;
105 No_Unit_Exception : constant Unit_Exception :=
106 (Name => No_Name,
107 Spec => No_File,
108 Impl => No_File);
110 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
111 (Header_Num => Header_Num,
112 Element => Unit_Exception,
113 No_Element => No_Unit_Exception,
114 Key => Name_Id,
115 Hash => Hash,
116 Equal => "=");
117 -- Hash table to store the unit exceptions
119 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
120 (Header_Num => Header_Num,
121 Element => Boolean,
122 No_Element => False,
123 Key => Name_Id,
124 Hash => Hash,
125 Equal => "=");
126 -- Hash table to store recursive source directories, to avoid looking
127 -- several times, and to avoid cycles that may be introduced by symbolic
128 -- links.
130 type Ada_Naming_Exception_Id is new Nat;
131 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
133 type Unit_Info is record
134 Kind : Spec_Or_Body;
135 Unit : Name_Id;
136 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
137 end record;
138 -- Comment needed???
140 -- Why is the following commented out ???
141 -- No_Unit : constant Unit_Info :=
142 -- (Specification, No_Name, No_Ada_Naming_Exception);
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
148 Table_Initial => 20,
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,
157 Hash => Hash,
158 Equal => "=");
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 package Object_File_Names is new GNAT.HTable.Simple_HTable
163 (Header_Num => Header_Num,
164 Element => File_Name_Type,
165 No_Element => No_File,
166 Key => File_Name_Type,
167 Hash => Hash,
168 Equal => "=");
169 -- A hash table to store the object file names for a project, to check that
170 -- two different sources have different object file names.
172 type File_Found is record
173 File : File_Name_Type := No_File;
174 Found : Boolean := False;
175 Location : Source_Ptr := No_Location;
176 end record;
177 No_File_Found : constant File_Found := (No_File, False, No_Location);
178 -- Comments needed ???
180 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
181 (Header_Num => Header_Num,
182 Element => File_Found,
183 No_Element => No_File_Found,
184 Key => File_Name_Type,
185 Hash => Hash,
186 Equal => "=");
187 -- A hash table to store the excluded files, if any. This is filled by
188 -- Find_Excluded_Sources below.
190 procedure Find_Excluded_Sources
191 (Project : Project_Id;
192 In_Tree : Project_Tree_Ref;
193 Data : Project_Data);
194 -- Find the list of files that should not be considered as source files
195 -- for this project. Sets the list in the Excluded_Sources_Htable.
197 function Hash (Unit : Unit_Info) return Header_Num;
199 type Name_And_Index is record
200 Name : Name_Id := No_Name;
201 Index : Int := 0;
202 end record;
203 No_Name_And_Index : constant Name_And_Index :=
204 (Name => No_Name, Index => 0);
206 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
207 (Header_Num => Header_Num,
208 Element => Name_And_Index,
209 No_Element => No_Name_And_Index,
210 Key => Unit_Info,
211 Hash => Hash,
212 Equal => "=");
213 -- A table to check if a unit with an exceptional name will hide a source
214 -- with a file name following the naming convention.
216 procedure Add_Source
217 (Id : out Source_Id;
218 Data : in out Project_Data;
219 In_Tree : Project_Tree_Ref;
220 Project : Project_Id;
221 Lang : Name_Id;
222 Lang_Id : Language_Index;
223 Kind : Source_Kind;
224 File_Name : File_Name_Type;
225 Display_File : File_Name_Type;
226 Lang_Kind : Language_Kind;
227 Naming_Exception : Boolean := False;
228 Path : Path_Name_Type := No_Path;
229 Display_Path : Path_Name_Type := No_Path;
230 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
231 Other_Part : Source_Id := No_Source;
232 Unit : Name_Id := No_Name;
233 Index : Int := 0;
234 Source_To_Replace : Source_Id := No_Source);
235 -- Add a new source to the different lists: list of all sources in the
236 -- project tree, list of source of a project and list of sources of a
237 -- language.
239 -- If Path is specified, the file is also added to Source_Paths_HT.
240 -- If Source_To_Replace is specified, it points to the source in the
241 -- extended project that the new file is overriding.
243 function ALI_File_Name (Source : String) return String;
244 -- Return the ALI file name corresponding to a source
246 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
247 -- Check that a name is a valid Ada unit name
249 procedure Check_Naming_Schemes
250 (Data : in out Project_Data;
251 Project : Project_Id;
252 In_Tree : Project_Tree_Ref);
253 -- Check the naming scheme part of Data
255 procedure Check_Ada_Naming_Scheme_Validity
256 (Project : Project_Id;
257 In_Tree : Project_Tree_Ref;
258 Naming : Naming_Data);
259 -- Check that the package Naming is correct
261 procedure Check_Configuration
262 (Project : Project_Id;
263 In_Tree : Project_Tree_Ref;
264 Data : in out Project_Data);
265 -- Check the configuration attributes for the project
267 procedure Check_If_Externally_Built
268 (Project : Project_Id;
269 In_Tree : Project_Tree_Ref;
270 Data : in out Project_Data);
271 -- Check attribute Externally_Built of project Project in project tree
272 -- In_Tree and modify its data Data if it has the value "true".
274 procedure Check_Interfaces
275 (Project : Project_Id;
276 In_Tree : Project_Tree_Ref;
277 Data : in out Project_Data);
278 -- If a list of sources is specified in attribute Interfaces, set
279 -- In_Interfaces only for the sources specified in the list.
281 procedure Check_Library_Attributes
282 (Project : Project_Id;
283 In_Tree : Project_Tree_Ref;
284 Current_Dir : String;
285 Data : in out Project_Data);
286 -- Check the library attributes of project Project in project tree In_Tree
287 -- and modify its data Data accordingly.
288 -- Current_Dir should represent the current directory, and is passed for
289 -- efficiency to avoid system calls to recompute it.
291 procedure Check_Package_Naming
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Data : in out Project_Data);
295 -- Check package Naming of project Project in project tree In_Tree and
296 -- modify its data Data accordingly.
298 procedure Check_Programming_Languages
299 (In_Tree : Project_Tree_Ref;
300 Project : Project_Id;
301 Data : in out Project_Data);
302 -- Check attribute Languages for the project with data Data in project
303 -- tree In_Tree and set the components of Data for all the programming
304 -- languages indicated in attribute Languages, if any.
306 function Check_Project
307 (P : Project_Id;
308 Root_Project : Project_Id;
309 In_Tree : Project_Tree_Ref;
310 Extending : Boolean) return Boolean;
311 -- Returns True if P is Root_Project or, if Extending is True, a project
312 -- extended by Root_Project.
314 procedure Check_Stand_Alone_Library
315 (Project : Project_Id;
316 In_Tree : Project_Tree_Ref;
317 Data : in out Project_Data;
318 Current_Dir : String;
319 Extending : Boolean);
320 -- Check if project Project in project tree In_Tree is a Stand-Alone
321 -- Library project, and modify its data Data accordingly if it is one.
322 -- Current_Dir should represent the current directory, and is passed for
323 -- efficiency to avoid system calls to recompute it.
325 procedure Get_Path_Names_And_Record_Ada_Sources
326 (Project : Project_Id;
327 In_Tree : Project_Tree_Ref;
328 Data : in out Project_Data;
329 Current_Dir : String);
330 -- Find the path names of the source files in the Source_Names table
331 -- in the source directories and record those that are Ada sources.
333 function Compute_Directory_Last (Dir : String) return Natural;
334 -- Return the index of the last significant character in Dir. This is used
335 -- to avoid duplicate '/' (slash) characters at the end of directory names.
337 procedure Error_Msg
338 (Project : Project_Id;
339 In_Tree : Project_Tree_Ref;
340 Msg : String;
341 Flag_Location : Source_Ptr);
342 -- Output an error message. If Error_Report is null, simply call
343 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
344 -- Error_Report.
346 procedure Find_Ada_Sources
347 (Project : Project_Id;
348 In_Tree : Project_Tree_Ref;
349 Data : in out Project_Data;
350 Current_Dir : String);
351 -- Find all the Ada sources in all of the source directories of a project
352 -- Current_Dir should represent the current directory, and is passed for
353 -- efficiency to avoid system calls to recompute it.
355 procedure Search_Directories
356 (Project : Project_Id;
357 In_Tree : Project_Tree_Ref;
358 Data : in out Project_Data;
359 For_All_Sources : Boolean);
360 -- Search the source directories to find the sources.
361 -- If For_All_Sources is True, check each regular file name against the
362 -- naming schemes of the different languages. Otherwise consider only the
363 -- file names in the hash table Source_Names.
365 procedure Check_File
366 (Project : Project_Id;
367 In_Tree : Project_Tree_Ref;
368 Data : in out Project_Data;
369 Name : String;
370 File_Name : File_Name_Type;
371 Display_File_Name : File_Name_Type;
372 Source_Directory : String;
373 For_All_Sources : Boolean);
374 -- Check if file File_Name is a valid source of the project. This is used
375 -- in multi-language mode only.
376 -- When the file matches one of the naming schemes, it is added to
377 -- various htables through Add_Source and to Source_Paths_Htable.
379 -- Name is the name of the candidate file. It hasn't been normalized yet
380 -- and is the direct result of readdir().
382 -- File_Name is the same as Name, but has been normalized.
383 -- Display_File_Name, however, has not been normalized.
385 -- Source_Directory is the directory in which the file
386 -- was found. It hasn't been normalized (nor has had links resolved).
387 -- It should not end with a directory separator, to avoid duplicates
388 -- later on.
390 -- If For_All_Sources is True, then all possible file names are analyzed
391 -- otherwise only those currently set in the Source_Names htable.
393 procedure Check_Naming_Schemes
394 (In_Tree : Project_Tree_Ref;
395 Data : in out Project_Data;
396 Filename : String;
397 File_Name : File_Name_Type;
398 Alternate_Languages : out Alternate_Language_Id;
399 Language : out Language_Index;
400 Language_Name : out Name_Id;
401 Display_Language_Name : out Name_Id;
402 Unit : out Name_Id;
403 Lang_Kind : out Language_Kind;
404 Kind : out Source_Kind);
405 -- Check if the file name File_Name conforms to one of the naming
406 -- schemes of the project.
408 -- If the file does not match one of the naming schemes, set Language
409 -- to No_Language_Index.
411 -- Filename is the name of the file being investigated. It has been
412 -- normalized (case-folded). File_Name is the same value.
414 procedure Free_Ada_Naming_Exceptions;
415 -- Free the internal hash tables used for checking naming exceptions
417 procedure Get_Directories
418 (Project : Project_Id;
419 In_Tree : Project_Tree_Ref;
420 Current_Dir : String;
421 Data : in out Project_Data);
422 -- Get the object directory, the exec directory and the source directories
423 -- of a project.
425 -- Current_Dir should represent the current directory, and is passed for
426 -- efficiency to avoid system calls to recompute it.
428 procedure Get_Mains
429 (Project : Project_Id;
430 In_Tree : Project_Tree_Ref;
431 Data : in out Project_Data);
432 -- Get the mains of a project from attribute Main, if it exists, and put
433 -- them in the project data.
435 procedure Get_Sources_From_File
436 (Path : String;
437 Location : Source_Ptr;
438 Project : Project_Id;
439 In_Tree : Project_Tree_Ref);
440 -- Get the list of sources from a text file and put them in hash table
441 -- Source_Names.
443 procedure Find_Explicit_Sources
444 (Current_Dir : String;
445 Project : Project_Id;
446 In_Tree : Project_Tree_Ref;
447 Data : in out Project_Data);
448 -- Process the Source_Files and Source_List_File attributes, and store
449 -- the list of source files into the Source_Names htable.
451 -- Lang indicates which language is being processed when in Ada_Only mode
452 -- (all languages are processed anyway when in Multi_Language mode).
454 procedure Get_Unit
455 (In_Tree : Project_Tree_Ref;
456 Canonical_File_Name : File_Name_Type;
457 Naming : Naming_Data;
458 Exception_Id : out Ada_Naming_Exception_Id;
459 Unit_Name : out Name_Id;
460 Unit_Kind : out Spec_Or_Body;
461 Needs_Pragma : out Boolean);
462 -- Find out, from a file name, the unit name, the unit kind and if a
463 -- specific SFN pragma is needed. If the file name corresponds to no unit,
464 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
465 -- exception to the naming scheme, then Exception_Id is set to the unit or
466 -- units that the source contains.
468 function Is_Illegal_Suffix
469 (Suffix : String;
470 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean;
471 -- Returns True if the string Suffix cannot be used as a spec suffix, a
472 -- body suffix or a separate suffix.
474 procedure Locate_Directory
475 (Project : Project_Id;
476 In_Tree : Project_Tree_Ref;
477 Name : File_Name_Type;
478 Parent : Path_Name_Type;
479 Dir : out Path_Name_Type;
480 Display : out Path_Name_Type;
481 Create : String := "";
482 Current_Dir : String;
483 Location : Source_Ptr := No_Location);
484 -- Locate a directory. Name is the directory name. Parent is the root
485 -- directory, if Name a relative path name. Dir is set to the canonical
486 -- case path name of the directory, and Display is the directory path name
487 -- for display purposes. If the directory does not exist and Project_Setup
488 -- is True and Create is a non null string, an attempt is made to create
489 -- the directory. If the directory does not exist and Project_Setup is
490 -- false, then Dir and Display are set to No_Name.
492 -- Current_Dir should represent the current directory, and is passed for
493 -- efficiency to avoid system calls to recompute it.
495 procedure Look_For_Sources
496 (Project : Project_Id;
497 In_Tree : Project_Tree_Ref;
498 Data : in out Project_Data;
499 Current_Dir : String);
500 -- Find all the sources of project Project in project tree In_Tree and
501 -- update its Data accordingly.
503 -- Current_Dir should represent the current directory, and is passed for
504 -- efficiency to avoid system calls to recompute it.
506 function Path_Name_Of
507 (File_Name : File_Name_Type;
508 Directory : Path_Name_Type) return String;
509 -- Returns the path name of a (non project) file. Returns an empty string
510 -- if file cannot be found.
512 procedure Prepare_Ada_Naming_Exceptions
513 (List : Array_Element_Id;
514 In_Tree : Project_Tree_Ref;
515 Kind : Spec_Or_Body);
516 -- Prepare the internal hash tables used for checking naming exceptions
517 -- for Ada. Insert all elements of List in the tables.
519 function Project_Extends
520 (Extending : Project_Id;
521 Extended : Project_Id;
522 In_Tree : Project_Tree_Ref) return Boolean;
523 -- Returns True if Extending is extending Extended either directly or
524 -- indirectly.
526 procedure Record_Ada_Source
527 (File_Name : File_Name_Type;
528 Path_Name : Path_Name_Type;
529 Project : Project_Id;
530 In_Tree : Project_Tree_Ref;
531 Data : in out Project_Data;
532 Location : Source_Ptr;
533 Current_Source : in out String_List_Id;
534 Source_Recorded : in out Boolean;
535 Current_Dir : String);
536 -- Put a unit in the list of units of a project, if the file name
537 -- corresponds to a valid unit name.
539 -- Current_Dir should represent the current directory, and is passed for
540 -- efficiency to avoid system calls to recompute it.
542 procedure Remove_Source
543 (Id : Source_Id;
544 Replaced_By : Source_Id;
545 Project : Project_Id;
546 Data : in out Project_Data;
547 In_Tree : Project_Tree_Ref);
548 -- ??? needs comment
550 procedure Report_No_Sources
551 (Project : Project_Id;
552 Lang_Name : String;
553 In_Tree : Project_Tree_Ref;
554 Location : Source_Ptr;
555 Continuation : Boolean := False);
556 -- Report an error or a warning depending on the value of When_No_Sources
557 -- when there are no sources for language Lang_Name.
559 procedure Show_Source_Dirs
560 (Data : Project_Data; In_Tree : Project_Tree_Ref);
561 -- List all the source directories of a project
563 procedure Warn_If_Not_Sources
564 (Project : Project_Id;
565 In_Tree : Project_Tree_Ref;
566 Conventions : Array_Element_Id;
567 Specs : Boolean;
568 Extending : Boolean);
569 -- Check that individual naming conventions apply to immediate sources of
570 -- the project. If not, issue a warning.
572 ----------------
573 -- Add_Source --
574 ----------------
576 procedure Add_Source
577 (Id : out Source_Id;
578 Data : in out Project_Data;
579 In_Tree : Project_Tree_Ref;
580 Project : Project_Id;
581 Lang : Name_Id;
582 Lang_Id : Language_Index;
583 Kind : Source_Kind;
584 File_Name : File_Name_Type;
585 Display_File : File_Name_Type;
586 Lang_Kind : Language_Kind;
587 Naming_Exception : Boolean := False;
588 Path : Path_Name_Type := No_Path;
589 Display_Path : Path_Name_Type := No_Path;
590 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
591 Other_Part : Source_Id := No_Source;
592 Unit : Name_Id := No_Name;
593 Index : Int := 0;
594 Source_To_Replace : Source_Id := No_Source)
596 Source : constant Source_Id := Data.Last_Source;
597 Src_Data : Source_Data := No_Source_Data;
598 Config : constant Language_Config :=
599 In_Tree.Languages_Data.Table (Lang_Id).Config;
601 begin
602 -- This is a new source so create an entry for it in the Sources table
604 Source_Data_Table.Increment_Last (In_Tree.Sources);
605 Id := Source_Data_Table.Last (In_Tree.Sources);
607 if Current_Verbosity = High then
608 Write_Str ("Adding source #");
609 Write_Str (Id'Img);
610 Write_Str (", File : ");
611 Write_Str (Get_Name_String (File_Name));
613 if Lang_Kind = Unit_Based then
614 Write_Str (", Unit : ");
615 Write_Str (Get_Name_String (Unit));
616 end if;
618 Write_Eol;
619 end if;
621 Src_Data.Project := Project;
622 Src_Data.Language_Name := Lang;
623 Src_Data.Language := Lang_Id;
624 Src_Data.Lang_Kind := Lang_Kind;
625 Src_Data.Compiled := In_Tree.Languages_Data.Table
626 (Lang_Id).Config.Compiler_Driver /=
627 Empty_File_Name;
628 Src_Data.Kind := Kind;
629 Src_Data.Alternate_Languages := Alternate_Languages;
630 Src_Data.Other_Part := Other_Part;
632 Src_Data.Object_Exists := Config.Object_Generated;
633 Src_Data.Object_Linked := Config.Objects_Linked;
635 if Other_Part /= No_Source then
636 In_Tree.Sources.Table (Other_Part).Other_Part := Id;
637 end if;
639 Src_Data.Unit := Unit;
640 Src_Data.Index := Index;
641 Src_Data.File := File_Name;
642 Src_Data.Display_File := Display_File;
643 Src_Data.Dependency := In_Tree.Languages_Data.Table
644 (Lang_Id).Config.Dependency_Kind;
645 Src_Data.Naming_Exception := Naming_Exception;
647 if Src_Data.Compiled and then Src_Data.Object_Exists then
648 Src_Data.Object := Object_Name (File_Name);
649 Src_Data.Dep_Name :=
650 Dependency_Name (File_Name, Src_Data.Dependency);
651 Src_Data.Switches := Switches_Name (File_Name);
652 end if;
654 if Path /= No_Path then
655 Src_Data.Path := (Path, Display_Path);
656 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path, Id);
657 end if;
659 -- Add the source to the global list
661 Src_Data.Next_In_Sources := In_Tree.First_Source;
662 In_Tree.First_Source := Id;
664 -- Add the source to the project list
666 if Source = No_Source then
667 Data.First_Source := Id;
668 else
669 In_Tree.Sources.Table (Source).Next_In_Project := Id;
670 end if;
672 Data.Last_Source := Id;
674 -- Add the source to the language list
676 Src_Data.Next_In_Lang :=
677 In_Tree.Languages_Data.Table (Lang_Id).First_Source;
678 In_Tree.Languages_Data.Table (Lang_Id).First_Source := Id;
680 In_Tree.Sources.Table (Id) := Src_Data;
682 if Source_To_Replace /= No_Source then
683 Remove_Source (Source_To_Replace, Id, Project, Data, In_Tree);
684 end if;
685 end Add_Source;
687 -------------------
688 -- ALI_File_Name --
689 -------------------
691 function ALI_File_Name (Source : String) return String is
692 begin
693 -- If the source name has an extension, then replace it with
694 -- the ALI suffix.
696 for Index in reverse Source'First + 1 .. Source'Last loop
697 if Source (Index) = '.' then
698 return Source (Source'First .. Index - 1) & ALI_Suffix;
699 end if;
700 end loop;
702 -- If there is no dot, or if it is the first character, just add the
703 -- ALI suffix.
705 return Source & ALI_Suffix;
706 end ALI_File_Name;
708 -----------
709 -- Check --
710 -----------
712 procedure Check
713 (Project : Project_Id;
714 In_Tree : Project_Tree_Ref;
715 Report_Error : Put_Line_Access;
716 When_No_Sources : Error_Warning;
717 Current_Dir : String)
719 Data : Project_Data := In_Tree.Projects.Table (Project);
720 Extending : Boolean := False;
722 begin
723 Nmsc.When_No_Sources := When_No_Sources;
724 Error_Report := Report_Error;
726 Recursive_Dirs.Reset;
728 Check_If_Externally_Built (Project, In_Tree, Data);
730 -- Object, exec and source directories
732 Get_Directories (Project, In_Tree, Current_Dir, Data);
734 -- Get the programming languages
736 Check_Programming_Languages (In_Tree, Project, Data);
738 if Data.Qualifier = Dry and then Data.Source_Dirs /= Nil_String then
739 Error_Msg
740 (Project, In_Tree,
741 "an abstract project need to have no language, no sources or no " &
742 "source directories",
743 Data.Location);
744 end if;
746 -- Check configuration in multi language mode
748 if Must_Check_Configuration then
749 Check_Configuration (Project, In_Tree, Data);
750 end if;
752 -- Library attributes
754 Check_Library_Attributes (Project, In_Tree, Current_Dir, Data);
756 if Current_Verbosity = High then
757 Show_Source_Dirs (Data, In_Tree);
758 end if;
760 Check_Package_Naming (Project, In_Tree, Data);
762 Extending := Data.Extends /= No_Project;
764 Check_Naming_Schemes (Data, Project, In_Tree);
766 if Get_Mode = Ada_Only then
767 Prepare_Ada_Naming_Exceptions
768 (Data.Naming.Bodies, In_Tree, Body_Part);
769 Prepare_Ada_Naming_Exceptions
770 (Data.Naming.Specs, In_Tree, Specification);
771 end if;
773 -- Find the sources
775 if Data.Source_Dirs /= Nil_String then
776 Look_For_Sources (Project, In_Tree, Data, Current_Dir);
778 if Get_Mode = Ada_Only then
780 -- Check that all individual naming conventions apply to sources
781 -- of this project file.
783 Warn_If_Not_Sources
784 (Project, In_Tree, Data.Naming.Bodies,
785 Specs => False,
786 Extending => Extending);
787 Warn_If_Not_Sources
788 (Project, In_Tree, Data.Naming.Specs,
789 Specs => True,
790 Extending => Extending);
792 elsif Get_Mode = Multi_Language and then
793 (not Data.Externally_Built) and then
794 (not Extending)
795 then
796 declare
797 Language : Language_Index;
798 Source : Source_Id;
799 Src_Data : Source_Data;
800 Alt_Lang : Alternate_Language_Id;
801 Alt_Lang_Data : Alternate_Language_Data;
802 Continuation : Boolean := False;
804 begin
805 Language := Data.First_Language_Processing;
806 while Language /= No_Language_Index loop
807 Source := Data.First_Source;
808 Source_Loop : while Source /= No_Source loop
809 Src_Data := In_Tree.Sources.Table (Source);
811 exit Source_Loop when Src_Data.Language = Language;
813 Alt_Lang := Src_Data.Alternate_Languages;
815 Alternate_Loop :
816 while Alt_Lang /= No_Alternate_Language loop
817 Alt_Lang_Data :=
818 In_Tree.Alt_Langs.Table (Alt_Lang);
819 exit Source_Loop
820 when Alt_Lang_Data.Language = Language;
821 Alt_Lang := Alt_Lang_Data.Next;
822 end loop Alternate_Loop;
824 Source := Src_Data.Next_In_Project;
825 end loop Source_Loop;
827 if Source = No_Source then
828 Report_No_Sources
829 (Project,
830 Get_Name_String
831 (In_Tree.Languages_Data.Table
832 (Language).Display_Name),
833 In_Tree,
834 Data.Location,
835 Continuation);
836 Continuation := True;
837 end if;
839 Language := In_Tree.Languages_Data.Table (Language).Next;
840 end loop;
841 end;
842 end if;
843 end if;
845 if Get_Mode = Multi_Language then
847 -- If a list of sources is specified in attribute Interfaces, set
848 -- In_Interfaces only for the sources specified in the list.
850 Check_Interfaces (Project, In_Tree, Data);
851 end if;
853 -- If it is a library project file, check if it is a standalone library
855 if Data.Library then
856 Check_Stand_Alone_Library
857 (Project, In_Tree, Data, Current_Dir, Extending);
858 end if;
860 -- Put the list of Mains, if any, in the project data
862 Get_Mains (Project, In_Tree, Data);
864 -- Update the project data in the Projects table
866 In_Tree.Projects.Table (Project) := Data;
868 Free_Ada_Naming_Exceptions;
869 end Check;
871 --------------------
872 -- Check_Ada_Name --
873 --------------------
875 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
876 The_Name : String := Name;
877 Real_Name : Name_Id;
878 Need_Letter : Boolean := True;
879 Last_Underscore : Boolean := False;
880 OK : Boolean := The_Name'Length > 0;
881 First : Positive;
883 function Is_Reserved (Name : Name_Id) return Boolean;
884 function Is_Reserved (S : String) return Boolean;
885 -- Check that the given name is not an Ada 95 reserved word. The reason
886 -- for the Ada 95 here is that we do not want to exclude the case of an
887 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
888 -- name would be rejected anyway by the compiler. That means there is no
889 -- requirement that the project file parser reject this.
891 -----------------
892 -- Is_Reserved --
893 -----------------
895 function Is_Reserved (S : String) return Boolean is
896 begin
897 Name_Len := 0;
898 Add_Str_To_Name_Buffer (S);
899 return Is_Reserved (Name_Find);
900 end Is_Reserved;
902 -----------------
903 -- Is_Reserved --
904 -----------------
906 function Is_Reserved (Name : Name_Id) return Boolean is
907 begin
908 if Get_Name_Table_Byte (Name) /= 0
909 and then Name /= Name_Project
910 and then Name /= Name_Extends
911 and then Name /= Name_External
912 and then Name not in Ada_2005_Reserved_Words
913 then
914 Unit := No_Name;
916 if Current_Verbosity = High then
917 Write_Str (The_Name);
918 Write_Line (" is an Ada reserved word.");
919 end if;
921 return True;
923 else
924 return False;
925 end if;
926 end Is_Reserved;
928 -- Start of processing for Check_Ada_Name
930 begin
931 To_Lower (The_Name);
933 Name_Len := The_Name'Length;
934 Name_Buffer (1 .. Name_Len) := The_Name;
936 -- Special cases of children of packages A, G, I and S on VMS
938 if OpenVMS_On_Target
939 and then Name_Len > 3
940 and then Name_Buffer (2 .. 3) = "__"
941 and then
942 ((Name_Buffer (1) = 'a') or else
943 (Name_Buffer (1) = 'g') or else
944 (Name_Buffer (1) = 'i') or else
945 (Name_Buffer (1) = 's'))
946 then
947 Name_Buffer (2) := '.';
948 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
949 Name_Len := Name_Len - 1;
950 end if;
952 Real_Name := Name_Find;
954 if Is_Reserved (Real_Name) then
955 return;
956 end if;
958 First := The_Name'First;
960 for Index in The_Name'Range loop
961 if Need_Letter then
963 -- We need a letter (at the beginning, and following a dot),
964 -- but we don't have one.
966 if Is_Letter (The_Name (Index)) then
967 Need_Letter := False;
969 else
970 OK := False;
972 if Current_Verbosity = High then
973 Write_Int (Types.Int (Index));
974 Write_Str (": '");
975 Write_Char (The_Name (Index));
976 Write_Line ("' is not a letter.");
977 end if;
979 exit;
980 end if;
982 elsif Last_Underscore
983 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
984 then
985 -- Two underscores are illegal, and a dot cannot follow
986 -- an underscore.
988 OK := False;
990 if Current_Verbosity = High then
991 Write_Int (Types.Int (Index));
992 Write_Str (": '");
993 Write_Char (The_Name (Index));
994 Write_Line ("' is illegal here.");
995 end if;
997 exit;
999 elsif The_Name (Index) = '.' then
1001 -- First, check if the name before the dot is not a reserved word
1002 if Is_Reserved (The_Name (First .. Index - 1)) then
1003 return;
1004 end if;
1006 First := Index + 1;
1008 -- We need a letter after a dot
1010 Need_Letter := True;
1012 elsif The_Name (Index) = '_' then
1013 Last_Underscore := True;
1015 else
1016 -- We need an letter or a digit
1018 Last_Underscore := False;
1020 if not Is_Alphanumeric (The_Name (Index)) then
1021 OK := False;
1023 if Current_Verbosity = High then
1024 Write_Int (Types.Int (Index));
1025 Write_Str (": '");
1026 Write_Char (The_Name (Index));
1027 Write_Line ("' is not alphanumeric.");
1028 end if;
1030 exit;
1031 end if;
1032 end if;
1033 end loop;
1035 -- Cannot end with an underscore or a dot
1037 OK := OK and then not Need_Letter and then not Last_Underscore;
1039 if OK then
1040 if First /= Name'First and then
1041 Is_Reserved (The_Name (First .. The_Name'Last))
1042 then
1043 return;
1044 end if;
1046 Unit := Real_Name;
1048 else
1049 -- Signal a problem with No_Name
1051 Unit := No_Name;
1052 end if;
1053 end Check_Ada_Name;
1055 --------------------------------------
1056 -- Check_Ada_Naming_Scheme_Validity --
1057 --------------------------------------
1059 procedure Check_Ada_Naming_Scheme_Validity
1060 (Project : Project_Id;
1061 In_Tree : Project_Tree_Ref;
1062 Naming : Naming_Data)
1064 begin
1065 -- Only check if we are not using the Default naming scheme
1067 if Naming /= In_Tree.Private_Part.Default_Naming then
1068 declare
1069 Dot_Replacement : constant String :=
1070 Get_Name_String
1071 (Naming.Dot_Replacement);
1073 Spec_Suffix : constant String :=
1074 Spec_Suffix_Of (In_Tree, "ada", Naming);
1076 Body_Suffix : constant String :=
1077 Body_Suffix_Of (In_Tree, "ada", Naming);
1079 Separate_Suffix : constant String :=
1080 Get_Name_String
1081 (Naming.Separate_Suffix);
1083 begin
1084 -- Dot_Replacement cannot
1086 -- - be empty
1087 -- - start or end with an alphanumeric
1088 -- - be a single '_'
1089 -- - start with an '_' followed by an alphanumeric
1090 -- - contain a '.' except if it is "."
1092 if Dot_Replacement'Length = 0
1093 or else Is_Alphanumeric
1094 (Dot_Replacement (Dot_Replacement'First))
1095 or else Is_Alphanumeric
1096 (Dot_Replacement (Dot_Replacement'Last))
1097 or else (Dot_Replacement (Dot_Replacement'First) = '_'
1098 and then
1099 (Dot_Replacement'Length = 1
1100 or else
1101 Is_Alphanumeric
1102 (Dot_Replacement (Dot_Replacement'First + 1))))
1103 or else (Dot_Replacement'Length > 1
1104 and then
1105 Index (Source => Dot_Replacement,
1106 Pattern => ".") /= 0)
1107 then
1108 Error_Msg
1109 (Project, In_Tree,
1110 '"' & Dot_Replacement &
1111 """ is illegal for Dot_Replacement.",
1112 Naming.Dot_Repl_Loc);
1113 end if;
1115 -- Suffixes cannot
1116 -- - be empty
1118 if Is_Illegal_Suffix
1119 (Spec_Suffix, Dot_Replacement = ".")
1120 then
1121 Err_Vars.Error_Msg_File_1 :=
1122 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1123 Error_Msg
1124 (Project, In_Tree,
1125 "{ is illegal for Spec_Suffix",
1126 Naming.Ada_Spec_Suffix_Loc);
1127 end if;
1129 if Is_Illegal_Suffix
1130 (Body_Suffix, Dot_Replacement = ".")
1131 then
1132 Err_Vars.Error_Msg_File_1 :=
1133 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
1134 Error_Msg
1135 (Project, In_Tree,
1136 "{ is illegal for Body_Suffix",
1137 Naming.Ada_Body_Suffix_Loc);
1138 end if;
1140 if Body_Suffix /= Separate_Suffix then
1141 if Is_Illegal_Suffix
1142 (Separate_Suffix, Dot_Replacement = ".")
1143 then
1144 Err_Vars.Error_Msg_File_1 := Naming.Separate_Suffix;
1145 Error_Msg
1146 (Project, In_Tree,
1147 "{ is illegal for Separate_Suffix",
1148 Naming.Sep_Suffix_Loc);
1149 end if;
1150 end if;
1152 -- Spec_Suffix cannot be equal to Body_Suffix Separate_Suffix,
1153 -- since that would cause a clear ambiguity. Note that we do
1154 -- allow a Spec_Suffix to have the same termination as one of
1155 -- these, which causes a potential ambiguity, but we resolve
1156 -- that my matching the longest possible suffix.
1158 if Spec_Suffix = Body_Suffix then
1159 Error_Msg
1160 (Project, In_Tree,
1161 "Body_Suffix (""" &
1162 Body_Suffix &
1163 """) cannot be the same as Spec_Suffix.",
1164 Naming.Ada_Body_Suffix_Loc);
1165 end if;
1167 if Body_Suffix /= Separate_Suffix
1168 and then Spec_Suffix = Separate_Suffix
1169 then
1170 Error_Msg
1171 (Project, In_Tree,
1172 "Separate_Suffix (""" &
1173 Separate_Suffix &
1174 """) cannot be the same as Spec_Suffix.",
1175 Naming.Sep_Suffix_Loc);
1176 end if;
1177 end;
1178 end if;
1179 end Check_Ada_Naming_Scheme_Validity;
1181 -------------------------
1182 -- Check_Configuration --
1183 -------------------------
1185 procedure Check_Configuration
1186 (Project : Project_Id;
1187 In_Tree : Project_Tree_Ref;
1188 Data : in out Project_Data)
1190 Dot_Replacement : File_Name_Type := No_File;
1191 Casing : Casing_Type := All_Lower_Case;
1192 Separate_Suffix : File_Name_Type := No_File;
1194 Lang_Index : Language_Index := No_Language_Index;
1195 -- The index of the language data being checked
1197 Prev_Index : Language_Index := No_Language_Index;
1198 -- The index of the previous language
1200 Current_Language : Name_Id := No_Name;
1201 -- The name of the language
1203 Lang_Data : Language_Data;
1204 -- The data of the language being checked
1206 procedure Get_Language_Index_Of (Language : Name_Id);
1207 -- Get the language index of Language, if Language is one of the
1208 -- languages of the project.
1210 procedure Process_Project_Level_Simple_Attributes;
1211 -- Process the simple attributes at the project level
1213 procedure Process_Project_Level_Array_Attributes;
1214 -- Process the associate array attributes at the project level
1216 procedure Process_Packages;
1217 -- Read the packages of the project
1219 ---------------------------
1220 -- Get_Language_Index_Of --
1221 ---------------------------
1223 procedure Get_Language_Index_Of (Language : Name_Id) is
1224 Real_Language : Name_Id;
1226 begin
1227 Get_Name_String (Language);
1228 To_Lower (Name_Buffer (1 .. Name_Len));
1229 Real_Language := Name_Find;
1231 -- Nothing to do if the language is the same as the current language
1233 if Current_Language /= Real_Language then
1234 Lang_Index := Data.First_Language_Processing;
1235 while Lang_Index /= No_Language_Index loop
1236 exit when In_Tree.Languages_Data.Table (Lang_Index).Name =
1237 Real_Language;
1238 Lang_Index :=
1239 In_Tree.Languages_Data.Table (Lang_Index).Next;
1240 end loop;
1242 if Lang_Index = No_Language_Index then
1243 Current_Language := No_Name;
1244 else
1245 Current_Language := Real_Language;
1246 end if;
1247 end if;
1248 end Get_Language_Index_Of;
1250 ----------------------
1251 -- Process_Packages --
1252 ----------------------
1254 procedure Process_Packages is
1255 Packages : Package_Id;
1256 Element : Package_Element;
1258 procedure Process_Binder (Arrays : Array_Id);
1259 -- Process the associate array attributes of package Binder
1261 procedure Process_Builder (Attributes : Variable_Id);
1262 -- Process the simple attributes of package Builder
1264 procedure Process_Compiler (Arrays : Array_Id);
1265 -- Process the associate array attributes of package Compiler
1267 procedure Process_Naming (Attributes : Variable_Id);
1268 -- Process the simple attributes of package Naming
1270 procedure Process_Naming (Arrays : Array_Id);
1271 -- Process the associate array attributes of package Naming
1273 procedure Process_Linker (Attributes : Variable_Id);
1274 -- Process the simple attributes of package Linker of a
1275 -- configuration project.
1277 --------------------
1278 -- Process_Binder --
1279 --------------------
1281 procedure Process_Binder (Arrays : Array_Id) is
1282 Current_Array_Id : Array_Id;
1283 Current_Array : Array_Data;
1284 Element_Id : Array_Element_Id;
1285 Element : Array_Element;
1287 begin
1288 -- Process the associative array attribute of package Binder
1290 Current_Array_Id := Arrays;
1291 while Current_Array_Id /= No_Array loop
1292 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1294 Element_Id := Current_Array.Value;
1295 while Element_Id /= No_Array_Element loop
1296 Element := In_Tree.Array_Elements.Table (Element_Id);
1298 if Element.Index /= All_Other_Names then
1300 -- Get the name of the language
1302 Get_Language_Index_Of (Element.Index);
1304 if Lang_Index /= No_Language_Index then
1305 case Current_Array.Name is
1306 when Name_Driver =>
1308 -- Attribute Driver (<language>)
1310 In_Tree.Languages_Data.Table
1311 (Lang_Index).Config.Binder_Driver :=
1312 File_Name_Type (Element.Value.Value);
1314 when Name_Required_Switches =>
1315 Put (Into_List =>
1316 In_Tree.Languages_Data.Table
1317 (Lang_Index).Config.Binder_Required_Switches,
1318 From_List => Element.Value.Values,
1319 In_Tree => In_Tree);
1321 when Name_Prefix =>
1323 -- Attribute Prefix (<language>)
1325 In_Tree.Languages_Data.Table
1326 (Lang_Index).Config.Binder_Prefix :=
1327 Element.Value.Value;
1329 when Name_Objects_Path =>
1331 -- Attribute Objects_Path (<language>)
1333 In_Tree.Languages_Data.Table
1334 (Lang_Index).Config.Objects_Path :=
1335 Element.Value.Value;
1337 when Name_Objects_Path_File =>
1339 -- Attribute Objects_Path (<language>)
1341 In_Tree.Languages_Data.Table
1342 (Lang_Index).Config.Objects_Path_File :=
1343 Element.Value.Value;
1345 when others =>
1346 null;
1347 end case;
1348 end if;
1349 end if;
1351 Element_Id := Element.Next;
1352 end loop;
1354 Current_Array_Id := Current_Array.Next;
1355 end loop;
1356 end Process_Binder;
1358 ---------------------
1359 -- Process_Builder --
1360 ---------------------
1362 procedure Process_Builder (Attributes : Variable_Id) is
1363 Attribute_Id : Variable_Id;
1364 Attribute : Variable;
1366 begin
1367 -- Process non associated array attribute from package Builder
1369 Attribute_Id := Attributes;
1370 while Attribute_Id /= No_Variable loop
1371 Attribute :=
1372 In_Tree.Variable_Elements.Table (Attribute_Id);
1374 if not Attribute.Value.Default then
1375 if Attribute.Name = Name_Executable_Suffix then
1377 -- Attribute Executable_Suffix: the suffix of the
1378 -- executables.
1380 Data.Config.Executable_Suffix :=
1381 Attribute.Value.Value;
1382 end if;
1383 end if;
1385 Attribute_Id := Attribute.Next;
1386 end loop;
1387 end Process_Builder;
1389 ----------------------
1390 -- Process_Compiler --
1391 ----------------------
1393 procedure Process_Compiler (Arrays : Array_Id) is
1394 Current_Array_Id : Array_Id;
1395 Current_Array : Array_Data;
1396 Element_Id : Array_Element_Id;
1397 Element : Array_Element;
1398 List : String_List_Id;
1400 begin
1401 -- Process the associative array attribute of package Compiler
1403 Current_Array_Id := Arrays;
1404 while Current_Array_Id /= No_Array loop
1405 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1407 Element_Id := Current_Array.Value;
1408 while Element_Id /= No_Array_Element loop
1409 Element := In_Tree.Array_Elements.Table (Element_Id);
1411 if Element.Index /= All_Other_Names then
1413 -- Get the name of the language
1415 Get_Language_Index_Of (Element.Index);
1417 if Lang_Index /= No_Language_Index then
1418 case Current_Array.Name is
1419 when Name_Dependency_Switches =>
1421 -- Attribute Dependency_Switches (<language>)
1423 if In_Tree.Languages_Data.Table
1424 (Lang_Index).Config.Dependency_Kind = None
1425 then
1426 In_Tree.Languages_Data.Table
1427 (Lang_Index).Config.Dependency_Kind :=
1428 Makefile;
1429 end if;
1431 List := Element.Value.Values;
1433 if List /= Nil_String then
1434 Put (Into_List =>
1435 In_Tree.Languages_Data.Table
1436 (Lang_Index).Config.Dependency_Option,
1437 From_List => List,
1438 In_Tree => In_Tree);
1439 end if;
1441 when Name_Dependency_Driver =>
1443 -- Attribute Dependency_Driver (<language>)
1445 if In_Tree.Languages_Data.Table
1446 (Lang_Index).Config.Dependency_Kind = None
1447 then
1448 In_Tree.Languages_Data.Table
1449 (Lang_Index).Config.Dependency_Kind :=
1450 Makefile;
1451 end if;
1453 List := Element.Value.Values;
1455 if List /= Nil_String then
1456 Put (Into_List =>
1457 In_Tree.Languages_Data.Table
1458 (Lang_Index).Config.Compute_Dependency,
1459 From_List => List,
1460 In_Tree => In_Tree);
1461 end if;
1463 when Name_Include_Switches =>
1465 -- Attribute Include_Switches (<language>)
1467 List := Element.Value.Values;
1469 if List = Nil_String then
1470 Error_Msg
1471 (Project,
1472 In_Tree,
1473 "include option cannot be null",
1474 Element.Value.Location);
1475 end if;
1477 Put (Into_List =>
1478 In_Tree.Languages_Data.Table
1479 (Lang_Index).Config.Include_Option,
1480 From_List => List,
1481 In_Tree => In_Tree);
1483 when Name_Include_Path =>
1485 -- Attribute Include_Path (<language>)
1487 In_Tree.Languages_Data.Table
1488 (Lang_Index).Config.Include_Path :=
1489 Element.Value.Value;
1491 when Name_Include_Path_File =>
1493 -- Attribute Include_Path_File (<language>)
1495 In_Tree.Languages_Data.Table
1496 (Lang_Index).Config.Include_Path_File :=
1497 Element.Value.Value;
1499 when Name_Driver =>
1501 -- Attribute Driver (<language>)
1503 Get_Name_String (Element.Value.Value);
1505 In_Tree.Languages_Data.Table
1506 (Lang_Index).Config.Compiler_Driver :=
1507 File_Name_Type (Element.Value.Value);
1509 when Name_Required_Switches =>
1510 Put (Into_List =>
1511 In_Tree.Languages_Data.Table
1512 (Lang_Index).Config.
1513 Compiler_Required_Switches,
1514 From_List => Element.Value.Values,
1515 In_Tree => In_Tree);
1517 when Name_Path_Syntax =>
1518 begin
1519 In_Tree.Languages_Data.Table
1520 (Lang_Index).Config.Path_Syntax :=
1521 Path_Syntax_Kind'Value
1522 (Get_Name_String (Element.Value.Value));
1524 exception
1525 when Constraint_Error =>
1526 Error_Msg
1527 (Project,
1528 In_Tree,
1529 "invalid value for Path_Syntax",
1530 Element.Value.Location);
1531 end;
1533 when Name_Pic_Option =>
1535 -- Attribute Compiler_Pic_Option (<language>)
1537 List := Element.Value.Values;
1539 if List = Nil_String then
1540 Error_Msg
1541 (Project,
1542 In_Tree,
1543 "compiler PIC option cannot be null",
1544 Element.Value.Location);
1545 end if;
1547 Put (Into_List =>
1548 In_Tree.Languages_Data.Table
1549 (Lang_Index).Config.Compilation_PIC_Option,
1550 From_List => List,
1551 In_Tree => In_Tree);
1553 when Name_Mapping_File_Switches =>
1555 -- Attribute Mapping_File_Switches (<language>)
1557 List := Element.Value.Values;
1559 if List = Nil_String then
1560 Error_Msg
1561 (Project,
1562 In_Tree,
1563 "mapping file switches cannot be null",
1564 Element.Value.Location);
1565 end if;
1567 Put (Into_List =>
1568 In_Tree.Languages_Data.Table
1569 (Lang_Index).Config.Mapping_File_Switches,
1570 From_List => List,
1571 In_Tree => In_Tree);
1573 when Name_Mapping_Spec_Suffix =>
1575 -- Attribute Mapping_Spec_Suffix (<language>)
1577 In_Tree.Languages_Data.Table
1578 (Lang_Index).Config.Mapping_Spec_Suffix :=
1579 File_Name_Type (Element.Value.Value);
1581 when Name_Mapping_Body_Suffix =>
1583 -- Attribute Mapping_Body_Suffix (<language>)
1585 In_Tree.Languages_Data.Table
1586 (Lang_Index).Config.Mapping_Body_Suffix :=
1587 File_Name_Type (Element.Value.Value);
1589 when Name_Config_File_Switches =>
1591 -- Attribute Config_File_Switches (<language>)
1593 List := Element.Value.Values;
1595 if List = Nil_String then
1596 Error_Msg
1597 (Project,
1598 In_Tree,
1599 "config file switches cannot be null",
1600 Element.Value.Location);
1601 end if;
1603 Put (Into_List =>
1604 In_Tree.Languages_Data.Table
1605 (Lang_Index).Config.Config_File_Switches,
1606 From_List => List,
1607 In_Tree => In_Tree);
1609 when Name_Objects_Path =>
1611 -- Attribute Objects_Path (<language>)
1613 In_Tree.Languages_Data.Table
1614 (Lang_Index).Config.Objects_Path :=
1615 Element.Value.Value;
1617 when Name_Objects_Path_File =>
1619 -- Attribute Objects_Path_File (<language>)
1621 In_Tree.Languages_Data.Table
1622 (Lang_Index).Config.Objects_Path_File :=
1623 Element.Value.Value;
1625 when Name_Config_Body_File_Name =>
1627 -- Attribute Config_Body_File_Name (<language>)
1629 In_Tree.Languages_Data.Table
1630 (Lang_Index).Config.Config_Body :=
1631 Element.Value.Value;
1633 when Name_Config_Body_File_Name_Pattern =>
1635 -- Attribute Config_Body_File_Name_Pattern
1636 -- (<language>)
1638 In_Tree.Languages_Data.Table
1639 (Lang_Index).Config.Config_Body_Pattern :=
1640 Element.Value.Value;
1642 when Name_Config_Spec_File_Name =>
1644 -- Attribute Config_Spec_File_Name (<language>)
1646 In_Tree.Languages_Data.Table
1647 (Lang_Index).Config.Config_Spec :=
1648 Element.Value.Value;
1650 when Name_Config_Spec_File_Name_Pattern =>
1652 -- Attribute Config_Spec_File_Name_Pattern
1653 -- (<language>)
1655 In_Tree.Languages_Data.Table
1656 (Lang_Index).Config.Config_Spec_Pattern :=
1657 Element.Value.Value;
1659 when Name_Config_File_Unique =>
1661 -- Attribute Config_File_Unique (<language>)
1663 begin
1664 In_Tree.Languages_Data.Table
1665 (Lang_Index).Config.Config_File_Unique :=
1666 Boolean'Value
1667 (Get_Name_String (Element.Value.Value));
1668 exception
1669 when Constraint_Error =>
1670 Error_Msg
1671 (Project,
1672 In_Tree,
1673 "illegal value for Config_File_Unique",
1674 Element.Value.Location);
1675 end;
1677 when others =>
1678 null;
1679 end case;
1680 end if;
1681 end if;
1683 Element_Id := Element.Next;
1684 end loop;
1686 Current_Array_Id := Current_Array.Next;
1687 end loop;
1688 end Process_Compiler;
1690 --------------------
1691 -- Process_Naming --
1692 --------------------
1694 procedure Process_Naming (Attributes : Variable_Id) is
1695 Attribute_Id : Variable_Id;
1696 Attribute : Variable;
1698 begin
1699 -- Process non associated array attribute from package Naming
1701 Attribute_Id := Attributes;
1702 while Attribute_Id /= No_Variable loop
1703 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1705 if not Attribute.Value.Default then
1706 if Attribute.Name = Name_Separate_Suffix then
1708 -- Attribute Separate_Suffix
1710 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1712 elsif Attribute.Name = Name_Casing then
1714 -- Attribute Casing
1716 begin
1717 Casing :=
1718 Value (Get_Name_String (Attribute.Value.Value));
1720 exception
1721 when Constraint_Error =>
1722 Error_Msg
1723 (Project,
1724 In_Tree,
1725 "invalid value for Casing",
1726 Attribute.Value.Location);
1727 end;
1729 elsif Attribute.Name = Name_Dot_Replacement then
1731 -- Attribute Dot_Replacement
1733 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1735 end if;
1736 end if;
1738 Attribute_Id := Attribute.Next;
1739 end loop;
1740 end Process_Naming;
1742 procedure Process_Naming (Arrays : Array_Id) is
1743 Current_Array_Id : Array_Id;
1744 Current_Array : Array_Data;
1745 Element_Id : Array_Element_Id;
1746 Element : Array_Element;
1747 begin
1748 -- Process the associative array attribute of package Naming
1750 Current_Array_Id := Arrays;
1751 while Current_Array_Id /= No_Array loop
1752 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1754 Element_Id := Current_Array.Value;
1755 while Element_Id /= No_Array_Element loop
1756 Element := In_Tree.Array_Elements.Table (Element_Id);
1758 -- Get the name of the language
1760 Get_Language_Index_Of (Element.Index);
1762 if Lang_Index /= No_Language_Index then
1763 case Current_Array.Name is
1764 when Name_Specification_Suffix | Name_Spec_Suffix =>
1766 -- Attribute Spec_Suffix (<language>)
1768 In_Tree.Languages_Data.Table
1769 (Lang_Index).Config.Naming_Data.Spec_Suffix :=
1770 File_Name_Type (Element.Value.Value);
1772 when Name_Implementation_Suffix | Name_Body_Suffix =>
1774 -- Attribute Body_Suffix (<language>)
1776 In_Tree.Languages_Data.Table
1777 (Lang_Index).Config.Naming_Data.Body_Suffix :=
1778 File_Name_Type (Element.Value.Value);
1780 In_Tree.Languages_Data.Table
1781 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
1782 File_Name_Type (Element.Value.Value);
1784 when others =>
1785 null;
1786 end case;
1787 end if;
1789 Element_Id := Element.Next;
1790 end loop;
1792 Current_Array_Id := Current_Array.Next;
1793 end loop;
1794 end Process_Naming;
1796 --------------------
1797 -- Process_Linker --
1798 --------------------
1800 procedure Process_Linker (Attributes : Variable_Id) is
1801 Attribute_Id : Variable_Id;
1802 Attribute : Variable;
1804 begin
1805 -- Process non associated array attribute from package Linker
1807 Attribute_Id := Attributes;
1808 while Attribute_Id /= No_Variable loop
1809 Attribute :=
1810 In_Tree.Variable_Elements.Table (Attribute_Id);
1812 if not Attribute.Value.Default then
1813 if Attribute.Name = Name_Driver then
1815 -- Attribute Linker'Driver: the default linker to use
1817 Data.Config.Linker :=
1818 Path_Name_Type (Attribute.Value.Value);
1820 elsif Attribute.Name = Name_Required_Switches then
1822 -- Attribute Required_Switches: the minimum
1823 -- options to use when invoking the linker
1825 Put (Into_List =>
1826 Data.Config.Minimum_Linker_Options,
1827 From_List => Attribute.Value.Values,
1828 In_Tree => In_Tree);
1830 elsif Attribute.Name = Name_Map_File_Option then
1831 Data.Config.Map_File_Option := Attribute.Value.Value;
1832 end if;
1833 end if;
1835 Attribute_Id := Attribute.Next;
1836 end loop;
1837 end Process_Linker;
1839 -- Start of processing for Process_Packages
1841 begin
1842 Packages := Data.Decl.Packages;
1843 while Packages /= No_Package loop
1844 Element := In_Tree.Packages.Table (Packages);
1846 case Element.Name is
1847 when Name_Binder =>
1849 -- Process attributes of package Binder
1851 Process_Binder (Element.Decl.Arrays);
1853 when Name_Builder =>
1855 -- Process attributes of package Builder
1857 Process_Builder (Element.Decl.Attributes);
1859 when Name_Compiler =>
1861 -- Process attributes of package Compiler
1863 Process_Compiler (Element.Decl.Arrays);
1865 when Name_Linker =>
1867 -- Process attributes of package Linker
1869 Process_Linker (Element.Decl.Attributes);
1871 when Name_Naming =>
1873 -- Process attributes of package Naming
1875 Process_Naming (Element.Decl.Attributes);
1876 Process_Naming (Element.Decl.Arrays);
1878 when others =>
1879 null;
1880 end case;
1882 Packages := Element.Next;
1883 end loop;
1884 end Process_Packages;
1886 ---------------------------------------------
1887 -- Process_Project_Level_Simple_Attributes --
1888 ---------------------------------------------
1890 procedure Process_Project_Level_Simple_Attributes is
1891 Attribute_Id : Variable_Id;
1892 Attribute : Variable;
1893 List : String_List_Id;
1895 begin
1896 -- Process non associated array attribute at project level
1898 Attribute_Id := Data.Decl.Attributes;
1899 while Attribute_Id /= No_Variable loop
1900 Attribute :=
1901 In_Tree.Variable_Elements.Table (Attribute_Id);
1903 if not Attribute.Value.Default then
1904 if Attribute.Name = Name_Library_Builder then
1906 -- Attribute Library_Builder: the application to invoke
1907 -- to build libraries.
1909 Data.Config.Library_Builder :=
1910 Path_Name_Type (Attribute.Value.Value);
1912 elsif Attribute.Name = Name_Archive_Builder then
1914 -- Attribute Archive_Builder: the archive builder
1915 -- (usually "ar") and its minimum options (usually "cr").
1917 List := Attribute.Value.Values;
1919 if List = Nil_String then
1920 Error_Msg
1921 (Project,
1922 In_Tree,
1923 "archive builder cannot be null",
1924 Attribute.Value.Location);
1925 end if;
1927 Put (Into_List => Data.Config.Archive_Builder,
1928 From_List => List,
1929 In_Tree => In_Tree);
1931 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1933 -- Attribute Archive_Builder: the archive builder
1934 -- (usually "ar") and its minimum options (usually "cr").
1936 List := Attribute.Value.Values;
1938 if List /= Nil_String then
1940 (Into_List => Data.Config.Archive_Builder_Append_Option,
1941 From_List => List,
1942 In_Tree => In_Tree);
1943 end if;
1945 elsif Attribute.Name = Name_Archive_Indexer then
1947 -- Attribute Archive_Indexer: the optional archive
1948 -- indexer (usually "ranlib") with its minimum options
1949 -- (usually none).
1951 List := Attribute.Value.Values;
1953 if List = Nil_String then
1954 Error_Msg
1955 (Project,
1956 In_Tree,
1957 "archive indexer cannot be null",
1958 Attribute.Value.Location);
1959 end if;
1961 Put (Into_List => Data.Config.Archive_Indexer,
1962 From_List => List,
1963 In_Tree => In_Tree);
1965 elsif Attribute.Name = Name_Library_Partial_Linker then
1967 -- Attribute Library_Partial_Linker: the optional linker
1968 -- driver with its minimum options, to partially link
1969 -- archives.
1971 List := Attribute.Value.Values;
1973 if List = Nil_String then
1974 Error_Msg
1975 (Project,
1976 In_Tree,
1977 "partial linker cannot be null",
1978 Attribute.Value.Location);
1979 end if;
1981 Put (Into_List => Data.Config.Lib_Partial_Linker,
1982 From_List => List,
1983 In_Tree => In_Tree);
1985 elsif Attribute.Name = Name_Library_GCC then
1986 Data.Config.Shared_Lib_Driver :=
1987 File_Name_Type (Attribute.Value.Value);
1989 elsif Attribute.Name = Name_Archive_Suffix then
1990 Data.Config.Archive_Suffix :=
1991 File_Name_Type (Attribute.Value.Value);
1993 elsif Attribute.Name = Name_Linker_Executable_Option then
1995 -- Attribute Linker_Executable_Option: optional options
1996 -- to specify an executable name. Defaults to "-o".
1998 List := Attribute.Value.Values;
2000 if List = Nil_String then
2001 Error_Msg
2002 (Project,
2003 In_Tree,
2004 "linker executable option cannot be null",
2005 Attribute.Value.Location);
2006 end if;
2008 Put (Into_List => Data.Config.Linker_Executable_Option,
2009 From_List => List,
2010 In_Tree => In_Tree);
2012 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2014 -- Attribute Linker_Lib_Dir_Option: optional options
2015 -- to specify a library search directory. Defaults to
2016 -- "-L".
2018 Get_Name_String (Attribute.Value.Value);
2020 if Name_Len = 0 then
2021 Error_Msg
2022 (Project,
2023 In_Tree,
2024 "linker library directory option cannot be empty",
2025 Attribute.Value.Location);
2026 end if;
2028 Data.Config.Linker_Lib_Dir_Option := Attribute.Value.Value;
2030 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2032 -- Attribute Linker_Lib_Name_Option: optional options
2033 -- to specify the name of a library to be linked in.
2034 -- Defaults to "-l".
2036 Get_Name_String (Attribute.Value.Value);
2038 if Name_Len = 0 then
2039 Error_Msg
2040 (Project,
2041 In_Tree,
2042 "linker library name option cannot be empty",
2043 Attribute.Value.Location);
2044 end if;
2046 Data.Config.Linker_Lib_Name_Option := Attribute.Value.Value;
2048 elsif Attribute.Name = Name_Run_Path_Option then
2050 -- Attribute Run_Path_Option: optional options to
2051 -- specify a path for libraries.
2053 List := Attribute.Value.Values;
2055 if List /= Nil_String then
2056 Put (Into_List => Data.Config.Run_Path_Option,
2057 From_List => List,
2058 In_Tree => In_Tree);
2059 end if;
2061 elsif Attribute.Name = Name_Library_Support then
2062 declare
2063 pragma Unsuppress (All_Checks);
2064 begin
2065 Data.Config.Lib_Support :=
2066 Library_Support'Value (Get_Name_String
2067 (Attribute.Value.Value));
2068 exception
2069 when Constraint_Error =>
2070 Error_Msg
2071 (Project,
2072 In_Tree,
2073 "invalid value """ &
2074 Get_Name_String (Attribute.Value.Value) &
2075 """ for Library_Support",
2076 Attribute.Value.Location);
2077 end;
2079 elsif Attribute.Name = Name_Shared_Library_Prefix then
2080 Data.Config.Shared_Lib_Prefix :=
2081 File_Name_Type (Attribute.Value.Value);
2083 elsif Attribute.Name = Name_Shared_Library_Suffix then
2084 Data.Config.Shared_Lib_Suffix :=
2085 File_Name_Type (Attribute.Value.Value);
2087 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2088 declare
2089 pragma Unsuppress (All_Checks);
2090 begin
2091 Data.Config.Symbolic_Link_Supported :=
2092 Boolean'Value (Get_Name_String
2093 (Attribute.Value.Value));
2094 exception
2095 when Constraint_Error =>
2096 Error_Msg
2097 (Project,
2098 In_Tree,
2099 "invalid value """
2100 & Get_Name_String (Attribute.Value.Value)
2101 & """ for Symbolic_Link_Supported",
2102 Attribute.Value.Location);
2103 end;
2105 elsif
2106 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2107 then
2108 declare
2109 pragma Unsuppress (All_Checks);
2110 begin
2111 Data.Config.Lib_Maj_Min_Id_Supported :=
2112 Boolean'Value (Get_Name_String
2113 (Attribute.Value.Value));
2114 exception
2115 when Constraint_Error =>
2116 Error_Msg
2117 (Project,
2118 In_Tree,
2119 "invalid value """ &
2120 Get_Name_String (Attribute.Value.Value) &
2121 """ for Library_Major_Minor_Id_Supported",
2122 Attribute.Value.Location);
2123 end;
2125 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2126 declare
2127 pragma Unsuppress (All_Checks);
2128 begin
2129 Data.Config.Auto_Init_Supported :=
2130 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2131 exception
2132 when Constraint_Error =>
2133 Error_Msg
2134 (Project,
2135 In_Tree,
2136 "invalid value """
2137 & Get_Name_String (Attribute.Value.Value)
2138 & """ for Library_Auto_Init_Supported",
2139 Attribute.Value.Location);
2140 end;
2142 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2143 List := Attribute.Value.Values;
2145 if List /= Nil_String then
2146 Put (Into_List => Data.Config.Shared_Lib_Min_Options,
2147 From_List => List,
2148 In_Tree => In_Tree);
2149 end if;
2151 elsif Attribute.Name = Name_Library_Version_Switches then
2152 List := Attribute.Value.Values;
2154 if List /= Nil_String then
2155 Put (Into_List => Data.Config.Lib_Version_Options,
2156 From_List => List,
2157 In_Tree => In_Tree);
2158 end if;
2159 end if;
2160 end if;
2162 Attribute_Id := Attribute.Next;
2163 end loop;
2164 end Process_Project_Level_Simple_Attributes;
2166 --------------------------------------------
2167 -- Process_Project_Level_Array_Attributes --
2168 --------------------------------------------
2170 procedure Process_Project_Level_Array_Attributes is
2171 Current_Array_Id : Array_Id;
2172 Current_Array : Array_Data;
2173 Element_Id : Array_Element_Id;
2174 Element : Array_Element;
2175 List : String_List_Id;
2177 begin
2178 -- Process the associative array attributes at project level
2180 Current_Array_Id := Data.Decl.Arrays;
2181 while Current_Array_Id /= No_Array loop
2182 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2184 Element_Id := Current_Array.Value;
2185 while Element_Id /= No_Array_Element loop
2186 Element := In_Tree.Array_Elements.Table (Element_Id);
2188 -- Get the name of the language
2190 Get_Language_Index_Of (Element.Index);
2192 if Lang_Index /= No_Language_Index then
2193 case Current_Array.Name is
2194 when Name_Inherit_Source_Path =>
2195 List := Element.Value.Values;
2197 if List /= Nil_String then
2199 (Into_List =>
2200 In_Tree.Languages_Data.Table (Lang_Index).
2201 Config.Include_Compatible_Languages,
2202 From_List => List,
2203 In_Tree => In_Tree,
2204 Lower_Case => True);
2205 end if;
2207 when Name_Toolchain_Description =>
2209 -- Attribute Toolchain_Description (<language>)
2211 In_Tree.Languages_Data.Table
2212 (Lang_Index).Config.Toolchain_Description :=
2213 Element.Value.Value;
2215 when Name_Toolchain_Version =>
2217 -- Attribute Toolchain_Version (<language>)
2219 In_Tree.Languages_Data.Table
2220 (Lang_Index).Config.Toolchain_Version :=
2221 Element.Value.Value;
2223 when Name_Runtime_Library_Dir =>
2225 -- Attribute Runtime_Library_Dir (<language>)
2227 In_Tree.Languages_Data.Table
2228 (Lang_Index).Config.Runtime_Library_Dir :=
2229 Element.Value.Value;
2231 when Name_Object_Generated =>
2232 declare
2233 pragma Unsuppress (All_Checks);
2234 Value : Boolean;
2236 begin
2237 Value :=
2238 Boolean'Value
2239 (Get_Name_String (Element.Value.Value));
2241 In_Tree.Languages_Data.Table
2242 (Lang_Index).Config.Object_Generated := Value;
2244 -- If no object is generated, no object may be
2245 -- linked.
2247 if not Value then
2248 In_Tree.Languages_Data.Table
2249 (Lang_Index).Config.Objects_Linked := False;
2250 end if;
2252 exception
2253 when Constraint_Error =>
2254 Error_Msg
2255 (Project,
2256 In_Tree,
2257 "invalid value """
2258 & Get_Name_String (Element.Value.Value)
2259 & """ for Object_Generated",
2260 Element.Value.Location);
2261 end;
2263 when Name_Objects_Linked =>
2264 declare
2265 pragma Unsuppress (All_Checks);
2266 Value : Boolean;
2268 begin
2269 Value :=
2270 Boolean'Value
2271 (Get_Name_String (Element.Value.Value));
2273 -- No change if Object_Generated is False, as this
2274 -- forces Objects_Linked to be False too.
2276 if In_Tree.Languages_Data.Table
2277 (Lang_Index).Config.Object_Generated
2278 then
2279 In_Tree.Languages_Data.Table
2280 (Lang_Index).Config.Objects_Linked :=
2281 Value;
2282 end if;
2284 exception
2285 when Constraint_Error =>
2286 Error_Msg
2287 (Project,
2288 In_Tree,
2289 "invalid value """
2290 & Get_Name_String (Element.Value.Value)
2291 & """ for Objects_Linked",
2292 Element.Value.Location);
2293 end;
2294 when others =>
2295 null;
2296 end case;
2297 end if;
2299 Element_Id := Element.Next;
2300 end loop;
2302 Current_Array_Id := Current_Array.Next;
2303 end loop;
2304 end Process_Project_Level_Array_Attributes;
2306 begin
2307 Process_Project_Level_Simple_Attributes;
2308 Process_Project_Level_Array_Attributes;
2309 Process_Packages;
2311 -- For unit based languages, set Casing, Dot_Replacement and
2312 -- Separate_Suffix in Naming_Data.
2314 Lang_Index := Data.First_Language_Processing;
2315 while Lang_Index /= No_Language_Index loop
2316 if In_Tree.Languages_Data.Table
2317 (Lang_Index).Name = Name_Ada
2318 then
2319 In_Tree.Languages_Data.Table
2320 (Lang_Index).Config.Naming_Data.Casing := Casing;
2321 In_Tree.Languages_Data.Table
2322 (Lang_Index).Config.Naming_Data.Dot_Replacement :=
2323 Dot_Replacement;
2325 if Separate_Suffix /= No_File then
2326 In_Tree.Languages_Data.Table
2327 (Lang_Index).Config.Naming_Data.Separate_Suffix :=
2328 Separate_Suffix;
2329 end if;
2331 exit;
2332 end if;
2334 Lang_Index := In_Tree.Languages_Data.Table (Lang_Index).Next;
2335 end loop;
2337 -- Give empty names to various prefixes/suffixes, if they have not
2338 -- been specified in the configuration.
2340 if Data.Config.Archive_Suffix = No_File then
2341 Data.Config.Archive_Suffix := Empty_File;
2342 end if;
2344 if Data.Config.Shared_Lib_Prefix = No_File then
2345 Data.Config.Shared_Lib_Prefix := Empty_File;
2346 end if;
2348 if Data.Config.Shared_Lib_Suffix = No_File then
2349 Data.Config.Shared_Lib_Suffix := Empty_File;
2350 end if;
2352 Lang_Index := Data.First_Language_Processing;
2353 while Lang_Index /= No_Language_Index loop
2354 Lang_Data := In_Tree.Languages_Data.Table (Lang_Index);
2356 Current_Language := Lang_Data.Display_Name;
2358 -- For all languages, Compiler_Driver needs to be specified
2360 if Lang_Data.Config.Compiler_Driver = No_File then
2361 Error_Msg_Name_1 := Current_Language;
2362 Error_Msg
2363 (Project,
2364 In_Tree,
2365 "?no compiler specified for language %%" &
2366 ", ignoring all its sources",
2367 No_Location);
2369 if Lang_Index = Data.First_Language_Processing then
2370 Data.First_Language_Processing :=
2371 Lang_Data.Next;
2372 else
2373 In_Tree.Languages_Data.Table (Prev_Index).Next :=
2374 Lang_Data.Next;
2375 end if;
2377 elsif Lang_Data.Name = Name_Ada then
2378 Prev_Index := Lang_Index;
2380 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2381 -- Body_Suffix need to be specified.
2383 if Lang_Data.Config.Naming_Data.Dot_Replacement = No_File then
2384 Error_Msg
2385 (Project,
2386 In_Tree,
2387 "Dot_Replacement not specified for Ada",
2388 No_Location);
2389 end if;
2391 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File then
2392 Error_Msg
2393 (Project,
2394 In_Tree,
2395 "Spec_Suffix not specified for Ada",
2396 No_Location);
2397 end if;
2399 if Lang_Data.Config.Naming_Data.Body_Suffix = No_File then
2400 Error_Msg
2401 (Project,
2402 In_Tree,
2403 "Body_Suffix not specified for Ada",
2404 No_Location);
2405 end if;
2407 else
2408 Prev_Index := Lang_Index;
2410 -- For file based languages, either Spec_Suffix or Body_Suffix
2411 -- need to be specified.
2413 if Lang_Data.Config.Naming_Data.Spec_Suffix = No_File and then
2414 Lang_Data.Config.Naming_Data.Body_Suffix = No_File
2415 then
2416 Error_Msg_Name_1 := Current_Language;
2417 Error_Msg
2418 (Project,
2419 In_Tree,
2420 "no suffixes specified for %%",
2421 No_Location);
2422 end if;
2423 end if;
2425 Lang_Index := Lang_Data.Next;
2426 end loop;
2427 end Check_Configuration;
2429 -------------------------------
2430 -- Check_If_Externally_Built --
2431 -------------------------------
2433 procedure Check_If_Externally_Built
2434 (Project : Project_Id;
2435 In_Tree : Project_Tree_Ref;
2436 Data : in out Project_Data)
2438 Externally_Built : constant Variable_Value :=
2439 Util.Value_Of
2440 (Name_Externally_Built,
2441 Data.Decl.Attributes, In_Tree);
2443 begin
2444 if not Externally_Built.Default then
2445 Get_Name_String (Externally_Built.Value);
2446 To_Lower (Name_Buffer (1 .. Name_Len));
2448 if Name_Buffer (1 .. Name_Len) = "true" then
2449 Data.Externally_Built := True;
2451 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2452 Error_Msg (Project, In_Tree,
2453 "Externally_Built may only be true or false",
2454 Externally_Built.Location);
2455 end if;
2456 end if;
2458 -- A virtual project extending an externally built project is itself
2459 -- externally built.
2461 if Data.Virtual and then Data.Extends /= No_Project then
2462 Data.Externally_Built :=
2463 In_Tree.Projects.Table (Data.Extends).Externally_Built;
2464 end if;
2466 if Current_Verbosity = High then
2467 Write_Str ("Project is ");
2469 if not Data.Externally_Built then
2470 Write_Str ("not ");
2471 end if;
2473 Write_Line ("externally built.");
2474 end if;
2475 end Check_If_Externally_Built;
2477 ----------------------
2478 -- Check_Interfaces --
2479 ----------------------
2481 procedure Check_Interfaces
2482 (Project : Project_Id;
2483 In_Tree : Project_Tree_Ref;
2484 Data : in out Project_Data)
2486 Interfaces : constant Prj.Variable_Value :=
2487 Prj.Util.Value_Of
2488 (Snames.Name_Interfaces,
2489 Data.Decl.Attributes,
2490 In_Tree);
2492 List : String_List_Id;
2493 Element : String_Element;
2494 Name : File_Name_Type;
2496 Source : Source_Id;
2497 Src_Data : Source_Data;
2499 Project_2 : Project_Id;
2500 Data_2 : Project_Data;
2502 begin
2503 if not Interfaces.Default then
2505 -- Set In_Interfaces to False for all sources. It will be set to True
2506 -- later for the sources in the Interfaces list.
2508 Project_2 := Project;
2509 Data_2 := Data;
2510 loop
2511 Source := Data_2.First_Source;
2512 while Source /= No_Source loop
2513 Src_Data := In_Tree.Sources.Table (Source);
2514 Src_Data.In_Interfaces := False;
2515 In_Tree.Sources.Table (Source) := Src_Data;
2516 Source := Src_Data.Next_In_Project;
2517 end loop;
2519 Project_2 := Data_2.Extends;
2521 exit when Project_2 = No_Project;
2523 Data_2 := In_Tree.Projects.Table (Project_2);
2524 end loop;
2526 List := Interfaces.Values;
2527 while List /= Nil_String loop
2528 Element := In_Tree.String_Elements.Table (List);
2529 Get_Name_String (Element.Value);
2530 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2531 Name := Name_Find;
2533 Project_2 := Project;
2534 Data_2 := Data;
2535 Big_Loop :
2536 loop
2537 Source := Data_2.First_Source;
2538 while Source /= No_Source loop
2539 Src_Data := In_Tree.Sources.Table (Source);
2540 if Src_Data.File = Name then
2541 if not Src_Data.Locally_Removed then
2542 In_Tree.Sources.Table (Source).In_Interfaces := True;
2543 In_Tree.Sources.Table
2544 (Source).Declared_In_Interfaces := True;
2546 if Src_Data.Other_Part /= No_Source then
2547 In_Tree.Sources.Table
2548 (Src_Data.Other_Part).In_Interfaces := True;
2549 In_Tree.Sources.Table
2550 (Src_Data.Other_Part).Declared_In_Interfaces :=
2551 True;
2552 end if;
2554 if Current_Verbosity = High then
2555 Write_Str (" interface: ");
2556 Write_Line (Get_Name_String (Src_Data.Path.Name));
2557 end if;
2558 end if;
2560 exit Big_Loop;
2561 end if;
2563 Source := Src_Data.Next_In_Project;
2564 end loop;
2566 Project_2 := Data_2.Extends;
2568 exit Big_Loop when Project_2 = No_Project;
2570 Data_2 := In_Tree.Projects.Table (Project_2);
2571 end loop Big_Loop;
2573 if Source = No_Source then
2574 Error_Msg_File_1 := File_Name_Type (Element.Value);
2575 Error_Msg_Name_1 := Data.Name;
2577 Error_Msg
2578 (Project,
2579 In_Tree,
2580 "{ cannot be an interface of project %% " &
2581 "as it is not one of its sources",
2582 Element.Location);
2583 end if;
2585 List := Element.Next;
2586 end loop;
2588 Data.Interfaces_Defined := True;
2590 elsif Data.Extends /= No_Project then
2591 Data.Interfaces_Defined :=
2592 In_Tree.Projects.Table (Data.Extends).Interfaces_Defined;
2594 if Data.Interfaces_Defined then
2595 Source := Data.First_Source;
2596 while Source /= No_Source loop
2597 Src_Data := In_Tree.Sources.Table (Source);
2599 if not Src_Data.Declared_In_Interfaces then
2600 Src_Data.In_Interfaces := False;
2601 In_Tree.Sources.Table (Source) := Src_Data;
2602 end if;
2604 Source := Src_Data.Next_In_Project;
2605 end loop;
2606 end if;
2607 end if;
2608 end Check_Interfaces;
2610 --------------------------
2611 -- Check_Naming_Schemes --
2612 --------------------------
2614 procedure Check_Naming_Schemes
2615 (Data : in out Project_Data;
2616 Project : Project_Id;
2617 In_Tree : Project_Tree_Ref)
2619 Naming_Id : constant Package_Id :=
2620 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
2621 Naming : Package_Element;
2623 procedure Check_Unit_Names (List : Array_Element_Id);
2624 -- Check that a list of unit names contains only valid names
2626 procedure Get_Exceptions (Kind : Source_Kind);
2628 procedure Get_Unit_Exceptions (Kind : Source_Kind);
2630 ----------------------
2631 -- Check_Unit_Names --
2632 ----------------------
2634 procedure Check_Unit_Names (List : Array_Element_Id) is
2635 Current : Array_Element_Id;
2636 Element : Array_Element;
2637 Unit_Name : Name_Id;
2639 begin
2640 -- Loop through elements of the string list
2642 Current := List;
2643 while Current /= No_Array_Element loop
2644 Element := In_Tree.Array_Elements.Table (Current);
2646 -- Put file name in canonical case
2648 if not Osint.File_Names_Case_Sensitive then
2649 Get_Name_String (Element.Value.Value);
2650 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2651 Element.Value.Value := Name_Find;
2652 end if;
2654 -- Check that it contains a valid unit name
2656 Get_Name_String (Element.Index);
2657 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2659 if Unit_Name = No_Name then
2660 Err_Vars.Error_Msg_Name_1 := Element.Index;
2661 Error_Msg
2662 (Project, In_Tree,
2663 "%% is not a valid unit name.",
2664 Element.Value.Location);
2666 else
2667 if Current_Verbosity = High then
2668 Write_Str (" Unit (""");
2669 Write_Str (Get_Name_String (Unit_Name));
2670 Write_Line (""")");
2671 end if;
2673 Element.Index := Unit_Name;
2674 In_Tree.Array_Elements.Table (Current) := Element;
2675 end if;
2677 Current := Element.Next;
2678 end loop;
2679 end Check_Unit_Names;
2681 --------------------
2682 -- Get_Exceptions --
2683 --------------------
2685 procedure Get_Exceptions (Kind : Source_Kind) is
2686 Exceptions : Array_Element_Id;
2687 Exception_List : Variable_Value;
2688 Element_Id : String_List_Id;
2689 Element : String_Element;
2690 File_Name : File_Name_Type;
2691 Lang_Id : Language_Index;
2692 Lang : Name_Id;
2693 Lang_Kind : Language_Kind;
2694 Source : Source_Id;
2696 begin
2697 if Kind = Impl then
2698 Exceptions :=
2699 Value_Of
2700 (Name_Implementation_Exceptions,
2701 In_Arrays => Naming.Decl.Arrays,
2702 In_Tree => In_Tree);
2704 else
2705 Exceptions :=
2706 Value_Of
2707 (Name_Specification_Exceptions,
2708 In_Arrays => Naming.Decl.Arrays,
2709 In_Tree => In_Tree);
2710 end if;
2712 Lang_Id := Data.First_Language_Processing;
2713 while Lang_Id /= No_Language_Index loop
2714 if In_Tree.Languages_Data.Table (Lang_Id).Config.Kind =
2715 File_Based
2716 then
2717 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
2718 Lang_Kind :=
2719 In_Tree.Languages_Data.Table (Lang_Id).Config.Kind;
2721 Exception_List := Value_Of
2722 (Index => Lang,
2723 In_Array => Exceptions,
2724 In_Tree => In_Tree);
2726 if Exception_List /= Nil_Variable_Value then
2727 Element_Id := Exception_List.Values;
2728 while Element_Id /= Nil_String loop
2729 Element := In_Tree.String_Elements.Table (Element_Id);
2731 if Osint.File_Names_Case_Sensitive then
2732 File_Name := File_Name_Type (Element.Value);
2733 else
2734 Get_Name_String (Element.Value);
2735 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2736 File_Name := Name_Find;
2737 end if;
2739 Source := Data.First_Source;
2740 while Source /= No_Source
2741 and then
2742 In_Tree.Sources.Table (Source).File /= File_Name
2743 loop
2744 Source :=
2745 In_Tree.Sources.Table (Source).Next_In_Project;
2746 end loop;
2748 if Source = No_Source then
2749 Add_Source
2750 (Id => Source,
2751 Data => Data,
2752 In_Tree => In_Tree,
2753 Project => Project,
2754 Lang => Lang,
2755 Lang_Id => Lang_Id,
2756 Kind => Kind,
2757 File_Name => File_Name,
2758 Display_File => File_Name_Type (Element.Value),
2759 Naming_Exception => True,
2760 Lang_Kind => Lang_Kind);
2762 else
2763 -- Check if the file name is already recorded for
2764 -- another language or another kind.
2767 In_Tree.Sources.Table (Source).Language /= Lang_Id
2768 then
2769 Error_Msg
2770 (Project,
2771 In_Tree,
2772 "the same file cannot be a source " &
2773 "of two languages",
2774 Element.Location);
2776 elsif In_Tree.Sources.Table (Source).Kind /= Kind then
2777 Error_Msg
2778 (Project,
2779 In_Tree,
2780 "the same file cannot be a source " &
2781 "and a template",
2782 Element.Location);
2783 end if;
2785 -- If the file is already recorded for the same
2786 -- language and the same kind, it means that the file
2787 -- name appears several times in the *_Exceptions
2788 -- attribute; so there is nothing to do.
2790 end if;
2792 Element_Id := Element.Next;
2793 end loop;
2794 end if;
2795 end if;
2797 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
2798 end loop;
2799 end Get_Exceptions;
2801 -------------------------
2802 -- Get_Unit_Exceptions --
2803 -------------------------
2805 procedure Get_Unit_Exceptions (Kind : Source_Kind) is
2806 Exceptions : Array_Element_Id;
2807 Element : Array_Element;
2808 Unit : Name_Id;
2809 Index : Int;
2810 File_Name : File_Name_Type;
2811 Lang_Id : constant Language_Index :=
2812 Data.Unit_Based_Language_Index;
2813 Lang : constant Name_Id :=
2814 Data.Unit_Based_Language_Name;
2816 Source : Source_Id;
2817 Source_To_Replace : Source_Id := No_Source;
2819 Other_Project : Project_Id;
2820 Other_Part : Source_Id := No_Source;
2822 begin
2823 if Lang_Id = No_Language_Index or else Lang = No_Name then
2824 return;
2825 end if;
2827 if Kind = Impl then
2828 Exceptions := Value_Of
2829 (Name_Body,
2830 In_Arrays => Naming.Decl.Arrays,
2831 In_Tree => In_Tree);
2833 if Exceptions = No_Array_Element then
2834 Exceptions :=
2835 Value_Of
2836 (Name_Implementation,
2837 In_Arrays => Naming.Decl.Arrays,
2838 In_Tree => In_Tree);
2839 end if;
2841 else
2842 Exceptions :=
2843 Value_Of
2844 (Name_Spec,
2845 In_Arrays => Naming.Decl.Arrays,
2846 In_Tree => In_Tree);
2848 if Exceptions = No_Array_Element then
2849 Exceptions := Value_Of
2850 (Name_Specification,
2851 In_Arrays => Naming.Decl.Arrays,
2852 In_Tree => In_Tree);
2853 end if;
2855 end if;
2857 while Exceptions /= No_Array_Element loop
2858 Element := In_Tree.Array_Elements.Table (Exceptions);
2860 if Osint.File_Names_Case_Sensitive then
2861 File_Name := File_Name_Type (Element.Value.Value);
2862 else
2863 Get_Name_String (Element.Value.Value);
2864 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2865 File_Name := Name_Find;
2866 end if;
2868 Get_Name_String (Element.Index);
2869 To_Lower (Name_Buffer (1 .. Name_Len));
2870 Unit := Name_Find;
2872 Index := Element.Value.Index;
2874 -- For Ada, check if it is a valid unit name
2876 if Lang = Name_Ada then
2877 Get_Name_String (Element.Index);
2878 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2880 if Unit = No_Name then
2881 Err_Vars.Error_Msg_Name_1 := Element.Index;
2882 Error_Msg
2883 (Project, In_Tree,
2884 "%% is not a valid unit name.",
2885 Element.Value.Location);
2886 end if;
2887 end if;
2889 if Unit /= No_Name then
2891 -- Check if the source already exists
2893 Source := In_Tree.First_Source;
2894 Source_To_Replace := No_Source;
2896 while Source /= No_Source and then
2897 (In_Tree.Sources.Table (Source).Unit /= Unit or else
2898 In_Tree.Sources.Table (Source).Index /= Index)
2899 loop
2900 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
2901 end loop;
2903 if Source /= No_Source then
2904 if In_Tree.Sources.Table (Source).Kind /= Kind then
2905 Other_Part := Source;
2907 loop
2908 Source :=
2909 In_Tree.Sources.Table (Source).Next_In_Sources;
2911 exit when Source = No_Source or else
2912 (In_Tree.Sources.Table (Source).Unit = Unit
2913 and then
2914 In_Tree.Sources.Table (Source).Index = Index);
2915 end loop;
2916 end if;
2918 if Source /= No_Source then
2919 Other_Project := In_Tree.Sources.Table (Source).Project;
2921 if Is_Extending (Project, Other_Project, In_Tree) then
2922 Other_Part :=
2923 In_Tree.Sources.Table (Source).Other_Part;
2925 -- Record the source to be removed
2927 Source_To_Replace := Source;
2928 Source := No_Source;
2930 else
2931 Error_Msg_Name_1 := Unit;
2932 Error_Msg_Name_2 :=
2933 In_Tree.Projects.Table (Other_Project).Name;
2934 Error_Msg
2935 (Project,
2936 In_Tree,
2937 "%% is already a source of project %%",
2938 Element.Value.Location);
2939 end if;
2940 end if;
2941 end if;
2943 if Source = No_Source then
2944 Add_Source
2945 (Id => Source,
2946 Data => Data,
2947 In_Tree => In_Tree,
2948 Project => Project,
2949 Lang => Lang,
2950 Lang_Id => Lang_Id,
2951 Kind => Kind,
2952 File_Name => File_Name,
2953 Display_File => File_Name_Type (Element.Value.Value),
2954 Lang_Kind => Unit_Based,
2955 Other_Part => Other_Part,
2956 Unit => Unit,
2957 Index => Index,
2958 Naming_Exception => True,
2959 Source_To_Replace => Source_To_Replace);
2960 end if;
2961 end if;
2963 Exceptions := Element.Next;
2964 end loop;
2966 end Get_Unit_Exceptions;
2968 -- Start of processing for Check_Naming_Schemes
2970 begin
2971 if Get_Mode = Ada_Only then
2973 -- If there is a package Naming, we will put in Data.Naming what is
2974 -- in this package Naming.
2976 if Naming_Id /= No_Package then
2977 Naming := In_Tree.Packages.Table (Naming_Id);
2979 if Current_Verbosity = High then
2980 Write_Line ("Checking ""Naming"" for Ada.");
2981 end if;
2983 declare
2984 Bodies : constant Array_Element_Id :=
2985 Util.Value_Of
2986 (Name_Body, Naming.Decl.Arrays, In_Tree);
2988 Specs : constant Array_Element_Id :=
2989 Util.Value_Of
2990 (Name_Spec, Naming.Decl.Arrays, In_Tree);
2992 begin
2993 if Bodies /= No_Array_Element then
2995 -- We have elements in the array Body_Part
2997 if Current_Verbosity = High then
2998 Write_Line ("Found Bodies.");
2999 end if;
3001 Data.Naming.Bodies := Bodies;
3002 Check_Unit_Names (Bodies);
3004 else
3005 if Current_Verbosity = High then
3006 Write_Line ("No Bodies.");
3007 end if;
3008 end if;
3010 if Specs /= No_Array_Element then
3012 -- We have elements in the array Specs
3014 if Current_Verbosity = High then
3015 Write_Line ("Found Specs.");
3016 end if;
3018 Data.Naming.Specs := Specs;
3019 Check_Unit_Names (Specs);
3021 else
3022 if Current_Verbosity = High then
3023 Write_Line ("No Specs.");
3024 end if;
3025 end if;
3026 end;
3028 -- We are now checking if variables Dot_Replacement, Casing,
3029 -- Spec_Suffix, Body_Suffix and/or Separate_Suffix exist.
3031 -- For each variable, if it does not exist, we do nothing,
3032 -- because we already have the default.
3034 -- Check Dot_Replacement
3036 declare
3037 Dot_Replacement : constant Variable_Value :=
3038 Util.Value_Of
3039 (Name_Dot_Replacement,
3040 Naming.Decl.Attributes, In_Tree);
3042 begin
3043 pragma Assert (Dot_Replacement.Kind = Single,
3044 "Dot_Replacement is not a single string");
3046 if not Dot_Replacement.Default then
3047 Get_Name_String (Dot_Replacement.Value);
3049 if Name_Len = 0 then
3050 Error_Msg
3051 (Project, In_Tree,
3052 "Dot_Replacement cannot be empty",
3053 Dot_Replacement.Location);
3055 else
3056 if Osint.File_Names_Case_Sensitive then
3057 Data.Naming.Dot_Replacement :=
3058 File_Name_Type (Dot_Replacement.Value);
3059 else
3060 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3061 Data.Naming.Dot_Replacement := Name_Find;
3062 end if;
3063 Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
3064 end if;
3065 end if;
3066 end;
3068 if Current_Verbosity = High then
3069 Write_Str (" Dot_Replacement = """);
3070 Write_Str (Get_Name_String (Data.Naming.Dot_Replacement));
3071 Write_Char ('"');
3072 Write_Eol;
3073 end if;
3075 -- Check Casing
3077 declare
3078 Casing_String : constant Variable_Value :=
3079 Util.Value_Of
3080 (Name_Casing,
3081 Naming.Decl.Attributes,
3082 In_Tree);
3084 begin
3085 pragma Assert (Casing_String.Kind = Single,
3086 "Casing is not a single string");
3088 if not Casing_String.Default then
3089 declare
3090 Casing_Image : constant String :=
3091 Get_Name_String (Casing_String.Value);
3092 begin
3093 declare
3094 Casing_Value : constant Casing_Type :=
3095 Value (Casing_Image);
3096 begin
3097 Data.Naming.Casing := Casing_Value;
3098 end;
3100 exception
3101 when Constraint_Error =>
3102 if Casing_Image'Length = 0 then
3103 Error_Msg
3104 (Project, In_Tree,
3105 "Casing cannot be an empty string",
3106 Casing_String.Location);
3108 else
3109 Name_Len := Casing_Image'Length;
3110 Name_Buffer (1 .. Name_Len) := Casing_Image;
3111 Err_Vars.Error_Msg_Name_1 := Name_Find;
3112 Error_Msg
3113 (Project, In_Tree,
3114 "%% is not a correct Casing",
3115 Casing_String.Location);
3116 end if;
3117 end;
3118 end if;
3119 end;
3121 if Current_Verbosity = High then
3122 Write_Str (" Casing = ");
3123 Write_Str (Image (Data.Naming.Casing));
3124 Write_Char ('.');
3125 Write_Eol;
3126 end if;
3128 -- Check Spec_Suffix
3130 declare
3131 Ada_Spec_Suffix : constant Variable_Value :=
3132 Prj.Util.Value_Of
3133 (Index => Name_Ada,
3134 Src_Index => 0,
3135 In_Array => Data.Naming.Spec_Suffix,
3136 In_Tree => In_Tree);
3138 begin
3139 if Ada_Spec_Suffix.Kind = Single
3140 and then Get_Name_String (Ada_Spec_Suffix.Value) /= ""
3141 then
3142 Get_Name_String (Ada_Spec_Suffix.Value);
3143 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3144 Set_Spec_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3145 Data.Naming.Ada_Spec_Suffix_Loc := Ada_Spec_Suffix.Location;
3147 else
3148 Set_Spec_Suffix
3149 (In_Tree,
3150 "ada",
3151 Data.Naming,
3152 Default_Ada_Spec_Suffix);
3153 end if;
3154 end;
3156 if Current_Verbosity = High then
3157 Write_Str (" Spec_Suffix = """);
3158 Write_Str (Spec_Suffix_Of (In_Tree, "ada", Data.Naming));
3159 Write_Char ('"');
3160 Write_Eol;
3161 end if;
3163 -- Check Body_Suffix
3165 declare
3166 Ada_Body_Suffix : constant Variable_Value :=
3167 Prj.Util.Value_Of
3168 (Index => Name_Ada,
3169 Src_Index => 0,
3170 In_Array => Data.Naming.Body_Suffix,
3171 In_Tree => In_Tree);
3173 begin
3174 if Ada_Body_Suffix.Kind = Single
3175 and then Get_Name_String (Ada_Body_Suffix.Value) /= ""
3176 then
3177 Get_Name_String (Ada_Body_Suffix.Value);
3178 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3179 Set_Body_Suffix (In_Tree, "ada", Data.Naming, Name_Find);
3180 Data.Naming.Ada_Body_Suffix_Loc := Ada_Body_Suffix.Location;
3182 else
3183 Set_Body_Suffix
3184 (In_Tree,
3185 "ada",
3186 Data.Naming,
3187 Default_Ada_Body_Suffix);
3188 end if;
3189 end;
3191 if Current_Verbosity = High then
3192 Write_Str (" Body_Suffix = """);
3193 Write_Str (Body_Suffix_Of (In_Tree, "ada", Data.Naming));
3194 Write_Char ('"');
3195 Write_Eol;
3196 end if;
3198 -- Check Separate_Suffix
3200 declare
3201 Ada_Sep_Suffix : constant Variable_Value :=
3202 Prj.Util.Value_Of
3203 (Variable_Name => Name_Separate_Suffix,
3204 In_Variables => Naming.Decl.Attributes,
3205 In_Tree => In_Tree);
3207 begin
3208 if Ada_Sep_Suffix.Default then
3209 Data.Naming.Separate_Suffix :=
3210 Body_Suffix_Id_Of (In_Tree, Name_Ada, Data.Naming);
3212 else
3213 Get_Name_String (Ada_Sep_Suffix.Value);
3215 if Name_Len = 0 then
3216 Error_Msg
3217 (Project, In_Tree,
3218 "Separate_Suffix cannot be empty",
3219 Ada_Sep_Suffix.Location);
3221 else
3222 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3223 Data.Naming.Separate_Suffix := Name_Find;
3224 Data.Naming.Sep_Suffix_Loc := Ada_Sep_Suffix.Location;
3225 end if;
3226 end if;
3227 end;
3229 if Current_Verbosity = High then
3230 Write_Str (" Separate_Suffix = """);
3231 Write_Str (Get_Name_String (Data.Naming.Separate_Suffix));
3232 Write_Char ('"');
3233 Write_Eol;
3234 end if;
3236 -- Check if Data.Naming is valid
3238 Check_Ada_Naming_Scheme_Validity (Project, In_Tree, Data.Naming);
3239 end if;
3241 elsif not In_Configuration then
3243 -- Look into package Naming, if there is one
3245 if Naming_Id /= No_Package then
3246 Naming := In_Tree.Packages.Table (Naming_Id);
3248 if Current_Verbosity = High then
3249 Write_Line ("Checking package Naming.");
3250 end if;
3252 -- We are now checking if attribute Dot_Replacement, Casing,
3253 -- and/or Separate_Suffix exist.
3255 -- For each attribute, if it does not exist, we do nothing,
3256 -- because we already have the default.
3257 -- Otherwise, for all unit-based languages, we put the declared
3258 -- value in the language config.
3260 declare
3261 Dot_Repl : constant Variable_Value :=
3262 Util.Value_Of
3263 (Name_Dot_Replacement,
3264 Naming.Decl.Attributes, In_Tree);
3265 Dot_Replacement : File_Name_Type := No_File;
3267 Casing_String : constant Variable_Value :=
3268 Util.Value_Of
3269 (Name_Casing,
3270 Naming.Decl.Attributes,
3271 In_Tree);
3272 Casing : Casing_Type;
3273 Casing_Defined : Boolean := False;
3275 Sep_Suffix : constant Variable_Value :=
3276 Prj.Util.Value_Of
3277 (Variable_Name => Name_Separate_Suffix,
3278 In_Variables => Naming.Decl.Attributes,
3279 In_Tree => In_Tree);
3280 Separate_Suffix : File_Name_Type := No_File;
3282 Lang_Id : Language_Index;
3283 begin
3284 -- Check attribute Dot_Replacement
3286 if not Dot_Repl.Default then
3287 Get_Name_String (Dot_Repl.Value);
3289 if Name_Len = 0 then
3290 Error_Msg
3291 (Project, In_Tree,
3292 "Dot_Replacement cannot be empty",
3293 Dot_Repl.Location);
3295 else
3296 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3297 Dot_Replacement := Name_Find;
3299 if Current_Verbosity = High then
3300 Write_Str (" Dot_Replacement = """);
3301 Write_Str (Get_Name_String (Dot_Replacement));
3302 Write_Char ('"');
3303 Write_Eol;
3304 end if;
3305 end if;
3306 end if;
3308 -- Check attribute Casing
3310 if not Casing_String.Default then
3311 declare
3312 Casing_Image : constant String :=
3313 Get_Name_String (Casing_String.Value);
3314 begin
3315 declare
3316 Casing_Value : constant Casing_Type :=
3317 Value (Casing_Image);
3318 begin
3319 Casing := Casing_Value;
3320 Casing_Defined := True;
3322 if Current_Verbosity = High then
3323 Write_Str (" Casing = ");
3324 Write_Str (Image (Casing));
3325 Write_Char ('.');
3326 Write_Eol;
3327 end if;
3328 end;
3330 exception
3331 when Constraint_Error =>
3332 if Casing_Image'Length = 0 then
3333 Error_Msg
3334 (Project, In_Tree,
3335 "Casing cannot be an empty string",
3336 Casing_String.Location);
3338 else
3339 Name_Len := Casing_Image'Length;
3340 Name_Buffer (1 .. Name_Len) := Casing_Image;
3341 Err_Vars.Error_Msg_Name_1 := Name_Find;
3342 Error_Msg
3343 (Project, In_Tree,
3344 "%% is not a correct Casing",
3345 Casing_String.Location);
3346 end if;
3347 end;
3348 end if;
3350 if not Sep_Suffix.Default then
3351 Get_Name_String (Sep_Suffix.Value);
3353 if Name_Len = 0 then
3354 Error_Msg
3355 (Project, In_Tree,
3356 "Separate_Suffix cannot be empty",
3357 Sep_Suffix.Location);
3359 else
3360 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3361 Separate_Suffix := Name_Find;
3363 if Current_Verbosity = High then
3364 Write_Str (" Separate_Suffix = """);
3365 Write_Str (Get_Name_String (Separate_Suffix));
3366 Write_Char ('"');
3367 Write_Eol;
3368 end if;
3369 end if;
3370 end if;
3372 -- For all unit based languages, if any, set the specified
3373 -- value of Dot_Replacement, Casing and/or Separate_Suffix.
3375 if Dot_Replacement /= No_File
3376 or else Casing_Defined
3377 or else Separate_Suffix /= No_File
3378 then
3379 Lang_Id := Data.First_Language_Processing;
3380 while Lang_Id /= No_Language_Index loop
3381 if In_Tree.Languages_Data.Table
3382 (Lang_Id).Config.Kind = Unit_Based
3383 then
3384 if Dot_Replacement /= No_File then
3385 In_Tree.Languages_Data.Table
3386 (Lang_Id).Config.Naming_Data.Dot_Replacement :=
3387 Dot_Replacement;
3388 end if;
3390 if Casing_Defined then
3391 In_Tree.Languages_Data.Table
3392 (Lang_Id).Config.Naming_Data.Casing := Casing;
3393 end if;
3395 if Separate_Suffix /= No_File then
3396 In_Tree.Languages_Data.Table
3397 (Lang_Id).Config.Naming_Data.Separate_Suffix :=
3398 Separate_Suffix;
3399 end if;
3400 end if;
3402 Lang_Id :=
3403 In_Tree.Languages_Data.Table (Lang_Id).Next;
3404 end loop;
3405 end if;
3406 end;
3408 -- Next, get the spec and body suffixes
3410 declare
3411 Suffix : Variable_Value;
3412 Lang_Id : Language_Index;
3413 Lang : Name_Id;
3415 begin
3416 Lang_Id := Data.First_Language_Processing;
3417 while Lang_Id /= No_Language_Index loop
3418 Lang := In_Tree.Languages_Data.Table (Lang_Id).Name;
3420 -- Spec_Suffix
3422 Suffix := Value_Of
3423 (Name => Lang,
3424 Attribute_Or_Array_Name => Name_Spec_Suffix,
3425 In_Package => Naming_Id,
3426 In_Tree => In_Tree);
3428 if Suffix = Nil_Variable_Value then
3429 Suffix := Value_Of
3430 (Name => Lang,
3431 Attribute_Or_Array_Name => Name_Specification_Suffix,
3432 In_Package => Naming_Id,
3433 In_Tree => In_Tree);
3434 end if;
3436 if Suffix /= Nil_Variable_Value then
3437 In_Tree.Languages_Data.Table (Lang_Id).
3438 Config.Naming_Data.Spec_Suffix :=
3439 File_Name_Type (Suffix.Value);
3440 end if;
3442 -- Body_Suffix
3444 Suffix := Value_Of
3445 (Name => Lang,
3446 Attribute_Or_Array_Name => Name_Body_Suffix,
3447 In_Package => Naming_Id,
3448 In_Tree => In_Tree);
3450 if Suffix = Nil_Variable_Value then
3451 Suffix := Value_Of
3452 (Name => Lang,
3453 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3454 In_Package => Naming_Id,
3455 In_Tree => In_Tree);
3456 end if;
3458 if Suffix /= Nil_Variable_Value then
3459 In_Tree.Languages_Data.Table (Lang_Id).
3460 Config.Naming_Data.Body_Suffix :=
3461 File_Name_Type (Suffix.Value);
3462 end if;
3464 Lang_Id := In_Tree.Languages_Data.Table (Lang_Id).Next;
3465 end loop;
3466 end;
3468 -- Get the exceptions for file based languages
3470 Get_Exceptions (Spec);
3471 Get_Exceptions (Impl);
3473 -- Get the exceptions for unit based languages
3475 Get_Unit_Exceptions (Spec);
3476 Get_Unit_Exceptions (Impl);
3478 end if;
3479 end if;
3480 end Check_Naming_Schemes;
3482 ------------------------------
3483 -- Check_Library_Attributes --
3484 ------------------------------
3486 procedure Check_Library_Attributes
3487 (Project : Project_Id;
3488 In_Tree : Project_Tree_Ref;
3489 Current_Dir : String;
3490 Data : in out Project_Data)
3492 Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
3494 Lib_Dir : constant Prj.Variable_Value :=
3495 Prj.Util.Value_Of
3496 (Snames.Name_Library_Dir, Attributes, In_Tree);
3498 Lib_Name : constant Prj.Variable_Value :=
3499 Prj.Util.Value_Of
3500 (Snames.Name_Library_Name, Attributes, In_Tree);
3502 Lib_Version : constant Prj.Variable_Value :=
3503 Prj.Util.Value_Of
3504 (Snames.Name_Library_Version, Attributes, In_Tree);
3506 Lib_ALI_Dir : constant Prj.Variable_Value :=
3507 Prj.Util.Value_Of
3508 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3510 The_Lib_Kind : constant Prj.Variable_Value :=
3511 Prj.Util.Value_Of
3512 (Snames.Name_Library_Kind, Attributes, In_Tree);
3514 Imported_Project_List : Project_List := Empty_Project_List;
3516 Continuation : String_Access := No_Continuation_String'Access;
3518 Support_For_Libraries : Library_Support;
3520 Library_Directory_Present : Boolean;
3522 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3523 -- Check if an imported or extended project if also a library project
3525 -------------------
3526 -- Check_Library --
3527 -------------------
3529 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3530 Proj_Data : Project_Data;
3531 Src_Id : Source_Id;
3532 Src : Source_Data;
3534 begin
3535 if Proj /= No_Project then
3536 Proj_Data := In_Tree.Projects.Table (Proj);
3538 if not Proj_Data.Library then
3540 -- The only not library projects that are OK are those that
3541 -- have no sources. However, header files from non-Ada
3542 -- languages are OK, as there is nothing to compile.
3544 Src_Id := Proj_Data.First_Source;
3545 while Src_Id /= No_Source loop
3546 Src := In_Tree.Sources.Table (Src_Id);
3548 exit when Src.Lang_Kind /= File_Based
3549 or else Src.Kind /= Spec;
3551 Src_Id := Src.Next_In_Project;
3552 end loop;
3554 if Src_Id /= No_Source then
3555 Error_Msg_Name_1 := Data.Name;
3556 Error_Msg_Name_2 := Proj_Data.Name;
3558 if Extends then
3559 if Data.Library_Kind /= Static then
3560 Error_Msg
3561 (Project, In_Tree,
3562 Continuation.all &
3563 "shared library project %% cannot extend " &
3564 "project %% that is not a library project",
3565 Data.Location);
3566 Continuation := Continuation_String'Access;
3567 end if;
3569 elsif Data.Library_Kind /= Static then
3570 Error_Msg
3571 (Project, In_Tree,
3572 Continuation.all &
3573 "shared library project %% cannot import project %% " &
3574 "that is not a shared library project",
3575 Data.Location);
3576 Continuation := Continuation_String'Access;
3577 end if;
3578 end if;
3580 elsif Data.Library_Kind /= Static and then
3581 Proj_Data.Library_Kind = Static
3582 then
3583 Error_Msg_Name_1 := Data.Name;
3584 Error_Msg_Name_2 := Proj_Data.Name;
3586 if Extends then
3587 Error_Msg
3588 (Project, In_Tree,
3589 Continuation.all &
3590 "shared library project %% cannot extend static " &
3591 "library project %%",
3592 Data.Location);
3594 else
3595 Error_Msg
3596 (Project, In_Tree,
3597 Continuation.all &
3598 "shared library project %% cannot import static " &
3599 "library project %%",
3600 Data.Location);
3601 end if;
3603 Continuation := Continuation_String'Access;
3604 end if;
3605 end if;
3606 end Check_Library;
3608 -- Start of processing for Check_Library_Attributes
3610 begin
3611 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3613 -- Special case of extending project
3615 if Data.Extends /= No_Project then
3616 declare
3617 Extended_Data : constant Project_Data :=
3618 In_Tree.Projects.Table (Data.Extends);
3620 begin
3621 -- If the project extended is a library project, we inherit the
3622 -- library name, if it is not redefined; we check that the library
3623 -- directory is specified.
3625 if Extended_Data.Library then
3626 if Data.Qualifier = Standard then
3627 Error_Msg
3628 (Project, In_Tree,
3629 "a standard project cannot extend a library project",
3630 Data.Location);
3632 else
3633 if Lib_Name.Default then
3634 Data.Library_Name := Extended_Data.Library_Name;
3635 end if;
3637 if Lib_Dir.Default then
3638 if not Data.Virtual then
3639 Error_Msg
3640 (Project, In_Tree,
3641 "a project extending a library project must " &
3642 "specify an attribute Library_Dir",
3643 Data.Location);
3645 else
3646 -- For a virtual project extending a library project,
3647 -- inherit library directory.
3649 Data.Library_Dir := Extended_Data.Library_Dir;
3650 Library_Directory_Present := True;
3651 end if;
3652 end if;
3653 end if;
3654 end if;
3655 end;
3656 end if;
3658 pragma Assert (Lib_Name.Kind = Single);
3660 if Lib_Name.Value = Empty_String then
3661 if Current_Verbosity = High
3662 and then Data.Library_Name = No_Name
3663 then
3664 Write_Line ("No library name");
3665 end if;
3667 else
3668 -- There is no restriction on the syntax of library names
3670 Data.Library_Name := Lib_Name.Value;
3671 end if;
3673 if Data.Library_Name /= No_Name then
3674 if Current_Verbosity = High then
3675 Write_Str ("Library name = """);
3676 Write_Str (Get_Name_String (Data.Library_Name));
3677 Write_Line ("""");
3678 end if;
3680 pragma Assert (Lib_Dir.Kind = Single);
3682 if not Library_Directory_Present then
3683 if Current_Verbosity = High then
3684 Write_Line ("No library directory");
3685 end if;
3687 else
3688 -- Find path name (unless inherited), check that it is a directory
3690 if Data.Library_Dir = No_Path_Information then
3691 Locate_Directory
3692 (Project,
3693 In_Tree,
3694 File_Name_Type (Lib_Dir.Value),
3695 Data.Directory.Display_Name,
3696 Data.Library_Dir.Name,
3697 Data.Library_Dir.Display_Name,
3698 Create => "library",
3699 Current_Dir => Current_Dir,
3700 Location => Lib_Dir.Location);
3701 end if;
3703 if Data.Library_Dir = No_Path_Information then
3705 -- Get the absolute name of the library directory that
3706 -- does not exist, to report an error.
3708 declare
3709 Dir_Name : constant String :=
3710 Get_Name_String (Lib_Dir.Value);
3712 begin
3713 if Is_Absolute_Path (Dir_Name) then
3714 Err_Vars.Error_Msg_File_1 :=
3715 File_Name_Type (Lib_Dir.Value);
3717 else
3718 Get_Name_String (Data.Directory.Display_Name);
3720 if Name_Buffer (Name_Len) /= Directory_Separator then
3721 Name_Len := Name_Len + 1;
3722 Name_Buffer (Name_Len) := Directory_Separator;
3723 end if;
3725 Name_Buffer
3726 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3727 Dir_Name;
3728 Name_Len := Name_Len + Dir_Name'Length;
3729 Err_Vars.Error_Msg_File_1 := Name_Find;
3730 end if;
3732 -- Report the error
3734 Error_Msg
3735 (Project, In_Tree,
3736 "library directory { does not exist",
3737 Lib_Dir.Location);
3738 end;
3740 -- The library directory cannot be the same as the Object
3741 -- directory.
3743 elsif Data.Library_Dir.Name = Data.Object_Directory.Name then
3744 Error_Msg
3745 (Project, In_Tree,
3746 "library directory cannot be the same " &
3747 "as object directory",
3748 Lib_Dir.Location);
3749 Data.Library_Dir := No_Path_Information;
3751 else
3752 declare
3753 OK : Boolean := True;
3754 Dirs_Id : String_List_Id;
3755 Dir_Elem : String_Element;
3757 begin
3758 -- The library directory cannot be the same as a source
3759 -- directory of the current project.
3761 Dirs_Id := Data.Source_Dirs;
3762 while Dirs_Id /= Nil_String loop
3763 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3764 Dirs_Id := Dir_Elem.Next;
3767 Data.Library_Dir.Name = Path_Name_Type (Dir_Elem.Value)
3768 then
3769 Err_Vars.Error_Msg_File_1 :=
3770 File_Name_Type (Dir_Elem.Value);
3771 Error_Msg
3772 (Project, In_Tree,
3773 "library directory cannot be the same " &
3774 "as source directory {",
3775 Lib_Dir.Location);
3776 OK := False;
3777 exit;
3778 end if;
3779 end loop;
3781 if OK then
3783 -- The library directory cannot be the same as a source
3784 -- directory of another project either.
3786 Project_Loop :
3787 for Pid in 1 .. Project_Table.Last (In_Tree.Projects) loop
3788 if Pid /= Project then
3789 Dirs_Id := In_Tree.Projects.Table (Pid).Source_Dirs;
3791 Dir_Loop : while Dirs_Id /= Nil_String loop
3792 Dir_Elem :=
3793 In_Tree.String_Elements.Table (Dirs_Id);
3794 Dirs_Id := Dir_Elem.Next;
3796 if Data.Library_Dir.Name =
3797 Path_Name_Type (Dir_Elem.Value)
3798 then
3799 Err_Vars.Error_Msg_File_1 :=
3800 File_Name_Type (Dir_Elem.Value);
3801 Err_Vars.Error_Msg_Name_1 :=
3802 In_Tree.Projects.Table (Pid).Name;
3804 Error_Msg
3805 (Project, In_Tree,
3806 "library directory cannot be the same " &
3807 "as source directory { of project %%",
3808 Lib_Dir.Location);
3809 OK := False;
3810 exit Project_Loop;
3811 end if;
3812 end loop Dir_Loop;
3813 end if;
3814 end loop Project_Loop;
3815 end if;
3817 if not OK then
3818 Data.Library_Dir := No_Path_Information;
3820 elsif Current_Verbosity = High then
3822 -- Display the Library directory in high verbosity
3824 Write_Str ("Library directory =""");
3825 Write_Str
3826 (Get_Name_String (Data.Library_Dir.Display_Name));
3827 Write_Line ("""");
3828 end if;
3829 end;
3830 end if;
3831 end if;
3833 end if;
3835 Data.Library :=
3836 Data.Library_Dir /= No_Path_Information
3837 and then
3838 Data.Library_Name /= No_Name;
3840 if Data.Extends = No_Project then
3841 case Data.Qualifier is
3842 when Standard =>
3843 if Data.Library then
3844 Error_Msg
3845 (Project, In_Tree,
3846 "a standard project cannot be a library project",
3847 Lib_Name.Location);
3848 end if;
3850 when Library =>
3851 if not Data.Library then
3852 Error_Msg
3853 (Project, In_Tree,
3854 "not a library project",
3855 Data.Location);
3856 end if;
3858 when others =>
3859 null;
3861 end case;
3862 end if;
3864 if Data.Library then
3865 if Get_Mode = Multi_Language then
3866 Support_For_Libraries := Data.Config.Lib_Support;
3868 else
3869 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3870 end if;
3872 if Support_For_Libraries = Prj.None then
3873 Error_Msg
3874 (Project, In_Tree,
3875 "?libraries are not supported on this platform",
3876 Lib_Name.Location);
3877 Data.Library := False;
3879 else
3880 if Lib_ALI_Dir.Value = Empty_String then
3881 if Current_Verbosity = High then
3882 Write_Line ("No library ALI directory specified");
3883 end if;
3884 Data.Library_ALI_Dir := Data.Library_Dir;
3886 else
3887 -- Find path name, check that it is a directory
3889 Locate_Directory
3890 (Project,
3891 In_Tree,
3892 File_Name_Type (Lib_ALI_Dir.Value),
3893 Data.Directory.Display_Name,
3894 Data.Library_ALI_Dir.Name,
3895 Data.Library_ALI_Dir.Display_Name,
3896 Create => "library ALI",
3897 Current_Dir => Current_Dir,
3898 Location => Lib_ALI_Dir.Location);
3900 if Data.Library_ALI_Dir = No_Path_Information then
3902 -- Get the absolute name of the library ALI directory that
3903 -- does not exist, to report an error.
3905 declare
3906 Dir_Name : constant String :=
3907 Get_Name_String (Lib_ALI_Dir.Value);
3909 begin
3910 if Is_Absolute_Path (Dir_Name) then
3911 Err_Vars.Error_Msg_File_1 :=
3912 File_Name_Type (Lib_Dir.Value);
3914 else
3915 Get_Name_String (Data.Directory.Display_Name);
3917 if Name_Buffer (Name_Len) /= Directory_Separator then
3918 Name_Len := Name_Len + 1;
3919 Name_Buffer (Name_Len) := Directory_Separator;
3920 end if;
3922 Name_Buffer
3923 (Name_Len + 1 .. Name_Len + Dir_Name'Length) :=
3924 Dir_Name;
3925 Name_Len := Name_Len + Dir_Name'Length;
3926 Err_Vars.Error_Msg_File_1 := Name_Find;
3927 end if;
3929 -- Report the error
3931 Error_Msg
3932 (Project, In_Tree,
3933 "library 'A'L'I directory { does not exist",
3934 Lib_ALI_Dir.Location);
3935 end;
3936 end if;
3938 if Data.Library_ALI_Dir /= Data.Library_Dir then
3940 -- The library ALI directory cannot be the same as the
3941 -- Object directory.
3943 if Data.Library_ALI_Dir = Data.Object_Directory then
3944 Error_Msg
3945 (Project, In_Tree,
3946 "library 'A'L'I directory cannot be the same " &
3947 "as object directory",
3948 Lib_ALI_Dir.Location);
3949 Data.Library_ALI_Dir := No_Path_Information;
3951 else
3952 declare
3953 OK : Boolean := True;
3954 Dirs_Id : String_List_Id;
3955 Dir_Elem : String_Element;
3957 begin
3958 -- The library ALI directory cannot be the same as
3959 -- a source directory of the current project.
3961 Dirs_Id := Data.Source_Dirs;
3962 while Dirs_Id /= Nil_String loop
3963 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3964 Dirs_Id := Dir_Elem.Next;
3966 if Data.Library_ALI_Dir.Name =
3967 Path_Name_Type (Dir_Elem.Value)
3968 then
3969 Err_Vars.Error_Msg_File_1 :=
3970 File_Name_Type (Dir_Elem.Value);
3971 Error_Msg
3972 (Project, In_Tree,
3973 "library 'A'L'I directory cannot be " &
3974 "the same as source directory {",
3975 Lib_ALI_Dir.Location);
3976 OK := False;
3977 exit;
3978 end if;
3979 end loop;
3981 if OK then
3983 -- The library ALI directory cannot be the same as
3984 -- a source directory of another project either.
3986 ALI_Project_Loop :
3988 Pid in 1 .. Project_Table.Last (In_Tree.Projects)
3989 loop
3990 if Pid /= Project then
3991 Dirs_Id :=
3992 In_Tree.Projects.Table (Pid).Source_Dirs;
3994 ALI_Dir_Loop :
3995 while Dirs_Id /= Nil_String loop
3996 Dir_Elem :=
3997 In_Tree.String_Elements.Table (Dirs_Id);
3998 Dirs_Id := Dir_Elem.Next;
4000 if Data.Library_ALI_Dir.Name =
4001 Path_Name_Type (Dir_Elem.Value)
4002 then
4003 Err_Vars.Error_Msg_File_1 :=
4004 File_Name_Type (Dir_Elem.Value);
4005 Err_Vars.Error_Msg_Name_1 :=
4006 In_Tree.Projects.Table (Pid).Name;
4008 Error_Msg
4009 (Project, In_Tree,
4010 "library 'A'L'I directory cannot " &
4011 "be the same as source directory " &
4012 "{ of project %%",
4013 Lib_ALI_Dir.Location);
4014 OK := False;
4015 exit ALI_Project_Loop;
4016 end if;
4017 end loop ALI_Dir_Loop;
4018 end if;
4019 end loop ALI_Project_Loop;
4020 end if;
4022 if not OK then
4023 Data.Library_ALI_Dir := No_Path_Information;
4025 elsif Current_Verbosity = High then
4027 -- Display the Library ALI directory in high
4028 -- verbosity.
4030 Write_Str ("Library ALI directory =""");
4031 Write_Str
4032 (Get_Name_String
4033 (Data.Library_ALI_Dir.Display_Name));
4034 Write_Line ("""");
4035 end if;
4036 end;
4037 end if;
4038 end if;
4039 end if;
4041 pragma Assert (Lib_Version.Kind = Single);
4043 if Lib_Version.Value = Empty_String then
4044 if Current_Verbosity = High then
4045 Write_Line ("No library version specified");
4046 end if;
4048 else
4049 Data.Lib_Internal_Name := Lib_Version.Value;
4050 end if;
4052 pragma Assert (The_Lib_Kind.Kind = Single);
4054 if The_Lib_Kind.Value = Empty_String then
4055 if Current_Verbosity = High then
4056 Write_Line ("No library kind specified");
4057 end if;
4059 else
4060 Get_Name_String (The_Lib_Kind.Value);
4062 declare
4063 Kind_Name : constant String :=
4064 To_Lower (Name_Buffer (1 .. Name_Len));
4066 OK : Boolean := True;
4068 begin
4069 if Kind_Name = "static" then
4070 Data.Library_Kind := Static;
4072 elsif Kind_Name = "dynamic" then
4073 Data.Library_Kind := Dynamic;
4075 elsif Kind_Name = "relocatable" then
4076 Data.Library_Kind := Relocatable;
4078 else
4079 Error_Msg
4080 (Project, In_Tree,
4081 "illegal value for Library_Kind",
4082 The_Lib_Kind.Location);
4083 OK := False;
4084 end if;
4086 if Current_Verbosity = High and then OK then
4087 Write_Str ("Library kind = ");
4088 Write_Line (Kind_Name);
4089 end if;
4091 if Data.Library_Kind /= Static and then
4092 Support_For_Libraries = Prj.Static_Only
4093 then
4094 Error_Msg
4095 (Project, In_Tree,
4096 "only static libraries are supported " &
4097 "on this platform",
4098 The_Lib_Kind.Location);
4099 Data.Library := False;
4100 end if;
4101 end;
4102 end if;
4104 if Data.Library then
4105 if Current_Verbosity = High then
4106 Write_Line ("This is a library project file");
4107 end if;
4109 if Get_Mode = Multi_Language then
4110 Check_Library (Data.Extends, Extends => True);
4112 Imported_Project_List := Data.Imported_Projects;
4113 while Imported_Project_List /= Empty_Project_List loop
4114 Check_Library
4115 (In_Tree.Project_Lists.Table
4116 (Imported_Project_List).Project,
4117 Extends => False);
4118 Imported_Project_List :=
4119 In_Tree.Project_Lists.Table
4120 (Imported_Project_List).Next;
4121 end loop;
4122 end if;
4123 end if;
4125 end if;
4126 end if;
4128 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4129 -- Warn if they are declared, as it is a common error to think that
4130 -- library are "linked" with Linker switches.
4132 if Data.Library then
4133 declare
4134 Linker_Package_Id : constant Package_Id :=
4135 Util.Value_Of
4136 (Name_Linker, Data.Decl.Packages, In_Tree);
4137 Linker_Package : Package_Element;
4138 Switches : Array_Element_Id := No_Array_Element;
4140 begin
4141 if Linker_Package_Id /= No_Package then
4142 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4144 Switches :=
4145 Value_Of
4146 (Name => Name_Switches,
4147 In_Arrays => Linker_Package.Decl.Arrays,
4148 In_Tree => In_Tree);
4150 if Switches = No_Array_Element then
4151 Switches :=
4152 Value_Of
4153 (Name => Name_Default_Switches,
4154 In_Arrays => Linker_Package.Decl.Arrays,
4155 In_Tree => In_Tree);
4156 end if;
4158 if Switches /= No_Array_Element then
4159 Error_Msg
4160 (Project, In_Tree,
4161 "?Linker switches not taken into account in library " &
4162 "projects",
4163 No_Location);
4164 end if;
4165 end if;
4166 end;
4167 end if;
4169 if Data.Extends /= No_Project then
4170 In_Tree.Projects.Table (Data.Extends).Library := False;
4171 end if;
4172 end Check_Library_Attributes;
4174 --------------------------
4175 -- Check_Package_Naming --
4176 --------------------------
4178 procedure Check_Package_Naming
4179 (Project : Project_Id;
4180 In_Tree : Project_Tree_Ref;
4181 Data : in out Project_Data)
4183 Naming_Id : constant Package_Id :=
4184 Util.Value_Of (Name_Naming, Data.Decl.Packages, In_Tree);
4186 Naming : Package_Element;
4188 begin
4189 -- If there is a package Naming, we will put in Data.Naming
4190 -- what is in this package Naming.
4192 if Naming_Id /= No_Package then
4193 Naming := In_Tree.Packages.Table (Naming_Id);
4195 if Current_Verbosity = High then
4196 Write_Line ("Checking ""Naming"".");
4197 end if;
4199 -- Check Spec_Suffix
4201 declare
4202 Spec_Suffixs : Array_Element_Id :=
4203 Util.Value_Of
4204 (Name_Spec_Suffix,
4205 Naming.Decl.Arrays,
4206 In_Tree);
4208 Suffix : Array_Element_Id;
4209 Element : Array_Element;
4210 Suffix2 : Array_Element_Id;
4212 begin
4213 -- If some suffixes have been specified, we make sure that
4214 -- for each language for which a default suffix has been
4215 -- specified, there is a suffix specified, either the one
4216 -- in the project file or if there were none, the default.
4218 if Spec_Suffixs /= No_Array_Element then
4219 Suffix := Data.Naming.Spec_Suffix;
4221 while Suffix /= No_Array_Element loop
4222 Element :=
4223 In_Tree.Array_Elements.Table (Suffix);
4224 Suffix2 := Spec_Suffixs;
4226 while Suffix2 /= No_Array_Element loop
4227 exit when In_Tree.Array_Elements.Table
4228 (Suffix2).Index = Element.Index;
4229 Suffix2 := In_Tree.Array_Elements.Table
4230 (Suffix2).Next;
4231 end loop;
4233 -- There is a registered default suffix, but no
4234 -- suffix specified in the project file.
4235 -- Add the default to the array.
4237 if Suffix2 = No_Array_Element then
4238 Array_Element_Table.Increment_Last
4239 (In_Tree.Array_Elements);
4240 In_Tree.Array_Elements.Table
4241 (Array_Element_Table.Last
4242 (In_Tree.Array_Elements)) :=
4243 (Index => Element.Index,
4244 Src_Index => Element.Src_Index,
4245 Index_Case_Sensitive => False,
4246 Value => Element.Value,
4247 Next => Spec_Suffixs);
4248 Spec_Suffixs := Array_Element_Table.Last
4249 (In_Tree.Array_Elements);
4250 end if;
4252 Suffix := Element.Next;
4253 end loop;
4255 -- Put the resulting array as the specification suffixes
4257 Data.Naming.Spec_Suffix := Spec_Suffixs;
4258 end if;
4259 end;
4261 declare
4262 Current : Array_Element_Id;
4263 Element : Array_Element;
4265 begin
4266 Current := Data.Naming.Spec_Suffix;
4267 while Current /= No_Array_Element loop
4268 Element := In_Tree.Array_Elements.Table (Current);
4269 Get_Name_String (Element.Value.Value);
4271 if Name_Len = 0 then
4272 Error_Msg
4273 (Project, In_Tree,
4274 "Spec_Suffix cannot be empty",
4275 Element.Value.Location);
4276 end if;
4278 In_Tree.Array_Elements.Table (Current) := Element;
4279 Current := Element.Next;
4280 end loop;
4281 end;
4283 -- Check Body_Suffix
4285 declare
4286 Impl_Suffixs : Array_Element_Id :=
4287 Util.Value_Of
4288 (Name_Body_Suffix,
4289 Naming.Decl.Arrays,
4290 In_Tree);
4292 Suffix : Array_Element_Id;
4293 Element : Array_Element;
4294 Suffix2 : Array_Element_Id;
4296 begin
4297 -- If some suffixes have been specified, we make sure that
4298 -- for each language for which a default suffix has been
4299 -- specified, there is a suffix specified, either the one
4300 -- in the project file or if there were none, the default.
4302 if Impl_Suffixs /= No_Array_Element then
4303 Suffix := Data.Naming.Body_Suffix;
4304 while Suffix /= No_Array_Element loop
4305 Element :=
4306 In_Tree.Array_Elements.Table (Suffix);
4308 Suffix2 := Impl_Suffixs;
4309 while Suffix2 /= No_Array_Element loop
4310 exit when In_Tree.Array_Elements.Table
4311 (Suffix2).Index = Element.Index;
4312 Suffix2 := In_Tree.Array_Elements.Table
4313 (Suffix2).Next;
4314 end loop;
4316 -- There is a registered default suffix, but no suffix was
4317 -- specified in the project file. Add default to the array.
4319 if Suffix2 = No_Array_Element then
4320 Array_Element_Table.Increment_Last
4321 (In_Tree.Array_Elements);
4322 In_Tree.Array_Elements.Table
4323 (Array_Element_Table.Last
4324 (In_Tree.Array_Elements)) :=
4325 (Index => Element.Index,
4326 Src_Index => Element.Src_Index,
4327 Index_Case_Sensitive => False,
4328 Value => Element.Value,
4329 Next => Impl_Suffixs);
4330 Impl_Suffixs := Array_Element_Table.Last
4331 (In_Tree.Array_Elements);
4332 end if;
4334 Suffix := Element.Next;
4335 end loop;
4337 -- Put the resulting array as the implementation suffixes
4339 Data.Naming.Body_Suffix := Impl_Suffixs;
4340 end if;
4341 end;
4343 declare
4344 Current : Array_Element_Id;
4345 Element : Array_Element;
4347 begin
4348 Current := Data.Naming.Body_Suffix;
4349 while Current /= No_Array_Element loop
4350 Element := In_Tree.Array_Elements.Table (Current);
4351 Get_Name_String (Element.Value.Value);
4353 if Name_Len = 0 then
4354 Error_Msg
4355 (Project, In_Tree,
4356 "Body_Suffix cannot be empty",
4357 Element.Value.Location);
4358 end if;
4360 In_Tree.Array_Elements.Table (Current) := Element;
4361 Current := Element.Next;
4362 end loop;
4363 end;
4365 -- Get the exceptions, if any
4367 Data.Naming.Specification_Exceptions :=
4368 Util.Value_Of
4369 (Name_Specification_Exceptions,
4370 In_Arrays => Naming.Decl.Arrays,
4371 In_Tree => In_Tree);
4373 Data.Naming.Implementation_Exceptions :=
4374 Util.Value_Of
4375 (Name_Implementation_Exceptions,
4376 In_Arrays => Naming.Decl.Arrays,
4377 In_Tree => In_Tree);
4378 end if;
4379 end Check_Package_Naming;
4381 ---------------------------------
4382 -- Check_Programming_Languages --
4383 ---------------------------------
4385 procedure Check_Programming_Languages
4386 (In_Tree : Project_Tree_Ref;
4387 Project : Project_Id;
4388 Data : in out Project_Data)
4390 Languages : Variable_Value := Nil_Variable_Value;
4391 Def_Lang : Variable_Value := Nil_Variable_Value;
4392 Def_Lang_Id : Name_Id;
4394 begin
4395 Data.First_Language_Processing := No_Language_Index;
4396 Languages :=
4397 Prj.Util.Value_Of (Name_Languages, Data.Decl.Attributes, In_Tree);
4398 Def_Lang :=
4399 Prj.Util.Value_Of
4400 (Name_Default_Language, Data.Decl.Attributes, In_Tree);
4401 Data.Ada_Sources_Present := Data.Source_Dirs /= Nil_String;
4402 Data.Other_Sources_Present := Data.Source_Dirs /= Nil_String;
4404 if Data.Source_Dirs /= Nil_String then
4406 -- Check if languages are specified in this project
4408 if Languages.Default then
4410 -- Attribute Languages is not specified. So, it defaults to
4411 -- a project of the default language only.
4413 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4414 Data.Languages := Name_List_Table.Last (In_Tree.Name_Lists);
4416 -- In Ada_Only mode, the default language is Ada
4418 if Get_Mode = Ada_Only then
4419 In_Tree.Name_Lists.Table (Data.Languages) :=
4420 (Name => Name_Ada, Next => No_Name_List);
4422 -- Attribute Languages is not specified. So, it defaults to
4423 -- a project of language Ada only. No sources of languages
4424 -- other than Ada
4426 Data.Other_Sources_Present := False;
4428 else
4429 -- Fail if there is no default language defined
4431 if Def_Lang.Default then
4432 if not Default_Language_Is_Ada then
4433 Error_Msg
4434 (Project,
4435 In_Tree,
4436 "no languages defined for this project",
4437 Data.Location);
4438 Def_Lang_Id := No_Name;
4439 else
4440 Def_Lang_Id := Name_Ada;
4441 end if;
4443 else
4444 Get_Name_String (Def_Lang.Value);
4445 To_Lower (Name_Buffer (1 .. Name_Len));
4446 Def_Lang_Id := Name_Find;
4447 end if;
4449 if Def_Lang_Id /= No_Name then
4450 In_Tree.Name_Lists.Table (Data.Languages) :=
4451 (Name => Def_Lang_Id, Next => No_Name_List);
4453 Language_Data_Table.Increment_Last (In_Tree.Languages_Data);
4455 Data.First_Language_Processing :=
4456 Language_Data_Table.Last (In_Tree.Languages_Data);
4457 In_Tree.Languages_Data.Table
4458 (Data.First_Language_Processing) := No_Language_Data;
4459 In_Tree.Languages_Data.Table
4460 (Data.First_Language_Processing).Name := Def_Lang_Id;
4461 Get_Name_String (Def_Lang_Id);
4462 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4463 In_Tree.Languages_Data.Table
4464 (Data.First_Language_Processing).Display_Name := Name_Find;
4466 if Def_Lang_Id = Name_Ada then
4467 In_Tree.Languages_Data.Table
4468 (Data.First_Language_Processing).Config.Kind
4469 := Unit_Based;
4470 In_Tree.Languages_Data.Table
4471 (Data.First_Language_Processing).Config.Dependency_Kind
4472 := ALI_File;
4473 Data.Unit_Based_Language_Name := Name_Ada;
4474 Data.Unit_Based_Language_Index :=
4475 Data.First_Language_Processing;
4476 else
4477 In_Tree.Languages_Data.Table
4478 (Data.First_Language_Processing).Config.Kind
4479 := File_Based;
4480 end if;
4481 end if;
4482 end if;
4484 else
4485 declare
4486 Current : String_List_Id := Languages.Values;
4487 Element : String_Element;
4488 Lang_Name : Name_Id;
4489 Index : Language_Index;
4490 Lang_Data : Language_Data;
4491 NL_Id : Name_List_Index := No_Name_List;
4493 begin
4494 -- Assume there are no language declared
4496 Data.Ada_Sources_Present := False;
4497 Data.Other_Sources_Present := False;
4499 -- If there are no languages declared, there are no sources
4501 if Current = Nil_String then
4502 Data.Source_Dirs := Nil_String;
4504 if Data.Qualifier = Standard then
4505 Error_Msg
4506 (Project,
4507 In_Tree,
4508 "a standard project cannot have no language declared",
4509 Languages.Location);
4510 end if;
4512 else
4513 -- Look through all the languages specified in attribute
4514 -- Languages.
4516 while Current /= Nil_String loop
4517 Element :=
4518 In_Tree.String_Elements.Table (Current);
4519 Get_Name_String (Element.Value);
4520 To_Lower (Name_Buffer (1 .. Name_Len));
4521 Lang_Name := Name_Find;
4523 NL_Id := Data.Languages;
4524 while NL_Id /= No_Name_List loop
4525 exit when
4526 Lang_Name = In_Tree.Name_Lists.Table (NL_Id).Name;
4527 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4528 end loop;
4530 if NL_Id = No_Name_List then
4531 Name_List_Table.Increment_Last (In_Tree.Name_Lists);
4533 if Data.Languages = No_Name_List then
4534 Data.Languages :=
4535 Name_List_Table.Last (In_Tree.Name_Lists);
4537 else
4538 NL_Id := Data.Languages;
4539 while In_Tree.Name_Lists.Table (NL_Id).Next /=
4540 No_Name_List
4541 loop
4542 NL_Id := In_Tree.Name_Lists.Table (NL_Id).Next;
4543 end loop;
4545 In_Tree.Name_Lists.Table (NL_Id).Next :=
4546 Name_List_Table.Last (In_Tree.Name_Lists);
4547 end if;
4549 NL_Id := Name_List_Table.Last (In_Tree.Name_Lists);
4550 In_Tree.Name_Lists.Table (NL_Id) :=
4551 (Lang_Name, No_Name_List);
4553 if Get_Mode = Ada_Only then
4554 -- Check for language Ada
4556 if Lang_Name = Name_Ada then
4557 Data.Ada_Sources_Present := True;
4559 else
4560 Data.Other_Sources_Present := True;
4561 end if;
4563 else
4564 Language_Data_Table.Increment_Last
4565 (In_Tree.Languages_Data);
4566 Index :=
4567 Language_Data_Table.Last (In_Tree.Languages_Data);
4568 Lang_Data.Name := Lang_Name;
4569 Lang_Data.Display_Name := Element.Value;
4570 Lang_Data.Next := Data.First_Language_Processing;
4572 if Lang_Name = Name_Ada then
4573 Lang_Data.Config.Kind := Unit_Based;
4574 Lang_Data.Config.Dependency_Kind := ALI_File;
4575 Data.Unit_Based_Language_Name := Name_Ada;
4576 Data.Unit_Based_Language_Index := Index;
4578 else
4579 Lang_Data.Config.Kind := File_Based;
4580 Lang_Data.Config.Dependency_Kind := None;
4581 end if;
4583 In_Tree.Languages_Data.Table (Index) := Lang_Data;
4584 Data.First_Language_Processing := Index;
4585 end if;
4586 end if;
4588 Current := Element.Next;
4589 end loop;
4590 end if;
4591 end;
4592 end if;
4593 end if;
4594 end Check_Programming_Languages;
4596 -------------------
4597 -- Check_Project --
4598 -------------------
4600 function Check_Project
4601 (P : Project_Id;
4602 Root_Project : Project_Id;
4603 In_Tree : Project_Tree_Ref;
4604 Extending : Boolean) return Boolean
4606 begin
4607 if P = Root_Project then
4608 return True;
4610 elsif Extending then
4611 declare
4612 Data : Project_Data := In_Tree.Projects.Table (Root_Project);
4614 begin
4615 while Data.Extends /= No_Project loop
4616 if P = Data.Extends then
4617 return True;
4618 end if;
4620 Data := In_Tree.Projects.Table (Data.Extends);
4621 end loop;
4622 end;
4623 end if;
4625 return False;
4626 end Check_Project;
4628 -------------------------------
4629 -- Check_Stand_Alone_Library --
4630 -------------------------------
4632 procedure Check_Stand_Alone_Library
4633 (Project : Project_Id;
4634 In_Tree : Project_Tree_Ref;
4635 Data : in out Project_Data;
4636 Current_Dir : String;
4637 Extending : Boolean)
4639 Lib_Interfaces : constant Prj.Variable_Value :=
4640 Prj.Util.Value_Of
4641 (Snames.Name_Library_Interface,
4642 Data.Decl.Attributes,
4643 In_Tree);
4645 Lib_Auto_Init : constant Prj.Variable_Value :=
4646 Prj.Util.Value_Of
4647 (Snames.Name_Library_Auto_Init,
4648 Data.Decl.Attributes,
4649 In_Tree);
4651 Lib_Src_Dir : constant Prj.Variable_Value :=
4652 Prj.Util.Value_Of
4653 (Snames.Name_Library_Src_Dir,
4654 Data.Decl.Attributes,
4655 In_Tree);
4657 Lib_Symbol_File : constant Prj.Variable_Value :=
4658 Prj.Util.Value_Of
4659 (Snames.Name_Library_Symbol_File,
4660 Data.Decl.Attributes,
4661 In_Tree);
4663 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4664 Prj.Util.Value_Of
4665 (Snames.Name_Library_Symbol_Policy,
4666 Data.Decl.Attributes,
4667 In_Tree);
4669 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4670 Prj.Util.Value_Of
4671 (Snames.Name_Library_Reference_Symbol_File,
4672 Data.Decl.Attributes,
4673 In_Tree);
4675 Auto_Init_Supported : Boolean;
4676 OK : Boolean := True;
4677 Source : Source_Id;
4678 Next_Proj : Project_Id;
4680 begin
4681 if Get_Mode = Multi_Language then
4682 Auto_Init_Supported := Data.Config.Auto_Init_Supported;
4683 else
4684 Auto_Init_Supported :=
4685 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4686 end if;
4688 pragma Assert (Lib_Interfaces.Kind = List);
4690 -- It is a stand-alone library project file if attribute
4691 -- Library_Interface is defined.
4693 if not Lib_Interfaces.Default then
4694 SAL_Library : declare
4695 Interfaces : String_List_Id := Lib_Interfaces.Values;
4696 Interface_ALIs : String_List_Id := Nil_String;
4697 Unit : Name_Id;
4698 The_Unit_Id : Unit_Index;
4699 The_Unit_Data : Unit_Data;
4701 procedure Add_ALI_For (Source : File_Name_Type);
4702 -- Add an ALI file name to the list of Interface ALIs
4704 -----------------
4705 -- Add_ALI_For --
4706 -----------------
4708 procedure Add_ALI_For (Source : File_Name_Type) is
4709 begin
4710 Get_Name_String (Source);
4712 declare
4713 ALI : constant String :=
4714 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4715 ALI_Name_Id : Name_Id;
4717 begin
4718 Name_Len := ALI'Length;
4719 Name_Buffer (1 .. Name_Len) := ALI;
4720 ALI_Name_Id := Name_Find;
4722 String_Element_Table.Increment_Last
4723 (In_Tree.String_Elements);
4724 In_Tree.String_Elements.Table
4725 (String_Element_Table.Last
4726 (In_Tree.String_Elements)) :=
4727 (Value => ALI_Name_Id,
4728 Index => 0,
4729 Display_Value => ALI_Name_Id,
4730 Location =>
4731 In_Tree.String_Elements.Table
4732 (Interfaces).Location,
4733 Flag => False,
4734 Next => Interface_ALIs);
4735 Interface_ALIs := String_Element_Table.Last
4736 (In_Tree.String_Elements);
4737 end;
4738 end Add_ALI_For;
4740 -- Start of processing for SAL_Library
4742 begin
4743 Data.Standalone_Library := True;
4745 -- Library_Interface cannot be an empty list
4747 if Interfaces = Nil_String then
4748 Error_Msg
4749 (Project, In_Tree,
4750 "Library_Interface cannot be an empty list",
4751 Lib_Interfaces.Location);
4752 end if;
4754 -- Process each unit name specified in the attribute
4755 -- Library_Interface.
4757 while Interfaces /= Nil_String loop
4758 Get_Name_String
4759 (In_Tree.String_Elements.Table (Interfaces).Value);
4760 To_Lower (Name_Buffer (1 .. Name_Len));
4762 if Name_Len = 0 then
4763 Error_Msg
4764 (Project, In_Tree,
4765 "an interface cannot be an empty string",
4766 In_Tree.String_Elements.Table (Interfaces).Location);
4768 else
4769 Unit := Name_Find;
4770 Error_Msg_Name_1 := Unit;
4772 if Get_Mode = Ada_Only then
4773 The_Unit_Id :=
4774 Units_Htable.Get (In_Tree.Units_HT, Unit);
4776 if The_Unit_Id = No_Unit_Index then
4777 Error_Msg
4778 (Project, In_Tree,
4779 "unknown unit %%",
4780 In_Tree.String_Elements.Table
4781 (Interfaces).Location);
4783 else
4784 -- Check that the unit is part of the project
4786 The_Unit_Data :=
4787 In_Tree.Units.Table (The_Unit_Id);
4789 if The_Unit_Data.File_Names (Body_Part).Name /= No_File
4790 and then The_Unit_Data.File_Names
4791 (Body_Part).Path.Name /= Slash
4792 then
4793 if Check_Project
4794 (The_Unit_Data.File_Names (Body_Part).Project,
4795 Project, In_Tree, Extending)
4796 then
4797 -- There is a body for this unit.
4798 -- If there is no spec, we need to check
4799 -- that it is not a subunit.
4801 if The_Unit_Data.File_Names
4802 (Specification).Name = No_File
4803 then
4804 declare
4805 Src_Ind : Source_File_Index;
4807 begin
4808 Src_Ind := Sinput.P.Load_Project_File
4809 (Get_Name_String
4810 (The_Unit_Data.File_Names
4811 (Body_Part).Path.Name));
4813 if Sinput.P.Source_File_Is_Subunit
4814 (Src_Ind)
4815 then
4816 Error_Msg
4817 (Project, In_Tree,
4818 "%% is a subunit; " &
4819 "it cannot be an interface",
4820 In_Tree.
4821 String_Elements.Table
4822 (Interfaces).Location);
4823 end if;
4824 end;
4825 end if;
4827 -- The unit is not a subunit, so we add
4828 -- to the Interface ALIs the ALI file
4829 -- corresponding to the body.
4831 Add_ALI_For
4832 (The_Unit_Data.File_Names (Body_Part).Name);
4834 else
4835 Error_Msg
4836 (Project, In_Tree,
4837 "%% is not an unit of this project",
4838 In_Tree.String_Elements.Table
4839 (Interfaces).Location);
4840 end if;
4842 elsif The_Unit_Data.File_Names
4843 (Specification).Name /= No_File
4844 and then The_Unit_Data.File_Names
4845 (Specification).Path.Name /= Slash
4846 and then Check_Project
4847 (The_Unit_Data.File_Names
4848 (Specification).Project,
4849 Project, In_Tree, Extending)
4851 then
4852 -- The unit is part of the project, it has
4853 -- a spec, but no body. We add to the Interface
4854 -- ALIs the ALI file corresponding to the spec.
4856 Add_ALI_For
4857 (The_Unit_Data.File_Names (Specification).Name);
4859 else
4860 Error_Msg
4861 (Project, In_Tree,
4862 "%% is not an unit of this project",
4863 In_Tree.String_Elements.Table
4864 (Interfaces).Location);
4865 end if;
4866 end if;
4868 else
4869 -- Multi_Language mode
4871 Next_Proj := Data.Extends;
4872 Source := Data.First_Source;
4874 loop
4875 while Source /= No_Source and then
4876 In_Tree.Sources.Table (Source).Unit /= Unit
4877 loop
4878 Source :=
4879 In_Tree.Sources.Table (Source).Next_In_Project;
4880 end loop;
4882 exit when Source /= No_Source or else
4883 Next_Proj = No_Project;
4885 Source :=
4886 In_Tree.Projects.Table (Next_Proj).First_Source;
4887 Next_Proj :=
4888 In_Tree.Projects.Table (Next_Proj).Extends;
4889 end loop;
4891 if Source /= No_Source then
4892 if In_Tree.Sources.Table (Source).Kind = Sep then
4893 Source := No_Source;
4895 elsif In_Tree.Sources.Table (Source).Kind = Spec
4896 and then
4897 In_Tree.Sources.Table (Source).Other_Part /=
4898 No_Source
4899 then
4900 Source := In_Tree.Sources.Table (Source).Other_Part;
4901 end if;
4902 end if;
4904 if Source /= No_Source then
4905 if In_Tree.Sources.Table (Source).Project /= Project
4906 and then
4907 not Is_Extending
4908 (Project,
4909 In_Tree.Sources.Table (Source).Project,
4910 In_Tree)
4911 then
4912 Source := No_Source;
4913 end if;
4914 end if;
4916 if Source = No_Source then
4917 Error_Msg
4918 (Project, In_Tree,
4919 "%% is not an unit of this project",
4920 In_Tree.String_Elements.Table
4921 (Interfaces).Location);
4923 else
4924 if In_Tree.Sources.Table (Source).Kind = Spec and then
4925 In_Tree.Sources.Table (Source).Other_Part /=
4926 No_Source
4927 then
4928 Source := In_Tree.Sources.Table (Source).Other_Part;
4929 end if;
4931 String_Element_Table.Increment_Last
4932 (In_Tree.String_Elements);
4933 In_Tree.String_Elements.Table
4934 (String_Element_Table.Last
4935 (In_Tree.String_Elements)) :=
4936 (Value =>
4937 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4938 Index => 0,
4939 Display_Value =>
4940 Name_Id (In_Tree.Sources.Table (Source).Dep_Name),
4941 Location =>
4942 In_Tree.String_Elements.Table
4943 (Interfaces).Location,
4944 Flag => False,
4945 Next => Interface_ALIs);
4946 Interface_ALIs := String_Element_Table.Last
4947 (In_Tree.String_Elements);
4948 end if;
4950 end if;
4952 end if;
4954 Interfaces :=
4955 In_Tree.String_Elements.Table (Interfaces).Next;
4956 end loop;
4958 -- Put the list of Interface ALIs in the project data
4960 Data.Lib_Interface_ALIs := Interface_ALIs;
4962 -- Check value of attribute Library_Auto_Init and set
4963 -- Lib_Auto_Init accordingly.
4965 if Lib_Auto_Init.Default then
4967 -- If no attribute Library_Auto_Init is declared, then set auto
4968 -- init only if it is supported.
4970 Data.Lib_Auto_Init := Auto_Init_Supported;
4972 else
4973 Get_Name_String (Lib_Auto_Init.Value);
4974 To_Lower (Name_Buffer (1 .. Name_Len));
4976 if Name_Buffer (1 .. Name_Len) = "false" then
4977 Data.Lib_Auto_Init := False;
4979 elsif Name_Buffer (1 .. Name_Len) = "true" then
4980 if Auto_Init_Supported then
4981 Data.Lib_Auto_Init := True;
4983 else
4984 -- Library_Auto_Init cannot be "true" if auto init is not
4985 -- supported
4987 Error_Msg
4988 (Project, In_Tree,
4989 "library auto init not supported " &
4990 "on this platform",
4991 Lib_Auto_Init.Location);
4992 end if;
4994 else
4995 Error_Msg
4996 (Project, In_Tree,
4997 "invalid value for attribute Library_Auto_Init",
4998 Lib_Auto_Init.Location);
4999 end if;
5000 end if;
5001 end SAL_Library;
5003 -- If attribute Library_Src_Dir is defined and not the empty string,
5004 -- check if the directory exist and is not the object directory or
5005 -- one of the source directories. This is the directory where copies
5006 -- of the interface sources will be copied. Note that this directory
5007 -- may be the library directory.
5009 if Lib_Src_Dir.Value /= Empty_String then
5010 declare
5011 Dir_Id : constant File_Name_Type :=
5012 File_Name_Type (Lib_Src_Dir.Value);
5014 begin
5015 Locate_Directory
5016 (Project,
5017 In_Tree,
5018 Dir_Id,
5019 Data.Directory.Display_Name,
5020 Data.Library_Src_Dir.Name,
5021 Data.Library_Src_Dir.Display_Name,
5022 Create => "library source copy",
5023 Current_Dir => Current_Dir,
5024 Location => Lib_Src_Dir.Location);
5026 -- If directory does not exist, report an error
5028 if Data.Library_Src_Dir = No_Path_Information then
5030 -- Get the absolute name of the library directory that does
5031 -- not exist, to report an error.
5033 declare
5034 Dir_Name : constant String :=
5035 Get_Name_String (Dir_Id);
5037 begin
5038 if Is_Absolute_Path (Dir_Name) then
5039 Err_Vars.Error_Msg_File_1 := Dir_Id;
5041 else
5042 Get_Name_String (Data.Directory.Name);
5044 if Name_Buffer (Name_Len) /=
5045 Directory_Separator
5046 then
5047 Name_Len := Name_Len + 1;
5048 Name_Buffer (Name_Len) :=
5049 Directory_Separator;
5050 end if;
5052 Name_Buffer
5053 (Name_Len + 1 ..
5054 Name_Len + Dir_Name'Length) :=
5055 Dir_Name;
5056 Name_Len := Name_Len + Dir_Name'Length;
5057 Err_Vars.Error_Msg_Name_1 := Name_Find;
5058 end if;
5060 -- Report the error
5062 Error_Msg_File_1 := Dir_Id;
5063 Error_Msg
5064 (Project, In_Tree,
5065 "Directory { does not exist",
5066 Lib_Src_Dir.Location);
5067 end;
5069 -- Report error if it is the same as the object directory
5071 elsif Data.Library_Src_Dir = Data.Object_Directory then
5072 Error_Msg
5073 (Project, In_Tree,
5074 "directory to copy interfaces cannot be " &
5075 "the object directory",
5076 Lib_Src_Dir.Location);
5077 Data.Library_Src_Dir := No_Path_Information;
5079 else
5080 declare
5081 Src_Dirs : String_List_Id;
5082 Src_Dir : String_Element;
5084 begin
5085 -- Interface copy directory cannot be one of the source
5086 -- directory of the current project.
5088 Src_Dirs := Data.Source_Dirs;
5089 while Src_Dirs /= Nil_String loop
5090 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
5092 -- Report error if it is one of the source directories
5094 if Data.Library_Src_Dir.Name =
5095 Path_Name_Type (Src_Dir.Value)
5096 then
5097 Error_Msg
5098 (Project, In_Tree,
5099 "directory to copy interfaces cannot " &
5100 "be one of the source directories",
5101 Lib_Src_Dir.Location);
5102 Data.Library_Src_Dir := No_Path_Information;
5103 exit;
5104 end if;
5106 Src_Dirs := Src_Dir.Next;
5107 end loop;
5109 if Data.Library_Src_Dir /= No_Path_Information then
5111 -- It cannot be a source directory of any other
5112 -- project either.
5114 Project_Loop : for Pid in 1 ..
5115 Project_Table.Last (In_Tree.Projects)
5116 loop
5117 Src_Dirs :=
5118 In_Tree.Projects.Table (Pid).Source_Dirs;
5119 Dir_Loop : while Src_Dirs /= Nil_String loop
5120 Src_Dir :=
5121 In_Tree.String_Elements.Table (Src_Dirs);
5123 -- Report error if it is one of the source
5124 -- directories
5126 if Data.Library_Src_Dir.Name =
5127 Path_Name_Type (Src_Dir.Value)
5128 then
5129 Error_Msg_File_1 :=
5130 File_Name_Type (Src_Dir.Value);
5131 Error_Msg_Name_1 :=
5132 In_Tree.Projects.Table (Pid).Name;
5133 Error_Msg
5134 (Project, In_Tree,
5135 "directory to copy interfaces cannot " &
5136 "be the same as source directory { of " &
5137 "project %%",
5138 Lib_Src_Dir.Location);
5139 Data.Library_Src_Dir := No_Path_Information;
5140 exit Project_Loop;
5141 end if;
5143 Src_Dirs := Src_Dir.Next;
5144 end loop Dir_Loop;
5145 end loop Project_Loop;
5146 end if;
5147 end;
5149 -- In high verbosity, if there is a valid Library_Src_Dir,
5150 -- display its path name.
5152 if Data.Library_Src_Dir /= No_Path_Information
5153 and then Current_Verbosity = High
5154 then
5155 Write_Str ("Directory to copy interfaces =""");
5156 Write_Str (Get_Name_String (Data.Library_Src_Dir.Name));
5157 Write_Line ("""");
5158 end if;
5159 end if;
5160 end;
5161 end if;
5163 -- Check the symbol related attributes
5165 -- First, the symbol policy
5167 if not Lib_Symbol_Policy.Default then
5168 declare
5169 Value : constant String :=
5170 To_Lower
5171 (Get_Name_String (Lib_Symbol_Policy.Value));
5173 begin
5174 -- Symbol policy must hove one of a limited number of values
5176 if Value = "autonomous" or else Value = "default" then
5177 Data.Symbol_Data.Symbol_Policy := Autonomous;
5179 elsif Value = "compliant" then
5180 Data.Symbol_Data.Symbol_Policy := Compliant;
5182 elsif Value = "controlled" then
5183 Data.Symbol_Data.Symbol_Policy := Controlled;
5185 elsif Value = "restricted" then
5186 Data.Symbol_Data.Symbol_Policy := Restricted;
5188 elsif Value = "direct" then
5189 Data.Symbol_Data.Symbol_Policy := Direct;
5191 else
5192 Error_Msg
5193 (Project, In_Tree,
5194 "illegal value for Library_Symbol_Policy",
5195 Lib_Symbol_Policy.Location);
5196 end if;
5197 end;
5198 end if;
5200 -- If attribute Library_Symbol_File is not specified, symbol policy
5201 -- cannot be Restricted.
5203 if Lib_Symbol_File.Default then
5204 if Data.Symbol_Data.Symbol_Policy = Restricted then
5205 Error_Msg
5206 (Project, In_Tree,
5207 "Library_Symbol_File needs to be defined when " &
5208 "symbol policy is Restricted",
5209 Lib_Symbol_Policy.Location);
5210 end if;
5212 else
5213 -- Library_Symbol_File is defined
5215 Data.Symbol_Data.Symbol_File :=
5216 Path_Name_Type (Lib_Symbol_File.Value);
5218 Get_Name_String (Lib_Symbol_File.Value);
5220 if Name_Len = 0 then
5221 Error_Msg
5222 (Project, In_Tree,
5223 "symbol file name cannot be an empty string",
5224 Lib_Symbol_File.Location);
5226 else
5227 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
5229 if OK then
5230 for J in 1 .. Name_Len loop
5231 if Name_Buffer (J) = '/'
5232 or else Name_Buffer (J) = Directory_Separator
5233 then
5234 OK := False;
5235 exit;
5236 end if;
5237 end loop;
5238 end if;
5240 if not OK then
5241 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
5242 Error_Msg
5243 (Project, In_Tree,
5244 "symbol file name { is illegal. " &
5245 "Name cannot include directory info.",
5246 Lib_Symbol_File.Location);
5247 end if;
5248 end if;
5249 end if;
5251 -- If attribute Library_Reference_Symbol_File is not defined,
5252 -- symbol policy cannot be Compliant or Controlled.
5254 if Lib_Ref_Symbol_File.Default then
5255 if Data.Symbol_Data.Symbol_Policy = Compliant
5256 or else Data.Symbol_Data.Symbol_Policy = Controlled
5257 then
5258 Error_Msg
5259 (Project, In_Tree,
5260 "a reference symbol file need to be defined",
5261 Lib_Symbol_Policy.Location);
5262 end if;
5264 else
5265 -- Library_Reference_Symbol_File is defined, check file exists
5267 Data.Symbol_Data.Reference :=
5268 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5270 Get_Name_String (Lib_Ref_Symbol_File.Value);
5272 if Name_Len = 0 then
5273 Error_Msg
5274 (Project, In_Tree,
5275 "reference symbol file name cannot be an empty string",
5276 Lib_Symbol_File.Location);
5278 else
5279 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5280 Name_Len := 0;
5281 Add_Str_To_Name_Buffer
5282 (Get_Name_String (Data.Directory.Name));
5283 Add_Char_To_Name_Buffer (Directory_Separator);
5284 Add_Str_To_Name_Buffer
5285 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5286 Data.Symbol_Data.Reference := Name_Find;
5287 end if;
5289 if not Is_Regular_File
5290 (Get_Name_String (Data.Symbol_Data.Reference))
5291 then
5292 Error_Msg_File_1 :=
5293 File_Name_Type (Lib_Ref_Symbol_File.Value);
5295 -- For controlled and direct symbol policies, it is an error
5296 -- if the reference symbol file does not exist. For other
5297 -- symbol policies, this is just a warning
5299 Error_Msg_Warn :=
5300 Data.Symbol_Data.Symbol_Policy /= Controlled
5301 and then Data.Symbol_Data.Symbol_Policy /= Direct;
5303 Error_Msg
5304 (Project, In_Tree,
5305 "<library reference symbol file { does not exist",
5306 Lib_Ref_Symbol_File.Location);
5308 -- In addition in the non-controlled case, if symbol policy
5309 -- is Compliant, it is changed to Autonomous, because there
5310 -- is no reference to check against, and we don't want to
5311 -- fail in this case.
5313 if Data.Symbol_Data.Symbol_Policy /= Controlled then
5314 if Data.Symbol_Data.Symbol_Policy = Compliant then
5315 Data.Symbol_Data.Symbol_Policy := Autonomous;
5316 end if;
5317 end if;
5318 end if;
5320 -- If both the reference symbol file and the symbol file are
5321 -- defined, then check that they are not the same file.
5323 if Data.Symbol_Data.Symbol_File /= No_Path then
5324 Get_Name_String (Data.Symbol_Data.Symbol_File);
5326 if Name_Len > 0 then
5327 declare
5328 Symb_Path : constant String :=
5329 Normalize_Pathname
5330 (Get_Name_String
5331 (Data.Object_Directory.Name) &
5332 Directory_Separator &
5333 Name_Buffer (1 .. Name_Len),
5334 Directory => Current_Dir,
5335 Resolve_Links =>
5336 Opt.Follow_Links_For_Files);
5337 Ref_Path : constant String :=
5338 Normalize_Pathname
5339 (Get_Name_String
5340 (Data.Symbol_Data.Reference),
5341 Directory => Current_Dir,
5342 Resolve_Links =>
5343 Opt.Follow_Links_For_Files);
5344 begin
5345 if Symb_Path = Ref_Path then
5346 Error_Msg
5347 (Project, In_Tree,
5348 "library reference symbol file and library" &
5349 " symbol file cannot be the same file",
5350 Lib_Ref_Symbol_File.Location);
5351 end if;
5352 end;
5353 end if;
5354 end if;
5355 end if;
5356 end if;
5357 end if;
5358 end Check_Stand_Alone_Library;
5360 ----------------------------
5361 -- Compute_Directory_Last --
5362 ----------------------------
5364 function Compute_Directory_Last (Dir : String) return Natural is
5365 begin
5366 if Dir'Length > 1
5367 and then (Dir (Dir'Last - 1) = Directory_Separator
5368 or else Dir (Dir'Last - 1) = '/')
5369 then
5370 return Dir'Last - 1;
5371 else
5372 return Dir'Last;
5373 end if;
5374 end Compute_Directory_Last;
5376 ---------------
5377 -- Error_Msg --
5378 ---------------
5380 procedure Error_Msg
5381 (Project : Project_Id;
5382 In_Tree : Project_Tree_Ref;
5383 Msg : String;
5384 Flag_Location : Source_Ptr)
5386 Real_Location : Source_Ptr := Flag_Location;
5387 Error_Buffer : String (1 .. 5_000);
5388 Error_Last : Natural := 0;
5389 Name_Number : Natural := 0;
5390 File_Number : Natural := 0;
5391 First : Positive := Msg'First;
5392 Index : Positive;
5394 procedure Add (C : Character);
5395 -- Add a character to the buffer
5397 procedure Add (S : String);
5398 -- Add a string to the buffer
5400 procedure Add_Name;
5401 -- Add a name to the buffer
5403 procedure Add_File;
5404 -- Add a file name to the buffer
5406 ---------
5407 -- Add --
5408 ---------
5410 procedure Add (C : Character) is
5411 begin
5412 Error_Last := Error_Last + 1;
5413 Error_Buffer (Error_Last) := C;
5414 end Add;
5416 procedure Add (S : String) is
5417 begin
5418 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5419 Error_Last := Error_Last + S'Length;
5420 end Add;
5422 --------------
5423 -- Add_File --
5424 --------------
5426 procedure Add_File is
5427 File : File_Name_Type;
5429 begin
5430 Add ('"');
5431 File_Number := File_Number + 1;
5433 case File_Number is
5434 when 1 =>
5435 File := Err_Vars.Error_Msg_File_1;
5436 when 2 =>
5437 File := Err_Vars.Error_Msg_File_2;
5438 when 3 =>
5439 File := Err_Vars.Error_Msg_File_3;
5440 when others =>
5441 null;
5442 end case;
5444 Get_Name_String (File);
5445 Add (Name_Buffer (1 .. Name_Len));
5446 Add ('"');
5447 end Add_File;
5449 --------------
5450 -- Add_Name --
5451 --------------
5453 procedure Add_Name is
5454 Name : Name_Id;
5456 begin
5457 Add ('"');
5458 Name_Number := Name_Number + 1;
5460 case Name_Number is
5461 when 1 =>
5462 Name := Err_Vars.Error_Msg_Name_1;
5463 when 2 =>
5464 Name := Err_Vars.Error_Msg_Name_2;
5465 when 3 =>
5466 Name := Err_Vars.Error_Msg_Name_3;
5467 when others =>
5468 null;
5469 end case;
5471 Get_Name_String (Name);
5472 Add (Name_Buffer (1 .. Name_Len));
5473 Add ('"');
5474 end Add_Name;
5476 -- Start of processing for Error_Msg
5478 begin
5479 -- If location of error is unknown, use the location of the project
5481 if Real_Location = No_Location then
5482 Real_Location := In_Tree.Projects.Table (Project).Location;
5483 end if;
5485 if Error_Report = null then
5486 Prj.Err.Error_Msg (Msg, Real_Location);
5487 return;
5488 end if;
5490 -- Ignore continuation character
5492 if Msg (First) = '\' then
5493 First := First + 1;
5494 end if;
5496 -- Warning character is always the first one in this package
5497 -- this is an undocumented kludge???
5499 if Msg (First) = '?' then
5500 First := First + 1;
5501 Add ("Warning: ");
5503 elsif Msg (First) = '<' then
5504 First := First + 1;
5506 if Err_Vars.Error_Msg_Warn then
5507 Add ("Warning: ");
5508 end if;
5509 end if;
5511 Index := First;
5512 while Index <= Msg'Last loop
5513 if Msg (Index) = '{' then
5514 Add_File;
5516 elsif Msg (Index) = '%' then
5517 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5518 Index := Index + 1;
5519 end if;
5521 Add_Name;
5522 else
5523 Add (Msg (Index));
5524 end if;
5525 Index := Index + 1;
5527 end loop;
5529 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5530 end Error_Msg;
5532 ----------------------
5533 -- Find_Ada_Sources --
5534 ----------------------
5536 procedure Find_Ada_Sources
5537 (Project : Project_Id;
5538 In_Tree : Project_Tree_Ref;
5539 Data : in out Project_Data;
5540 Current_Dir : String)
5542 Source_Dir : String_List_Id := Data.Source_Dirs;
5543 Element : String_Element;
5544 Dir : Dir_Type;
5545 Current_Source : String_List_Id := Nil_String;
5546 Source_Recorded : Boolean := False;
5548 begin
5549 if Current_Verbosity = High then
5550 Write_Line ("Looking for sources:");
5551 end if;
5553 -- For each subdirectory
5555 while Source_Dir /= Nil_String loop
5556 begin
5557 Source_Recorded := False;
5558 Element := In_Tree.String_Elements.Table (Source_Dir);
5559 if Element.Value /= No_Name then
5560 Get_Name_String (Element.Display_Value);
5562 declare
5563 Source_Directory : constant String :=
5564 Name_Buffer (1 .. Name_Len) & Directory_Separator;
5565 Dir_Last : constant Natural :=
5566 Compute_Directory_Last (Source_Directory);
5568 begin
5569 if Current_Verbosity = High then
5570 Write_Str ("Source_Dir = ");
5571 Write_Line (Source_Directory);
5572 end if;
5574 -- We look at every entry in the source directory
5576 Open (Dir,
5577 Source_Directory (Source_Directory'First .. Dir_Last));
5579 loop
5580 Read (Dir, Name_Buffer, Name_Len);
5582 if Current_Verbosity = High then
5583 Write_Str (" Checking ");
5584 Write_Line (Name_Buffer (1 .. Name_Len));
5585 end if;
5587 exit when Name_Len = 0;
5589 declare
5590 File_Name : constant File_Name_Type := Name_Find;
5592 -- ??? We could probably optimize the following call:
5593 -- we need to resolve links only once for the
5594 -- directory itself, and then do a single call to
5595 -- readlink() for each file. Unfortunately that would
5596 -- require a change in Normalize_Pathname so that it
5597 -- has the option of not resolving links for its
5598 -- Directory parameter, only for Name.
5600 Path : constant String :=
5601 Normalize_Pathname
5602 (Name => Name_Buffer (1 .. Name_Len),
5603 Directory =>
5604 Source_Directory
5605 (Source_Directory'First .. Dir_Last),
5606 Resolve_Links =>
5607 Opt.Follow_Links_For_Files,
5608 Case_Sensitive => True);
5610 Path_Name : Path_Name_Type;
5612 begin
5613 Name_Len := Path'Length;
5614 Name_Buffer (1 .. Name_Len) := Path;
5615 Path_Name := Name_Find;
5617 -- We attempt to register it as a source. However,
5618 -- there is no error if the file does not contain a
5619 -- valid source. But there is an error if we have a
5620 -- duplicate unit name.
5622 Record_Ada_Source
5623 (File_Name => File_Name,
5624 Path_Name => Path_Name,
5625 Project => Project,
5626 In_Tree => In_Tree,
5627 Data => Data,
5628 Location => No_Location,
5629 Current_Source => Current_Source,
5630 Source_Recorded => Source_Recorded,
5631 Current_Dir => Current_Dir);
5632 end;
5633 end loop;
5635 Close (Dir);
5636 end;
5637 end if;
5639 exception
5640 when Directory_Error =>
5641 null;
5642 end;
5644 if Source_Recorded then
5645 In_Tree.String_Elements.Table (Source_Dir).Flag :=
5646 True;
5647 end if;
5649 Source_Dir := Element.Next;
5650 end loop;
5652 if Current_Verbosity = High then
5653 Write_Line ("end Looking for sources.");
5654 end if;
5656 end Find_Ada_Sources;
5658 --------------------------------
5659 -- Free_Ada_Naming_Exceptions --
5660 --------------------------------
5662 procedure Free_Ada_Naming_Exceptions is
5663 begin
5664 Ada_Naming_Exception_Table.Set_Last (0);
5665 Ada_Naming_Exceptions.Reset;
5666 Reverse_Ada_Naming_Exceptions.Reset;
5667 end Free_Ada_Naming_Exceptions;
5669 ---------------------
5670 -- Get_Directories --
5671 ---------------------
5673 procedure Get_Directories
5674 (Project : Project_Id;
5675 In_Tree : Project_Tree_Ref;
5676 Current_Dir : String;
5677 Data : in out Project_Data)
5679 Object_Dir : constant Variable_Value :=
5680 Util.Value_Of
5681 (Name_Object_Dir, Data.Decl.Attributes, In_Tree);
5683 Exec_Dir : constant Variable_Value :=
5684 Util.Value_Of
5685 (Name_Exec_Dir, Data.Decl.Attributes, In_Tree);
5687 Source_Dirs : constant Variable_Value :=
5688 Util.Value_Of
5689 (Name_Source_Dirs, Data.Decl.Attributes, In_Tree);
5691 Excluded_Source_Dirs : constant Variable_Value :=
5692 Util.Value_Of
5693 (Name_Excluded_Source_Dirs,
5694 Data.Decl.Attributes,
5695 In_Tree);
5697 Source_Files : constant Variable_Value :=
5698 Util.Value_Of
5699 (Name_Source_Files, Data.Decl.Attributes, In_Tree);
5701 Last_Source_Dir : String_List_Id := Nil_String;
5703 procedure Find_Source_Dirs
5704 (From : File_Name_Type;
5705 Location : Source_Ptr;
5706 Removed : Boolean := False);
5707 -- Find one or several source directories, and add (or remove, if
5708 -- Removed is True) them to list of source directories of the project.
5710 ----------------------
5711 -- Find_Source_Dirs --
5712 ----------------------
5714 procedure Find_Source_Dirs
5715 (From : File_Name_Type;
5716 Location : Source_Ptr;
5717 Removed : Boolean := False)
5719 Directory : constant String := Get_Name_String (From);
5720 Element : String_Element;
5722 procedure Recursive_Find_Dirs (Path : Name_Id);
5723 -- Find all the subdirectories (recursively) of Path and add them
5724 -- to the list of source directories of the project.
5726 -------------------------
5727 -- Recursive_Find_Dirs --
5728 -------------------------
5730 procedure Recursive_Find_Dirs (Path : Name_Id) is
5731 Dir : Dir_Type;
5732 Name : String (1 .. 250);
5733 Last : Natural;
5734 List : String_List_Id;
5735 Prev : String_List_Id;
5736 Element : String_Element;
5737 Found : Boolean := False;
5739 Non_Canonical_Path : Name_Id := No_Name;
5740 Canonical_Path : Name_Id := No_Name;
5742 The_Path : constant String :=
5743 Normalize_Pathname
5744 (Get_Name_String (Path),
5745 Directory => Current_Dir,
5746 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5747 Directory_Separator;
5749 The_Path_Last : constant Natural :=
5750 Compute_Directory_Last (The_Path);
5752 begin
5753 Name_Len := The_Path_Last - The_Path'First + 1;
5754 Name_Buffer (1 .. Name_Len) :=
5755 The_Path (The_Path'First .. The_Path_Last);
5756 Non_Canonical_Path := Name_Find;
5758 if Osint.File_Names_Case_Sensitive then
5759 Canonical_Path := Non_Canonical_Path;
5760 else
5761 Get_Name_String (Non_Canonical_Path);
5762 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5763 Canonical_Path := Name_Find;
5764 end if;
5766 -- To avoid processing the same directory several times, check
5767 -- if the directory is already in Recursive_Dirs. If it is, then
5768 -- there is nothing to do, just return. If it is not, put it there
5769 -- and continue recursive processing.
5771 if not Removed then
5772 if Recursive_Dirs.Get (Canonical_Path) then
5773 return;
5774 else
5775 Recursive_Dirs.Set (Canonical_Path, True);
5776 end if;
5777 end if;
5779 -- Check if directory is already in list
5781 List := Data.Source_Dirs;
5782 Prev := Nil_String;
5783 while List /= Nil_String loop
5784 Element := In_Tree.String_Elements.Table (List);
5786 if Element.Value /= No_Name then
5787 Found := Element.Value = Canonical_Path;
5788 exit when Found;
5789 end if;
5791 Prev := List;
5792 List := Element.Next;
5793 end loop;
5795 -- If directory is not already in list, put it there
5797 if (not Removed) and (not Found) then
5798 if Current_Verbosity = High then
5799 Write_Str (" ");
5800 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5801 end if;
5803 String_Element_Table.Increment_Last
5804 (In_Tree.String_Elements);
5805 Element :=
5806 (Value => Canonical_Path,
5807 Display_Value => Non_Canonical_Path,
5808 Location => No_Location,
5809 Flag => False,
5810 Next => Nil_String,
5811 Index => 0);
5813 -- Case of first source directory
5815 if Last_Source_Dir = Nil_String then
5816 Data.Source_Dirs := String_Element_Table.Last
5817 (In_Tree.String_Elements);
5819 -- Here we already have source directories
5821 else
5822 -- Link the previous last to the new one
5824 In_Tree.String_Elements.Table
5825 (Last_Source_Dir).Next :=
5826 String_Element_Table.Last
5827 (In_Tree.String_Elements);
5828 end if;
5830 -- And register this source directory as the new last
5832 Last_Source_Dir := String_Element_Table.Last
5833 (In_Tree.String_Elements);
5834 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5835 Element;
5837 elsif Removed and Found then
5838 if Prev = Nil_String then
5839 Data.Source_Dirs :=
5840 In_Tree.String_Elements.Table (List).Next;
5841 else
5842 In_Tree.String_Elements.Table (Prev).Next :=
5843 In_Tree.String_Elements.Table (List).Next;
5844 end if;
5845 end if;
5847 -- Now look for subdirectories. We do that even when this
5848 -- directory is already in the list, because some of its
5849 -- subdirectories may not be in the list yet.
5851 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5853 loop
5854 Read (Dir, Name, Last);
5855 exit when Last = 0;
5857 if Name (1 .. Last) /= "."
5858 and then Name (1 .. Last) /= ".."
5859 then
5860 -- Avoid . and .. directories
5862 if Current_Verbosity = High then
5863 Write_Str (" Checking ");
5864 Write_Line (Name (1 .. Last));
5865 end if;
5867 declare
5868 Path_Name : constant String :=
5869 Normalize_Pathname
5870 (Name => Name (1 .. Last),
5871 Directory =>
5872 The_Path (The_Path'First .. The_Path_Last),
5873 Resolve_Links => Opt.Follow_Links_For_Dirs,
5874 Case_Sensitive => True);
5876 begin
5877 if Is_Directory (Path_Name) then
5878 -- We have found a new subdirectory, call self
5880 Name_Len := Path_Name'Length;
5881 Name_Buffer (1 .. Name_Len) := Path_Name;
5882 Recursive_Find_Dirs (Name_Find);
5883 end if;
5884 end;
5885 end if;
5886 end loop;
5888 Close (Dir);
5890 exception
5891 when Directory_Error =>
5892 null;
5893 end Recursive_Find_Dirs;
5895 -- Start of processing for Find_Source_Dirs
5897 begin
5898 if Current_Verbosity = High and then not Removed then
5899 Write_Str ("Find_Source_Dirs (""");
5900 Write_Str (Directory);
5901 Write_Line (""")");
5902 end if;
5904 -- First, check if we are looking for a directory tree, indicated
5905 -- by "/**" at the end.
5907 if Directory'Length >= 3
5908 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5909 and then (Directory (Directory'Last - 2) = '/'
5910 or else
5911 Directory (Directory'Last - 2) = Directory_Separator)
5912 then
5913 if not Removed then
5914 Data.Known_Order_Of_Source_Dirs := False;
5915 end if;
5917 Name_Len := Directory'Length - 3;
5919 if Name_Len = 0 then
5921 -- Case of "/**": all directories in file system
5923 Name_Len := 1;
5924 Name_Buffer (1) := Directory (Directory'First);
5926 else
5927 Name_Buffer (1 .. Name_Len) :=
5928 Directory (Directory'First .. Directory'Last - 3);
5929 end if;
5931 if Current_Verbosity = High then
5932 Write_Str ("Looking for all subdirectories of """);
5933 Write_Str (Name_Buffer (1 .. Name_Len));
5934 Write_Line ("""");
5935 end if;
5937 declare
5938 Base_Dir : constant File_Name_Type := Name_Find;
5939 Root_Dir : constant String :=
5940 Normalize_Pathname
5941 (Name => Get_Name_String (Base_Dir),
5942 Directory =>
5943 Get_Name_String (Data.Directory.Display_Name),
5944 Resolve_Links => False,
5945 Case_Sensitive => True);
5947 begin
5948 if Root_Dir'Length = 0 then
5949 Err_Vars.Error_Msg_File_1 := Base_Dir;
5951 if Location = No_Location then
5952 Error_Msg
5953 (Project, In_Tree,
5954 "{ is not a valid directory.",
5955 Data.Location);
5956 else
5957 Error_Msg
5958 (Project, In_Tree,
5959 "{ is not a valid directory.",
5960 Location);
5961 end if;
5963 else
5964 -- We have an existing directory, we register it and all of
5965 -- its subdirectories.
5967 if Current_Verbosity = High then
5968 Write_Line ("Looking for source directories:");
5969 end if;
5971 Name_Len := Root_Dir'Length;
5972 Name_Buffer (1 .. Name_Len) := Root_Dir;
5973 Recursive_Find_Dirs (Name_Find);
5975 if Current_Verbosity = High then
5976 Write_Line ("End of looking for source directories.");
5977 end if;
5978 end if;
5979 end;
5981 -- We have a single directory
5983 else
5984 declare
5985 Path_Name : Path_Name_Type;
5986 Display_Path_Name : Path_Name_Type;
5987 List : String_List_Id;
5988 Prev : String_List_Id;
5990 begin
5991 Locate_Directory
5992 (Project => Project,
5993 In_Tree => In_Tree,
5994 Name => From,
5995 Parent => Data.Directory.Display_Name,
5996 Dir => Path_Name,
5997 Display => Display_Path_Name,
5998 Current_Dir => Current_Dir);
6000 if Path_Name = No_Path then
6001 Err_Vars.Error_Msg_File_1 := From;
6003 if Location = No_Location then
6004 Error_Msg
6005 (Project, In_Tree,
6006 "{ is not a valid directory",
6007 Data.Location);
6008 else
6009 Error_Msg
6010 (Project, In_Tree,
6011 "{ is not a valid directory",
6012 Location);
6013 end if;
6015 else
6016 declare
6017 Path : constant String :=
6018 Get_Name_String (Path_Name) &
6019 Directory_Separator;
6020 Last_Path : constant Natural :=
6021 Compute_Directory_Last (Path);
6022 Path_Id : Name_Id;
6023 Display_Path : constant String :=
6024 Get_Name_String
6025 (Display_Path_Name) &
6026 Directory_Separator;
6027 Last_Display_Path : constant Natural :=
6028 Compute_Directory_Last
6029 (Display_Path);
6030 Display_Path_Id : Name_Id;
6032 begin
6033 Name_Len := 0;
6034 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
6035 Path_Id := Name_Find;
6036 Name_Len := 0;
6037 Add_Str_To_Name_Buffer
6038 (Display_Path
6039 (Display_Path'First .. Last_Display_Path));
6040 Display_Path_Id := Name_Find;
6042 if not Removed then
6044 -- As it is an existing directory, we add it to the
6045 -- list of directories.
6047 String_Element_Table.Increment_Last
6048 (In_Tree.String_Elements);
6049 Element :=
6050 (Value => Path_Id,
6051 Index => 0,
6052 Display_Value => Display_Path_Id,
6053 Location => No_Location,
6054 Flag => False,
6055 Next => Nil_String);
6057 if Last_Source_Dir = Nil_String then
6059 -- This is the first source directory
6061 Data.Source_Dirs := String_Element_Table.Last
6062 (In_Tree.String_Elements);
6064 else
6065 -- We already have source directories, link the
6066 -- previous last to the new one.
6068 In_Tree.String_Elements.Table
6069 (Last_Source_Dir).Next :=
6070 String_Element_Table.Last
6071 (In_Tree.String_Elements);
6072 end if;
6074 -- And register this source directory as the new last
6076 Last_Source_Dir := String_Element_Table.Last
6077 (In_Tree.String_Elements);
6078 In_Tree.String_Elements.Table
6079 (Last_Source_Dir) := Element;
6081 else
6082 -- Remove source dir, if present
6084 List := Data.Source_Dirs;
6085 Prev := Nil_String;
6087 -- Look for source dir in current list
6089 while List /= Nil_String loop
6090 Element := In_Tree.String_Elements.Table (List);
6091 exit when Element.Value = Path_Id;
6092 Prev := List;
6093 List := Element.Next;
6094 end loop;
6096 if List /= Nil_String then
6097 -- Source dir was found, remove it from the list
6099 if Prev = Nil_String then
6100 Data.Source_Dirs :=
6101 In_Tree.String_Elements.Table (List).Next;
6103 else
6104 In_Tree.String_Elements.Table (Prev).Next :=
6105 In_Tree.String_Elements.Table (List).Next;
6106 end if;
6107 end if;
6108 end if;
6109 end;
6110 end if;
6111 end;
6112 end if;
6113 end Find_Source_Dirs;
6115 -- Start of processing for Get_Directories
6117 begin
6118 if Current_Verbosity = High then
6119 Write_Line ("Starting to look for directories");
6120 end if;
6122 -- Check the object directory
6124 pragma Assert (Object_Dir.Kind = Single,
6125 "Object_Dir is not a single string");
6127 -- We set the object directory to its default
6129 Data.Object_Directory := Data.Directory;
6131 if Object_Dir.Value /= Empty_String then
6132 Get_Name_String (Object_Dir.Value);
6134 if Name_Len = 0 then
6135 Error_Msg
6136 (Project, In_Tree,
6137 "Object_Dir cannot be empty",
6138 Object_Dir.Location);
6140 else
6141 -- We check that the specified object directory does exist
6143 Locate_Directory
6144 (Project,
6145 In_Tree,
6146 File_Name_Type (Object_Dir.Value),
6147 Data.Directory.Display_Name,
6148 Data.Object_Directory.Name,
6149 Data.Object_Directory.Display_Name,
6150 Create => "object",
6151 Location => Object_Dir.Location,
6152 Current_Dir => Current_Dir);
6154 if Data.Object_Directory = No_Path_Information then
6156 -- The object directory does not exist, report an error if the
6157 -- project is not externally built.
6159 if not Data.Externally_Built then
6160 Err_Vars.Error_Msg_File_1 :=
6161 File_Name_Type (Object_Dir.Value);
6162 Error_Msg
6163 (Project, In_Tree,
6164 "the object directory { cannot be found",
6165 Data.Location);
6166 end if;
6168 -- Do not keep a nil Object_Directory. Set it to the specified
6169 -- (relative or absolute) path. This is for the benefit of
6170 -- tools that recover from errors; for example, these tools
6171 -- could create the non existent directory.
6173 Data.Object_Directory.Display_Name :=
6174 Path_Name_Type (Object_Dir.Value);
6176 if Osint.File_Names_Case_Sensitive then
6177 Data.Object_Directory.Name :=
6178 Path_Name_Type (Object_Dir.Value);
6179 else
6180 Get_Name_String (Object_Dir.Value);
6181 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6182 Data.Object_Directory.Name := Name_Find;
6183 end if;
6184 end if;
6185 end if;
6187 elsif Subdirs /= null then
6188 Name_Len := 1;
6189 Name_Buffer (1) := '.';
6190 Locate_Directory
6191 (Project,
6192 In_Tree,
6193 Name_Find,
6194 Data.Directory.Display_Name,
6195 Data.Object_Directory.Name,
6196 Data.Object_Directory.Display_Name,
6197 Create => "object",
6198 Location => Object_Dir.Location,
6199 Current_Dir => Current_Dir);
6200 end if;
6202 if Current_Verbosity = High then
6203 if Data.Object_Directory = No_Path_Information then
6204 Write_Line ("No object directory");
6205 else
6206 Write_Str ("Object directory: """);
6207 Write_Str (Get_Name_String (Data.Object_Directory.Display_Name));
6208 Write_Line ("""");
6209 end if;
6210 end if;
6212 -- Check the exec directory
6214 pragma Assert (Exec_Dir.Kind = Single,
6215 "Exec_Dir is not a single string");
6217 -- We set the object directory to its default
6219 Data.Exec_Directory := Data.Object_Directory;
6221 if Exec_Dir.Value /= Empty_String then
6222 Get_Name_String (Exec_Dir.Value);
6224 if Name_Len = 0 then
6225 Error_Msg
6226 (Project, In_Tree,
6227 "Exec_Dir cannot be empty",
6228 Exec_Dir.Location);
6230 else
6231 -- We check that the specified exec directory does exist
6233 Locate_Directory
6234 (Project,
6235 In_Tree,
6236 File_Name_Type (Exec_Dir.Value),
6237 Data.Directory.Display_Name,
6238 Data.Exec_Directory.Name,
6239 Data.Exec_Directory.Display_Name,
6240 Create => "exec",
6241 Location => Exec_Dir.Location,
6242 Current_Dir => Current_Dir);
6244 if Data.Exec_Directory = No_Path_Information then
6245 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
6246 Error_Msg
6247 (Project, In_Tree,
6248 "the exec directory { cannot be found",
6249 Data.Location);
6250 end if;
6251 end if;
6252 end if;
6254 if Current_Verbosity = High then
6255 if Data.Exec_Directory = No_Path_Information then
6256 Write_Line ("No exec directory");
6257 else
6258 Write_Str ("Exec directory: """);
6259 Write_Str (Get_Name_String (Data.Exec_Directory.Display_Name));
6260 Write_Line ("""");
6261 end if;
6262 end if;
6264 -- Look for the source directories
6266 if Current_Verbosity = High then
6267 Write_Line ("Starting to look for source directories");
6268 end if;
6270 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
6272 if (not Source_Files.Default) and then
6273 Source_Files.Values = Nil_String
6274 then
6275 Data.Source_Dirs := Nil_String;
6277 if Data.Qualifier = Standard then
6278 Error_Msg
6279 (Project,
6280 In_Tree,
6281 "a standard project cannot have no sources",
6282 Source_Files.Location);
6283 end if;
6285 if Data.Extends = No_Project
6286 and then Data.Object_Directory = Data.Directory
6287 then
6288 Data.Object_Directory := No_Path_Information;
6289 end if;
6291 elsif Source_Dirs.Default then
6293 -- No Source_Dirs specified: the single source directory is the one
6294 -- containing the project file
6296 String_Element_Table.Increment_Last
6297 (In_Tree.String_Elements);
6298 Data.Source_Dirs := String_Element_Table.Last
6299 (In_Tree.String_Elements);
6300 In_Tree.String_Elements.Table (Data.Source_Dirs) :=
6301 (Value => Name_Id (Data.Directory.Name),
6302 Display_Value => Name_Id (Data.Directory.Display_Name),
6303 Location => No_Location,
6304 Flag => False,
6305 Next => Nil_String,
6306 Index => 0);
6308 if Current_Verbosity = High then
6309 Write_Line ("Single source directory:");
6310 Write_Str (" """);
6311 Write_Str (Get_Name_String (Data.Directory.Display_Name));
6312 Write_Line ("""");
6313 end if;
6315 elsif Source_Dirs.Values = Nil_String then
6316 if Data.Qualifier = Standard then
6317 Error_Msg
6318 (Project,
6319 In_Tree,
6320 "a standard project cannot have no source directories",
6321 Source_Dirs.Location);
6322 end if;
6324 -- If Source_Dirs is an empty string list, this means that this
6325 -- project contains no source. For projects that don't extend other
6326 -- projects, this also means that there is no need for an object
6327 -- directory, if not specified.
6329 if Data.Extends = No_Project
6330 and then Data.Object_Directory = Data.Directory
6331 then
6332 Data.Object_Directory := No_Path_Information;
6333 end if;
6335 Data.Source_Dirs := Nil_String;
6337 else
6338 declare
6339 Source_Dir : String_List_Id;
6340 Element : String_Element;
6342 begin
6343 -- Process the source directories for each element of the list
6345 Source_Dir := Source_Dirs.Values;
6346 while Source_Dir /= Nil_String loop
6347 Element := In_Tree.String_Elements.Table (Source_Dir);
6348 Find_Source_Dirs
6349 (File_Name_Type (Element.Value), Element.Location);
6350 Source_Dir := Element.Next;
6351 end loop;
6352 end;
6353 end if;
6355 if not Excluded_Source_Dirs.Default
6356 and then Excluded_Source_Dirs.Values /= Nil_String
6357 then
6358 declare
6359 Source_Dir : String_List_Id;
6360 Element : String_Element;
6362 begin
6363 -- Process the source directories for each element of the list
6365 Source_Dir := Excluded_Source_Dirs.Values;
6366 while Source_Dir /= Nil_String loop
6367 Element := In_Tree.String_Elements.Table (Source_Dir);
6368 Find_Source_Dirs
6369 (File_Name_Type (Element.Value),
6370 Element.Location,
6371 Removed => True);
6372 Source_Dir := Element.Next;
6373 end loop;
6374 end;
6375 end if;
6377 if Current_Verbosity = High then
6378 Write_Line ("Putting source directories in canonical cases");
6379 end if;
6381 declare
6382 Current : String_List_Id := Data.Source_Dirs;
6383 Element : String_Element;
6385 begin
6386 while Current /= Nil_String loop
6387 Element := In_Tree.String_Elements.Table (Current);
6388 if Element.Value /= No_Name then
6389 if not Osint.File_Names_Case_Sensitive then
6390 Get_Name_String (Element.Value);
6391 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6392 Element.Value := Name_Find;
6393 end if;
6395 In_Tree.String_Elements.Table (Current) := Element;
6396 end if;
6398 Current := Element.Next;
6399 end loop;
6400 end;
6402 end Get_Directories;
6404 ---------------
6405 -- Get_Mains --
6406 ---------------
6408 procedure Get_Mains
6409 (Project : Project_Id;
6410 In_Tree : Project_Tree_Ref;
6411 Data : in out Project_Data)
6413 Mains : constant Variable_Value :=
6414 Prj.Util.Value_Of (Name_Main, Data.Decl.Attributes, In_Tree);
6416 begin
6417 Data.Mains := Mains.Values;
6419 -- If no Mains were specified, and if we are an extending project,
6420 -- inherit the Mains from the project we are extending.
6422 if Mains.Default then
6423 if not Data.Library and then Data.Extends /= No_Project then
6424 Data.Mains :=
6425 In_Tree.Projects.Table (Data.Extends).Mains;
6426 end if;
6428 -- In a library project file, Main cannot be specified
6430 elsif Data.Library then
6431 Error_Msg
6432 (Project, In_Tree,
6433 "a library project file cannot have Main specified",
6434 Mains.Location);
6435 end if;
6436 end Get_Mains;
6438 ---------------------------
6439 -- Get_Sources_From_File --
6440 ---------------------------
6442 procedure Get_Sources_From_File
6443 (Path : String;
6444 Location : Source_Ptr;
6445 Project : Project_Id;
6446 In_Tree : Project_Tree_Ref)
6448 File : Prj.Util.Text_File;
6449 Line : String (1 .. 250);
6450 Last : Natural;
6451 Source_Name : File_Name_Type;
6452 Name_Loc : Name_Location;
6454 begin
6455 if Get_Mode = Ada_Only then
6456 Source_Names.Reset;
6457 end if;
6459 if Current_Verbosity = High then
6460 Write_Str ("Opening """);
6461 Write_Str (Path);
6462 Write_Line (""".");
6463 end if;
6465 -- Open the file
6467 Prj.Util.Open (File, Path);
6469 if not Prj.Util.Is_Valid (File) then
6470 Error_Msg (Project, In_Tree, "file does not exist", Location);
6472 else
6473 -- Read the lines one by one
6475 while not Prj.Util.End_Of_File (File) loop
6476 Prj.Util.Get_Line (File, Line, Last);
6478 -- A non empty, non comment line should contain a file name
6480 if Last /= 0
6481 and then (Last = 1 or else Line (1 .. 2) /= "--")
6482 then
6483 Name_Len := Last;
6484 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6485 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6486 Source_Name := Name_Find;
6488 -- Check that there is no directory information
6490 for J in 1 .. Last loop
6491 if Line (J) = '/' or else Line (J) = Directory_Separator then
6492 Error_Msg_File_1 := Source_Name;
6493 Error_Msg
6494 (Project,
6495 In_Tree,
6496 "file name cannot include directory information ({)",
6497 Location);
6498 exit;
6499 end if;
6500 end loop;
6502 Name_Loc := Source_Names.Get (Source_Name);
6504 if Name_Loc = No_Name_Location then
6505 Name_Loc :=
6506 (Name => Source_Name,
6507 Location => Location,
6508 Source => No_Source,
6509 Except => False,
6510 Found => False);
6511 end if;
6513 Source_Names.Set (Source_Name, Name_Loc);
6514 end if;
6515 end loop;
6517 Prj.Util.Close (File);
6519 end if;
6520 end Get_Sources_From_File;
6522 --------------
6523 -- Get_Unit --
6524 --------------
6526 procedure Get_Unit
6527 (In_Tree : Project_Tree_Ref;
6528 Canonical_File_Name : File_Name_Type;
6529 Naming : Naming_Data;
6530 Exception_Id : out Ada_Naming_Exception_Id;
6531 Unit_Name : out Name_Id;
6532 Unit_Kind : out Spec_Or_Body;
6533 Needs_Pragma : out Boolean)
6535 Info_Id : Ada_Naming_Exception_Id :=
6536 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6537 VMS_Name : File_Name_Type;
6539 begin
6540 if Info_Id = No_Ada_Naming_Exception then
6541 if Hostparm.OpenVMS then
6542 VMS_Name := Canonical_File_Name;
6543 Get_Name_String (VMS_Name);
6545 if Name_Buffer (Name_Len) = '.' then
6546 Name_Len := Name_Len - 1;
6547 VMS_Name := Name_Find;
6548 end if;
6550 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6551 end if;
6553 end if;
6555 if Info_Id /= No_Ada_Naming_Exception then
6556 Exception_Id := Info_Id;
6557 Unit_Name := No_Name;
6558 Unit_Kind := Specification;
6559 Needs_Pragma := True;
6560 return;
6561 end if;
6563 Needs_Pragma := False;
6564 Exception_Id := No_Ada_Naming_Exception;
6566 Get_Name_String (Canonical_File_Name);
6568 -- How about some comments and a name for this declare block ???
6569 -- In fact the whole code below needs more comments ???
6571 declare
6572 File : String := Name_Buffer (1 .. Name_Len);
6573 First : constant Positive := File'First;
6574 Last : Natural := File'Last;
6575 Standard_GNAT : Boolean;
6576 Spec : constant File_Name_Type :=
6577 Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6578 Body_Suff : constant File_Name_Type :=
6579 Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming);
6581 begin
6582 Standard_GNAT := Spec = Default_Ada_Spec_Suffix
6583 and then Body_Suff = Default_Ada_Body_Suffix;
6585 declare
6586 Spec_Suffix : constant String := Get_Name_String (Spec);
6587 Body_Suffix : constant String := Get_Name_String (Body_Suff);
6588 Sep_Suffix : constant String :=
6589 Get_Name_String (Naming.Separate_Suffix);
6591 May_Be_Spec : Boolean;
6592 May_Be_Body : Boolean;
6593 May_Be_Sep : Boolean;
6595 begin
6596 May_Be_Spec :=
6597 File'Length > Spec_Suffix'Length
6598 and then
6599 File (Last - Spec_Suffix'Length + 1 .. Last) = Spec_Suffix;
6601 May_Be_Body :=
6602 File'Length > Body_Suffix'Length
6603 and then
6604 File (Last - Body_Suffix'Length + 1 .. Last) = Body_Suffix;
6606 May_Be_Sep :=
6607 File'Length > Sep_Suffix'Length
6608 and then
6609 File (Last - Sep_Suffix'Length + 1 .. Last) = Sep_Suffix;
6611 -- If two May_Be_ booleans are True, always choose the longer one
6613 if May_Be_Spec then
6614 if May_Be_Body and then
6615 Spec_Suffix'Length < Body_Suffix'Length
6616 then
6617 Unit_Kind := Body_Part;
6619 if May_Be_Sep and then
6620 Body_Suffix'Length < Sep_Suffix'Length
6621 then
6622 Last := Last - Sep_Suffix'Length;
6623 May_Be_Body := False;
6625 else
6626 Last := Last - Body_Suffix'Length;
6627 May_Be_Sep := False;
6628 end if;
6630 elsif May_Be_Sep and then
6631 Spec_Suffix'Length < Sep_Suffix'Length
6632 then
6633 Unit_Kind := Body_Part;
6634 Last := Last - Sep_Suffix'Length;
6636 else
6637 Unit_Kind := Specification;
6638 Last := Last - Spec_Suffix'Length;
6639 end if;
6641 elsif May_Be_Body then
6642 Unit_Kind := Body_Part;
6644 if May_Be_Sep and then
6645 Body_Suffix'Length < Sep_Suffix'Length
6646 then
6647 Last := Last - Sep_Suffix'Length;
6648 May_Be_Body := False;
6649 else
6650 Last := Last - Body_Suffix'Length;
6651 May_Be_Sep := False;
6652 end if;
6654 elsif May_Be_Sep then
6655 Unit_Kind := Body_Part;
6656 Last := Last - Sep_Suffix'Length;
6658 else
6659 Last := 0;
6660 end if;
6662 if Last = 0 then
6664 -- This is not a source file
6666 Unit_Name := No_Name;
6667 Unit_Kind := Specification;
6669 if Current_Verbosity = High then
6670 Write_Line (" Not a valid file name.");
6671 end if;
6673 return;
6675 elsif Current_Verbosity = High then
6676 case Unit_Kind is
6677 when Specification =>
6678 Write_Str (" Specification: ");
6679 Write_Line (File (First .. Last + Spec_Suffix'Length));
6681 when Body_Part =>
6682 if May_Be_Body then
6683 Write_Str (" Body: ");
6684 Write_Line (File (First .. Last + Body_Suffix'Length));
6686 else
6687 Write_Str (" Separate: ");
6688 Write_Line (File (First .. Last + Sep_Suffix'Length));
6689 end if;
6690 end case;
6691 end if;
6692 end;
6694 Get_Name_String (Naming.Dot_Replacement);
6695 Standard_GNAT :=
6696 Standard_GNAT and then Name_Buffer (1 .. Name_Len) = "-";
6698 if Name_Buffer (1 .. Name_Len) /= "." then
6700 -- If Dot_Replacement is not a single dot, then there should not
6701 -- be any dot in the name.
6703 for Index in First .. Last loop
6704 if File (Index) = '.' then
6705 if Current_Verbosity = High then
6706 Write_Line
6707 (" Not a valid file name (some dot not replaced).");
6708 end if;
6710 Unit_Name := No_Name;
6711 return;
6713 end if;
6714 end loop;
6716 -- Replace the substring Dot_Replacement with dots
6718 declare
6719 Index : Positive := First;
6721 begin
6722 while Index <= Last - Name_Len + 1 loop
6724 if File (Index .. Index + Name_Len - 1) =
6725 Name_Buffer (1 .. Name_Len)
6726 then
6727 File (Index) := '.';
6729 if Name_Len > 1 and then Index < Last then
6730 File (Index + 1 .. Last - Name_Len + 1) :=
6731 File (Index + Name_Len .. Last);
6732 end if;
6734 Last := Last - Name_Len + 1;
6735 end if;
6737 Index := Index + 1;
6738 end loop;
6739 end;
6740 end if;
6742 -- Check if the casing is right
6744 declare
6745 Src : String := File (First .. Last);
6746 Src_Last : Positive := Last;
6748 begin
6749 case Naming.Casing is
6750 when All_Lower_Case =>
6751 Fixed.Translate
6752 (Source => Src,
6753 Mapping => Lower_Case_Map);
6755 when All_Upper_Case =>
6756 Fixed.Translate
6757 (Source => Src,
6758 Mapping => Upper_Case_Map);
6760 when Mixed_Case | Unknown =>
6761 null;
6762 end case;
6764 if Src /= File (First .. Last) then
6765 if Current_Verbosity = High then
6766 Write_Line (" Not a valid file name (casing).");
6767 end if;
6769 Unit_Name := No_Name;
6770 return;
6771 end if;
6773 -- We put the name in lower case
6775 Fixed.Translate
6776 (Source => Src,
6777 Mapping => Lower_Case_Map);
6779 -- In the standard GNAT naming scheme, check for special cases:
6780 -- children or separates of A, G, I or S, and run time sources.
6782 if Standard_GNAT and then Src'Length >= 3 then
6783 declare
6784 S1 : constant Character := Src (Src'First);
6785 S2 : constant Character := Src (Src'First + 1);
6786 S3 : constant Character := Src (Src'First + 2);
6788 begin
6789 if S1 = 'a' or else
6790 S1 = 'g' or else
6791 S1 = 'i' or else
6792 S1 = 's'
6793 then
6794 -- Children or separates of packages A, G, I or S. These
6795 -- names are x__ ... or x~... (where x is a, g, i, or s).
6796 -- Both versions (x__... and x~...) are allowed in all
6797 -- platforms, because it is not possible to know the
6798 -- platform before processing of the project files.
6800 if S2 = '_' and then S3 = '_' then
6801 Src (Src'First + 1) := '.';
6802 Src_Last := Src_Last - 1;
6803 Src (Src'First + 2 .. Src_Last) :=
6804 Src (Src'First + 3 .. Src_Last + 1);
6806 elsif S2 = '~' then
6807 Src (Src'First + 1) := '.';
6809 -- If it is potentially a run time source, disable
6810 -- filling of the mapping file to avoid warnings.
6812 elsif S2 = '.' then
6813 Set_Mapping_File_Initial_State_To_Empty;
6814 end if;
6815 end if;
6816 end;
6817 end if;
6819 if Current_Verbosity = High then
6820 Write_Str (" ");
6821 Write_Line (Src (Src'First .. Src_Last));
6822 end if;
6824 -- Now, we check if this name is a valid unit name
6826 Check_Ada_Name
6827 (Name => Src (Src'First .. Src_Last), Unit => Unit_Name);
6828 end;
6830 end;
6831 end Get_Unit;
6833 ----------
6834 -- Hash --
6835 ----------
6837 function Hash (Unit : Unit_Info) return Header_Num is
6838 begin
6839 return Header_Num (Unit.Unit mod 2048);
6840 end Hash;
6842 -----------------------
6843 -- Is_Illegal_Suffix --
6844 -----------------------
6846 function Is_Illegal_Suffix
6847 (Suffix : String;
6848 Dot_Replacement_Is_A_Single_Dot : Boolean) return Boolean
6850 begin
6851 if Suffix'Length = 0 or else Index (Suffix, ".") = 0 then
6852 return True;
6853 end if;
6855 -- If dot replacement is a single dot, and first character of suffix is
6856 -- also a dot
6858 if Dot_Replacement_Is_A_Single_Dot
6859 and then Suffix (Suffix'First) = '.'
6860 then
6861 for Index in Suffix'First + 1 .. Suffix'Last loop
6863 -- If there is another dot
6865 if Suffix (Index) = '.' then
6867 -- It is illegal to have a letter following the initial dot
6869 return Is_Letter (Suffix (Suffix'First + 1));
6870 end if;
6871 end loop;
6872 end if;
6874 -- Everything is OK
6876 return False;
6877 end Is_Illegal_Suffix;
6879 ----------------------
6880 -- Locate_Directory --
6881 ----------------------
6883 procedure Locate_Directory
6884 (Project : Project_Id;
6885 In_Tree : Project_Tree_Ref;
6886 Name : File_Name_Type;
6887 Parent : Path_Name_Type;
6888 Dir : out Path_Name_Type;
6889 Display : out Path_Name_Type;
6890 Create : String := "";
6891 Current_Dir : String;
6892 Location : Source_Ptr := No_Location)
6894 The_Parent : constant String :=
6895 Get_Name_String (Parent) & Directory_Separator;
6897 The_Parent_Last : constant Natural :=
6898 Compute_Directory_Last (The_Parent);
6900 Full_Name : File_Name_Type;
6902 The_Name : File_Name_Type;
6904 begin
6905 Get_Name_String (Name);
6907 -- Add Subdirs.all if it is a directory that may be created and
6908 -- Subdirs is not null;
6910 if Create /= "" and then Subdirs /= null then
6911 if Name_Buffer (Name_Len) /= Directory_Separator then
6912 Add_Char_To_Name_Buffer (Directory_Separator);
6913 end if;
6915 Add_Str_To_Name_Buffer (Subdirs.all);
6916 end if;
6918 -- Convert '/' to directory separator (for Windows)
6920 for J in 1 .. Name_Len loop
6921 if Name_Buffer (J) = '/' then
6922 Name_Buffer (J) := Directory_Separator;
6923 end if;
6924 end loop;
6926 The_Name := Name_Find;
6928 if Current_Verbosity = High then
6929 Write_Str ("Locate_Directory (""");
6930 Write_Str (Get_Name_String (The_Name));
6931 Write_Str (""", """);
6932 Write_Str (The_Parent);
6933 Write_Line (""")");
6934 end if;
6936 Dir := No_Path;
6937 Display := No_Path;
6939 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6940 Full_Name := The_Name;
6942 else
6943 Name_Len := 0;
6944 Add_Str_To_Name_Buffer
6945 (The_Parent (The_Parent'First .. The_Parent_Last));
6946 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6947 Full_Name := Name_Find;
6948 end if;
6950 declare
6951 Full_Path_Name : constant String := Get_Name_String (Full_Name);
6953 begin
6954 if (Setup_Projects or else Subdirs /= null)
6955 and then Create'Length > 0
6956 and then not Is_Directory (Full_Path_Name)
6957 then
6958 begin
6959 Create_Path (Full_Path_Name);
6961 if not Quiet_Output then
6962 Write_Str (Create);
6963 Write_Str (" directory """);
6964 Write_Str (Full_Path_Name);
6965 Write_Line (""" created");
6966 end if;
6968 exception
6969 when Use_Error =>
6970 Error_Msg
6971 (Project, In_Tree,
6972 "could not create " & Create &
6973 " directory " & Full_Path_Name,
6974 Location);
6975 end;
6976 end if;
6978 if Is_Directory (Full_Path_Name) then
6979 declare
6980 Normed : constant String :=
6981 Normalize_Pathname
6982 (Full_Path_Name,
6983 Directory => Current_Dir,
6984 Resolve_Links => False,
6985 Case_Sensitive => True);
6987 Canonical_Path : constant String :=
6988 Normalize_Pathname
6989 (Normed,
6990 Directory => Current_Dir,
6991 Resolve_Links =>
6992 Opt.Follow_Links_For_Dirs,
6993 Case_Sensitive => False);
6995 begin
6996 Name_Len := Normed'Length;
6997 Name_Buffer (1 .. Name_Len) := Normed;
6998 Display := Name_Find;
7000 Name_Len := Canonical_Path'Length;
7001 Name_Buffer (1 .. Name_Len) := Canonical_Path;
7002 Dir := Name_Find;
7003 end;
7004 end if;
7005 end;
7006 end Locate_Directory;
7008 ---------------------------
7009 -- Find_Excluded_Sources --
7010 ---------------------------
7012 procedure Find_Excluded_Sources
7013 (Project : Project_Id;
7014 In_Tree : Project_Tree_Ref;
7015 Data : Project_Data)
7017 Excluded_Sources : Variable_Value;
7019 Excluded_Source_List_File : Variable_Value;
7021 Current : String_List_Id;
7023 Element : String_Element;
7025 Location : Source_Ptr;
7027 Name : File_Name_Type;
7029 File : Prj.Util.Text_File;
7030 Line : String (1 .. 300);
7031 Last : Natural;
7033 Locally_Removed : Boolean := False;
7034 begin
7035 Excluded_Source_List_File :=
7036 Util.Value_Of
7037 (Name_Excluded_Source_List_File, Data.Decl.Attributes, In_Tree);
7039 Excluded_Sources :=
7040 Util.Value_Of
7041 (Name_Excluded_Source_Files, Data.Decl.Attributes, In_Tree);
7043 -- If Excluded_Source_Files is not declared, check
7044 -- Locally_Removed_Files.
7046 if Excluded_Sources.Default then
7047 Locally_Removed := True;
7048 Excluded_Sources :=
7049 Util.Value_Of
7050 (Name_Locally_Removed_Files, Data.Decl.Attributes, In_Tree);
7051 end if;
7053 Excluded_Sources_Htable.Reset;
7055 -- If there are excluded sources, put them in the table
7057 if not Excluded_Sources.Default then
7058 if not Excluded_Source_List_File.Default then
7059 if Locally_Removed then
7060 Error_Msg
7061 (Project, In_Tree,
7062 "?both attributes Locally_Removed_Files and " &
7063 "Excluded_Source_List_File are present",
7064 Excluded_Source_List_File.Location);
7065 else
7066 Error_Msg
7067 (Project, In_Tree,
7068 "?both attributes Excluded_Source_Files and " &
7069 "Excluded_Source_List_File are present",
7070 Excluded_Source_List_File.Location);
7071 end if;
7072 end if;
7074 Current := Excluded_Sources.Values;
7075 while Current /= Nil_String loop
7076 Element := In_Tree.String_Elements.Table (Current);
7078 if Osint.File_Names_Case_Sensitive then
7079 Name := File_Name_Type (Element.Value);
7080 else
7081 Get_Name_String (Element.Value);
7082 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7083 Name := Name_Find;
7084 end if;
7086 -- If the element has no location, then use the location
7087 -- of Excluded_Sources to report possible errors.
7089 if Element.Location = No_Location then
7090 Location := Excluded_Sources.Location;
7091 else
7092 Location := Element.Location;
7093 end if;
7095 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
7096 Current := Element.Next;
7097 end loop;
7099 elsif not Excluded_Source_List_File.Default then
7100 Location := Excluded_Source_List_File.Location;
7102 declare
7103 Source_File_Path_Name : constant String :=
7104 Path_Name_Of
7105 (File_Name_Type
7106 (Excluded_Source_List_File.Value),
7107 Data.Directory.Name);
7109 begin
7110 if Source_File_Path_Name'Length = 0 then
7111 Err_Vars.Error_Msg_File_1 :=
7112 File_Name_Type (Excluded_Source_List_File.Value);
7113 Error_Msg
7114 (Project, In_Tree,
7115 "file with excluded sources { does not exist",
7116 Excluded_Source_List_File.Location);
7118 else
7119 -- Open the file
7121 Prj.Util.Open (File, Source_File_Path_Name);
7123 if not Prj.Util.Is_Valid (File) then
7124 Error_Msg
7125 (Project, In_Tree, "file does not exist", Location);
7126 else
7127 -- Read the lines one by one
7129 while not Prj.Util.End_Of_File (File) loop
7130 Prj.Util.Get_Line (File, Line, Last);
7132 -- A non empty, non comment line should contain a file
7133 -- name
7135 if Last /= 0
7136 and then (Last = 1 or else Line (1 .. 2) /= "--")
7137 then
7138 Name_Len := Last;
7139 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
7140 Canonical_Case_File_Name
7141 (Name_Buffer (1 .. Name_Len));
7142 Name := Name_Find;
7144 -- Check that there is no directory information
7146 for J in 1 .. Last loop
7147 if Line (J) = '/'
7148 or else Line (J) = Directory_Separator
7149 then
7150 Error_Msg_File_1 := Name;
7151 Error_Msg
7152 (Project,
7153 In_Tree,
7154 "file name cannot include " &
7155 "directory information ({)",
7156 Location);
7157 exit;
7158 end if;
7159 end loop;
7161 Excluded_Sources_Htable.Set
7162 (Name, (Name, False, Location));
7163 end if;
7164 end loop;
7166 Prj.Util.Close (File);
7167 end if;
7168 end if;
7169 end;
7170 end if;
7171 end Find_Excluded_Sources;
7173 ---------------------------
7174 -- Find_Explicit_Sources --
7175 ---------------------------
7177 procedure Find_Explicit_Sources
7178 (Current_Dir : String;
7179 Project : Project_Id;
7180 In_Tree : Project_Tree_Ref;
7181 Data : in out Project_Data)
7183 Sources : constant Variable_Value :=
7184 Util.Value_Of
7185 (Name_Source_Files,
7186 Data.Decl.Attributes,
7187 In_Tree);
7188 Source_List_File : constant Variable_Value :=
7189 Util.Value_Of
7190 (Name_Source_List_File,
7191 Data.Decl.Attributes,
7192 In_Tree);
7193 Name_Loc : Name_Location;
7195 begin
7196 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
7197 pragma Assert
7198 (Source_List_File.Kind = Single,
7199 "Source_List_File is not a single string");
7201 -- If the user has specified a Sources attribute
7203 if not Sources.Default then
7204 if not Source_List_File.Default then
7205 Error_Msg
7206 (Project, In_Tree,
7207 "?both attributes source_files and " &
7208 "source_list_file are present",
7209 Source_List_File.Location);
7210 end if;
7212 -- Sources is a list of file names
7214 declare
7215 Current : String_List_Id := Sources.Values;
7216 Element : String_Element;
7217 Location : Source_Ptr;
7218 Name : File_Name_Type;
7220 begin
7221 if Get_Mode = Ada_Only then
7222 Data.Ada_Sources_Present := Current /= Nil_String;
7223 end if;
7225 if Get_Mode = Multi_Language then
7226 if Current = Nil_String then
7227 Data.First_Language_Processing := No_Language_Index;
7229 -- This project contains no source. For projects that
7230 -- don't extend other projects, this also means that
7231 -- there is no need for an object directory, if not
7232 -- specified.
7234 if Data.Extends = No_Project
7235 and then Data.Object_Directory = Data.Directory
7236 then
7237 Data.Object_Directory := No_Path_Information;
7238 end if;
7239 end if;
7240 end if;
7242 while Current /= Nil_String loop
7243 Element := In_Tree.String_Elements.Table (Current);
7244 Get_Name_String (Element.Value);
7246 if Osint.File_Names_Case_Sensitive then
7247 Name := File_Name_Type (Element.Value);
7248 else
7249 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
7250 Name := Name_Find;
7251 end if;
7253 -- If the element has no location, then use the
7254 -- location of Sources to report possible errors.
7256 if Element.Location = No_Location then
7257 Location := Sources.Location;
7258 else
7259 Location := Element.Location;
7260 end if;
7262 -- Check that there is no directory information
7264 for J in 1 .. Name_Len loop
7265 if Name_Buffer (J) = '/'
7266 or else Name_Buffer (J) = Directory_Separator
7267 then
7268 Error_Msg_File_1 := Name;
7269 Error_Msg
7270 (Project,
7271 In_Tree,
7272 "file name cannot include directory " &
7273 "information ({)",
7274 Location);
7275 exit;
7276 end if;
7277 end loop;
7279 -- In Multi_Language mode, check whether the file is
7280 -- already there: the same file name may be in the list; if
7281 -- the source is missing, the error will be on the first
7282 -- mention of the source file name.
7284 case Get_Mode is
7285 when Ada_Only =>
7286 Name_Loc := No_Name_Location;
7287 when Multi_Language =>
7288 Name_Loc := Source_Names.Get (Name);
7289 end case;
7291 if Name_Loc = No_Name_Location then
7292 Name_Loc :=
7293 (Name => Name,
7294 Location => Location,
7295 Source => No_Source,
7296 Except => False,
7297 Found => False);
7298 Source_Names.Set (Name, Name_Loc);
7299 end if;
7301 Current := Element.Next;
7302 end loop;
7304 if Get_Mode = Ada_Only then
7305 Get_Path_Names_And_Record_Ada_Sources
7306 (Project, In_Tree, Data, Current_Dir);
7307 end if;
7308 end;
7310 -- If we have no Source_Files attribute, check the Source_List_File
7311 -- attribute
7313 elsif not Source_List_File.Default then
7315 -- Source_List_File is the name of the file
7316 -- that contains the source file names
7318 declare
7319 Source_File_Path_Name : constant String :=
7320 Path_Name_Of
7321 (File_Name_Type (Source_List_File.Value), Data.Directory.Name);
7323 begin
7324 if Source_File_Path_Name'Length = 0 then
7325 Err_Vars.Error_Msg_File_1 :=
7326 File_Name_Type (Source_List_File.Value);
7327 Error_Msg
7328 (Project, In_Tree,
7329 "file with sources { does not exist",
7330 Source_List_File.Location);
7332 else
7333 Get_Sources_From_File
7334 (Source_File_Path_Name, Source_List_File.Location,
7335 Project, In_Tree);
7337 if Get_Mode = Ada_Only then
7338 -- Look in the source directories to find those sources
7340 Get_Path_Names_And_Record_Ada_Sources
7341 (Project, In_Tree, Data, Current_Dir);
7342 end if;
7343 end if;
7344 end;
7346 else
7347 -- Neither Source_Files nor Source_List_File has been
7348 -- specified. Find all the files that satisfy the naming
7349 -- scheme in all the source directories.
7351 if Get_Mode = Ada_Only then
7352 Find_Ada_Sources (Project, In_Tree, Data, Current_Dir);
7353 end if;
7354 end if;
7356 if Get_Mode = Multi_Language then
7357 Search_Directories
7358 (Project, In_Tree, Data,
7359 For_All_Sources =>
7360 Sources.Default and then Source_List_File.Default);
7362 -- Check if all exceptions have been found.
7363 -- For Ada, it is an error if an exception is not found.
7364 -- For other language, the source is simply removed.
7366 declare
7367 Source : Source_Id;
7368 Src_Data : Source_Data;
7370 begin
7371 Source := Data.First_Source;
7372 while Source /= No_Source loop
7373 Src_Data := In_Tree.Sources.Table (Source);
7375 if Src_Data.Naming_Exception
7376 and then Src_Data.Path = No_Path_Information
7377 then
7378 if Src_Data.Unit /= No_Name then
7379 Error_Msg_Name_1 := Name_Id (Src_Data.Display_File);
7380 Error_Msg_Name_2 := Name_Id (Src_Data.Unit);
7381 Error_Msg
7382 (Project, In_Tree,
7383 "source file %% for unit %% not found",
7384 No_Location);
7385 end if;
7387 Remove_Source (Source, No_Source, Project, Data, In_Tree);
7388 end if;
7390 Source := Src_Data.Next_In_Project;
7391 end loop;
7392 end;
7394 -- Check that all sources in Source_Files or the file
7395 -- Source_List_File has been found.
7397 declare
7398 Name_Loc : Name_Location;
7400 begin
7401 Name_Loc := Source_Names.Get_First;
7402 while Name_Loc /= No_Name_Location loop
7403 if (not Name_Loc.Except) and then (not Name_Loc.Found) then
7404 Error_Msg_Name_1 := Name_Id (Name_Loc.Name);
7405 Error_Msg
7406 (Project,
7407 In_Tree,
7408 "file %% not found",
7409 Name_Loc.Location);
7410 end if;
7412 Name_Loc := Source_Names.Get_Next;
7413 end loop;
7414 end;
7415 end if;
7417 if Get_Mode = Ada_Only
7418 and then Data.Extends = No_Project
7419 then
7420 -- We should have found at least one source, if not report an error
7422 if Data.Ada_Sources = Nil_String then
7423 Report_No_Sources
7424 (Project, "Ada", In_Tree, Source_List_File.Location);
7425 end if;
7426 end if;
7428 end Find_Explicit_Sources;
7430 -------------------------------------------
7431 -- Get_Path_Names_And_Record_Ada_Sources --
7432 -------------------------------------------
7434 procedure Get_Path_Names_And_Record_Ada_Sources
7435 (Project : Project_Id;
7436 In_Tree : Project_Tree_Ref;
7437 Data : in out Project_Data;
7438 Current_Dir : String)
7440 Source_Dir : String_List_Id;
7441 Element : String_Element;
7442 Path : Path_Name_Type;
7443 Dir : Dir_Type;
7444 Name : File_Name_Type;
7445 Canonical_Name : File_Name_Type;
7446 Name_Str : String (1 .. 1_024);
7447 Last : Natural := 0;
7448 NL : Name_Location;
7449 Current_Source : String_List_Id := Nil_String;
7450 First_Error : Boolean := True;
7451 Source_Recorded : Boolean := False;
7453 begin
7454 -- We look in all source directories for the file names in the hash
7455 -- table Source_Names.
7457 Source_Dir := Data.Source_Dirs;
7458 while Source_Dir /= Nil_String loop
7459 Source_Recorded := False;
7460 Element := In_Tree.String_Elements.Table (Source_Dir);
7462 declare
7463 Dir_Path : constant String :=
7464 Get_Name_String (Element.Display_Value);
7465 begin
7466 if Current_Verbosity = High then
7467 Write_Str ("checking directory """);
7468 Write_Str (Dir_Path);
7469 Write_Line ("""");
7470 end if;
7472 Open (Dir, Dir_Path);
7474 loop
7475 Read (Dir, Name_Str, Last);
7476 exit when Last = 0;
7478 Name_Len := Last;
7479 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7480 Name := Name_Find;
7482 if Osint.File_Names_Case_Sensitive then
7483 Canonical_Name := Name;
7484 else
7485 Canonical_Case_File_Name (Name_Str (1 .. Last));
7486 Name_Buffer (1 .. Name_Len) := Name_Str (1 .. Last);
7487 Canonical_Name := Name_Find;
7488 end if;
7490 NL := Source_Names.Get (Canonical_Name);
7492 if NL /= No_Name_Location and then not NL.Found then
7493 NL.Found := True;
7494 Source_Names.Set (Canonical_Name, NL);
7495 Name_Len := Dir_Path'Length;
7496 Name_Buffer (1 .. Name_Len) := Dir_Path;
7498 if Name_Buffer (Name_Len) /= Directory_Separator then
7499 Add_Char_To_Name_Buffer (Directory_Separator);
7500 end if;
7502 Add_Str_To_Name_Buffer (Name_Str (1 .. Last));
7503 Path := Name_Find;
7505 if Current_Verbosity = High then
7506 Write_Str (" found ");
7507 Write_Line (Get_Name_String (Name));
7508 end if;
7510 -- Register the source if it is an Ada compilation unit
7512 Record_Ada_Source
7513 (File_Name => Name,
7514 Path_Name => Path,
7515 Project => Project,
7516 In_Tree => In_Tree,
7517 Data => Data,
7518 Location => NL.Location,
7519 Current_Source => Current_Source,
7520 Source_Recorded => Source_Recorded,
7521 Current_Dir => Current_Dir);
7522 end if;
7523 end loop;
7525 Close (Dir);
7526 end;
7528 if Source_Recorded then
7529 In_Tree.String_Elements.Table (Source_Dir).Flag :=
7530 True;
7531 end if;
7533 Source_Dir := Element.Next;
7534 end loop;
7536 -- It is an error if a source file name in a source list or
7537 -- in a source list file is not found.
7539 NL := Source_Names.Get_First;
7540 while NL /= No_Name_Location loop
7541 if not NL.Found then
7542 Err_Vars.Error_Msg_File_1 := NL.Name;
7544 if First_Error then
7545 Error_Msg
7546 (Project, In_Tree,
7547 "source file { cannot be found",
7548 NL.Location);
7549 First_Error := False;
7551 else
7552 Error_Msg
7553 (Project, In_Tree,
7554 "\source file { cannot be found",
7555 NL.Location);
7556 end if;
7557 end if;
7559 NL := Source_Names.Get_Next;
7560 end loop;
7561 end Get_Path_Names_And_Record_Ada_Sources;
7563 --------------------------
7564 -- Check_Naming_Schemes --
7565 --------------------------
7567 procedure Check_Naming_Schemes
7568 (In_Tree : Project_Tree_Ref;
7569 Data : in out Project_Data;
7570 Filename : String;
7571 File_Name : File_Name_Type;
7572 Alternate_Languages : out Alternate_Language_Id;
7573 Language : out Language_Index;
7574 Language_Name : out Name_Id;
7575 Display_Language_Name : out Name_Id;
7576 Unit : out Name_Id;
7577 Lang_Kind : out Language_Kind;
7578 Kind : out Source_Kind)
7580 Last : Positive := Filename'Last;
7581 Config : Language_Config;
7582 Lang : Name_List_Index := Data.Languages;
7583 Header_File : Boolean := False;
7584 First_Language : Language_Index;
7585 OK : Boolean;
7587 Last_Spec : Natural;
7588 Last_Body : Natural;
7589 Last_Sep : Natural;
7591 begin
7592 Unit := No_Name;
7593 Alternate_Languages := No_Alternate_Language;
7595 while Lang /= No_Name_List loop
7596 Language_Name := In_Tree.Name_Lists.Table (Lang).Name;
7597 Language := Data.First_Language_Processing;
7599 if Current_Verbosity = High then
7600 Write_Line
7601 (" Testing language "
7602 & Get_Name_String (Language_Name)
7603 & " Header_File=" & Header_File'Img);
7604 end if;
7606 while Language /= No_Language_Index loop
7607 if In_Tree.Languages_Data.Table (Language).Name =
7608 Language_Name
7609 then
7610 Display_Language_Name :=
7611 In_Tree.Languages_Data.Table (Language).Display_Name;
7612 Config := In_Tree.Languages_Data.Table (Language).Config;
7613 Lang_Kind := Config.Kind;
7615 if Config.Kind = File_Based then
7617 -- For file based languages, there is no Unit. Just
7618 -- check if the file name has the implementation or,
7619 -- if it is specified, the template suffix of the
7620 -- language.
7622 Unit := No_Name;
7624 if not Header_File
7625 and then Config.Naming_Data.Body_Suffix /= No_File
7626 then
7627 declare
7628 Impl_Suffix : constant String :=
7629 Get_Name_String (Config.Naming_Data.Body_Suffix);
7631 begin
7632 if Filename'Length > Impl_Suffix'Length
7633 and then
7634 Filename
7635 (Last - Impl_Suffix'Length + 1 .. Last) =
7636 Impl_Suffix
7637 then
7638 Kind := Impl;
7640 if Current_Verbosity = High then
7641 Write_Str (" source of language ");
7642 Write_Line
7643 (Get_Name_String (Display_Language_Name));
7644 end if;
7646 return;
7647 end if;
7648 end;
7649 end if;
7651 if Config.Naming_Data.Spec_Suffix /= No_File then
7652 declare
7653 Spec_Suffix : constant String :=
7654 Get_Name_String
7655 (Config.Naming_Data.Spec_Suffix);
7657 begin
7658 if Filename'Length > Spec_Suffix'Length
7659 and then
7660 Filename
7661 (Last - Spec_Suffix'Length + 1 .. Last) =
7662 Spec_Suffix
7663 then
7664 Kind := Spec;
7666 if Current_Verbosity = High then
7667 Write_Str (" header file of language ");
7668 Write_Line
7669 (Get_Name_String (Display_Language_Name));
7670 end if;
7672 if Header_File then
7673 Alternate_Language_Table.Increment_Last
7674 (In_Tree.Alt_Langs);
7675 In_Tree.Alt_Langs.Table
7676 (Alternate_Language_Table.Last
7677 (In_Tree.Alt_Langs)) :=
7678 (Language => Language,
7679 Next => Alternate_Languages);
7680 Alternate_Languages :=
7681 Alternate_Language_Table.Last
7682 (In_Tree.Alt_Langs);
7683 else
7684 Header_File := True;
7685 First_Language := Language;
7686 end if;
7687 end if;
7688 end;
7689 end if;
7691 elsif not Header_File then
7692 -- Unit based language
7694 OK := Config.Naming_Data.Dot_Replacement /= No_File;
7696 if OK then
7698 -- Check casing
7699 -- ??? Are we doing this once per file in the project ?
7700 -- It should be done only once per project.
7702 case Config.Naming_Data.Casing is
7703 when All_Lower_Case =>
7704 for J in Filename'Range loop
7705 if Is_Letter (Filename (J)) then
7706 if not Is_Lower (Filename (J)) then
7707 OK := False;
7708 exit;
7709 end if;
7710 end if;
7711 end loop;
7713 when All_Upper_Case =>
7714 for J in Filename'Range loop
7715 if Is_Letter (Filename (J)) then
7716 if not Is_Upper (Filename (J)) then
7717 OK := False;
7718 exit;
7719 end if;
7720 end if;
7721 end loop;
7723 when Mixed_Case =>
7724 null;
7726 when others =>
7727 OK := False;
7728 end case;
7729 end if;
7731 if OK then
7732 Last_Spec := Natural'Last;
7733 Last_Body := Natural'Last;
7734 Last_Sep := Natural'Last;
7736 if Config.Naming_Data.Separate_Suffix /= No_File
7737 and then
7738 Config.Naming_Data.Separate_Suffix /=
7739 Config.Naming_Data.Body_Suffix
7740 then
7741 declare
7742 Suffix : constant String :=
7743 Get_Name_String
7744 (Config.Naming_Data.Separate_Suffix);
7745 begin
7746 if Filename'Length > Suffix'Length
7747 and then
7748 Filename
7749 (Last - Suffix'Length + 1 .. Last) =
7750 Suffix
7751 then
7752 Last_Sep := Last - Suffix'Length;
7753 end if;
7754 end;
7755 end if;
7757 if Config.Naming_Data.Body_Suffix /= No_File then
7758 declare
7759 Suffix : constant String :=
7760 Get_Name_String
7761 (Config.Naming_Data.Body_Suffix);
7762 begin
7763 if Filename'Length > Suffix'Length
7764 and then
7765 Filename
7766 (Last - Suffix'Length + 1 .. Last) =
7767 Suffix
7768 then
7769 Last_Body := Last - Suffix'Length;
7770 end if;
7771 end;
7772 end if;
7774 if Config.Naming_Data.Spec_Suffix /= No_File then
7775 declare
7776 Suffix : constant String :=
7777 Get_Name_String
7778 (Config.Naming_Data.Spec_Suffix);
7779 begin
7780 if Filename'Length > Suffix'Length
7781 and then
7782 Filename
7783 (Last - Suffix'Length + 1 .. Last) =
7784 Suffix
7785 then
7786 Last_Spec := Last - Suffix'Length;
7787 end if;
7788 end;
7789 end if;
7791 declare
7792 Last_Min : constant Natural :=
7793 Natural'Min (Natural'Min (Last_Spec,
7794 Last_Body),
7795 Last_Sep);
7797 begin
7798 OK := Last_Min < Last;
7800 if OK then
7801 Last := Last_Min;
7803 if Last_Min = Last_Spec then
7804 Kind := Spec;
7806 elsif Last_Min = Last_Body then
7807 Kind := Impl;
7809 else
7810 Kind := Sep;
7811 end if;
7812 end if;
7813 end;
7814 end if;
7816 if OK then
7818 -- Replace dot replacements with dots
7820 Name_Len := 0;
7822 declare
7823 J : Positive := Filename'First;
7825 Dot_Replacement : constant String :=
7826 Get_Name_String
7827 (Config.Naming_Data.
7828 Dot_Replacement);
7830 Max : constant Positive :=
7831 Last - Dot_Replacement'Length + 1;
7833 begin
7834 loop
7835 Name_Len := Name_Len + 1;
7837 if J <= Max and then
7838 Filename
7839 (J .. J + Dot_Replacement'Length - 1) =
7840 Dot_Replacement
7841 then
7842 Name_Buffer (Name_Len) := '.';
7843 J := J + Dot_Replacement'Length;
7845 else
7846 if Filename (J) = '.' then
7847 OK := False;
7848 exit;
7849 end if;
7851 Name_Buffer (Name_Len) :=
7852 GNAT.Case_Util.To_Lower (Filename (J));
7853 J := J + 1;
7854 end if;
7856 exit when J > Last;
7857 end loop;
7858 end;
7859 end if;
7861 if OK then
7863 -- The name buffer should contain the name of the
7864 -- the unit, if it is one.
7866 -- Check that this is a valid unit name
7868 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
7870 if Unit /= No_Name then
7872 if Current_Verbosity = High then
7873 if Kind = Spec then
7874 Write_Str (" spec of ");
7875 else
7876 Write_Str (" body of ");
7877 end if;
7879 Write_Str (Get_Name_String (Unit));
7880 Write_Str (" (language ");
7881 Write_Str
7882 (Get_Name_String (Display_Language_Name));
7883 Write_Line (")");
7884 end if;
7886 -- Comments required, declare block should
7887 -- be named ???
7889 declare
7890 Unit_Except : constant Unit_Exception :=
7891 Unit_Exceptions.Get (Unit);
7893 procedure Masked_Unit (Spec : Boolean);
7894 -- Indicate that there is an exception for
7895 -- the same unit, so the file is not a
7896 -- source for the unit.
7898 -----------------
7899 -- Masked_Unit --
7900 -----------------
7902 procedure Masked_Unit (Spec : Boolean) is
7903 begin
7904 if Current_Verbosity = High then
7905 Write_Str (" """);
7906 Write_Str (Filename);
7907 Write_Str (""" contains the ");
7909 if Spec then
7910 Write_Str ("spec");
7911 else
7912 Write_Str ("body");
7913 end if;
7915 Write_Str
7916 (" of a unit that is found in """);
7918 if Spec then
7919 Write_Str
7920 (Get_Name_String
7921 (Unit_Except.Spec));
7922 else
7923 Write_Str
7924 (Get_Name_String
7925 (Unit_Except.Impl));
7926 end if;
7928 Write_Line (""" (ignored)");
7929 end if;
7931 Language := No_Language_Index;
7932 end Masked_Unit;
7934 begin
7935 if Kind = Spec then
7936 if Unit_Except.Spec /= No_File
7937 and then Unit_Except.Spec /= File_Name
7938 then
7939 Masked_Unit (Spec => True);
7940 end if;
7942 else
7943 if Unit_Except.Impl /= No_File
7944 and then Unit_Except.Impl /= File_Name
7945 then
7946 Masked_Unit (Spec => False);
7947 end if;
7948 end if;
7949 end;
7951 return;
7952 end if;
7953 end if;
7954 end if;
7955 end if;
7957 Language := In_Tree.Languages_Data.Table (Language).Next;
7958 end loop;
7960 Lang := In_Tree.Name_Lists.Table (Lang).Next;
7961 end loop;
7963 -- Comment needed here ???
7965 if Header_File then
7966 Language := First_Language;
7968 else
7969 Language := No_Language_Index;
7971 if Current_Verbosity = High then
7972 Write_Line (" not a source of any language");
7973 end if;
7974 end if;
7975 end Check_Naming_Schemes;
7977 ----------------
7978 -- Check_File --
7979 ----------------
7981 procedure Check_File
7982 (Project : Project_Id;
7983 In_Tree : Project_Tree_Ref;
7984 Data : in out Project_Data;
7985 Name : String;
7986 File_Name : File_Name_Type;
7987 Display_File_Name : File_Name_Type;
7988 Source_Directory : String;
7989 For_All_Sources : Boolean)
7991 Display_Path : constant String :=
7992 Normalize_Pathname
7993 (Name => Name,
7994 Directory => Source_Directory,
7995 Resolve_Links => Opt.Follow_Links_For_Files,
7996 Case_Sensitive => True);
7998 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7999 Path_Id : Path_Name_Type;
8000 Display_Path_Id : Path_Name_Type;
8001 Check_Name : Boolean := False;
8002 Alternate_Languages : Alternate_Language_Id := No_Alternate_Language;
8003 Language : Language_Index;
8004 Source : Source_Id;
8005 Other_Part : Source_Id;
8006 Add_Src : Boolean;
8007 Src_Ind : Source_File_Index;
8008 Src_Data : Source_Data;
8009 Unit : Name_Id;
8010 Source_To_Replace : Source_Id := No_Source;
8011 Language_Name : Name_Id;
8012 Display_Language_Name : Name_Id;
8013 Lang_Kind : Language_Kind;
8014 Kind : Source_Kind := Spec;
8016 begin
8017 Name_Len := Display_Path'Length;
8018 Name_Buffer (1 .. Name_Len) := Display_Path;
8019 Display_Path_Id := Name_Find;
8021 if Osint.File_Names_Case_Sensitive then
8022 Path_Id := Display_Path_Id;
8023 else
8024 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8025 Path_Id := Name_Find;
8026 end if;
8028 if Name_Loc = No_Name_Location then
8029 Check_Name := For_All_Sources;
8031 else
8032 if Name_Loc.Found then
8034 -- Check if it is OK to have the same file name in several
8035 -- source directories.
8037 if not Data.Known_Order_Of_Source_Dirs then
8038 Error_Msg_File_1 := File_Name;
8039 Error_Msg
8040 (Project, In_Tree,
8041 "{ is found in several source directories",
8042 Name_Loc.Location);
8043 end if;
8045 else
8046 Name_Loc.Found := True;
8048 Source_Names.Set (File_Name, Name_Loc);
8050 if Name_Loc.Source = No_Source then
8051 Check_Name := True;
8053 else
8054 In_Tree.Sources.Table (Name_Loc.Source).Path :=
8055 (Path_Id, Display_Path_Id);
8057 Source_Paths_Htable.Set
8058 (In_Tree.Source_Paths_HT,
8059 Path_Id,
8060 Name_Loc.Source);
8062 -- Check if this is a subunit
8064 if In_Tree.Sources.Table (Name_Loc.Source).Unit /= No_Name
8065 and then
8066 In_Tree.Sources.Table (Name_Loc.Source).Kind = Impl
8067 then
8068 Src_Ind := Sinput.P.Load_Project_File
8069 (Get_Name_String (Path_Id));
8071 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
8072 In_Tree.Sources.Table (Name_Loc.Source).Kind := Sep;
8073 end if;
8074 end if;
8075 end if;
8076 end if;
8077 end if;
8079 if Check_Name then
8080 Other_Part := No_Source;
8082 Check_Naming_Schemes
8083 (In_Tree => In_Tree,
8084 Data => Data,
8085 Filename => Get_Name_String (File_Name),
8086 File_Name => File_Name,
8087 Alternate_Languages => Alternate_Languages,
8088 Language => Language,
8089 Language_Name => Language_Name,
8090 Display_Language_Name => Display_Language_Name,
8091 Unit => Unit,
8092 Lang_Kind => Lang_Kind,
8093 Kind => Kind);
8095 if Language = No_Language_Index then
8097 -- A file name in a list must be a source of a language
8099 if Name_Loc.Found then
8100 Error_Msg_File_1 := File_Name;
8101 Error_Msg
8102 (Project,
8103 In_Tree,
8104 "language unknown for {",
8105 Name_Loc.Location);
8106 end if;
8108 else
8109 -- Check if the same file name or unit is used in the prj tree
8111 Source := In_Tree.First_Source;
8112 Add_Src := True;
8113 while Source /= No_Source loop
8114 Src_Data := In_Tree.Sources.Table (Source);
8116 if Unit /= No_Name
8117 and then Src_Data.Unit = Unit
8118 and then
8119 ((Src_Data.Kind = Spec and then Kind = Impl)
8120 or else
8121 (Src_Data.Kind = Impl and then Kind = Spec))
8122 then
8123 Other_Part := Source;
8125 elsif (Unit /= No_Name
8126 and then Src_Data.Unit = Unit
8127 and then
8128 (Src_Data.Kind = Kind
8129 or else
8130 (Src_Data.Kind = Sep and then Kind = Impl)
8131 or else
8132 (Src_Data.Kind = Impl and then Kind = Sep)))
8133 or else (Unit = No_Name and then Src_Data.File = File_Name)
8134 then
8135 -- Duplication of file/unit in same project is only
8136 -- allowed if order of source directories is known.
8138 if Project = Src_Data.Project then
8139 if Data.Known_Order_Of_Source_Dirs then
8140 Add_Src := False;
8142 elsif Unit /= No_Name then
8143 Error_Msg_Name_1 := Unit;
8144 Error_Msg
8145 (Project, In_Tree, "duplicate unit %%", No_Location);
8146 Add_Src := False;
8148 else
8149 Error_Msg_File_1 := File_Name;
8150 Error_Msg
8151 (Project, In_Tree, "duplicate source file name {",
8152 No_Location);
8153 Add_Src := False;
8154 end if;
8156 -- Do not allow the same unit name in different
8157 -- projects, except if one is extending the other.
8159 -- For a file based language, the same file name
8160 -- replaces a file in a project being extended, but
8161 -- it is allowed to have the same file name in
8162 -- unrelated projects.
8164 elsif Is_Extending
8165 (Project, Src_Data.Project, In_Tree)
8166 then
8167 Source_To_Replace := Source;
8169 elsif Unit /= No_Name
8170 and then not Src_Data.Locally_Removed
8171 then
8172 Error_Msg_Name_1 := Unit;
8173 Error_Msg
8174 (Project, In_Tree,
8175 "unit %% cannot belong to several projects",
8176 No_Location);
8178 Error_Msg_Name_1 := In_Tree.Projects.Table (Project).Name;
8179 Error_Msg_Name_2 := Name_Id (Display_Path_Id);
8180 Error_Msg
8181 (Project, In_Tree, "\ project %%, %%", No_Location);
8183 Error_Msg_Name_1 :=
8184 In_Tree.Projects.Table (Src_Data.Project).Name;
8185 Error_Msg_Name_2 := Name_Id (Src_Data.Path.Display_Name);
8186 Error_Msg
8187 (Project, In_Tree, "\ project %%, %%", No_Location);
8189 Add_Src := False;
8190 end if;
8191 end if;
8193 Source := Src_Data.Next_In_Sources;
8194 end loop;
8196 if Add_Src then
8197 Add_Source
8198 (Id => Source,
8199 Data => Data,
8200 In_Tree => In_Tree,
8201 Project => Project,
8202 Lang => Language_Name,
8203 Lang_Id => Language,
8204 Lang_Kind => Lang_Kind,
8205 Kind => Kind,
8206 Alternate_Languages => Alternate_Languages,
8207 File_Name => File_Name,
8208 Display_File => Display_File_Name,
8209 Other_Part => Other_Part,
8210 Unit => Unit,
8211 Path => Path_Id,
8212 Display_Path => Display_Path_Id,
8213 Source_To_Replace => Source_To_Replace);
8214 end if;
8215 end if;
8216 end if;
8217 end Check_File;
8219 ------------------------
8220 -- Search_Directories --
8221 ------------------------
8223 procedure Search_Directories
8224 (Project : Project_Id;
8225 In_Tree : Project_Tree_Ref;
8226 Data : in out Project_Data;
8227 For_All_Sources : Boolean)
8229 Source_Dir : String_List_Id;
8230 Element : String_Element;
8231 Dir : Dir_Type;
8232 Name : String (1 .. 1_000);
8233 Last : Natural;
8234 File_Name : File_Name_Type;
8235 Display_File_Name : File_Name_Type;
8237 begin
8238 if Current_Verbosity = High then
8239 Write_Line ("Looking for sources:");
8240 end if;
8242 -- Loop through subdirectories
8244 Source_Dir := Data.Source_Dirs;
8245 while Source_Dir /= Nil_String loop
8246 begin
8247 Element := In_Tree.String_Elements.Table (Source_Dir);
8248 if Element.Value /= No_Name then
8249 Get_Name_String (Element.Display_Value);
8251 declare
8252 Source_Directory : constant String :=
8253 Name_Buffer (1 .. Name_Len) &
8254 Directory_Separator;
8256 Dir_Last : constant Natural :=
8257 Compute_Directory_Last
8258 (Source_Directory);
8260 begin
8261 if Current_Verbosity = High then
8262 Write_Str ("Source_Dir = ");
8263 Write_Line (Source_Directory);
8264 end if;
8266 -- We look to every entry in the source directory
8268 Open (Dir, Source_Directory);
8270 loop
8271 Read (Dir, Name, Last);
8273 exit when Last = 0;
8275 -- ??? Duplicate system call here, we just did a
8276 -- a similar one. Maybe Ada.Directories would be more
8277 -- appropriate here
8279 if Is_Regular_File
8280 (Source_Directory & Name (1 .. Last))
8281 then
8282 if Current_Verbosity = High then
8283 Write_Str (" Checking ");
8284 Write_Line (Name (1 .. Last));
8285 end if;
8287 Name_Len := Last;
8288 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
8289 Display_File_Name := Name_Find;
8291 if Osint.File_Names_Case_Sensitive then
8292 File_Name := Display_File_Name;
8293 else
8294 Canonical_Case_File_Name
8295 (Name_Buffer (1 .. Name_Len));
8296 File_Name := Name_Find;
8297 end if;
8299 declare
8300 FF : File_Found :=
8301 Excluded_Sources_Htable.Get (File_Name);
8303 begin
8304 if FF /= No_File_Found then
8305 if not FF.Found then
8306 FF.Found := True;
8307 Excluded_Sources_Htable.Set
8308 (File_Name, FF);
8310 if Current_Verbosity = High then
8311 Write_Str (" excluded source """);
8312 Write_Str (Get_Name_String (File_Name));
8313 Write_Line ("""");
8314 end if;
8315 end if;
8317 else
8318 Check_File
8319 (Project => Project,
8320 In_Tree => In_Tree,
8321 Data => Data,
8322 Name => Name (1 .. Last),
8323 File_Name => File_Name,
8324 Display_File_Name => Display_File_Name,
8325 Source_Directory => Source_Directory
8326 (Source_Directory'First .. Dir_Last),
8327 For_All_Sources => For_All_Sources);
8328 end if;
8329 end;
8330 end if;
8331 end loop;
8333 Close (Dir);
8334 end;
8335 end if;
8337 exception
8338 when Directory_Error =>
8339 null;
8340 end;
8342 Source_Dir := Element.Next;
8343 end loop;
8345 if Current_Verbosity = High then
8346 Write_Line ("end Looking for sources.");
8347 end if;
8348 end Search_Directories;
8350 ----------------------
8351 -- Look_For_Sources --
8352 ----------------------
8354 procedure Look_For_Sources
8355 (Project : Project_Id;
8356 In_Tree : Project_Tree_Ref;
8357 Data : in out Project_Data;
8358 Current_Dir : String)
8360 procedure Remove_Locally_Removed_Files_From_Units;
8361 -- Mark all locally removed sources as such in the Units table
8363 procedure Process_Sources_In_Multi_Language_Mode;
8364 -- Find all source files when in multi language mode
8366 ---------------------------------------------
8367 -- Remove_Locally_Removed_Files_From_Units --
8368 ---------------------------------------------
8370 procedure Remove_Locally_Removed_Files_From_Units is
8371 Excluded : File_Found;
8372 OK : Boolean;
8373 Unit : Unit_Data;
8374 Extended : Project_Id;
8376 begin
8377 Excluded := Excluded_Sources_Htable.Get_First;
8378 while Excluded /= No_File_Found loop
8379 OK := False;
8381 For_Each_Unit :
8382 for Index in Unit_Table.First ..
8383 Unit_Table.Last (In_Tree.Units)
8384 loop
8385 Unit := In_Tree.Units.Table (Index);
8387 for Kind in Spec_Or_Body'Range loop
8388 if Unit.File_Names (Kind).Name = Excluded.File then
8389 OK := True;
8391 -- Check that this is from the current project or
8392 -- that the current project extends.
8394 Extended := Unit.File_Names (Kind).Project;
8396 if Extended = Project
8397 or else Project_Extends (Project, Extended, In_Tree)
8398 then
8399 Unit.File_Names (Kind).Path.Name := Slash;
8400 Unit.File_Names (Kind).Needs_Pragma := False;
8401 In_Tree.Units.Table (Index) := Unit;
8402 Add_Forbidden_File_Name
8403 (Unit.File_Names (Kind).Name);
8404 else
8405 Error_Msg
8406 (Project, In_Tree,
8407 "cannot remove a source from " &
8408 "another project",
8409 Excluded.Location);
8410 end if;
8411 exit For_Each_Unit;
8412 end if;
8413 end loop;
8414 end loop For_Each_Unit;
8416 if not OK then
8417 Err_Vars.Error_Msg_File_1 := Excluded.File;
8418 Error_Msg
8419 (Project, In_Tree, "unknown file {", Excluded.Location);
8420 end if;
8422 Excluded := Excluded_Sources_Htable.Get_Next;
8423 end loop;
8424 end Remove_Locally_Removed_Files_From_Units;
8426 --------------------------------------------
8427 -- Process_Sources_In_Multi_Language_Mode --
8428 --------------------------------------------
8430 procedure Process_Sources_In_Multi_Language_Mode is
8431 Source : Source_Id;
8432 Src_Data : Source_Data;
8433 Name_Loc : Name_Location;
8434 OK : Boolean;
8435 FF : File_Found;
8437 begin
8438 -- First, put all naming exceptions if any, in the Source_Names table
8440 Unit_Exceptions.Reset;
8442 Source := Data.First_Source;
8443 while Source /= No_Source loop
8444 Src_Data := In_Tree.Sources.Table (Source);
8446 -- A file that is excluded cannot also be an exception file name
8448 if Excluded_Sources_Htable.Get (Src_Data.File) /=
8449 No_File_Found
8450 then
8451 Error_Msg_File_1 := Src_Data.File;
8452 Error_Msg
8453 (Project, In_Tree,
8454 "{ cannot be both excluded and an exception file name",
8455 No_Location);
8456 end if;
8458 Name_Loc := (Name => Src_Data.File,
8459 Location => No_Location,
8460 Source => Source,
8461 Except => Src_Data.Unit /= No_Name,
8462 Found => False);
8464 if Current_Verbosity = High then
8465 Write_Str ("Putting source #");
8466 Write_Str (Source'Img);
8467 Write_Str (", file ");
8468 Write_Str (Get_Name_String (Src_Data.File));
8469 Write_Line (" in Source_Names");
8470 end if;
8472 Source_Names.Set (K => Src_Data.File, E => Name_Loc);
8474 -- If this is an Ada exception, record it in table Unit_Exceptions
8476 if Src_Data.Unit /= No_Name then
8477 declare
8478 Unit_Except : Unit_Exception :=
8479 Unit_Exceptions.Get (Src_Data.Unit);
8481 begin
8482 Unit_Except.Name := Src_Data.Unit;
8484 if Src_Data.Kind = Spec then
8485 Unit_Except.Spec := Src_Data.File;
8486 else
8487 Unit_Except.Impl := Src_Data.File;
8488 end if;
8490 Unit_Exceptions.Set (Src_Data.Unit, Unit_Except);
8491 end;
8492 end if;
8494 Source := Src_Data.Next_In_Project;
8495 end loop;
8497 Find_Explicit_Sources
8498 (Current_Dir, Project, In_Tree, Data);
8500 -- Mark as such the sources that are declared as excluded
8502 FF := Excluded_Sources_Htable.Get_First;
8503 while FF /= No_File_Found loop
8504 OK := False;
8505 Source := In_Tree.First_Source;
8507 while Source /= No_Source loop
8508 Src_Data := In_Tree.Sources.Table (Source);
8510 if Src_Data.File = FF.File then
8512 -- Check that this is from this project or a project that
8513 -- the current project extends.
8515 if Src_Data.Project = Project or else
8516 Is_Extending (Project, Src_Data.Project, In_Tree)
8517 then
8518 Src_Data.Locally_Removed := True;
8519 Src_Data.In_Interfaces := False;
8520 In_Tree.Sources.Table (Source) := Src_Data;
8521 Add_Forbidden_File_Name (FF.File);
8522 OK := True;
8523 exit;
8524 end if;
8525 end if;
8527 Source := Src_Data.Next_In_Sources;
8528 end loop;
8530 if not FF.Found and not OK then
8531 Err_Vars.Error_Msg_File_1 := FF.File;
8532 Error_Msg (Project, In_Tree, "unknown file {", FF.Location);
8533 end if;
8535 FF := Excluded_Sources_Htable.Get_Next;
8536 end loop;
8538 -- Check that two sources of this project do not have the same object
8539 -- file name.
8541 Check_Object_File_Names : declare
8542 Src_Id : Source_Id;
8543 Src_Data : Source_Data;
8544 Source_Name : File_Name_Type;
8546 procedure Check_Object;
8547 -- Check if object file name of the current source is already in
8548 -- hash table Object_File_Names. If it is, report an error. If it
8549 -- is not, put it there with the file name of the current source.
8551 ------------------
8552 -- Check_Object --
8553 ------------------
8555 procedure Check_Object is
8556 begin
8557 Source_Name := Object_File_Names.Get (Src_Data.Object);
8559 if Source_Name /= No_File then
8560 Error_Msg_File_1 := Src_Data.File;
8561 Error_Msg_File_2 := Source_Name;
8562 Error_Msg
8563 (Project,
8564 In_Tree,
8565 "{ and { have the same object file name",
8566 No_Location);
8568 else
8569 Object_File_Names.Set (Src_Data.Object, Src_Data.File);
8570 end if;
8571 end Check_Object;
8573 -- Start of processing for Check_Object_File_Names
8575 begin
8576 Object_File_Names.Reset;
8577 Src_Id := In_Tree.First_Source;
8578 while Src_Id /= No_Source loop
8579 Src_Data := In_Tree.Sources.Table (Src_Id);
8581 if Src_Data.Compiled and then Src_Data.Object_Exists
8582 and then Project_Extends (Project, Src_Data.Project, In_Tree)
8583 then
8584 if Src_Data.Unit = No_Name then
8585 if Src_Data.Kind = Impl then
8586 Check_Object;
8587 end if;
8589 else
8590 case Src_Data.Kind is
8591 when Spec =>
8592 if Src_Data.Other_Part = No_Source then
8593 Check_Object;
8594 end if;
8596 when Sep =>
8597 null;
8599 when Impl =>
8600 if Src_Data.Other_Part /= No_Source then
8601 Check_Object;
8603 else
8604 -- Check if it is a subunit
8606 declare
8607 Src_Ind : constant Source_File_Index :=
8608 Sinput.P.Load_Project_File
8609 (Get_Name_String
8610 (Src_Data.Path.Name));
8612 begin
8613 if Sinput.P.Source_File_Is_Subunit
8614 (Src_Ind)
8615 then
8616 In_Tree.Sources.Table (Src_Id).Kind := Sep;
8617 else
8618 Check_Object;
8619 end if;
8620 end;
8621 end if;
8622 end case;
8623 end if;
8624 end if;
8626 Src_Id := Src_Data.Next_In_Sources;
8627 end loop;
8628 end Check_Object_File_Names;
8629 end Process_Sources_In_Multi_Language_Mode;
8631 -- Start of processing for Look_For_Sources
8633 begin
8634 Source_Names.Reset;
8635 Find_Excluded_Sources (Project, In_Tree, Data);
8637 case Get_Mode is
8638 when Ada_Only =>
8639 if Is_A_Language (In_Tree, Data, Name_Ada) then
8640 Find_Explicit_Sources (Current_Dir, Project, In_Tree, Data);
8641 Remove_Locally_Removed_Files_From_Units;
8642 end if;
8644 when Multi_Language =>
8645 if Data.First_Language_Processing /= No_Language_Index then
8646 Process_Sources_In_Multi_Language_Mode;
8647 end if;
8648 end case;
8649 end Look_For_Sources;
8651 ------------------
8652 -- Path_Name_Of --
8653 ------------------
8655 function Path_Name_Of
8656 (File_Name : File_Name_Type;
8657 Directory : Path_Name_Type) return String
8659 Result : String_Access;
8660 The_Directory : constant String := Get_Name_String (Directory);
8662 begin
8663 Get_Name_String (File_Name);
8664 Result :=
8665 Locate_Regular_File
8666 (File_Name => Name_Buffer (1 .. Name_Len),
8667 Path => The_Directory);
8669 if Result = null then
8670 return "";
8671 else
8672 Canonical_Case_File_Name (Result.all);
8673 return Result.all;
8674 end if;
8675 end Path_Name_Of;
8677 -------------------------------
8678 -- Prepare_Ada_Naming_Exceptions --
8679 -------------------------------
8681 procedure Prepare_Ada_Naming_Exceptions
8682 (List : Array_Element_Id;
8683 In_Tree : Project_Tree_Ref;
8684 Kind : Spec_Or_Body)
8686 Current : Array_Element_Id;
8687 Element : Array_Element;
8688 Unit : Unit_Info;
8690 begin
8691 -- Traverse the list
8693 Current := List;
8694 while Current /= No_Array_Element loop
8695 Element := In_Tree.Array_Elements.Table (Current);
8697 if Element.Index /= No_Name then
8698 Unit :=
8699 (Kind => Kind,
8700 Unit => Element.Index,
8701 Next => No_Ada_Naming_Exception);
8702 Reverse_Ada_Naming_Exceptions.Set
8703 (Unit, (Element.Value.Value, Element.Value.Index));
8704 Unit.Next :=
8705 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8706 Ada_Naming_Exception_Table.Increment_Last;
8707 Ada_Naming_Exception_Table.Table
8708 (Ada_Naming_Exception_Table.Last) := Unit;
8709 Ada_Naming_Exceptions.Set
8710 (File_Name_Type (Element.Value.Value),
8711 Ada_Naming_Exception_Table.Last);
8712 end if;
8714 Current := Element.Next;
8715 end loop;
8716 end Prepare_Ada_Naming_Exceptions;
8718 ---------------------
8719 -- Project_Extends --
8720 ---------------------
8722 function Project_Extends
8723 (Extending : Project_Id;
8724 Extended : Project_Id;
8725 In_Tree : Project_Tree_Ref) return Boolean
8727 Current : Project_Id := Extending;
8729 begin
8730 loop
8731 if Current = No_Project then
8732 return False;
8734 elsif Current = Extended then
8735 return True;
8736 end if;
8738 Current := In_Tree.Projects.Table (Current).Extends;
8739 end loop;
8740 end Project_Extends;
8742 -----------------------
8743 -- Record_Ada_Source --
8744 -----------------------
8746 procedure Record_Ada_Source
8747 (File_Name : File_Name_Type;
8748 Path_Name : Path_Name_Type;
8749 Project : Project_Id;
8750 In_Tree : Project_Tree_Ref;
8751 Data : in out Project_Data;
8752 Location : Source_Ptr;
8753 Current_Source : in out String_List_Id;
8754 Source_Recorded : in out Boolean;
8755 Current_Dir : String)
8757 Canonical_File_Name : File_Name_Type;
8758 Canonical_Path_Name : Path_Name_Type;
8760 Exception_Id : Ada_Naming_Exception_Id;
8761 Unit_Name : Name_Id;
8762 Unit_Kind : Spec_Or_Body;
8763 Unit_Ind : Int := 0;
8764 Info : Unit_Info;
8765 Name_Index : Name_And_Index;
8766 Needs_Pragma : Boolean;
8768 The_Location : Source_Ptr := Location;
8769 Previous_Source : constant String_List_Id := Current_Source;
8770 Except_Name : Name_And_Index := No_Name_And_Index;
8772 Unit_Prj : Unit_Project;
8774 File_Name_Recorded : Boolean := False;
8776 begin
8777 if Osint.File_Names_Case_Sensitive then
8778 Canonical_File_Name := File_Name;
8779 Canonical_Path_Name := Path_Name;
8780 else
8781 Get_Name_String (File_Name);
8782 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
8783 Canonical_File_Name := Name_Find;
8785 declare
8786 Canonical_Path : constant String :=
8787 Normalize_Pathname
8788 (Get_Name_String (Path_Name),
8789 Directory => Current_Dir,
8790 Resolve_Links => Opt.Follow_Links_For_Files,
8791 Case_Sensitive => False);
8792 begin
8793 Name_Len := 0;
8794 Add_Str_To_Name_Buffer (Canonical_Path);
8795 Canonical_Path_Name := Name_Find;
8796 end;
8797 end if;
8799 -- Find out the unit name, the unit kind and if it needs
8800 -- a specific SFN pragma.
8802 Get_Unit
8803 (In_Tree => In_Tree,
8804 Canonical_File_Name => Canonical_File_Name,
8805 Naming => Data.Naming,
8806 Exception_Id => Exception_Id,
8807 Unit_Name => Unit_Name,
8808 Unit_Kind => Unit_Kind,
8809 Needs_Pragma => Needs_Pragma);
8811 if Exception_Id = No_Ada_Naming_Exception
8812 and then Unit_Name = No_Name
8813 then
8814 if Current_Verbosity = High then
8815 Write_Str (" """);
8816 Write_Str (Get_Name_String (Canonical_File_Name));
8817 Write_Line (""" is not a valid source file name (ignored).");
8818 end if;
8820 else
8821 -- Check to see if the source has been hidden by an exception,
8822 -- but only if it is not an exception.
8824 if not Needs_Pragma then
8825 Except_Name :=
8826 Reverse_Ada_Naming_Exceptions.Get
8827 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8829 if Except_Name /= No_Name_And_Index then
8830 if Current_Verbosity = High then
8831 Write_Str (" """);
8832 Write_Str (Get_Name_String (Canonical_File_Name));
8833 Write_Str (""" contains a unit that is found in """);
8834 Write_Str (Get_Name_String (Except_Name.Name));
8835 Write_Line (""" (ignored).");
8836 end if;
8838 -- The file is not included in the source of the project since
8839 -- it is hidden by the exception. So, nothing else to do.
8841 return;
8842 end if;
8843 end if;
8845 loop
8846 if Exception_Id /= No_Ada_Naming_Exception then
8847 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8848 Exception_Id := Info.Next;
8849 Info.Next := No_Ada_Naming_Exception;
8850 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8852 Unit_Name := Info.Unit;
8853 Unit_Ind := Name_Index.Index;
8854 Unit_Kind := Info.Kind;
8855 end if;
8857 -- Put the file name in the list of sources of the project
8859 String_Element_Table.Increment_Last (In_Tree.String_Elements);
8860 In_Tree.String_Elements.Table
8861 (String_Element_Table.Last (In_Tree.String_Elements)) :=
8862 (Value => Name_Id (Canonical_File_Name),
8863 Display_Value => Name_Id (File_Name),
8864 Location => No_Location,
8865 Flag => False,
8866 Next => Nil_String,
8867 Index => Unit_Ind);
8869 if Current_Source = Nil_String then
8870 Data.Ada_Sources :=
8871 String_Element_Table.Last (In_Tree.String_Elements);
8872 else
8873 In_Tree.String_Elements.Table (Current_Source).Next :=
8874 String_Element_Table.Last (In_Tree.String_Elements);
8875 end if;
8877 Current_Source :=
8878 String_Element_Table.Last (In_Tree.String_Elements);
8880 -- Put the unit in unit list
8882 declare
8883 The_Unit : Unit_Index :=
8884 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8886 The_Unit_Data : Unit_Data;
8888 begin
8889 if Current_Verbosity = High then
8890 Write_Str ("Putting ");
8891 Write_Str (Get_Name_String (Unit_Name));
8892 Write_Line (" in the unit list.");
8893 end if;
8895 -- The unit is already in the list, but may be it is
8896 -- only the other unit kind (spec or body), or what is
8897 -- in the unit list is a unit of a project we are extending.
8899 if The_Unit /= No_Unit_Index then
8900 The_Unit_Data := In_Tree.Units.Table (The_Unit);
8902 if (The_Unit_Data.File_Names (Unit_Kind).Name =
8903 Canonical_File_Name
8904 and then
8905 The_Unit_Data.File_Names
8906 (Unit_Kind).Path.Name = Slash)
8907 or else The_Unit_Data.File_Names (Unit_Kind).Name = No_File
8908 or else Project_Extends
8909 (Data.Extends,
8910 The_Unit_Data.File_Names (Unit_Kind).Project,
8911 In_Tree)
8912 then
8914 The_Unit_Data.File_Names (Unit_Kind).Path.Name = Slash
8915 then
8916 Remove_Forbidden_File_Name
8917 (The_Unit_Data.File_Names (Unit_Kind).Name);
8918 end if;
8920 -- Record the file name in the hash table Files_Htable
8922 Unit_Prj := (Unit => The_Unit, Project => Project);
8923 Files_Htable.Set
8924 (In_Tree.Files_HT,
8925 Canonical_File_Name,
8926 Unit_Prj);
8928 The_Unit_Data.File_Names (Unit_Kind) :=
8929 (Name => Canonical_File_Name,
8930 Index => Unit_Ind,
8931 Display_Name => File_Name,
8932 Path => (Canonical_Path_Name, Path_Name),
8933 Project => Project,
8934 Needs_Pragma => Needs_Pragma);
8935 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
8936 Source_Recorded := True;
8938 elsif The_Unit_Data.File_Names (Unit_Kind).Project = Project
8939 and then (Data.Known_Order_Of_Source_Dirs
8940 or else
8941 The_Unit_Data.File_Names
8942 (Unit_Kind).Path.Name = Canonical_Path_Name)
8943 then
8944 if Previous_Source = Nil_String then
8945 Data.Ada_Sources := Nil_String;
8946 else
8947 In_Tree.String_Elements.Table (Previous_Source).Next :=
8948 Nil_String;
8949 String_Element_Table.Decrement_Last
8950 (In_Tree.String_Elements);
8951 end if;
8953 Current_Source := Previous_Source;
8955 else
8956 -- It is an error to have two units with the same name
8957 -- and the same kind (spec or body).
8959 if The_Location = No_Location then
8960 The_Location :=
8961 In_Tree.Projects.Table (Project).Location;
8962 end if;
8964 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8965 Error_Msg
8966 (Project, In_Tree, "duplicate unit %%", The_Location);
8968 Err_Vars.Error_Msg_Name_1 :=
8969 In_Tree.Projects.Table
8970 (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
8971 Err_Vars.Error_Msg_File_1 :=
8972 File_Name_Type
8973 (The_Unit_Data.File_Names (Unit_Kind).Path.Name);
8974 Error_Msg
8975 (Project, In_Tree,
8976 "\ project file %%, {", The_Location);
8978 Err_Vars.Error_Msg_Name_1 :=
8979 In_Tree.Projects.Table (Project).Name;
8980 Err_Vars.Error_Msg_File_1 :=
8981 File_Name_Type (Canonical_Path_Name);
8982 Error_Msg
8983 (Project, In_Tree,
8984 "\ project file %%, {", The_Location);
8985 end if;
8987 -- It is a new unit, create a new record
8989 else
8990 -- First, check if there is no other unit with this file
8991 -- name in another project. If it is, report error but note
8992 -- we do that only for the first unit in the source file.
8994 Unit_Prj :=
8995 Files_Htable.Get (In_Tree.Files_HT, Canonical_File_Name);
8997 if not File_Name_Recorded and then
8998 Unit_Prj /= No_Unit_Project
8999 then
9000 Error_Msg_File_1 := File_Name;
9001 Error_Msg_Name_1 :=
9002 In_Tree.Projects.Table (Unit_Prj.Project).Name;
9003 Error_Msg
9004 (Project, In_Tree,
9005 "{ is already a source of project %%",
9006 Location);
9008 else
9009 Unit_Table.Increment_Last (In_Tree.Units);
9010 The_Unit := Unit_Table.Last (In_Tree.Units);
9011 Units_Htable.Set
9012 (In_Tree.Units_HT, Unit_Name, The_Unit);
9013 Unit_Prj := (Unit => The_Unit, Project => Project);
9014 Files_Htable.Set
9015 (In_Tree.Files_HT,
9016 Canonical_File_Name,
9017 Unit_Prj);
9018 The_Unit_Data.Name := Unit_Name;
9019 The_Unit_Data.File_Names (Unit_Kind) :=
9020 (Name => Canonical_File_Name,
9021 Index => Unit_Ind,
9022 Display_Name => File_Name,
9023 Path => (Canonical_Path_Name, Path_Name),
9024 Project => Project,
9025 Needs_Pragma => Needs_Pragma);
9026 In_Tree.Units.Table (The_Unit) := The_Unit_Data;
9027 Source_Recorded := True;
9028 end if;
9029 end if;
9030 end;
9032 exit when Exception_Id = No_Ada_Naming_Exception;
9033 File_Name_Recorded := True;
9034 end loop;
9035 end if;
9036 end Record_Ada_Source;
9038 -------------------
9039 -- Remove_Source --
9040 -------------------
9042 procedure Remove_Source
9043 (Id : Source_Id;
9044 Replaced_By : Source_Id;
9045 Project : Project_Id;
9046 Data : in out Project_Data;
9047 In_Tree : Project_Tree_Ref)
9049 Src_Data : constant Source_Data := In_Tree.Sources.Table (Id);
9050 Source : Source_Id;
9052 begin
9053 if Current_Verbosity = High then
9054 Write_Str ("Removing source #");
9055 Write_Line (Id'Img);
9056 end if;
9058 if Replaced_By /= No_Source then
9059 In_Tree.Sources.Table (Id).Replaced_By := Replaced_By;
9060 In_Tree.Sources.Table (Replaced_By).Declared_In_Interfaces :=
9061 In_Tree.Sources.Table (Id).Declared_In_Interfaces;
9062 end if;
9064 -- Remove the source from the global source list
9066 Source := In_Tree.First_Source;
9068 if Source = Id then
9069 In_Tree.First_Source := Src_Data.Next_In_Sources;
9071 else
9072 while In_Tree.Sources.Table (Source).Next_In_Sources /= Id loop
9073 Source := In_Tree.Sources.Table (Source).Next_In_Sources;
9074 end loop;
9076 In_Tree.Sources.Table (Source).Next_In_Sources :=
9077 Src_Data.Next_In_Sources;
9078 end if;
9080 -- Remove the source from the project list
9082 if Src_Data.Project = Project then
9083 Source := Data.First_Source;
9085 if Source = Id then
9086 Data.First_Source := Src_Data.Next_In_Project;
9088 if Src_Data.Next_In_Project = No_Source then
9089 Data.Last_Source := No_Source;
9090 end if;
9092 else
9093 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9094 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9095 end loop;
9097 In_Tree.Sources.Table (Source).Next_In_Project :=
9098 Src_Data.Next_In_Project;
9100 if Src_Data.Next_In_Project = No_Source then
9101 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9102 end if;
9103 end if;
9105 else
9106 Source := In_Tree.Projects.Table (Src_Data.Project).First_Source;
9108 if Source = Id then
9109 In_Tree.Projects.Table (Src_Data.Project).First_Source :=
9110 Src_Data.Next_In_Project;
9112 if Src_Data.Next_In_Project = No_Source then
9113 In_Tree.Projects.Table (Src_Data.Project).Last_Source :=
9114 No_Source;
9115 end if;
9117 else
9118 while In_Tree.Sources.Table (Source).Next_In_Project /= Id loop
9119 Source := In_Tree.Sources.Table (Source).Next_In_Project;
9120 end loop;
9122 In_Tree.Sources.Table (Source).Next_In_Project :=
9123 Src_Data.Next_In_Project;
9125 if Src_Data.Next_In_Project = No_Source then
9126 In_Tree.Projects.Table (Src_Data.Project).Last_Source := Source;
9127 end if;
9128 end if;
9129 end if;
9131 -- Remove source from the language list
9133 Source := In_Tree.Languages_Data.Table (Src_Data.Language).First_Source;
9135 if Source = Id then
9136 In_Tree.Languages_Data.Table (Src_Data.Language).First_Source :=
9137 Src_Data.Next_In_Lang;
9139 else
9140 while In_Tree.Sources.Table (Source).Next_In_Lang /= Id loop
9141 Source := In_Tree.Sources.Table (Source).Next_In_Lang;
9142 end loop;
9144 In_Tree.Sources.Table (Source).Next_In_Lang :=
9145 Src_Data.Next_In_Lang;
9146 end if;
9147 end Remove_Source;
9149 -----------------------
9150 -- Report_No_Sources --
9151 -----------------------
9153 procedure Report_No_Sources
9154 (Project : Project_Id;
9155 Lang_Name : String;
9156 In_Tree : Project_Tree_Ref;
9157 Location : Source_Ptr;
9158 Continuation : Boolean := False)
9160 begin
9161 case When_No_Sources is
9162 when Silent =>
9163 null;
9165 when Warning | Error =>
9166 declare
9167 Msg : constant String :=
9168 "<there are no " &
9169 Lang_Name &
9170 " sources in this project";
9172 begin
9173 Error_Msg_Warn := When_No_Sources = Warning;
9175 if Continuation then
9176 Error_Msg
9177 (Project, In_Tree, "\" & Msg, Location);
9179 else
9180 Error_Msg
9181 (Project, In_Tree, Msg, Location);
9182 end if;
9183 end;
9184 end case;
9185 end Report_No_Sources;
9187 ----------------------
9188 -- Show_Source_Dirs --
9189 ----------------------
9191 procedure Show_Source_Dirs
9192 (Data : Project_Data;
9193 In_Tree : Project_Tree_Ref)
9195 Current : String_List_Id;
9196 Element : String_Element;
9198 begin
9199 Write_Line ("Source_Dirs:");
9201 Current := Data.Source_Dirs;
9202 while Current /= Nil_String loop
9203 Element := In_Tree.String_Elements.Table (Current);
9204 Write_Str (" ");
9205 Write_Line (Get_Name_String (Element.Value));
9206 Current := Element.Next;
9207 end loop;
9209 Write_Line ("end Source_Dirs.");
9210 end Show_Source_Dirs;
9212 -------------------------
9213 -- Warn_If_Not_Sources --
9214 -------------------------
9216 -- comments needed in this body ???
9218 procedure Warn_If_Not_Sources
9219 (Project : Project_Id;
9220 In_Tree : Project_Tree_Ref;
9221 Conventions : Array_Element_Id;
9222 Specs : Boolean;
9223 Extending : Boolean)
9225 Conv : Array_Element_Id;
9226 Unit : Name_Id;
9227 The_Unit_Id : Unit_Index;
9228 The_Unit_Data : Unit_Data;
9229 Location : Source_Ptr;
9231 begin
9232 Conv := Conventions;
9233 while Conv /= No_Array_Element loop
9234 Unit := In_Tree.Array_Elements.Table (Conv).Index;
9235 Error_Msg_Name_1 := Unit;
9236 Get_Name_String (Unit);
9237 To_Lower (Name_Buffer (1 .. Name_Len));
9238 Unit := Name_Find;
9239 The_Unit_Id := Units_Htable.Get (In_Tree.Units_HT, Unit);
9240 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
9242 if The_Unit_Id = No_Unit_Index then
9243 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
9245 else
9246 The_Unit_Data := In_Tree.Units.Table (The_Unit_Id);
9247 Error_Msg_Name_2 :=
9248 In_Tree.Array_Elements.Table (Conv).Value.Value;
9250 if Specs then
9251 if not Check_Project
9252 (The_Unit_Data.File_Names (Specification).Project,
9253 Project, In_Tree, Extending)
9254 then
9255 Error_Msg
9256 (Project, In_Tree,
9257 "?source of spec of unit %% (%%)" &
9258 " cannot be found in this project",
9259 Location);
9260 end if;
9262 else
9263 if not Check_Project
9264 (The_Unit_Data.File_Names (Body_Part).Project,
9265 Project, In_Tree, Extending)
9266 then
9267 Error_Msg
9268 (Project, In_Tree,
9269 "?source of body of unit %% (%%)" &
9270 " cannot be found in this project",
9271 Location);
9272 end if;
9273 end if;
9274 end if;
9276 Conv := In_Tree.Array_Elements.Table (Conv).Next;
9277 end loop;
9278 end Warn_If_Not_Sources;
9280 end Prj.Nmsc;