[multiple changes]
[gcc.git] / gcc / ada / prj-nmsc.adb
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-2009, 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 ------------------------------------------------------------------------------
25
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
28 with GNAT.HTable;
29
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;
44
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;
50
51 package body Prj.Nmsc is
52
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.
57
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
60
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.
64
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
67
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.
78 -- Except is set to True if source is a naming exception in the project.
79
80 No_Name_Location : constant Name_Location :=
81 (Name => No_File,
82 Location => No_Location,
83 Source => No_Source,
84 Except => False,
85 Found => False);
86
87 package Source_Names is new GNAT.HTable.Simple_HTable
88 (Header_Num => Header_Num,
89 Element => Name_Location,
90 No_Element => No_Name_Location,
91 Key => File_Name_Type,
92 Hash => Hash,
93 Equal => "=");
94 -- Hash table to store file names found in string list attribute
95 -- Source_Files or in a source list file, stored in hash table
96 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97
98 -- More documentation needed on what unit exceptions are about ???
99
100 type Unit_Exception is record
101 Name : Name_Id;
102 Spec : File_Name_Type;
103 Impl : File_Name_Type;
104 end record;
105 -- Record special naming schemes for Ada units (name of spec file and name
106 -- of implementation file).
107
108 No_Unit_Exception : constant Unit_Exception :=
109 (Name => No_Name,
110 Spec => No_File,
111 Impl => No_File);
112
113 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
114 (Header_Num => Header_Num,
115 Element => Unit_Exception,
116 No_Element => No_Unit_Exception,
117 Key => Name_Id,
118 Hash => Hash,
119 Equal => "=");
120 -- Hash table to store the unit exceptions.
121 -- ??? Seems to be used only by the multi_lang mode
122 -- ??? Should not be a global array, but stored in the project_data
123
124 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
125 (Header_Num => Header_Num,
126 Element => Boolean,
127 No_Element => False,
128 Key => Name_Id,
129 Hash => Hash,
130 Equal => "=");
131 -- Hash table to store recursive source directories, to avoid looking
132 -- several times, and to avoid cycles that may be introduced by symbolic
133 -- links.
134
135 type Ada_Naming_Exception_Id is new Nat;
136 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
137
138 type Unit_Info is record
139 Kind : Spec_Or_Body;
140 Unit : Name_Id;
141 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
142 end record;
143 -- Comment needed???
144
145 package Ada_Naming_Exception_Table is new Table.Table
146 (Table_Component_Type => Unit_Info,
147 Table_Index_Type => Ada_Naming_Exception_Id,
148 Table_Low_Bound => 1,
149 Table_Initial => 20,
150 Table_Increment => 100,
151 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
152
153 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
154 (Header_Num => Header_Num,
155 Element => Ada_Naming_Exception_Id,
156 No_Element => No_Ada_Naming_Exception,
157 Key => File_Name_Type,
158 Hash => Hash,
159 Equal => "=");
160 -- A hash table to store naming exceptions for Ada. For each file name
161 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 -- ??? This is for ada_only mode, we should be able to merge with
163 -- Unit_Exceptions table, used by multi_lang mode.
164
165 package Object_File_Names is new GNAT.HTable.Simple_HTable
166 (Header_Num => Header_Num,
167 Element => File_Name_Type,
168 No_Element => No_File,
169 Key => File_Name_Type,
170 Hash => Hash,
171 Equal => "=");
172 -- A hash table to store the object file names for a project, to check that
173 -- two different sources have different object file names.
174
175 type File_Found is record
176 File : File_Name_Type := No_File;
177 Found : Boolean := False;
178 Location : Source_Ptr := No_Location;
179 end record;
180 No_File_Found : constant File_Found := (No_File, False, No_Location);
181 -- Comments needed ???
182
183 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
184 (Header_Num => Header_Num,
185 Element => File_Found,
186 No_Element => No_File_Found,
187 Key => File_Name_Type,
188 Hash => Hash,
189 Equal => "=");
190 -- A hash table to store the excluded files, if any. This is filled by
191 -- Find_Excluded_Sources below.
192
193 procedure Find_Excluded_Sources
194 (Project : Project_Id;
195 In_Tree : Project_Tree_Ref);
196 -- Find the list of files that should not be considered as source files
197 -- for this project. Sets the list in the Excluded_Sources_Htable.
198
199 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
200 -- Override the reference kind for a source file. This properly updates
201 -- the unit data if necessary.
202
203 function Hash (Unit : Unit_Info) return Header_Num;
204
205 type Name_And_Index is record
206 Name : Name_Id := No_Name;
207 Index : Int := 0;
208 end record;
209 No_Name_And_Index : constant Name_And_Index :=
210 (Name => No_Name, Index => 0);
211 -- Name of a unit, and its index inside the source file. The first unit has
212 -- index 1 (see doc for pragma Source_File_Name), but the index might be
213 -- set to 0 when the source file contains a single unit.
214
215 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
216 (Header_Num => Header_Num,
217 Element => Name_And_Index,
218 No_Element => No_Name_And_Index,
219 Key => Unit_Info,
220 Hash => Hash,
221 Equal => "=");
222 -- A table to check if a unit with an exceptional name will hide a source
223 -- with a file name following the naming convention.
224
225 procedure Load_Naming_Exceptions
226 (Project : Project_Id;
227 In_Tree : Project_Tree_Ref);
228 -- All source files in Data.First_Source are considered as naming
229 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
230 -- as appropriate.
231
232 procedure Add_Source
233 (Id : out Source_Id;
234 In_Tree : Project_Tree_Ref;
235 Project : Project_Id;
236 Lang_Id : Language_Ptr;
237 Kind : Source_Kind;
238 File_Name : File_Name_Type;
239 Display_File : File_Name_Type;
240 Naming_Exception : Boolean := False;
241 Path : Path_Information := No_Path_Information;
242 Alternate_Languages : Language_List := null;
243 Unit : Name_Id := No_Name;
244 Index : Int := 0;
245 Source_To_Replace : Source_Id := No_Source);
246 -- Add a new source to the different lists: list of all sources in the
247 -- project tree, list of source of a project and list of sources of a
248 -- language.
249 --
250 -- If Path is specified, the file is also added to Source_Paths_HT.
251 -- If Source_To_Replace is specified, it points to the source in the
252 -- extended project that the new file is overriding.
253
254 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
255 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
256 -- This alters Name_Buffer
257
258 function Suffix_Matches
259 (Filename : String;
260 Suffix : File_Name_Type) return Boolean;
261 -- True if the file name ends with the given suffix. Always returns False
262 -- if Suffix is No_Name.
263
264 procedure Replace_Into_Name_Buffer
265 (Str : String;
266 Pattern : String;
267 Replacement : Character);
268 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
269 -- converted to lower-case at the same time.
270
271 function ALI_File_Name (Source : String) return String;
272 -- Return the ALI file name corresponding to a source
273
274 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
275 -- Check that a name is a valid Ada unit name
276
277 procedure Check_Naming_Schemes
278 (Project : Project_Id;
279 In_Tree : Project_Tree_Ref;
280 Is_Config_File : Boolean);
281 -- Check the naming scheme part of Data.
282 -- Is_Config_File should be True if Project is a config file (.cgpr)
283
284 procedure Check_Configuration
285 (Project : Project_Id;
286 In_Tree : Project_Tree_Ref;
287 Compiler_Driver_Mandatory : Boolean);
288 -- Check the configuration attributes for the project
289 -- If Compiler_Driver_Mandatory is true, then a Compiler.Driver attribute
290 -- for each language must be defined, or we will not look for its source
291 -- files.
292
293 procedure Check_If_Externally_Built
294 (Project : Project_Id;
295 In_Tree : Project_Tree_Ref);
296 -- Check attribute Externally_Built of project Project in project tree
297 -- In_Tree and modify its data Data if it has the value "true".
298
299 procedure Check_Interfaces
300 (Project : Project_Id;
301 In_Tree : Project_Tree_Ref);
302 -- If a list of sources is specified in attribute Interfaces, set
303 -- In_Interfaces only for the sources specified in the list.
304
305 procedure Check_Library_Attributes
306 (Project : Project_Id;
307 In_Tree : Project_Tree_Ref);
308 -- Check the library attributes of project Project in project tree In_Tree
309 -- and modify its data Data accordingly.
310 -- Current_Dir should represent the current directory, and is passed for
311 -- efficiency to avoid system calls to recompute it.
312
313 procedure Check_Package_Naming
314 (Project : Project_Id;
315 In_Tree : Project_Tree_Ref);
316 -- Check package Naming of project Project in project tree In_Tree and
317 -- modify its data Data accordingly.
318
319 procedure Check_Programming_Languages
320 (In_Tree : Project_Tree_Ref;
321 Project : Project_Id);
322 -- Check attribute Languages for the project with data Data in project
323 -- tree In_Tree and set the components of Data for all the programming
324 -- languages indicated in attribute Languages, if any.
325
326 function Check_Project
327 (P : Project_Id;
328 Root_Project : Project_Id;
329 Extending : Boolean) return Boolean;
330 -- Returns True if P is Root_Project or, if Extending is True, a project
331 -- extended by Root_Project.
332
333 procedure Check_Stand_Alone_Library
334 (Project : Project_Id;
335 In_Tree : Project_Tree_Ref;
336 Current_Dir : String;
337 Extending : Boolean);
338 -- Check if project Project in project tree In_Tree is a Stand-Alone
339 -- Library project, and modify its data Data accordingly if it is one.
340 -- Current_Dir should represent the current directory, and is passed for
341 -- efficiency to avoid system calls to recompute it.
342
343 procedure Check_And_Normalize_Unit_Names
344 (Project : Project_Id;
345 In_Tree : Project_Tree_Ref;
346 List : Array_Element_Id;
347 Debug_Name : String);
348 -- Check that a list of unit names contains only valid names. Casing
349 -- is normalized where appropriate.
350 -- Debug_Name is the name representing the list, and is used for debug
351 -- output only.
352
353 procedure Find_Ada_Sources
354 (Project : Project_Id;
355 In_Tree : Project_Tree_Ref;
356 Explicit_Sources_Only : Boolean;
357 Proc_Data : in out Processing_Data);
358 -- Find all Ada sources by traversing all source directories. If
359 -- Explicit_Sources_Only is True, then the sources found must belong to
360 -- the list of sources specified explicitly in the project file. If
361 -- Explicit_Sources_Only is False, then all sources matching the naming
362 -- scheme are recorded.
363
364 function Compute_Directory_Last (Dir : String) return Natural;
365 -- Return the index of the last significant character in Dir. This is used
366 -- to avoid duplicate '/' (slash) characters at the end of directory names.
367
368 procedure Error_Msg
369 (Project : Project_Id;
370 In_Tree : Project_Tree_Ref;
371 Msg : String;
372 Flag_Location : Source_Ptr);
373 -- Output an error message. If Error_Report is null, simply call
374 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
375 -- Error_Report.
376
377 procedure Search_Directories
378 (Project : Project_Id;
379 In_Tree : Project_Tree_Ref;
380 For_All_Sources : Boolean;
381 Allow_Duplicate_Basenames : Boolean);
382 -- Search the source directories to find the sources. If For_All_Sources is
383 -- True, check each regular file name against the naming schemes of the
384 -- different languages. Otherwise consider only the file names in the hash
385 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
386 -- same base names are authorized within a project for source-based
387 -- languages (never for unit based languages)
388
389 procedure Check_File
390 (Project : Project_Id;
391 In_Tree : Project_Tree_Ref;
392 Path : Path_Name_Type;
393 File_Name : File_Name_Type;
394 Display_File_Name : File_Name_Type;
395 For_All_Sources : Boolean;
396 Allow_Duplicate_Basenames : Boolean);
397 -- Check if file File_Name is a valid source of the project. This is used
398 -- in multi-language mode only. When the file matches one of the naming
399 -- schemes, it is added to various htables through Add_Source and to
400 -- Source_Paths_Htable.
401 --
402 -- Name is the name of the candidate file. It hasn't been normalized yet
403 -- and is the direct result of readdir().
404 --
405 -- File_Name is the same as Name, but has been normalized.
406 -- Display_File_Name, however, has not been normalized.
407 --
408 -- Source_Directory is the directory in which the file
409 -- was found. It hasn't been normalized (nor has had links resolved).
410 -- It should not end with a directory separator, to avoid duplicates
411 -- later on.
412 --
413 -- If For_All_Sources is True, then all possible file names are analyzed
414 -- otherwise only those currently set in the Source_Names htable.
415 --
416 -- If Allow_Duplicate_Basenames, then files with the same base names are
417 -- authorized within a project for source-based languages (never for unit
418 -- based languages)
419
420 procedure Check_File_Naming_Schemes
421 (In_Tree : Project_Tree_Ref;
422 Project : Project_Id;
423 File_Name : File_Name_Type;
424 Alternate_Languages : out Language_List;
425 Language : out Language_Ptr;
426 Display_Language_Name : out Name_Id;
427 Unit : out Name_Id;
428 Lang_Kind : out Language_Kind;
429 Kind : out Source_Kind);
430 -- Check if the file name File_Name conforms to one of the naming
431 -- schemes of the project.
432 --
433 -- If the file does not match one of the naming schemes, set Language
434 -- to No_Language_Index.
435 --
436 -- Filename is the name of the file being investigated. It has been
437 -- normalized (case-folded). File_Name is the same value.
438
439 procedure Free_Ada_Naming_Exceptions;
440 -- Free the internal hash tables used for checking naming exceptions
441
442 procedure Get_Directories
443 (Project : Project_Id;
444 In_Tree : Project_Tree_Ref;
445 Current_Dir : String);
446 -- Get the object directory, the exec directory and the source directories
447 -- of a project.
448 --
449 -- Current_Dir should represent the current directory, and is passed for
450 -- efficiency to avoid system calls to recompute it.
451
452 procedure Get_Mains
453 (Project : Project_Id;
454 In_Tree : Project_Tree_Ref);
455 -- Get the mains of a project from attribute Main, if it exists, and put
456 -- them in the project data.
457
458 procedure Get_Sources_From_File
459 (Path : String;
460 Location : Source_Ptr;
461 Project : Project_Id;
462 In_Tree : Project_Tree_Ref);
463 -- Get the list of sources from a text file and put them in hash table
464 -- Source_Names.
465
466 procedure Find_Sources
467 (Project : Project_Id;
468 In_Tree : Project_Tree_Ref;
469 Proc_Data : in out Processing_Data;
470 Allow_Duplicate_Basenames : Boolean);
471 -- Process the Source_Files and Source_List_File attributes, and store
472 -- the list of source files into the Source_Names htable.
473 -- When these attributes are not defined, find all files matching the
474 -- naming schemes in the source directories.
475 -- If Allow_Duplicate_Basenames, then files with the same base names are
476 -- authorized within a project for source-based languages (never for unit
477 -- based languages)
478
479 procedure Compute_Unit_Name
480 (File_Name : File_Name_Type;
481 Dot_Replacement : File_Name_Type;
482 Separate_Suffix : File_Name_Type;
483 Body_Suffix : File_Name_Type;
484 Spec_Suffix : File_Name_Type;
485 Casing : Casing_Type;
486 Kind : out Source_Kind;
487 Unit : out Name_Id;
488 In_Tree : Project_Tree_Ref);
489 -- Check whether the file matches the naming scheme. If it does,
490 -- compute its unit name. If Unit is set to No_Name on exit, none of the
491 -- other out parameters are relevant.
492
493 procedure Get_Unit
494 (In_Tree : Project_Tree_Ref;
495 Canonical_File_Name : File_Name_Type;
496 Naming : Naming_Data;
497 Exception_Id : out Ada_Naming_Exception_Id;
498 Unit_Name : out Name_Id;
499 Unit_Kind : out Spec_Or_Body);
500 -- Find out, from a file name, the unit name, the unit kind and if a
501 -- specific SFN pragma is needed. If the file name corresponds to no unit,
502 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
503 -- exception to the naming scheme, then Exception_Id is set to the unit or
504 -- units that the source contains, and the other information are not set.
505
506 function Is_Illegal_Suffix
507 (Suffix : File_Name_Type;
508 Dot_Replacement : File_Name_Type) return Boolean;
509 -- Returns True if the string Suffix cannot be used as a spec suffix, a
510 -- body suffix or a separate suffix.
511
512 procedure Locate_Directory
513 (Project : Project_Id;
514 In_Tree : Project_Tree_Ref;
515 Name : File_Name_Type;
516 Path : out Path_Information;
517 Dir_Exists : out Boolean;
518 Create : String := "";
519 Location : Source_Ptr := No_Location;
520 Must_Exist : Boolean := True;
521 Externally_Built : Boolean := False);
522 -- Locate a directory. Name is the directory name.
523 -- Relative paths are resolved relative to the project's directory.
524 -- If the directory does not exist and Setup_Projects
525 -- is True and Create is a non null string, an attempt is made to create
526 -- the directory.
527 -- If the directory does not exist, it is either created if Setup_Projects
528 -- is False (and then returned), or simply returned without checking for
529 -- its existence (if Must_Exist is False) or No_Path_Information is
530 -- returned. In all cases, Dir_Exists indicates whether the directory now
531 -- exists.
532 --
533 -- Create is also used for debugging traces to show which path we are
534 -- computing
535
536 procedure Look_For_Sources
537 (Project : Project_Id;
538 In_Tree : Project_Tree_Ref;
539 Proc_Data : in out Processing_Data;
540 Allow_Duplicate_Basenames : Boolean);
541 -- Find all the sources of project Project in project tree In_Tree and
542 -- update its Data accordingly. This assumes that Data.First_Source has
543 -- been initialized with the list of excluded sources and special naming
544 -- exceptions. If Allow_Duplicate_Basenames, then files with the same base
545 -- names are authorized within a project for source-based languages (never
546 -- for unit based languages)
547
548 function Path_Name_Of
549 (File_Name : File_Name_Type;
550 Directory : Path_Name_Type) return String;
551 -- Returns the path name of a (non project) file. Returns an empty string
552 -- if file cannot be found.
553
554 procedure Prepare_Ada_Naming_Exceptions
555 (List : Array_Element_Id;
556 In_Tree : Project_Tree_Ref;
557 Kind : Spec_Or_Body);
558 -- Prepare the internal hash tables used for checking naming exceptions
559 -- for Ada. Insert all elements of List in the tables.
560
561 procedure Record_Ada_Source
562 (File_Name : File_Name_Type;
563 Path_Name : Path_Name_Type;
564 Project : Project_Id;
565 In_Tree : Project_Tree_Ref;
566 Proc_Data : in out Processing_Data;
567 Ada_Language : Language_Ptr;
568 Location : Source_Ptr;
569 Source_Recorded : in out Boolean);
570 -- Put a unit in the list of units of a project, if the file name
571 -- corresponds to a valid unit name. Ada_Language is a pointer to the
572 -- Language_Data for "Ada" in Project.
573
574 procedure Remove_Source
575 (Id : Source_Id;
576 Replaced_By : Source_Id);
577 -- ??? needs comment
578
579 procedure Report_No_Sources
580 (Project : Project_Id;
581 Lang_Name : String;
582 In_Tree : Project_Tree_Ref;
583 Location : Source_Ptr;
584 Continuation : Boolean := False);
585 -- Report an error or a warning depending on the value of When_No_Sources
586 -- when there are no sources for language Lang_Name.
587
588 procedure Show_Source_Dirs
589 (Project : Project_Id; In_Tree : Project_Tree_Ref);
590 -- List all the source directories of a project
591
592 procedure Warn_If_Not_Sources
593 (Project : Project_Id;
594 In_Tree : Project_Tree_Ref;
595 Conventions : Array_Element_Id;
596 Specs : Boolean;
597 Extending : Boolean);
598 -- Check that individual naming conventions apply to immediate sources of
599 -- the project. If not, issue a warning.
600
601 procedure Write_Attr (Name, Value : String);
602 -- Debug print a value for a specific property. Does nothing when not in
603 -- debug mode
604
605 ------------------------------
606 -- Replace_Into_Name_Buffer --
607 ------------------------------
608
609 procedure Replace_Into_Name_Buffer
610 (Str : String;
611 Pattern : String;
612 Replacement : Character)
613 is
614 Max : constant Integer := Str'Last - Pattern'Length + 1;
615 J : Positive;
616
617 begin
618 Name_Len := 0;
619
620 J := Str'First;
621 while J <= Str'Last loop
622 Name_Len := Name_Len + 1;
623
624 if J <= Max
625 and then Str (J .. J + Pattern'Length - 1) = Pattern
626 then
627 Name_Buffer (Name_Len) := Replacement;
628 J := J + Pattern'Length;
629
630 else
631 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
632 J := J + 1;
633 end if;
634 end loop;
635 end Replace_Into_Name_Buffer;
636
637 --------------------
638 -- Suffix_Matches --
639 --------------------
640
641 function Suffix_Matches
642 (Filename : String;
643 Suffix : File_Name_Type) return Boolean
644 is
645 Min_Prefix_Length : Natural := 0;
646 begin
647 if Suffix = No_File or else Suffix = Empty_File then
648 return False;
649 end if;
650
651 declare
652 Suf : constant String := Get_Name_String (Suffix);
653 begin
654
655 -- The file name must end with the suffix (which is not an extension)
656 -- For instance a suffix "configure.in" must match a file with the
657 -- same name. To avoid dummy cases, though, a suffix starting with
658 -- '.' requires a file that is at least one character longer ('.cpp'
659 -- should not match a file with the same name)
660
661 if Suf (Suf'First) = '.' then
662 Min_Prefix_Length := 1;
663 end if;
664
665 return Filename'Length >= Suf'Length + Min_Prefix_Length
666 and then Filename
667 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
668 end;
669 end Suffix_Matches;
670
671 ----------------
672 -- Write_Attr --
673 ----------------
674
675 procedure Write_Attr (Name, Value : String) is
676 begin
677 if Current_Verbosity = High then
678 Write_Str (" " & Name & " = """);
679 Write_Str (Value);
680 Write_Char ('"');
681 Write_Eol;
682 end if;
683 end Write_Attr;
684
685 ----------------
686 -- Add_Source --
687 ----------------
688
689 procedure Add_Source
690 (Id : out Source_Id;
691 In_Tree : Project_Tree_Ref;
692 Project : Project_Id;
693 Lang_Id : Language_Ptr;
694 Kind : Source_Kind;
695 File_Name : File_Name_Type;
696 Display_File : File_Name_Type;
697 Naming_Exception : Boolean := False;
698 Path : Path_Information := No_Path_Information;
699 Alternate_Languages : Language_List := null;
700 Unit : Name_Id := No_Name;
701 Index : Int := 0;
702 Source_To_Replace : Source_Id := No_Source)
703 is
704 Config : constant Language_Config := Lang_Id.Config;
705 UData : Unit_Index;
706
707 begin
708 Id := new Source_Data;
709
710 if Current_Verbosity = High then
711 Write_Str ("Adding source File: ");
712 Write_Str (Get_Name_String (File_Name));
713
714 if Lang_Id.Config.Kind = Unit_Based then
715 Write_Str (" Unit: ");
716 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
717 -- (see test extended_projects)
718 if Unit /= No_Name then
719 Write_Str (Get_Name_String (Unit));
720 end if;
721 Write_Str (" Kind: ");
722 Write_Str (Source_Kind'Image (Kind));
723 end if;
724
725 Write_Eol;
726 end if;
727
728 Id.Project := Project;
729 Id.Language := Lang_Id;
730 Id.Kind := Kind;
731 Id.Alternate_Languages := Alternate_Languages;
732
733 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
734 -- is not null.
735
736 if Unit /= No_Name then
737 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
738
739 -- ??? Record_Unit has already fetched that earlier, so this isn't
740 -- the most efficient way. But we can't really pass a parameter since
741 -- Process_Exceptions_Unit_Based and Check_File haven't looked it up.
742
743 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
744
745 if UData = No_Unit_Index then
746 UData := new Unit_Data;
747 UData.Name := Unit;
748 Units_Htable.Set (In_Tree.Units_HT, Unit, UData);
749 end if;
750
751 Id.Unit := UData;
752
753 -- Note that this updates Unit information as well
754
755 Override_Kind (Id, Kind);
756 end if;
757
758 Id.Index := Index;
759 Id.File := File_Name;
760 Id.Display_File := Display_File;
761 Id.Dep_Name := Dependency_Name
762 (File_Name, Lang_Id.Config.Dependency_Kind);
763 Id.Naming_Exception := Naming_Exception;
764
765 if Is_Compilable (Id) and then Config.Object_Generated then
766 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
767 Id.Switches := Switches_Name (File_Name);
768 end if;
769
770 if Path /= No_Path_Information then
771 Id.Path := Path;
772 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path.Name, Id);
773 end if;
774
775 -- Add the source to the language list
776
777 Id.Next_In_Lang := Lang_Id.First_Source;
778 Lang_Id.First_Source := Id;
779
780 if Source_To_Replace /= No_Source then
781 Remove_Source (Source_To_Replace, Id);
782 end if;
783 end Add_Source;
784
785 -------------------
786 -- ALI_File_Name --
787 -------------------
788
789 function ALI_File_Name (Source : String) return String is
790 begin
791 -- If the source name has extension, replace it with the ALI suffix
792
793 for Index in reverse Source'First + 1 .. Source'Last loop
794 if Source (Index) = '.' then
795 return Source (Source'First .. Index - 1) & ALI_Suffix;
796 end if;
797 end loop;
798
799 -- If no dot, or if it is the first character, just add the ALI suffix
800
801 return Source & ALI_Suffix;
802 end ALI_File_Name;
803
804 ------------------------------
805 -- Canonical_Case_File_Name --
806 ------------------------------
807
808 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
809 begin
810 if Osint.File_Names_Case_Sensitive then
811 return File_Name_Type (Name);
812 else
813 Get_Name_String (Name);
814 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
815 return Name_Find;
816 end if;
817 end Canonical_Case_File_Name;
818
819 -----------
820 -- Check --
821 -----------
822
823 procedure Check
824 (Project : Project_Id;
825 In_Tree : Project_Tree_Ref;
826 Report_Error : Put_Line_Access;
827 When_No_Sources : Error_Warning;
828 Current_Dir : String;
829 Proc_Data : in out Processing_Data;
830 Is_Config_File : Boolean;
831 Compiler_Driver_Mandatory : Boolean;
832 Allow_Duplicate_Basenames : Boolean)
833 is
834 Extending : Boolean := False;
835
836 begin
837 Nmsc.When_No_Sources := When_No_Sources;
838 Error_Report := Report_Error;
839
840 Recursive_Dirs.Reset;
841
842 Check_If_Externally_Built (Project, In_Tree);
843
844 -- Object, exec and source directories
845
846 Get_Directories (Project, In_Tree, Current_Dir);
847
848 -- Get the programming languages
849
850 Check_Programming_Languages (In_Tree, Project);
851
852 if Project.Qualifier = Dry
853 and then Project.Source_Dirs /= Nil_String
854 then
855 declare
856 Source_Dirs : constant Variable_Value :=
857 Util.Value_Of
858 (Name_Source_Dirs,
859 Project.Decl.Attributes, In_Tree);
860 Source_Files : constant Variable_Value :=
861 Util.Value_Of
862 (Name_Source_Files,
863 Project.Decl.Attributes, In_Tree);
864 Source_List_File : constant Variable_Value :=
865 Util.Value_Of
866 (Name_Source_List_File,
867 Project.Decl.Attributes, In_Tree);
868 Languages : constant Variable_Value :=
869 Util.Value_Of
870 (Name_Languages,
871 Project.Decl.Attributes, In_Tree);
872
873 begin
874 if Source_Dirs.Values = Nil_String
875 and then Source_Files.Values = Nil_String
876 and then Languages.Values = Nil_String
877 and then Source_List_File.Default
878 then
879 Project.Source_Dirs := Nil_String;
880
881 else
882 Error_Msg
883 (Project, In_Tree,
884 "at least one of Source_Files, Source_Dirs or Languages " &
885 "must be declared empty for an abstract project",
886 Project.Location);
887 end if;
888 end;
889 end if;
890
891 -- Check configuration in multi language mode
892
893 if Must_Check_Configuration then
894 Check_Configuration
895 (Project, In_Tree,
896 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory);
897 end if;
898
899 -- Library attributes
900
901 Check_Library_Attributes (Project, In_Tree);
902
903 if Current_Verbosity = High then
904 Show_Source_Dirs (Project, In_Tree);
905 end if;
906
907 Check_Package_Naming (Project, In_Tree);
908
909 Extending := Project.Extends /= No_Project;
910
911 Check_Naming_Schemes (Project, In_Tree, Is_Config_File);
912
913 if Get_Mode = Ada_Only then
914 Prepare_Ada_Naming_Exceptions
915 (Project.Naming.Bodies, In_Tree, Impl);
916 Prepare_Ada_Naming_Exceptions
917 (Project.Naming.Specs, In_Tree, Spec);
918 end if;
919
920 -- Find the sources
921
922 if Project.Source_Dirs /= Nil_String then
923 Look_For_Sources
924 (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
925
926 if Get_Mode = Ada_Only then
927
928 -- Check that all individual naming conventions apply to sources
929 -- of this project file.
930
931 Warn_If_Not_Sources
932 (Project, In_Tree, Project.Naming.Bodies,
933 Specs => False,
934 Extending => Extending);
935 Warn_If_Not_Sources
936 (Project, In_Tree, Project.Naming.Specs,
937 Specs => True,
938 Extending => Extending);
939
940 elsif Get_Mode = Multi_Language and then
941 (not Project.Externally_Built) and then
942 (not Extending)
943 then
944 declare
945 Language : Language_Ptr;
946 Source : Source_Id;
947 Alt_Lang : Language_List;
948 Continuation : Boolean := False;
949 Iter : Source_Iterator;
950
951 begin
952 Language := Project.Languages;
953 while Language /= No_Language_Index loop
954
955 -- If there are no sources for this language, check whether
956 -- there are sources for which this is an alternate
957 -- language.
958
959 if Language.First_Source = No_Source then
960 Iter := For_Each_Source (In_Tree => In_Tree,
961 Project => Project);
962 Source_Loop : loop
963 Source := Element (Iter);
964 exit Source_Loop when Source = No_Source
965 or else Source.Language = Language;
966
967 Alt_Lang := Source.Alternate_Languages;
968 while Alt_Lang /= null loop
969 exit Source_Loop when Alt_Lang.Language = Language;
970 Alt_Lang := Alt_Lang.Next;
971 end loop;
972
973 Next (Iter);
974 end loop Source_Loop;
975
976 if Source = No_Source then
977 Report_No_Sources
978 (Project,
979 Get_Name_String (Language.Display_Name),
980 In_Tree,
981 Project.Location,
982 Continuation);
983 Continuation := True;
984 end if;
985 end if;
986
987 Language := Language.Next;
988 end loop;
989 end;
990 end if;
991 end if;
992
993 if Get_Mode = Multi_Language then
994
995 -- If a list of sources is specified in attribute Interfaces, set
996 -- In_Interfaces only for the sources specified in the list.
997
998 Check_Interfaces (Project, In_Tree);
999 end if;
1000
1001 -- If it is a library project file, check if it is a standalone library
1002
1003 if Project.Library then
1004 Check_Stand_Alone_Library
1005 (Project, In_Tree, Current_Dir, Extending);
1006 end if;
1007
1008 -- Put the list of Mains, if any, in the project data
1009
1010 Get_Mains (Project, In_Tree);
1011
1012 Free_Ada_Naming_Exceptions;
1013 end Check;
1014
1015 --------------------
1016 -- Check_Ada_Name --
1017 --------------------
1018
1019 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1020 The_Name : String := Name;
1021 Real_Name : Name_Id;
1022 Need_Letter : Boolean := True;
1023 Last_Underscore : Boolean := False;
1024 OK : Boolean := The_Name'Length > 0;
1025 First : Positive;
1026
1027 function Is_Reserved (Name : Name_Id) return Boolean;
1028 function Is_Reserved (S : String) return Boolean;
1029 -- Check that the given name is not an Ada 95 reserved word. The reason
1030 -- for the Ada 95 here is that we do not want to exclude the case of an
1031 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1032 -- name would be rejected anyway by the compiler. That means there is no
1033 -- requirement that the project file parser reject this.
1034
1035 -----------------
1036 -- Is_Reserved --
1037 -----------------
1038
1039 function Is_Reserved (S : String) return Boolean is
1040 begin
1041 Name_Len := 0;
1042 Add_Str_To_Name_Buffer (S);
1043 return Is_Reserved (Name_Find);
1044 end Is_Reserved;
1045
1046 -----------------
1047 -- Is_Reserved --
1048 -----------------
1049
1050 function Is_Reserved (Name : Name_Id) return Boolean is
1051 begin
1052 if Get_Name_Table_Byte (Name) /= 0
1053 and then Name /= Name_Project
1054 and then Name /= Name_Extends
1055 and then Name /= Name_External
1056 and then Name not in Ada_2005_Reserved_Words
1057 then
1058 Unit := No_Name;
1059
1060 if Current_Verbosity = High then
1061 Write_Str (The_Name);
1062 Write_Line (" is an Ada reserved word.");
1063 end if;
1064
1065 return True;
1066
1067 else
1068 return False;
1069 end if;
1070 end Is_Reserved;
1071
1072 -- Start of processing for Check_Ada_Name
1073
1074 begin
1075 To_Lower (The_Name);
1076
1077 Name_Len := The_Name'Length;
1078 Name_Buffer (1 .. Name_Len) := The_Name;
1079
1080 -- Special cases of children of packages A, G, I and S on VMS
1081
1082 if OpenVMS_On_Target
1083 and then Name_Len > 3
1084 and then Name_Buffer (2 .. 3) = "__"
1085 and then
1086 ((Name_Buffer (1) = 'a') or else
1087 (Name_Buffer (1) = 'g') or else
1088 (Name_Buffer (1) = 'i') or else
1089 (Name_Buffer (1) = 's'))
1090 then
1091 Name_Buffer (2) := '.';
1092 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1093 Name_Len := Name_Len - 1;
1094 end if;
1095
1096 Real_Name := Name_Find;
1097
1098 if Is_Reserved (Real_Name) then
1099 return;
1100 end if;
1101
1102 First := The_Name'First;
1103
1104 for Index in The_Name'Range loop
1105 if Need_Letter then
1106
1107 -- We need a letter (at the beginning, and following a dot),
1108 -- but we don't have one.
1109
1110 if Is_Letter (The_Name (Index)) then
1111 Need_Letter := False;
1112
1113 else
1114 OK := False;
1115
1116 if Current_Verbosity = High then
1117 Write_Int (Types.Int (Index));
1118 Write_Str (": '");
1119 Write_Char (The_Name (Index));
1120 Write_Line ("' is not a letter.");
1121 end if;
1122
1123 exit;
1124 end if;
1125
1126 elsif Last_Underscore
1127 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1128 then
1129 -- Two underscores are illegal, and a dot cannot follow
1130 -- an underscore.
1131
1132 OK := False;
1133
1134 if Current_Verbosity = High then
1135 Write_Int (Types.Int (Index));
1136 Write_Str (": '");
1137 Write_Char (The_Name (Index));
1138 Write_Line ("' is illegal here.");
1139 end if;
1140
1141 exit;
1142
1143 elsif The_Name (Index) = '.' then
1144
1145 -- First, check if the name before the dot is not a reserved word
1146 if Is_Reserved (The_Name (First .. Index - 1)) then
1147 return;
1148 end if;
1149
1150 First := Index + 1;
1151
1152 -- We need a letter after a dot
1153
1154 Need_Letter := True;
1155
1156 elsif The_Name (Index) = '_' then
1157 Last_Underscore := True;
1158
1159 else
1160 -- We need an letter or a digit
1161
1162 Last_Underscore := False;
1163
1164 if not Is_Alphanumeric (The_Name (Index)) then
1165 OK := False;
1166
1167 if Current_Verbosity = High then
1168 Write_Int (Types.Int (Index));
1169 Write_Str (": '");
1170 Write_Char (The_Name (Index));
1171 Write_Line ("' is not alphanumeric.");
1172 end if;
1173
1174 exit;
1175 end if;
1176 end if;
1177 end loop;
1178
1179 -- Cannot end with an underscore or a dot
1180
1181 OK := OK and then not Need_Letter and then not Last_Underscore;
1182
1183 if OK then
1184 if First /= Name'First and then
1185 Is_Reserved (The_Name (First .. The_Name'Last))
1186 then
1187 return;
1188 end if;
1189
1190 Unit := Real_Name;
1191
1192 else
1193 -- Signal a problem with No_Name
1194
1195 Unit := No_Name;
1196 end if;
1197 end Check_Ada_Name;
1198
1199 -------------------------
1200 -- Check_Configuration --
1201 -------------------------
1202
1203 procedure Check_Configuration
1204 (Project : Project_Id;
1205 In_Tree : Project_Tree_Ref;
1206 Compiler_Driver_Mandatory : Boolean)
1207 is
1208 Dot_Replacement : File_Name_Type := No_File;
1209 Casing : Casing_Type := All_Lower_Case;
1210 Separate_Suffix : File_Name_Type := No_File;
1211
1212 Lang_Index : Language_Ptr := No_Language_Index;
1213 -- The index of the language data being checked
1214
1215 Prev_Index : Language_Ptr := No_Language_Index;
1216 -- The index of the previous language
1217
1218 procedure Process_Project_Level_Simple_Attributes;
1219 -- Process the simple attributes at the project level
1220
1221 procedure Process_Project_Level_Array_Attributes;
1222 -- Process the associate array attributes at the project level
1223
1224 procedure Process_Packages;
1225 -- Read the packages of the project
1226
1227 ----------------------
1228 -- Process_Packages --
1229 ----------------------
1230
1231 procedure Process_Packages is
1232 Packages : Package_Id;
1233 Element : Package_Element;
1234
1235 procedure Process_Binder (Arrays : Array_Id);
1236 -- Process the associate array attributes of package Binder
1237
1238 procedure Process_Builder (Attributes : Variable_Id);
1239 -- Process the simple attributes of package Builder
1240
1241 procedure Process_Compiler (Arrays : Array_Id);
1242 -- Process the associate array attributes of package Compiler
1243
1244 procedure Process_Naming (Attributes : Variable_Id);
1245 -- Process the simple attributes of package Naming
1246
1247 procedure Process_Naming (Arrays : Array_Id);
1248 -- Process the associate array attributes of package Naming
1249
1250 procedure Process_Linker (Attributes : Variable_Id);
1251 -- Process the simple attributes of package Linker of a
1252 -- configuration project.
1253
1254 --------------------
1255 -- Process_Binder --
1256 --------------------
1257
1258 procedure Process_Binder (Arrays : Array_Id) is
1259 Current_Array_Id : Array_Id;
1260 Current_Array : Array_Data;
1261 Element_Id : Array_Element_Id;
1262 Element : Array_Element;
1263
1264 begin
1265 -- Process the associative array attribute of package Binder
1266
1267 Current_Array_Id := Arrays;
1268 while Current_Array_Id /= No_Array loop
1269 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1270
1271 Element_Id := Current_Array.Value;
1272 while Element_Id /= No_Array_Element loop
1273 Element := In_Tree.Array_Elements.Table (Element_Id);
1274
1275 if Element.Index /= All_Other_Names then
1276
1277 -- Get the name of the language
1278
1279 Lang_Index :=
1280 Get_Language_From_Name
1281 (Project, Get_Name_String (Element.Index));
1282
1283 if Lang_Index /= No_Language_Index then
1284 case Current_Array.Name is
1285 when Name_Driver =>
1286
1287 -- Attribute Driver (<language>)
1288
1289 Lang_Index.Config.Binder_Driver :=
1290 File_Name_Type (Element.Value.Value);
1291
1292 when Name_Required_Switches =>
1293 Put
1294 (Into_List =>
1295 Lang_Index.Config.Binder_Required_Switches,
1296 From_List => Element.Value.Values,
1297 In_Tree => In_Tree);
1298
1299 when Name_Prefix =>
1300
1301 -- Attribute Prefix (<language>)
1302
1303 Lang_Index.Config.Binder_Prefix :=
1304 Element.Value.Value;
1305
1306 when Name_Objects_Path =>
1307
1308 -- Attribute Objects_Path (<language>)
1309
1310 Lang_Index.Config.Objects_Path :=
1311 Element.Value.Value;
1312
1313 when Name_Objects_Path_File =>
1314
1315 -- Attribute Objects_Path (<language>)
1316
1317 Lang_Index.Config.Objects_Path_File :=
1318 Element.Value.Value;
1319
1320 when others =>
1321 null;
1322 end case;
1323 end if;
1324 end if;
1325
1326 Element_Id := Element.Next;
1327 end loop;
1328
1329 Current_Array_Id := Current_Array.Next;
1330 end loop;
1331 end Process_Binder;
1332
1333 ---------------------
1334 -- Process_Builder --
1335 ---------------------
1336
1337 procedure Process_Builder (Attributes : Variable_Id) is
1338 Attribute_Id : Variable_Id;
1339 Attribute : Variable;
1340
1341 begin
1342 -- Process non associated array attribute from package Builder
1343
1344 Attribute_Id := Attributes;
1345 while Attribute_Id /= No_Variable loop
1346 Attribute :=
1347 In_Tree.Variable_Elements.Table (Attribute_Id);
1348
1349 if not Attribute.Value.Default then
1350 if Attribute.Name = Name_Executable_Suffix then
1351
1352 -- Attribute Executable_Suffix: the suffix of the
1353 -- executables.
1354
1355 Project.Config.Executable_Suffix :=
1356 Attribute.Value.Value;
1357 end if;
1358 end if;
1359
1360 Attribute_Id := Attribute.Next;
1361 end loop;
1362 end Process_Builder;
1363
1364 ----------------------
1365 -- Process_Compiler --
1366 ----------------------
1367
1368 procedure Process_Compiler (Arrays : Array_Id) is
1369 Current_Array_Id : Array_Id;
1370 Current_Array : Array_Data;
1371 Element_Id : Array_Element_Id;
1372 Element : Array_Element;
1373 List : String_List_Id;
1374
1375 begin
1376 -- Process the associative array attribute of package Compiler
1377
1378 Current_Array_Id := Arrays;
1379 while Current_Array_Id /= No_Array loop
1380 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1381
1382 Element_Id := Current_Array.Value;
1383 while Element_Id /= No_Array_Element loop
1384 Element := In_Tree.Array_Elements.Table (Element_Id);
1385
1386 if Element.Index /= All_Other_Names then
1387
1388 -- Get the name of the language
1389
1390 Lang_Index := Get_Language_From_Name
1391 (Project, Get_Name_String (Element.Index));
1392
1393 if Lang_Index /= No_Language_Index then
1394 case Current_Array.Name is
1395 when Name_Dependency_Switches =>
1396
1397 -- Attribute Dependency_Switches (<language>)
1398
1399 if Lang_Index.Config.Dependency_Kind = None then
1400 Lang_Index.Config.Dependency_Kind := Makefile;
1401 end if;
1402
1403 List := Element.Value.Values;
1404
1405 if List /= Nil_String then
1406 Put (Into_List =>
1407 Lang_Index.Config.Dependency_Option,
1408 From_List => List,
1409 In_Tree => In_Tree);
1410 end if;
1411
1412 when Name_Dependency_Driver =>
1413
1414 -- Attribute Dependency_Driver (<language>)
1415
1416 if Lang_Index.Config.Dependency_Kind = None then
1417 Lang_Index.Config.Dependency_Kind := Makefile;
1418 end if;
1419
1420 List := Element.Value.Values;
1421
1422 if List /= Nil_String then
1423 Put (Into_List =>
1424 Lang_Index.Config.Compute_Dependency,
1425 From_List => List,
1426 In_Tree => In_Tree);
1427 end if;
1428
1429 when Name_Include_Switches =>
1430
1431 -- Attribute Include_Switches (<language>)
1432
1433 List := Element.Value.Values;
1434
1435 if List = Nil_String then
1436 Error_Msg
1437 (Project,
1438 In_Tree,
1439 "include option cannot be null",
1440 Element.Value.Location);
1441 end if;
1442
1443 Put (Into_List =>
1444 Lang_Index.Config.Include_Option,
1445 From_List => List,
1446 In_Tree => In_Tree);
1447
1448 when Name_Include_Path =>
1449
1450 -- Attribute Include_Path (<language>)
1451
1452 Lang_Index.Config.Include_Path :=
1453 Element.Value.Value;
1454
1455 when Name_Include_Path_File =>
1456
1457 -- Attribute Include_Path_File (<language>)
1458
1459 Lang_Index.Config.Include_Path_File :=
1460 Element.Value.Value;
1461
1462 when Name_Driver =>
1463
1464 -- Attribute Driver (<language>)
1465
1466 Lang_Index.Config.Compiler_Driver :=
1467 File_Name_Type (Element.Value.Value);
1468
1469 when Name_Required_Switches |
1470 Name_Leading_Required_Switches =>
1471 Put (Into_List =>
1472 Lang_Index.Config.
1473 Compiler_Leading_Required_Switches,
1474 From_List => Element.Value.Values,
1475 In_Tree => In_Tree);
1476
1477 when Name_Trailing_Required_Switches =>
1478 Put (Into_List =>
1479 Lang_Index.Config.
1480 Compiler_Trailing_Required_Switches,
1481 From_List => Element.Value.Values,
1482 In_Tree => In_Tree);
1483
1484 when Name_Path_Syntax =>
1485 begin
1486 Lang_Index.Config.Path_Syntax :=
1487 Path_Syntax_Kind'Value
1488 (Get_Name_String (Element.Value.Value));
1489
1490 exception
1491 when Constraint_Error =>
1492 Error_Msg
1493 (Project,
1494 In_Tree,
1495 "invalid value for Path_Syntax",
1496 Element.Value.Location);
1497 end;
1498
1499 when Name_Object_File_Suffix =>
1500 if Get_Name_String (Element.Value.Value) = "" then
1501 Error_Msg
1502 (Project, In_Tree,
1503 "object file suffix cannot be empty",
1504 Element.Value.Location);
1505
1506 else
1507 Lang_Index.Config.Object_File_Suffix :=
1508 Element.Value.Value;
1509 end if;
1510
1511 when Name_Object_File_Switches =>
1512 Put (Into_List =>
1513 Lang_Index.Config.Object_File_Switches,
1514 From_List => Element.Value.Values,
1515 In_Tree => In_Tree);
1516
1517 when Name_Pic_Option =>
1518
1519 -- Attribute Compiler_Pic_Option (<language>)
1520
1521 List := Element.Value.Values;
1522
1523 if List = Nil_String then
1524 Error_Msg
1525 (Project,
1526 In_Tree,
1527 "compiler PIC option cannot be null",
1528 Element.Value.Location);
1529 end if;
1530
1531 Put (Into_List =>
1532 Lang_Index.Config.Compilation_PIC_Option,
1533 From_List => List,
1534 In_Tree => In_Tree);
1535
1536 when Name_Mapping_File_Switches =>
1537
1538 -- Attribute Mapping_File_Switches (<language>)
1539
1540 List := Element.Value.Values;
1541
1542 if List = Nil_String then
1543 Error_Msg
1544 (Project,
1545 In_Tree,
1546 "mapping file switches cannot be null",
1547 Element.Value.Location);
1548 end if;
1549
1550 Put (Into_List =>
1551 Lang_Index.Config.Mapping_File_Switches,
1552 From_List => List,
1553 In_Tree => In_Tree);
1554
1555 when Name_Mapping_Spec_Suffix =>
1556
1557 -- Attribute Mapping_Spec_Suffix (<language>)
1558
1559 Lang_Index.Config.Mapping_Spec_Suffix :=
1560 File_Name_Type (Element.Value.Value);
1561
1562 when Name_Mapping_Body_Suffix =>
1563
1564 -- Attribute Mapping_Body_Suffix (<language>)
1565
1566 Lang_Index.Config.Mapping_Body_Suffix :=
1567 File_Name_Type (Element.Value.Value);
1568
1569 when Name_Config_File_Switches =>
1570
1571 -- Attribute Config_File_Switches (<language>)
1572
1573 List := Element.Value.Values;
1574
1575 if List = Nil_String then
1576 Error_Msg
1577 (Project,
1578 In_Tree,
1579 "config file switches cannot be null",
1580 Element.Value.Location);
1581 end if;
1582
1583 Put (Into_List =>
1584 Lang_Index.Config.Config_File_Switches,
1585 From_List => List,
1586 In_Tree => In_Tree);
1587
1588 when Name_Objects_Path =>
1589
1590 -- Attribute Objects_Path (<language>)
1591
1592 Lang_Index.Config.Objects_Path :=
1593 Element.Value.Value;
1594
1595 when Name_Objects_Path_File =>
1596
1597 -- Attribute Objects_Path_File (<language>)
1598
1599 Lang_Index.Config.Objects_Path_File :=
1600 Element.Value.Value;
1601
1602 when Name_Config_Body_File_Name =>
1603
1604 -- Attribute Config_Body_File_Name (<language>)
1605
1606 Lang_Index.Config.Config_Body :=
1607 Element.Value.Value;
1608
1609 when Name_Config_Body_File_Name_Pattern =>
1610
1611 -- Attribute Config_Body_File_Name_Pattern
1612 -- (<language>)
1613
1614 Lang_Index.Config.Config_Body_Pattern :=
1615 Element.Value.Value;
1616
1617 when Name_Config_Spec_File_Name =>
1618
1619 -- Attribute Config_Spec_File_Name (<language>)
1620
1621 Lang_Index.Config.Config_Spec :=
1622 Element.Value.Value;
1623
1624 when Name_Config_Spec_File_Name_Pattern =>
1625
1626 -- Attribute Config_Spec_File_Name_Pattern
1627 -- (<language>)
1628
1629 Lang_Index.Config.Config_Spec_Pattern :=
1630 Element.Value.Value;
1631
1632 when Name_Config_File_Unique =>
1633
1634 -- Attribute Config_File_Unique (<language>)
1635
1636 begin
1637 Lang_Index.Config.Config_File_Unique :=
1638 Boolean'Value
1639 (Get_Name_String (Element.Value.Value));
1640 exception
1641 when Constraint_Error =>
1642 Error_Msg
1643 (Project,
1644 In_Tree,
1645 "illegal value for Config_File_Unique",
1646 Element.Value.Location);
1647 end;
1648
1649 when others =>
1650 null;
1651 end case;
1652 end if;
1653 end if;
1654
1655 Element_Id := Element.Next;
1656 end loop;
1657
1658 Current_Array_Id := Current_Array.Next;
1659 end loop;
1660 end Process_Compiler;
1661
1662 --------------------
1663 -- Process_Naming --
1664 --------------------
1665
1666 procedure Process_Naming (Attributes : Variable_Id) is
1667 Attribute_Id : Variable_Id;
1668 Attribute : Variable;
1669
1670 begin
1671 -- Process non associated array attribute from package Naming
1672
1673 Attribute_Id := Attributes;
1674 while Attribute_Id /= No_Variable loop
1675 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1676
1677 if not Attribute.Value.Default then
1678 if Attribute.Name = Name_Separate_Suffix then
1679
1680 -- Attribute Separate_Suffix
1681
1682 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1683
1684 elsif Attribute.Name = Name_Casing then
1685
1686 -- Attribute Casing
1687
1688 begin
1689 Casing :=
1690 Value (Get_Name_String (Attribute.Value.Value));
1691
1692 exception
1693 when Constraint_Error =>
1694 Error_Msg
1695 (Project,
1696 In_Tree,
1697 "invalid value for Casing",
1698 Attribute.Value.Location);
1699 end;
1700
1701 elsif Attribute.Name = Name_Dot_Replacement then
1702
1703 -- Attribute Dot_Replacement
1704
1705 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1706
1707 end if;
1708 end if;
1709
1710 Attribute_Id := Attribute.Next;
1711 end loop;
1712 end Process_Naming;
1713
1714 procedure Process_Naming (Arrays : Array_Id) is
1715 Current_Array_Id : Array_Id;
1716 Current_Array : Array_Data;
1717 Element_Id : Array_Element_Id;
1718 Element : Array_Element;
1719 begin
1720 -- Process the associative array attribute of package Naming
1721
1722 Current_Array_Id := Arrays;
1723 while Current_Array_Id /= No_Array loop
1724 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1725
1726 Element_Id := Current_Array.Value;
1727 while Element_Id /= No_Array_Element loop
1728 Element := In_Tree.Array_Elements.Table (Element_Id);
1729
1730 -- Get the name of the language
1731
1732 Lang_Index := Get_Language_From_Name
1733 (Project, Get_Name_String (Element.Index));
1734
1735 if Lang_Index /= No_Language_Index then
1736 case Current_Array.Name is
1737 when Name_Spec_Suffix | Name_Specification_Suffix =>
1738
1739 -- Attribute Spec_Suffix (<language>)
1740
1741 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1742 File_Name_Type (Element.Value.Value);
1743
1744 when Name_Implementation_Suffix | Name_Body_Suffix =>
1745
1746 -- Attribute Body_Suffix (<language>)
1747
1748 Lang_Index.Config.Naming_Data.Body_Suffix :=
1749 File_Name_Type (Element.Value.Value);
1750
1751 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1752 File_Name_Type (Element.Value.Value);
1753
1754 when others =>
1755 null;
1756 end case;
1757 end if;
1758
1759 Element_Id := Element.Next;
1760 end loop;
1761
1762 Current_Array_Id := Current_Array.Next;
1763 end loop;
1764 end Process_Naming;
1765
1766 --------------------
1767 -- Process_Linker --
1768 --------------------
1769
1770 procedure Process_Linker (Attributes : Variable_Id) is
1771 Attribute_Id : Variable_Id;
1772 Attribute : Variable;
1773
1774 begin
1775 -- Process non associated array attribute from package Linker
1776
1777 Attribute_Id := Attributes;
1778 while Attribute_Id /= No_Variable loop
1779 Attribute :=
1780 In_Tree.Variable_Elements.Table (Attribute_Id);
1781
1782 if not Attribute.Value.Default then
1783 if Attribute.Name = Name_Driver then
1784
1785 -- Attribute Linker'Driver: the default linker to use
1786
1787 Project.Config.Linker :=
1788 Path_Name_Type (Attribute.Value.Value);
1789
1790 -- Linker'Driver is also used to link shared libraries
1791 -- if the obsolescent attribute Library_GCC has not been
1792 -- specified.
1793
1794 if Project.Config.Shared_Lib_Driver = No_File then
1795 Project.Config.Shared_Lib_Driver :=
1796 File_Name_Type (Attribute.Value.Value);
1797 end if;
1798
1799 elsif Attribute.Name = Name_Required_Switches then
1800
1801 -- Attribute Required_Switches: the minimum
1802 -- options to use when invoking the linker
1803
1804 Put (Into_List => Project.Config.Minimum_Linker_Options,
1805 From_List => Attribute.Value.Values,
1806 In_Tree => In_Tree);
1807
1808 elsif Attribute.Name = Name_Map_File_Option then
1809 Project.Config.Map_File_Option := Attribute.Value.Value;
1810
1811 elsif Attribute.Name = Name_Max_Command_Line_Length then
1812 begin
1813 Project.Config.Max_Command_Line_Length :=
1814 Natural'Value (Get_Name_String
1815 (Attribute.Value.Value));
1816
1817 exception
1818 when Constraint_Error =>
1819 Error_Msg
1820 (Project,
1821 In_Tree,
1822 "value must be positive or equal to 0",
1823 Attribute.Value.Location);
1824 end;
1825
1826 elsif Attribute.Name = Name_Response_File_Format then
1827 declare
1828 Name : Name_Id;
1829
1830 begin
1831 Get_Name_String (Attribute.Value.Value);
1832 To_Lower (Name_Buffer (1 .. Name_Len));
1833 Name := Name_Find;
1834
1835 if Name = Name_None then
1836 Project.Config.Resp_File_Format := None;
1837
1838 elsif Name = Name_Gnu then
1839 Project.Config.Resp_File_Format := GNU;
1840
1841 elsif Name = Name_Object_List then
1842 Project.Config.Resp_File_Format := Object_List;
1843
1844 elsif Name = Name_Option_List then
1845 Project.Config.Resp_File_Format := Option_List;
1846
1847 else
1848 Error_Msg
1849 (Project,
1850 In_Tree,
1851 "illegal response file format",
1852 Attribute.Value.Location);
1853 end if;
1854 end;
1855
1856 elsif Attribute.Name = Name_Response_File_Switches then
1857 Put (Into_List => Project.Config.Resp_File_Options,
1858 From_List => Attribute.Value.Values,
1859 In_Tree => In_Tree);
1860 end if;
1861 end if;
1862
1863 Attribute_Id := Attribute.Next;
1864 end loop;
1865 end Process_Linker;
1866
1867 -- Start of processing for Process_Packages
1868
1869 begin
1870 Packages := Project.Decl.Packages;
1871 while Packages /= No_Package loop
1872 Element := In_Tree.Packages.Table (Packages);
1873
1874 case Element.Name is
1875 when Name_Binder =>
1876
1877 -- Process attributes of package Binder
1878
1879 Process_Binder (Element.Decl.Arrays);
1880
1881 when Name_Builder =>
1882
1883 -- Process attributes of package Builder
1884
1885 Process_Builder (Element.Decl.Attributes);
1886
1887 when Name_Compiler =>
1888
1889 -- Process attributes of package Compiler
1890
1891 Process_Compiler (Element.Decl.Arrays);
1892
1893 when Name_Linker =>
1894
1895 -- Process attributes of package Linker
1896
1897 Process_Linker (Element.Decl.Attributes);
1898
1899 when Name_Naming =>
1900
1901 -- Process attributes of package Naming
1902
1903 Process_Naming (Element.Decl.Attributes);
1904 Process_Naming (Element.Decl.Arrays);
1905
1906 when others =>
1907 null;
1908 end case;
1909
1910 Packages := Element.Next;
1911 end loop;
1912 end Process_Packages;
1913
1914 ---------------------------------------------
1915 -- Process_Project_Level_Simple_Attributes --
1916 ---------------------------------------------
1917
1918 procedure Process_Project_Level_Simple_Attributes is
1919 Attribute_Id : Variable_Id;
1920 Attribute : Variable;
1921 List : String_List_Id;
1922
1923 begin
1924 -- Process non associated array attribute at project level
1925
1926 Attribute_Id := Project.Decl.Attributes;
1927 while Attribute_Id /= No_Variable loop
1928 Attribute :=
1929 In_Tree.Variable_Elements.Table (Attribute_Id);
1930
1931 if not Attribute.Value.Default then
1932 if Attribute.Name = Name_Target then
1933
1934 -- Attribute Target: the target specified
1935
1936 Project.Config.Target := Attribute.Value.Value;
1937
1938 elsif Attribute.Name = Name_Library_Builder then
1939
1940 -- Attribute Library_Builder: the application to invoke
1941 -- to build libraries.
1942
1943 Project.Config.Library_Builder :=
1944 Path_Name_Type (Attribute.Value.Value);
1945
1946 elsif Attribute.Name = Name_Archive_Builder then
1947
1948 -- Attribute Archive_Builder: the archive builder
1949 -- (usually "ar") and its minimum options (usually "cr").
1950
1951 List := Attribute.Value.Values;
1952
1953 if List = Nil_String then
1954 Error_Msg
1955 (Project,
1956 In_Tree,
1957 "archive builder cannot be null",
1958 Attribute.Value.Location);
1959 end if;
1960
1961 Put (Into_List => Project.Config.Archive_Builder,
1962 From_List => List,
1963 In_Tree => In_Tree);
1964
1965 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1966
1967 -- Attribute Archive_Builder: the archive builder
1968 -- (usually "ar") and its minimum options (usually "cr").
1969
1970 List := Attribute.Value.Values;
1971
1972 if List /= Nil_String then
1973 Put
1974 (Into_List =>
1975 Project.Config.Archive_Builder_Append_Option,
1976 From_List => List,
1977 In_Tree => In_Tree);
1978 end if;
1979
1980 elsif Attribute.Name = Name_Archive_Indexer then
1981
1982 -- Attribute Archive_Indexer: the optional archive
1983 -- indexer (usually "ranlib") with its minimum options
1984 -- (usually none).
1985
1986 List := Attribute.Value.Values;
1987
1988 if List = Nil_String then
1989 Error_Msg
1990 (Project,
1991 In_Tree,
1992 "archive indexer cannot be null",
1993 Attribute.Value.Location);
1994 end if;
1995
1996 Put (Into_List => Project.Config.Archive_Indexer,
1997 From_List => List,
1998 In_Tree => In_Tree);
1999
2000 elsif Attribute.Name = Name_Library_Partial_Linker then
2001
2002 -- Attribute Library_Partial_Linker: the optional linker
2003 -- driver with its minimum options, to partially link
2004 -- archives.
2005
2006 List := Attribute.Value.Values;
2007
2008 if List = Nil_String then
2009 Error_Msg
2010 (Project,
2011 In_Tree,
2012 "partial linker cannot be null",
2013 Attribute.Value.Location);
2014 end if;
2015
2016 Put (Into_List => Project.Config.Lib_Partial_Linker,
2017 From_List => List,
2018 In_Tree => In_Tree);
2019
2020 elsif Attribute.Name = Name_Library_GCC then
2021 Project.Config.Shared_Lib_Driver :=
2022 File_Name_Type (Attribute.Value.Value);
2023 Error_Msg
2024 (Project,
2025 In_Tree,
2026 "?Library_'G'C'C is an obsolescent attribute, " &
2027 "use Linker''Driver instead",
2028 Attribute.Value.Location);
2029
2030 elsif Attribute.Name = Name_Archive_Suffix then
2031 Project.Config.Archive_Suffix :=
2032 File_Name_Type (Attribute.Value.Value);
2033
2034 elsif Attribute.Name = Name_Linker_Executable_Option then
2035
2036 -- Attribute Linker_Executable_Option: optional options
2037 -- to specify an executable name. Defaults to "-o".
2038
2039 List := Attribute.Value.Values;
2040
2041 if List = Nil_String then
2042 Error_Msg
2043 (Project,
2044 In_Tree,
2045 "linker executable option cannot be null",
2046 Attribute.Value.Location);
2047 end if;
2048
2049 Put (Into_List => Project.Config.Linker_Executable_Option,
2050 From_List => List,
2051 In_Tree => In_Tree);
2052
2053 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2054
2055 -- Attribute Linker_Lib_Dir_Option: optional options
2056 -- to specify a library search directory. Defaults to
2057 -- "-L".
2058
2059 Get_Name_String (Attribute.Value.Value);
2060
2061 if Name_Len = 0 then
2062 Error_Msg
2063 (Project,
2064 In_Tree,
2065 "linker library directory option cannot be empty",
2066 Attribute.Value.Location);
2067 end if;
2068
2069 Project.Config.Linker_Lib_Dir_Option :=
2070 Attribute.Value.Value;
2071
2072 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2073
2074 -- Attribute Linker_Lib_Name_Option: optional options
2075 -- to specify the name of a library to be linked in.
2076 -- Defaults to "-l".
2077
2078 Get_Name_String (Attribute.Value.Value);
2079
2080 if Name_Len = 0 then
2081 Error_Msg
2082 (Project,
2083 In_Tree,
2084 "linker library name option cannot be empty",
2085 Attribute.Value.Location);
2086 end if;
2087
2088 Project.Config.Linker_Lib_Name_Option :=
2089 Attribute.Value.Value;
2090
2091 elsif Attribute.Name = Name_Run_Path_Option then
2092
2093 -- Attribute Run_Path_Option: optional options to
2094 -- specify a path for libraries.
2095
2096 List := Attribute.Value.Values;
2097
2098 if List /= Nil_String then
2099 Put (Into_List => Project.Config.Run_Path_Option,
2100 From_List => List,
2101 In_Tree => In_Tree);
2102 end if;
2103
2104 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2105 declare
2106 pragma Unsuppress (All_Checks);
2107 begin
2108 Project.Config.Separate_Run_Path_Options :=
2109 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2110 exception
2111 when Constraint_Error =>
2112 Error_Msg
2113 (Project,
2114 In_Tree,
2115 "invalid value """ &
2116 Get_Name_String (Attribute.Value.Value) &
2117 """ for Separate_Run_Path_Options",
2118 Attribute.Value.Location);
2119 end;
2120
2121 elsif Attribute.Name = Name_Library_Support then
2122 declare
2123 pragma Unsuppress (All_Checks);
2124 begin
2125 Project.Config.Lib_Support :=
2126 Library_Support'Value (Get_Name_String
2127 (Attribute.Value.Value));
2128 exception
2129 when Constraint_Error =>
2130 Error_Msg
2131 (Project,
2132 In_Tree,
2133 "invalid value """ &
2134 Get_Name_String (Attribute.Value.Value) &
2135 """ for Library_Support",
2136 Attribute.Value.Location);
2137 end;
2138
2139 elsif Attribute.Name = Name_Shared_Library_Prefix then
2140 Project.Config.Shared_Lib_Prefix :=
2141 File_Name_Type (Attribute.Value.Value);
2142
2143 elsif Attribute.Name = Name_Shared_Library_Suffix then
2144 Project.Config.Shared_Lib_Suffix :=
2145 File_Name_Type (Attribute.Value.Value);
2146
2147 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2148 declare
2149 pragma Unsuppress (All_Checks);
2150 begin
2151 Project.Config.Symbolic_Link_Supported :=
2152 Boolean'Value (Get_Name_String
2153 (Attribute.Value.Value));
2154 exception
2155 when Constraint_Error =>
2156 Error_Msg
2157 (Project,
2158 In_Tree,
2159 "invalid value """
2160 & Get_Name_String (Attribute.Value.Value)
2161 & """ for Symbolic_Link_Supported",
2162 Attribute.Value.Location);
2163 end;
2164
2165 elsif
2166 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2167 then
2168 declare
2169 pragma Unsuppress (All_Checks);
2170 begin
2171 Project.Config.Lib_Maj_Min_Id_Supported :=
2172 Boolean'Value (Get_Name_String
2173 (Attribute.Value.Value));
2174 exception
2175 when Constraint_Error =>
2176 Error_Msg
2177 (Project,
2178 In_Tree,
2179 "invalid value """ &
2180 Get_Name_String (Attribute.Value.Value) &
2181 """ for Library_Major_Minor_Id_Supported",
2182 Attribute.Value.Location);
2183 end;
2184
2185 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2186 declare
2187 pragma Unsuppress (All_Checks);
2188 begin
2189 Project.Config.Auto_Init_Supported :=
2190 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2191 exception
2192 when Constraint_Error =>
2193 Error_Msg
2194 (Project,
2195 In_Tree,
2196 "invalid value """
2197 & Get_Name_String (Attribute.Value.Value)
2198 & """ for Library_Auto_Init_Supported",
2199 Attribute.Value.Location);
2200 end;
2201
2202 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2203 List := Attribute.Value.Values;
2204
2205 if List /= Nil_String then
2206 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2207 From_List => List,
2208 In_Tree => In_Tree);
2209 end if;
2210
2211 elsif Attribute.Name = Name_Library_Version_Switches then
2212 List := Attribute.Value.Values;
2213
2214 if List /= Nil_String then
2215 Put (Into_List => Project.Config.Lib_Version_Options,
2216 From_List => List,
2217 In_Tree => In_Tree);
2218 end if;
2219 end if;
2220 end if;
2221
2222 Attribute_Id := Attribute.Next;
2223 end loop;
2224 end Process_Project_Level_Simple_Attributes;
2225
2226 --------------------------------------------
2227 -- Process_Project_Level_Array_Attributes --
2228 --------------------------------------------
2229
2230 procedure Process_Project_Level_Array_Attributes is
2231 Current_Array_Id : Array_Id;
2232 Current_Array : Array_Data;
2233 Element_Id : Array_Element_Id;
2234 Element : Array_Element;
2235 List : String_List_Id;
2236
2237 begin
2238 -- Process the associative array attributes at project level
2239
2240 Current_Array_Id := Project.Decl.Arrays;
2241 while Current_Array_Id /= No_Array loop
2242 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2243
2244 Element_Id := Current_Array.Value;
2245 while Element_Id /= No_Array_Element loop
2246 Element := In_Tree.Array_Elements.Table (Element_Id);
2247
2248 -- Get the name of the language
2249
2250 Lang_Index :=
2251 Get_Language_From_Name
2252 (Project, Get_Name_String (Element.Index));
2253
2254 if Lang_Index /= No_Language_Index then
2255 case Current_Array.Name is
2256 when Name_Inherit_Source_Path =>
2257 List := Element.Value.Values;
2258
2259 if List /= Nil_String then
2260 Put
2261 (Into_List =>
2262 Lang_Index.Config.Include_Compatible_Languages,
2263 From_List => List,
2264 In_Tree => In_Tree,
2265 Lower_Case => True);
2266 end if;
2267
2268 when Name_Toolchain_Description =>
2269
2270 -- Attribute Toolchain_Description (<language>)
2271
2272 Lang_Index.Config.Toolchain_Description :=
2273 Element.Value.Value;
2274
2275 when Name_Toolchain_Version =>
2276
2277 -- Attribute Toolchain_Version (<language>)
2278
2279 Lang_Index.Config.Toolchain_Version :=
2280 Element.Value.Value;
2281
2282 when Name_Runtime_Library_Dir =>
2283
2284 -- Attribute Runtime_Library_Dir (<language>)
2285
2286 Lang_Index.Config.Runtime_Library_Dir :=
2287 Element.Value.Value;
2288
2289 when Name_Runtime_Source_Dir =>
2290
2291 -- Attribute Runtime_Library_Dir (<language>)
2292
2293 Lang_Index.Config.Runtime_Source_Dir :=
2294 Element.Value.Value;
2295
2296 when Name_Object_Generated =>
2297 declare
2298 pragma Unsuppress (All_Checks);
2299 Value : Boolean;
2300
2301 begin
2302 Value :=
2303 Boolean'Value
2304 (Get_Name_String (Element.Value.Value));
2305
2306 Lang_Index.Config.Object_Generated := Value;
2307
2308 -- If no object is generated, no object may be
2309 -- linked.
2310
2311 if not Value then
2312 Lang_Index.Config.Objects_Linked := False;
2313 end if;
2314
2315 exception
2316 when Constraint_Error =>
2317 Error_Msg
2318 (Project,
2319 In_Tree,
2320 "invalid value """
2321 & Get_Name_String (Element.Value.Value)
2322 & """ for Object_Generated",
2323 Element.Value.Location);
2324 end;
2325
2326 when Name_Objects_Linked =>
2327 declare
2328 pragma Unsuppress (All_Checks);
2329 Value : Boolean;
2330
2331 begin
2332 Value :=
2333 Boolean'Value
2334 (Get_Name_String (Element.Value.Value));
2335
2336 -- No change if Object_Generated is False, as this
2337 -- forces Objects_Linked to be False too.
2338
2339 if Lang_Index.Config.Object_Generated then
2340 Lang_Index.Config.Objects_Linked := Value;
2341 end if;
2342
2343 exception
2344 when Constraint_Error =>
2345 Error_Msg
2346 (Project,
2347 In_Tree,
2348 "invalid value """
2349 & Get_Name_String (Element.Value.Value)
2350 & """ for Objects_Linked",
2351 Element.Value.Location);
2352 end;
2353 when others =>
2354 null;
2355 end case;
2356 end if;
2357
2358 Element_Id := Element.Next;
2359 end loop;
2360
2361 Current_Array_Id := Current_Array.Next;
2362 end loop;
2363 end Process_Project_Level_Array_Attributes;
2364
2365 begin
2366 Process_Project_Level_Simple_Attributes;
2367 Process_Project_Level_Array_Attributes;
2368 Process_Packages;
2369
2370 -- For unit based languages, set Casing, Dot_Replacement and
2371 -- Separate_Suffix in Naming_Data.
2372
2373 Lang_Index := Project.Languages;
2374 while Lang_Index /= No_Language_Index loop
2375 if Lang_Index.Name = Name_Ada then
2376 Lang_Index.Config.Naming_Data.Casing := Casing;
2377 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2378
2379 if Separate_Suffix /= No_File then
2380 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2381 Separate_Suffix;
2382 end if;
2383
2384 exit;
2385 end if;
2386
2387 Lang_Index := Lang_Index.Next;
2388 end loop;
2389
2390 -- Give empty names to various prefixes/suffixes, if they have not
2391 -- been specified in the configuration.
2392
2393 if Project.Config.Archive_Suffix = No_File then
2394 Project.Config.Archive_Suffix := Empty_File;
2395 end if;
2396
2397 if Project.Config.Shared_Lib_Prefix = No_File then
2398 Project.Config.Shared_Lib_Prefix := Empty_File;
2399 end if;
2400
2401 if Project.Config.Shared_Lib_Suffix = No_File then
2402 Project.Config.Shared_Lib_Suffix := Empty_File;
2403 end if;
2404
2405 Lang_Index := Project.Languages;
2406 while Lang_Index /= No_Language_Index loop
2407 -- For all languages, Compiler_Driver needs to be specified. This is
2408 -- only necessary if we do intend to compiler (not in GPS for
2409 -- instance)
2410
2411 if Compiler_Driver_Mandatory
2412 and then Lang_Index.Config.Compiler_Driver = No_File
2413 then
2414 Error_Msg_Name_1 := Lang_Index.Display_Name;
2415 Error_Msg
2416 (Project,
2417 In_Tree,
2418 "?no compiler specified for language %%" &
2419 ", ignoring all its sources",
2420 No_Location);
2421
2422 if Lang_Index = Project.Languages then
2423 Project.Languages := Lang_Index.Next;
2424 else
2425 Prev_Index.Next := Lang_Index.Next;
2426 end if;
2427
2428 elsif Lang_Index.Name = Name_Ada then
2429 Prev_Index := Lang_Index;
2430
2431 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2432 -- Body_Suffix need to be specified.
2433
2434 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2435 Error_Msg
2436 (Project,
2437 In_Tree,
2438 "Dot_Replacement not specified for Ada",
2439 No_Location);
2440 end if;
2441
2442 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2443 Error_Msg
2444 (Project,
2445 In_Tree,
2446 "Spec_Suffix not specified for Ada",
2447 No_Location);
2448 end if;
2449
2450 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2451 Error_Msg
2452 (Project,
2453 In_Tree,
2454 "Body_Suffix not specified for Ada",
2455 No_Location);
2456 end if;
2457
2458 else
2459 Prev_Index := Lang_Index;
2460
2461 -- For file based languages, either Spec_Suffix or Body_Suffix
2462 -- need to be specified.
2463
2464 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2465 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2466 then
2467 Error_Msg_Name_1 := Lang_Index.Display_Name;
2468 Error_Msg
2469 (Project,
2470 In_Tree,
2471 "no suffixes specified for %%",
2472 No_Location);
2473 end if;
2474 end if;
2475
2476 Lang_Index := Lang_Index.Next;
2477 end loop;
2478 end Check_Configuration;
2479
2480 -------------------------------
2481 -- Check_If_Externally_Built --
2482 -------------------------------
2483
2484 procedure Check_If_Externally_Built
2485 (Project : Project_Id;
2486 In_Tree : Project_Tree_Ref)
2487 is
2488 Externally_Built : constant Variable_Value :=
2489 Util.Value_Of
2490 (Name_Externally_Built,
2491 Project.Decl.Attributes, In_Tree);
2492
2493 begin
2494 if not Externally_Built.Default then
2495 Get_Name_String (Externally_Built.Value);
2496 To_Lower (Name_Buffer (1 .. Name_Len));
2497
2498 if Name_Buffer (1 .. Name_Len) = "true" then
2499 Project.Externally_Built := True;
2500
2501 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2502 Error_Msg (Project, In_Tree,
2503 "Externally_Built may only be true or false",
2504 Externally_Built.Location);
2505 end if;
2506 end if;
2507
2508 -- A virtual project extending an externally built project is itself
2509 -- externally built.
2510
2511 if Project.Virtual and then Project.Extends /= No_Project then
2512 Project.Externally_Built := Project.Extends.Externally_Built;
2513 end if;
2514
2515 if Current_Verbosity = High then
2516 Write_Str ("Project is ");
2517
2518 if not Project.Externally_Built then
2519 Write_Str ("not ");
2520 end if;
2521
2522 Write_Line ("externally built.");
2523 end if;
2524 end Check_If_Externally_Built;
2525
2526 ----------------------
2527 -- Check_Interfaces --
2528 ----------------------
2529
2530 procedure Check_Interfaces
2531 (Project : Project_Id;
2532 In_Tree : Project_Tree_Ref)
2533 is
2534 Interfaces : constant Prj.Variable_Value :=
2535 Prj.Util.Value_Of
2536 (Snames.Name_Interfaces,
2537 Project.Decl.Attributes,
2538 In_Tree);
2539
2540 List : String_List_Id;
2541 Element : String_Element;
2542 Name : File_Name_Type;
2543 Iter : Source_Iterator;
2544 Source : Source_Id;
2545 Project_2 : Project_Id;
2546 Other : Source_Id;
2547
2548 begin
2549 if not Interfaces.Default then
2550
2551 -- Set In_Interfaces to False for all sources. It will be set to True
2552 -- later for the sources in the Interfaces list.
2553
2554 Project_2 := Project;
2555 while Project_2 /= No_Project loop
2556 Iter := For_Each_Source (In_Tree, Project_2);
2557
2558 loop
2559 Source := Prj.Element (Iter);
2560 exit when Source = No_Source;
2561 Source.In_Interfaces := False;
2562 Next (Iter);
2563 end loop;
2564
2565 Project_2 := Project_2.Extends;
2566 end loop;
2567
2568 List := Interfaces.Values;
2569 while List /= Nil_String loop
2570 Element := In_Tree.String_Elements.Table (List);
2571 Name := Canonical_Case_File_Name (Element.Value);
2572
2573 Project_2 := Project;
2574 Big_Loop :
2575 while Project_2 /= No_Project loop
2576 Iter := For_Each_Source (In_Tree, Project_2);
2577
2578 loop
2579 Source := Prj.Element (Iter);
2580 exit when Source = No_Source;
2581
2582 if Source.File = Name then
2583 if not Source.Locally_Removed then
2584 Source.In_Interfaces := True;
2585 Source.Declared_In_Interfaces := True;
2586
2587 Other := Other_Part (Source);
2588
2589 if Other /= No_Source then
2590 Other.In_Interfaces := True;
2591 Other.Declared_In_Interfaces := True;
2592 end if;
2593
2594 if Current_Verbosity = High then
2595 Write_Str (" interface: ");
2596 Write_Line (Get_Name_String (Source.Path.Name));
2597 end if;
2598 end if;
2599
2600 exit Big_Loop;
2601 end if;
2602
2603 Next (Iter);
2604 end loop;
2605
2606 Project_2 := Project_2.Extends;
2607 end loop Big_Loop;
2608
2609 if Source = No_Source then
2610 Error_Msg_File_1 := File_Name_Type (Element.Value);
2611 Error_Msg_Name_1 := Project.Name;
2612
2613 Error_Msg
2614 (Project,
2615 In_Tree,
2616 "{ cannot be an interface of project %% "
2617 & "as it is not one of its sources",
2618 Element.Location);
2619 end if;
2620
2621 List := Element.Next;
2622 end loop;
2623
2624 Project.Interfaces_Defined := True;
2625
2626 elsif Project.Extends /= No_Project then
2627 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2628
2629 if Project.Interfaces_Defined then
2630 Iter := For_Each_Source (In_Tree, Project);
2631 loop
2632 Source := Prj.Element (Iter);
2633 exit when Source = No_Source;
2634
2635 if not Source.Declared_In_Interfaces then
2636 Source.In_Interfaces := False;
2637 end if;
2638
2639 Next (Iter);
2640 end loop;
2641 end if;
2642 end if;
2643 end Check_Interfaces;
2644
2645 ------------------------------------
2646 -- Check_And_Normalize_Unit_Names --
2647 ------------------------------------
2648
2649 procedure Check_And_Normalize_Unit_Names
2650 (Project : Project_Id;
2651 In_Tree : Project_Tree_Ref;
2652 List : Array_Element_Id;
2653 Debug_Name : String)
2654 is
2655 Current : Array_Element_Id;
2656 Element : Array_Element;
2657 Unit_Name : Name_Id;
2658
2659 begin
2660 if Current_Verbosity = High then
2661 Write_Line (" Checking unit names in " & Debug_Name);
2662 end if;
2663
2664 Current := List;
2665 while Current /= No_Array_Element loop
2666 Element := In_Tree.Array_Elements.Table (Current);
2667 Element.Value.Value :=
2668 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2669
2670 -- Check that it contains a valid unit name
2671
2672 Get_Name_String (Element.Index);
2673 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2674
2675 if Unit_Name = No_Name then
2676 Err_Vars.Error_Msg_Name_1 := Element.Index;
2677 Error_Msg
2678 (Project, In_Tree,
2679 "%% is not a valid unit name.",
2680 Element.Value.Location);
2681
2682 else
2683 if Current_Verbosity = High then
2684 Write_Str (" for unit: ");
2685 Write_Line (Get_Name_String (Unit_Name));
2686 end if;
2687
2688 Element.Index := Unit_Name;
2689 In_Tree.Array_Elements.Table (Current) := Element;
2690 end if;
2691
2692 Current := Element.Next;
2693 end loop;
2694 end Check_And_Normalize_Unit_Names;
2695
2696 --------------------------
2697 -- Check_Naming_Schemes --
2698 --------------------------
2699
2700 procedure Check_Naming_Schemes
2701 (Project : Project_Id;
2702 In_Tree : Project_Tree_Ref;
2703 Is_Config_File : Boolean)
2704 is
2705 Naming_Id : constant Package_Id :=
2706 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
2707 Naming : Package_Element;
2708
2709 procedure Check_Naming_Ada_Only;
2710 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2711 -- If there is a package Naming, puts in Data.Naming the contents of
2712 -- this package.
2713
2714 procedure Check_Naming_Multi_Lang;
2715 -- Does Check_Naming_Schemes processing for Multi_Language mode
2716
2717 procedure Check_Common
2718 (Dot_Replacement : in out File_Name_Type;
2719 Casing : in out Casing_Type;
2720 Casing_Defined : out Boolean;
2721 Separate_Suffix : in out File_Name_Type;
2722 Sep_Suffix_Loc : out Source_Ptr);
2723 -- Check attributes common to Ada_Only and Multi_Lang modes
2724
2725 procedure Process_Exceptions_File_Based
2726 (Lang_Id : Language_Ptr;
2727 Kind : Source_Kind);
2728 procedure Process_Exceptions_Unit_Based
2729 (Lang_Id : Language_Ptr;
2730 Kind : Source_Kind);
2731 -- In Multi_Lang mode, process the naming exceptions for the two types
2732 -- of languages we can have.
2733
2734 ------------------
2735 -- Check_Common --
2736 ------------------
2737
2738 procedure Check_Common
2739 (Dot_Replacement : in out File_Name_Type;
2740 Casing : in out Casing_Type;
2741 Casing_Defined : out Boolean;
2742 Separate_Suffix : in out File_Name_Type;
2743 Sep_Suffix_Loc : out Source_Ptr)
2744 is
2745 Dot_Repl : constant Variable_Value :=
2746 Util.Value_Of
2747 (Name_Dot_Replacement,
2748 Naming.Decl.Attributes,
2749 In_Tree);
2750 Casing_String : constant Variable_Value :=
2751 Util.Value_Of
2752 (Name_Casing,
2753 Naming.Decl.Attributes,
2754 In_Tree);
2755 Sep_Suffix : constant Variable_Value :=
2756 Util.Value_Of
2757 (Name_Separate_Suffix,
2758 Naming.Decl.Attributes,
2759 In_Tree);
2760 Dot_Repl_Loc : Source_Ptr;
2761
2762 begin
2763 Sep_Suffix_Loc := No_Location;
2764
2765 if not Dot_Repl.Default then
2766 pragma Assert
2767 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2768
2769 if Length_Of_Name (Dot_Repl.Value) = 0 then
2770 Error_Msg
2771 (Project, In_Tree,
2772 "Dot_Replacement cannot be empty",
2773 Dot_Repl.Location);
2774 end if;
2775
2776 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2777 Dot_Repl_Loc := Dot_Repl.Location;
2778
2779 declare
2780 Repl : constant String := Get_Name_String (Dot_Replacement);
2781
2782 begin
2783 -- Dot_Replacement cannot
2784 -- - be empty
2785 -- - start or end with an alphanumeric
2786 -- - be a single '_'
2787 -- - start with an '_' followed by an alphanumeric
2788 -- - contain a '.' except if it is "."
2789
2790 if Repl'Length = 0
2791 or else Is_Alphanumeric (Repl (Repl'First))
2792 or else Is_Alphanumeric (Repl (Repl'Last))
2793 or else (Repl (Repl'First) = '_'
2794 and then
2795 (Repl'Length = 1
2796 or else
2797 Is_Alphanumeric (Repl (Repl'First + 1))))
2798 or else (Repl'Length > 1
2799 and then
2800 Index (Source => Repl, Pattern => ".") /= 0)
2801 then
2802 Error_Msg
2803 (Project, In_Tree,
2804 '"' & Repl &
2805 """ is illegal for Dot_Replacement.",
2806 Dot_Repl_Loc);
2807 end if;
2808 end;
2809 end if;
2810
2811 if Dot_Replacement /= No_File then
2812 Write_Attr
2813 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2814 end if;
2815
2816 Casing_Defined := False;
2817
2818 if not Casing_String.Default then
2819 pragma Assert
2820 (Casing_String.Kind = Single, "Casing is not a string");
2821
2822 declare
2823 Casing_Image : constant String :=
2824 Get_Name_String (Casing_String.Value);
2825 begin
2826 if Casing_Image'Length = 0 then
2827 Error_Msg
2828 (Project, In_Tree,
2829 "Casing cannot be an empty string",
2830 Casing_String.Location);
2831 end if;
2832
2833 Casing := Value (Casing_Image);
2834 Casing_Defined := True;
2835
2836 exception
2837 when Constraint_Error =>
2838 Name_Len := Casing_Image'Length;
2839 Name_Buffer (1 .. Name_Len) := Casing_Image;
2840 Err_Vars.Error_Msg_Name_1 := Name_Find;
2841 Error_Msg
2842 (Project, In_Tree,
2843 "%% is not a correct Casing",
2844 Casing_String.Location);
2845 end;
2846 end if;
2847
2848 Write_Attr ("Casing", Image (Casing));
2849
2850 if not Sep_Suffix.Default then
2851 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2852 Error_Msg
2853 (Project, In_Tree,
2854 "Separate_Suffix cannot be empty",
2855 Sep_Suffix.Location);
2856
2857 else
2858 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2859 Sep_Suffix_Loc := Sep_Suffix.Location;
2860
2861 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2862 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2863 Error_Msg
2864 (Project, In_Tree,
2865 "{ is illegal for Separate_Suffix",
2866 Sep_Suffix.Location);
2867 end if;
2868 end if;
2869 end if;
2870
2871 if Separate_Suffix /= No_File then
2872 Write_Attr
2873 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2874 end if;
2875 end Check_Common;
2876
2877 -----------------------------------
2878 -- Process_Exceptions_File_Based --
2879 -----------------------------------
2880
2881 procedure Process_Exceptions_File_Based
2882 (Lang_Id : Language_Ptr;
2883 Kind : Source_Kind)
2884 is
2885 Lang : constant Name_Id := Lang_Id.Name;
2886 Exceptions : Array_Element_Id;
2887 Exception_List : Variable_Value;
2888 Element_Id : String_List_Id;
2889 Element : String_Element;
2890 File_Name : File_Name_Type;
2891 Source : Source_Id;
2892 Iter : Source_Iterator;
2893
2894 begin
2895 case Kind is
2896 when Impl | Sep =>
2897 Exceptions :=
2898 Value_Of
2899 (Name_Implementation_Exceptions,
2900 In_Arrays => Naming.Decl.Arrays,
2901 In_Tree => In_Tree);
2902
2903 when Spec =>
2904 Exceptions :=
2905 Value_Of
2906 (Name_Specification_Exceptions,
2907 In_Arrays => Naming.Decl.Arrays,
2908 In_Tree => In_Tree);
2909 end case;
2910
2911 Exception_List := Value_Of
2912 (Index => Lang,
2913 In_Array => Exceptions,
2914 In_Tree => In_Tree);
2915
2916 if Exception_List /= Nil_Variable_Value then
2917 Element_Id := Exception_List.Values;
2918 while Element_Id /= Nil_String loop
2919 Element := In_Tree.String_Elements.Table (Element_Id);
2920 File_Name := Canonical_Case_File_Name (Element.Value);
2921
2922 Iter := For_Each_Source (In_Tree, Project);
2923 loop
2924 Source := Prj.Element (Iter);
2925 exit when Source = No_Source or else Source.File = File_Name;
2926 Next (Iter);
2927 end loop;
2928
2929 if Source = No_Source then
2930 Add_Source
2931 (Id => Source,
2932 In_Tree => In_Tree,
2933 Project => Project,
2934 Lang_Id => Lang_Id,
2935 Kind => Kind,
2936 File_Name => File_Name,
2937 Display_File => File_Name_Type (Element.Value),
2938 Naming_Exception => True);
2939
2940 else
2941 -- Check if the file name is already recorded for another
2942 -- language or another kind.
2943
2944 if Source.Language /= Lang_Id then
2945 Error_Msg
2946 (Project,
2947 In_Tree,
2948 "the same file cannot be a source of two languages",
2949 Element.Location);
2950
2951 elsif Source.Kind /= Kind then
2952 Error_Msg
2953 (Project,
2954 In_Tree,
2955 "the same file cannot be a source and a template",
2956 Element.Location);
2957 end if;
2958
2959 -- If the file is already recorded for the same
2960 -- language and the same kind, it means that the file
2961 -- name appears several times in the *_Exceptions
2962 -- attribute; so there is nothing to do.
2963 end if;
2964
2965 Element_Id := Element.Next;
2966 end loop;
2967 end if;
2968 end Process_Exceptions_File_Based;
2969
2970 -----------------------------------
2971 -- Process_Exceptions_Unit_Based --
2972 -----------------------------------
2973
2974 procedure Process_Exceptions_Unit_Based
2975 (Lang_Id : Language_Ptr;
2976 Kind : Source_Kind)
2977 is
2978 Lang : constant Name_Id := Lang_Id.Name;
2979 Exceptions : Array_Element_Id;
2980 Element : Array_Element;
2981 Unit : Name_Id;
2982 Index : Int;
2983 File_Name : File_Name_Type;
2984 Source : Source_Id;
2985 Source_To_Replace : Source_Id := No_Source;
2986 Other_Project : Project_Id;
2987 Iter : Source_Iterator;
2988
2989 begin
2990 case Kind is
2991 when Impl | Sep =>
2992 Exceptions := Value_Of
2993 (Name_Body,
2994 In_Arrays => Naming.Decl.Arrays,
2995 In_Tree => In_Tree);
2996
2997 if Exceptions = No_Array_Element then
2998 Exceptions :=
2999 Value_Of
3000 (Name_Implementation,
3001 In_Arrays => Naming.Decl.Arrays,
3002 In_Tree => In_Tree);
3003 end if;
3004
3005 when Spec =>
3006 Exceptions :=
3007 Value_Of
3008 (Name_Spec,
3009 In_Arrays => Naming.Decl.Arrays,
3010 In_Tree => In_Tree);
3011
3012 if Exceptions = No_Array_Element then
3013 Exceptions := Value_Of
3014 (Name_Spec,
3015 In_Arrays => Naming.Decl.Arrays,
3016 In_Tree => In_Tree);
3017 end if;
3018 end case;
3019
3020 while Exceptions /= No_Array_Element loop
3021 Element := In_Tree.Array_Elements.Table (Exceptions);
3022 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3023
3024 Get_Name_String (Element.Index);
3025 To_Lower (Name_Buffer (1 .. Name_Len));
3026 Unit := Name_Find;
3027 Index := Element.Value.Index;
3028
3029 -- For Ada, check if it is a valid unit name
3030
3031 if Lang = Name_Ada then
3032 Get_Name_String (Element.Index);
3033 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3034
3035 if Unit = No_Name then
3036 Err_Vars.Error_Msg_Name_1 := Element.Index;
3037 Error_Msg
3038 (Project, In_Tree,
3039 "%% is not a valid unit name.",
3040 Element.Value.Location);
3041 end if;
3042 end if;
3043
3044 if Unit /= No_Name then
3045
3046 -- Check if the source already exists
3047 -- ??? In Ada_Only mode (Record_Unit), we use a htable for
3048 -- efficiency
3049
3050 Source_To_Replace := No_Source;
3051 Iter := For_Each_Source (In_Tree);
3052
3053 loop
3054 Source := Prj.Element (Iter);
3055 exit when Source = No_Source
3056 or else (Source.Unit /= null
3057 and then Source.Unit.Name = Unit
3058 and then Source.Index = Index);
3059 Next (Iter);
3060 end loop;
3061
3062 if Source /= No_Source then
3063 if Source.Kind /= Kind then
3064 loop
3065 Next (Iter);
3066 Source := Prj.Element (Iter);
3067
3068 exit when Source = No_Source
3069 or else (Source.Unit /= null
3070 and then Source.Unit.Name = Unit
3071 and then Source.Index = Index);
3072 end loop;
3073 end if;
3074
3075 if Source /= No_Source then
3076 Other_Project := Source.Project;
3077
3078 if Is_Extending (Project, Other_Project) then
3079 Source_To_Replace := Source;
3080 Source := No_Source;
3081
3082 else
3083 Error_Msg_Name_1 := Unit;
3084 Error_Msg_Name_2 := Other_Project.Name;
3085 Error_Msg
3086 (Project,
3087 In_Tree,
3088 "%% is already a source of project %%",
3089 Element.Value.Location);
3090 end if;
3091 end if;
3092 end if;
3093
3094 if Source = No_Source then
3095 Add_Source
3096 (Id => Source,
3097 In_Tree => In_Tree,
3098 Project => Project,
3099 Lang_Id => Lang_Id,
3100 Kind => Kind,
3101 File_Name => File_Name,
3102 Display_File => File_Name_Type (Element.Value.Value),
3103 Unit => Unit,
3104 Index => Index,
3105 Naming_Exception => True,
3106 Source_To_Replace => Source_To_Replace);
3107 end if;
3108 end if;
3109
3110 Exceptions := Element.Next;
3111 end loop;
3112 end Process_Exceptions_Unit_Based;
3113
3114 ---------------------------
3115 -- Check_Naming_Ada_Only --
3116 ---------------------------
3117
3118 procedure Check_Naming_Ada_Only is
3119 Casing_Defined : Boolean;
3120 Spec_Suffix : File_Name_Type;
3121 Body_Suffix : File_Name_Type;
3122 Sep_Suffix_Loc : Source_Ptr;
3123
3124 Ada_Spec_Suffix : constant Variable_Value :=
3125 Prj.Util.Value_Of
3126 (Index => Name_Ada,
3127 Src_Index => 0,
3128 In_Array => Project.Naming.Spec_Suffix,
3129 In_Tree => In_Tree);
3130
3131 Ada_Body_Suffix : constant Variable_Value :=
3132 Prj.Util.Value_Of
3133 (Index => Name_Ada,
3134 Src_Index => 0,
3135 In_Array => Project.Naming.Body_Suffix,
3136 In_Tree => In_Tree);
3137
3138 begin
3139 -- The default value of separate suffix should be the same as the
3140 -- body suffix, so we need to compute that first.
3141
3142 if Ada_Body_Suffix.Kind = Single
3143 and then Length_Of_Name (Ada_Body_Suffix.Value) /= 0
3144 then
3145 Body_Suffix := Canonical_Case_File_Name (Ada_Body_Suffix.Value);
3146 Project.Naming.Separate_Suffix := Body_Suffix;
3147 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3148
3149 else
3150 Body_Suffix := Default_Ada_Body_Suffix;
3151 Project.Naming.Separate_Suffix := Body_Suffix;
3152 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3153 end if;
3154
3155 Write_Attr ("Body_Suffix", Get_Name_String (Body_Suffix));
3156
3157 -- We'll need the dot replacement below, so compute it now
3158
3159 Check_Common
3160 (Dot_Replacement => Project.Naming.Dot_Replacement,
3161 Casing => Project.Naming.Casing,
3162 Casing_Defined => Casing_Defined,
3163 Separate_Suffix => Project.Naming.Separate_Suffix,
3164 Sep_Suffix_Loc => Sep_Suffix_Loc);
3165
3166 Project.Naming.Bodies :=
3167 Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3168
3169 if Project.Naming.Bodies /= No_Array_Element then
3170 Check_And_Normalize_Unit_Names
3171 (Project, In_Tree, Project.Naming.Bodies, "Naming.Bodies");
3172 end if;
3173
3174 Project.Naming.Specs :=
3175 Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3176
3177 if Project.Naming.Specs /= No_Array_Element then
3178 Check_And_Normalize_Unit_Names
3179 (Project, In_Tree, Project.Naming.Specs, "Naming.Specs");
3180 end if;
3181
3182 -- Check Spec_Suffix
3183
3184 if Ada_Spec_Suffix.Kind = Single
3185 and then Length_Of_Name (Ada_Spec_Suffix.Value) /= 0
3186 then
3187 Spec_Suffix := Canonical_Case_File_Name (Ada_Spec_Suffix.Value);
3188 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3189
3190 if Is_Illegal_Suffix
3191 (Spec_Suffix, Project.Naming.Dot_Replacement)
3192 then
3193 Err_Vars.Error_Msg_File_1 := Spec_Suffix;
3194 Error_Msg
3195 (Project, In_Tree,
3196 "{ is illegal for Spec_Suffix",
3197 Ada_Spec_Suffix.Location);
3198 end if;
3199
3200 else
3201 Spec_Suffix := Default_Ada_Spec_Suffix;
3202 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3203 end if;
3204
3205 Write_Attr ("Spec_Suffix", Get_Name_String (Spec_Suffix));
3206
3207 -- Check Body_Suffix
3208
3209 if Is_Illegal_Suffix
3210 (Body_Suffix, Project.Naming.Dot_Replacement)
3211 then
3212 Err_Vars.Error_Msg_File_1 := Body_Suffix;
3213 Error_Msg
3214 (Project, In_Tree,
3215 "{ is illegal for Body_Suffix",
3216 Ada_Body_Suffix.Location);
3217 end if;
3218
3219 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3220 -- since that would cause a clear ambiguity. Note that we do allow a
3221 -- Spec_Suffix to have the same termination as one of these, which
3222 -- causes a potential ambiguity, but we resolve that my matching the
3223 -- longest possible suffix.
3224
3225 if Spec_Suffix = Body_Suffix then
3226 Error_Msg
3227 (Project, In_Tree,
3228 "Body_Suffix (""" &
3229 Get_Name_String (Body_Suffix) &
3230 """) cannot be the same as Spec_Suffix.",
3231 Ada_Body_Suffix.Location);
3232 end if;
3233
3234 if Body_Suffix /= Project.Naming.Separate_Suffix
3235 and then Spec_Suffix = Project.Naming.Separate_Suffix
3236 then
3237 Error_Msg
3238 (Project, In_Tree,
3239 "Separate_Suffix (""" &
3240 Get_Name_String (Project.Naming.Separate_Suffix) &
3241 """) cannot be the same as Spec_Suffix.",
3242 Sep_Suffix_Loc);
3243 end if;
3244 end Check_Naming_Ada_Only;
3245
3246 -----------------------------
3247 -- Check_Naming_Multi_Lang --
3248 -----------------------------
3249
3250 procedure Check_Naming_Multi_Lang is
3251 Dot_Replacement : File_Name_Type := No_File;
3252 Separate_Suffix : File_Name_Type := No_File;
3253 Casing : Casing_Type := All_Lower_Case;
3254 Casing_Defined : Boolean;
3255 Lang_Id : Language_Ptr;
3256 Sep_Suffix_Loc : Source_Ptr;
3257 Suffix : Variable_Value;
3258 Lang : Name_Id;
3259
3260 begin
3261 Check_Common
3262 (Dot_Replacement => Dot_Replacement,
3263 Casing => Casing,
3264 Casing_Defined => Casing_Defined,
3265 Separate_Suffix => Separate_Suffix,
3266 Sep_Suffix_Loc => Sep_Suffix_Loc);
3267
3268 -- For all unit based languages, if any, set the specified
3269 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3270 -- systematically overwrite, since the defaults come from the
3271 -- configuration file
3272
3273 if Dot_Replacement /= No_File
3274 or else Casing_Defined
3275 or else Separate_Suffix /= No_File
3276 then
3277 Lang_Id := Project.Languages;
3278 while Lang_Id /= No_Language_Index loop
3279 if Lang_Id.Config.Kind = Unit_Based then
3280 if Dot_Replacement /= No_File then
3281 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3282 Dot_Replacement;
3283 end if;
3284
3285 if Casing_Defined then
3286 Lang_Id.Config.Naming_Data.Casing := Casing;
3287 end if;
3288
3289 if Separate_Suffix /= No_File then
3290 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3291 Separate_Suffix;
3292 end if;
3293 end if;
3294
3295 Lang_Id := Lang_Id.Next;
3296 end loop;
3297 end if;
3298
3299 -- Next, get the spec and body suffixes
3300
3301 Lang_Id := Project.Languages;
3302 while Lang_Id /= No_Language_Index loop
3303 Lang := Lang_Id.Name;
3304
3305 -- Spec_Suffix
3306
3307 Suffix := Value_Of
3308 (Name => Lang,
3309 Attribute_Or_Array_Name => Name_Spec_Suffix,
3310 In_Package => Naming_Id,
3311 In_Tree => In_Tree);
3312
3313 if Suffix = Nil_Variable_Value then
3314 Suffix := Value_Of
3315 (Name => Lang,
3316 Attribute_Or_Array_Name => Name_Spec_Suffix,
3317 In_Package => Naming_Id,
3318 In_Tree => In_Tree);
3319 end if;
3320
3321 if Suffix /= Nil_Variable_Value then
3322 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3323 File_Name_Type (Suffix.Value);
3324 end if;
3325
3326 -- Body_Suffix
3327
3328 Suffix := Value_Of
3329 (Name => Lang,
3330 Attribute_Or_Array_Name => Name_Body_Suffix,
3331 In_Package => Naming_Id,
3332 In_Tree => In_Tree);
3333
3334 if Suffix = Nil_Variable_Value then
3335 Suffix := Value_Of
3336 (Name => Lang,
3337 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3338 In_Package => Naming_Id,
3339 In_Tree => In_Tree);
3340 end if;
3341
3342 if Suffix /= Nil_Variable_Value then
3343 Lang_Id.Config.Naming_Data.Body_Suffix :=
3344 File_Name_Type (Suffix.Value);
3345 end if;
3346
3347 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3348 -- we do not check whether spec_suffix=body_suffix, which
3349 -- should be illegal. Best would be to share this code into
3350 -- Check_Common, but we access the attributes from the project
3351 -- files slightly differently apparently.
3352
3353 Lang_Id := Lang_Id.Next;
3354 end loop;
3355
3356 -- Get the naming exceptions for all languages
3357
3358 for Kind in Spec .. Impl loop
3359 Lang_Id := Project.Languages;
3360 while Lang_Id /= No_Language_Index loop
3361 case Lang_Id.Config.Kind is
3362 when File_Based =>
3363 Process_Exceptions_File_Based (Lang_Id, Kind);
3364
3365 when Unit_Based =>
3366 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3367 end case;
3368
3369 Lang_Id := Lang_Id.Next;
3370 end loop;
3371 end loop;
3372 end Check_Naming_Multi_Lang;
3373
3374 -- Start of processing for Check_Naming_Schemes
3375
3376 begin
3377 -- No Naming package or parsing a configuration file? nothing to do
3378
3379 if Naming_Id /= No_Package and not Is_Config_File then
3380 Naming := In_Tree.Packages.Table (Naming_Id);
3381
3382 if Current_Verbosity = High then
3383 Write_Line ("Checking package Naming.");
3384 end if;
3385
3386 case Get_Mode is
3387 when Ada_Only =>
3388 Check_Naming_Ada_Only;
3389 when Multi_Language =>
3390 Check_Naming_Multi_Lang;
3391 end case;
3392 end if;
3393 end Check_Naming_Schemes;
3394
3395 ------------------------------
3396 -- Check_Library_Attributes --
3397 ------------------------------
3398
3399 procedure Check_Library_Attributes
3400 (Project : Project_Id;
3401 In_Tree : Project_Tree_Ref)
3402 is
3403 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3404
3405 Lib_Dir : constant Prj.Variable_Value :=
3406 Prj.Util.Value_Of
3407 (Snames.Name_Library_Dir, Attributes, In_Tree);
3408
3409 Lib_Name : constant Prj.Variable_Value :=
3410 Prj.Util.Value_Of
3411 (Snames.Name_Library_Name, Attributes, In_Tree);
3412
3413 Lib_Version : constant Prj.Variable_Value :=
3414 Prj.Util.Value_Of
3415 (Snames.Name_Library_Version, Attributes, In_Tree);
3416
3417 Lib_ALI_Dir : constant Prj.Variable_Value :=
3418 Prj.Util.Value_Of
3419 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3420
3421 Lib_GCC : constant Prj.Variable_Value :=
3422 Prj.Util.Value_Of
3423 (Snames.Name_Library_GCC, Attributes, In_Tree);
3424
3425 The_Lib_Kind : constant Prj.Variable_Value :=
3426 Prj.Util.Value_Of
3427 (Snames.Name_Library_Kind, Attributes, In_Tree);
3428
3429 Imported_Project_List : Project_List;
3430
3431 Continuation : String_Access := No_Continuation_String'Access;
3432
3433 Support_For_Libraries : Library_Support;
3434
3435 Library_Directory_Present : Boolean;
3436
3437 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3438 -- Check if an imported or extended project if also a library project
3439
3440 -------------------
3441 -- Check_Library --
3442 -------------------
3443
3444 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3445 Src_Id : Source_Id;
3446 Iter : Source_Iterator;
3447
3448 begin
3449 if Proj /= No_Project then
3450 if not Proj.Library then
3451
3452 -- The only not library projects that are OK are those that
3453 -- have no sources. However, header files from non-Ada
3454 -- languages are OK, as there is nothing to compile.
3455
3456 Iter := For_Each_Source (In_Tree, Proj);
3457 loop
3458 Src_Id := Prj.Element (Iter);
3459 exit when Src_Id = No_Source
3460 or else Src_Id.Language.Config.Kind /= File_Based
3461 or else Src_Id.Kind /= Spec;
3462 Next (Iter);
3463 end loop;
3464
3465 if Src_Id /= No_Source then
3466 Error_Msg_Name_1 := Project.Name;
3467 Error_Msg_Name_2 := Proj.Name;
3468
3469 if Extends then
3470 if Project.Library_Kind /= Static then
3471 Error_Msg
3472 (Project, In_Tree,
3473 Continuation.all &
3474 "shared library project %% cannot extend " &
3475 "project %% that is not a library project",
3476 Project.Location);
3477 Continuation := Continuation_String'Access;
3478 end if;
3479
3480 elsif (not Unchecked_Shared_Lib_Imports)
3481 and then Project.Library_Kind /= Static
3482 then
3483 Error_Msg
3484 (Project, In_Tree,
3485 Continuation.all &
3486 "shared library project %% cannot import project %% " &
3487 "that is not a shared library project",
3488 Project.Location);
3489 Continuation := Continuation_String'Access;
3490 end if;
3491 end if;
3492
3493 elsif Project.Library_Kind /= Static and then
3494 Proj.Library_Kind = Static
3495 then
3496 Error_Msg_Name_1 := Project.Name;
3497 Error_Msg_Name_2 := Proj.Name;
3498
3499 if Extends then
3500 Error_Msg
3501 (Project, In_Tree,
3502 Continuation.all &
3503 "shared library project %% cannot extend static " &
3504 "library project %%",
3505 Project.Location);
3506 Continuation := Continuation_String'Access;
3507
3508 elsif not Unchecked_Shared_Lib_Imports then
3509 Error_Msg
3510 (Project, In_Tree,
3511 Continuation.all &
3512 "shared library project %% cannot import static " &
3513 "library project %%",
3514 Project.Location);
3515 Continuation := Continuation_String'Access;
3516 end if;
3517
3518 end if;
3519 end if;
3520 end Check_Library;
3521
3522 Dir_Exists : Boolean;
3523
3524 -- Start of processing for Check_Library_Attributes
3525
3526 begin
3527 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3528
3529 -- Special case of extending project
3530
3531 if Project.Extends /= No_Project then
3532
3533 -- If the project extended is a library project, we inherit the
3534 -- library name, if it is not redefined; we check that the library
3535 -- directory is specified.
3536
3537 if Project.Extends.Library then
3538 if Project.Qualifier = Standard then
3539 Error_Msg
3540 (Project, In_Tree,
3541 "a standard project cannot extend a library project",
3542 Project.Location);
3543
3544 else
3545 if Lib_Name.Default then
3546 Project.Library_Name := Project.Extends.Library_Name;
3547 end if;
3548
3549 if Lib_Dir.Default then
3550 if not Project.Virtual then
3551 Error_Msg
3552 (Project, In_Tree,
3553 "a project extending a library project must " &
3554 "specify an attribute Library_Dir",
3555 Project.Location);
3556
3557 else
3558 -- For a virtual project extending a library project,
3559 -- inherit library directory.
3560
3561 Project.Library_Dir := Project.Extends.Library_Dir;
3562 Library_Directory_Present := True;
3563 end if;
3564 end if;
3565 end if;
3566 end if;
3567 end if;
3568
3569 pragma Assert (Lib_Name.Kind = Single);
3570
3571 if Lib_Name.Value = Empty_String then
3572 if Current_Verbosity = High
3573 and then Project.Library_Name = No_Name
3574 then
3575 Write_Line ("No library name");
3576 end if;
3577
3578 else
3579 -- There is no restriction on the syntax of library names
3580
3581 Project.Library_Name := Lib_Name.Value;
3582 end if;
3583
3584 if Project.Library_Name /= No_Name then
3585 if Current_Verbosity = High then
3586 Write_Attr
3587 ("Library name", Get_Name_String (Project.Library_Name));
3588 end if;
3589
3590 pragma Assert (Lib_Dir.Kind = Single);
3591
3592 if not Library_Directory_Present then
3593 if Current_Verbosity = High then
3594 Write_Line ("No library directory");
3595 end if;
3596
3597 else
3598 -- Find path name (unless inherited), check that it is a directory
3599
3600 if Project.Library_Dir = No_Path_Information then
3601 Locate_Directory
3602 (Project,
3603 In_Tree,
3604 File_Name_Type (Lib_Dir.Value),
3605 Path => Project.Library_Dir,
3606 Dir_Exists => Dir_Exists,
3607 Create => "library",
3608 Must_Exist => False,
3609 Location => Lib_Dir.Location,
3610 Externally_Built => Project.Externally_Built);
3611
3612 else
3613 Dir_Exists :=
3614 Is_Directory
3615 (Get_Name_String
3616 (Project.Library_Dir.Display_Name));
3617 end if;
3618
3619 if not Dir_Exists then
3620 -- Get the absolute name of the library directory that
3621 -- does not exist, to report an error.
3622
3623 Err_Vars.Error_Msg_File_1 :=
3624 File_Name_Type (Project.Library_Dir.Display_Name);
3625 Error_Msg
3626 (Project, In_Tree,
3627 "library directory { does not exist",
3628 Lib_Dir.Location);
3629
3630 -- The library directory cannot be the same as the Object
3631 -- directory.
3632
3633 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3634 Error_Msg
3635 (Project, In_Tree,
3636 "library directory cannot be the same " &
3637 "as object directory",
3638 Lib_Dir.Location);
3639 Project.Library_Dir := No_Path_Information;
3640
3641 else
3642 declare
3643 OK : Boolean := True;
3644 Dirs_Id : String_List_Id;
3645 Dir_Elem : String_Element;
3646 Pid : Project_List;
3647
3648 begin
3649 -- The library directory cannot be the same as a source
3650 -- directory of the current project.
3651
3652 Dirs_Id := Project.Source_Dirs;
3653 while Dirs_Id /= Nil_String loop
3654 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3655 Dirs_Id := Dir_Elem.Next;
3656
3657 if Project.Library_Dir.Name =
3658 Path_Name_Type (Dir_Elem.Value)
3659 then
3660 Err_Vars.Error_Msg_File_1 :=
3661 File_Name_Type (Dir_Elem.Value);
3662 Error_Msg
3663 (Project, In_Tree,
3664 "library directory cannot be the same " &
3665 "as source directory {",
3666 Lib_Dir.Location);
3667 OK := False;
3668 exit;
3669 end if;
3670 end loop;
3671
3672 if OK then
3673
3674 -- The library directory cannot be the same as a source
3675 -- directory of another project either.
3676
3677 Pid := In_Tree.Projects;
3678 Project_Loop : loop
3679 exit Project_Loop when Pid = null;
3680
3681 if Pid.Project /= Project then
3682 Dirs_Id := Pid.Project.Source_Dirs;
3683
3684 Dir_Loop : while Dirs_Id /= Nil_String loop
3685 Dir_Elem :=
3686 In_Tree.String_Elements.Table (Dirs_Id);
3687 Dirs_Id := Dir_Elem.Next;
3688
3689 if Project.Library_Dir.Name =
3690 Path_Name_Type (Dir_Elem.Value)
3691 then
3692 Err_Vars.Error_Msg_File_1 :=
3693 File_Name_Type (Dir_Elem.Value);
3694 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3695
3696 Error_Msg
3697 (Project, In_Tree,
3698 "library directory cannot be the same " &
3699 "as source directory { of project %%",
3700 Lib_Dir.Location);
3701 OK := False;
3702 exit Project_Loop;
3703 end if;
3704 end loop Dir_Loop;
3705 end if;
3706
3707 Pid := Pid.Next;
3708 end loop Project_Loop;
3709 end if;
3710
3711 if not OK then
3712 Project.Library_Dir := No_Path_Information;
3713
3714 elsif Current_Verbosity = High then
3715
3716 -- Display the Library directory in high verbosity
3717
3718 Write_Attr
3719 ("Library directory",
3720 Get_Name_String (Project.Library_Dir.Display_Name));
3721 end if;
3722 end;
3723 end if;
3724 end if;
3725
3726 end if;
3727
3728 Project.Library :=
3729 Project.Library_Dir /= No_Path_Information
3730 and then Project.Library_Name /= No_Name;
3731
3732 if Project.Extends = No_Project then
3733 case Project.Qualifier is
3734 when Standard =>
3735 if Project.Library then
3736 Error_Msg
3737 (Project, In_Tree,
3738 "a standard project cannot be a library project",
3739 Lib_Name.Location);
3740 end if;
3741
3742 when Library =>
3743 if not Project.Library then
3744 if Project.Library_Dir = No_Path_Information then
3745 Error_Msg
3746 (Project, In_Tree,
3747 "\attribute Library_Dir not declared",
3748 Project.Location);
3749 end if;
3750
3751 if Project.Library_Name = No_Name then
3752 Error_Msg
3753 (Project, In_Tree,
3754 "\attribute Library_Name not declared",
3755 Project.Location);
3756 end if;
3757 end if;
3758
3759 when others =>
3760 null;
3761
3762 end case;
3763 end if;
3764
3765 if Project.Library then
3766 if Get_Mode = Multi_Language then
3767 Support_For_Libraries := Project.Config.Lib_Support;
3768
3769 else
3770 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3771 end if;
3772
3773 if Support_For_Libraries = Prj.None then
3774 Error_Msg
3775 (Project, In_Tree,
3776 "?libraries are not supported on this platform",
3777 Lib_Name.Location);
3778 Project.Library := False;
3779
3780 else
3781 if Lib_ALI_Dir.Value = Empty_String then
3782 if Current_Verbosity = High then
3783 Write_Line ("No library ALI directory specified");
3784 end if;
3785
3786 Project.Library_ALI_Dir := Project.Library_Dir;
3787
3788 else
3789 -- Find path name, check that it is a directory
3790
3791 Locate_Directory
3792 (Project,
3793 In_Tree,
3794 File_Name_Type (Lib_ALI_Dir.Value),
3795 Path => Project.Library_ALI_Dir,
3796 Create => "library ALI",
3797 Dir_Exists => Dir_Exists,
3798 Must_Exist => False,
3799 Location => Lib_ALI_Dir.Location,
3800 Externally_Built => Project.Externally_Built);
3801
3802 if not Dir_Exists then
3803 -- Get the absolute name of the library ALI directory that
3804 -- does not exist, to report an error.
3805
3806 Err_Vars.Error_Msg_File_1 :=
3807 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3808 Error_Msg
3809 (Project, In_Tree,
3810 "library 'A'L'I directory { does not exist",
3811 Lib_ALI_Dir.Location);
3812 end if;
3813
3814 if Project.Library_ALI_Dir /= Project.Library_Dir then
3815
3816 -- The library ALI directory cannot be the same as the
3817 -- Object directory.
3818
3819 if Project.Library_ALI_Dir = Project.Object_Directory then
3820 Error_Msg
3821 (Project, In_Tree,
3822 "library 'A'L'I directory cannot be the same " &
3823 "as object directory",
3824 Lib_ALI_Dir.Location);
3825 Project.Library_ALI_Dir := No_Path_Information;
3826
3827 else
3828 declare
3829 OK : Boolean := True;
3830 Dirs_Id : String_List_Id;
3831 Dir_Elem : String_Element;
3832 Pid : Project_List;
3833
3834 begin
3835 -- The library ALI directory cannot be the same as
3836 -- a source directory of the current project.
3837
3838 Dirs_Id := Project.Source_Dirs;
3839 while Dirs_Id /= Nil_String loop
3840 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3841 Dirs_Id := Dir_Elem.Next;
3842
3843 if Project.Library_ALI_Dir.Name =
3844 Path_Name_Type (Dir_Elem.Value)
3845 then
3846 Err_Vars.Error_Msg_File_1 :=
3847 File_Name_Type (Dir_Elem.Value);
3848 Error_Msg
3849 (Project, In_Tree,
3850 "library 'A'L'I directory cannot be " &
3851 "the same as source directory {",
3852 Lib_ALI_Dir.Location);
3853 OK := False;
3854 exit;
3855 end if;
3856 end loop;
3857
3858 if OK then
3859
3860 -- The library ALI directory cannot be the same as
3861 -- a source directory of another project either.
3862
3863 Pid := In_Tree.Projects;
3864 ALI_Project_Loop : loop
3865 exit ALI_Project_Loop when Pid = null;
3866
3867 if Pid.Project /= Project then
3868 Dirs_Id := Pid.Project.Source_Dirs;
3869
3870 ALI_Dir_Loop :
3871 while Dirs_Id /= Nil_String loop
3872 Dir_Elem :=
3873 In_Tree.String_Elements.Table (Dirs_Id);
3874 Dirs_Id := Dir_Elem.Next;
3875
3876 if Project.Library_ALI_Dir.Name =
3877 Path_Name_Type (Dir_Elem.Value)
3878 then
3879 Err_Vars.Error_Msg_File_1 :=
3880 File_Name_Type (Dir_Elem.Value);
3881 Err_Vars.Error_Msg_Name_1 :=
3882 Pid.Project.Name;
3883
3884 Error_Msg
3885 (Project, In_Tree,
3886 "library 'A'L'I directory cannot " &
3887 "be the same as source directory " &
3888 "{ of project %%",
3889 Lib_ALI_Dir.Location);
3890 OK := False;
3891 exit ALI_Project_Loop;
3892 end if;
3893 end loop ALI_Dir_Loop;
3894 end if;
3895 Pid := Pid.Next;
3896 end loop ALI_Project_Loop;
3897 end if;
3898
3899 if not OK then
3900 Project.Library_ALI_Dir := No_Path_Information;
3901
3902 elsif Current_Verbosity = High then
3903
3904 -- Display the Library ALI directory in high
3905 -- verbosity.
3906
3907 Write_Attr
3908 ("Library ALI dir",
3909 Get_Name_String
3910 (Project.Library_ALI_Dir.Display_Name));
3911 end if;
3912 end;
3913 end if;
3914 end if;
3915 end if;
3916
3917 pragma Assert (Lib_Version.Kind = Single);
3918
3919 if Lib_Version.Value = Empty_String then
3920 if Current_Verbosity = High then
3921 Write_Line ("No library version specified");
3922 end if;
3923
3924 else
3925 Project.Lib_Internal_Name := Lib_Version.Value;
3926 end if;
3927
3928 pragma Assert (The_Lib_Kind.Kind = Single);
3929
3930 if The_Lib_Kind.Value = Empty_String then
3931 if Current_Verbosity = High then
3932 Write_Line ("No library kind specified");
3933 end if;
3934
3935 else
3936 Get_Name_String (The_Lib_Kind.Value);
3937
3938 declare
3939 Kind_Name : constant String :=
3940 To_Lower (Name_Buffer (1 .. Name_Len));
3941
3942 OK : Boolean := True;
3943
3944 begin
3945 if Kind_Name = "static" then
3946 Project.Library_Kind := Static;
3947
3948 elsif Kind_Name = "dynamic" then
3949 Project.Library_Kind := Dynamic;
3950
3951 elsif Kind_Name = "relocatable" then
3952 Project.Library_Kind := Relocatable;
3953
3954 else
3955 Error_Msg
3956 (Project, In_Tree,
3957 "illegal value for Library_Kind",
3958 The_Lib_Kind.Location);
3959 OK := False;
3960 end if;
3961
3962 if Current_Verbosity = High and then OK then
3963 Write_Attr ("Library kind", Kind_Name);
3964 end if;
3965
3966 if Project.Library_Kind /= Static then
3967 if Support_For_Libraries = Prj.Static_Only then
3968 Error_Msg
3969 (Project, In_Tree,
3970 "only static libraries are supported " &
3971 "on this platform",
3972 The_Lib_Kind.Location);
3973 Project.Library := False;
3974
3975 else
3976 -- Check if (obsolescent) attribute Library_GCC or
3977 -- Linker'Driver is declared.
3978
3979 if Lib_GCC.Value /= Empty_String then
3980 Error_Msg
3981 (Project,
3982 In_Tree,
3983 "?Library_'G'C'C is an obsolescent attribute, " &
3984 "use Linker''Driver instead",
3985 Lib_GCC.Location);
3986 Project.Config.Shared_Lib_Driver :=
3987 File_Name_Type (Lib_GCC.Value);
3988
3989 else
3990 declare
3991 Linker : constant Package_Id :=
3992 Value_Of
3993 (Name_Linker,
3994 Project.Decl.Packages,
3995 In_Tree);
3996 Driver : constant Variable_Value :=
3997 Value_Of
3998 (Name => No_Name,
3999 Attribute_Or_Array_Name =>
4000 Name_Driver,
4001 In_Package => Linker,
4002 In_Tree =>
4003 In_Tree);
4004
4005 begin
4006 if Driver /= Nil_Variable_Value
4007 and then Driver.Value /= Empty_String
4008 then
4009 Project.Config.Shared_Lib_Driver :=
4010 File_Name_Type (Driver.Value);
4011 end if;
4012 end;
4013 end if;
4014 end if;
4015 end if;
4016 end;
4017 end if;
4018
4019 if Project.Library then
4020 if Current_Verbosity = High then
4021 Write_Line ("This is a library project file");
4022 end if;
4023
4024 if Get_Mode = Multi_Language then
4025 Check_Library (Project.Extends, Extends => True);
4026
4027 Imported_Project_List := Project.Imported_Projects;
4028 while Imported_Project_List /= null loop
4029 Check_Library
4030 (Imported_Project_List.Project,
4031 Extends => False);
4032 Imported_Project_List := Imported_Project_List.Next;
4033 end loop;
4034 end if;
4035 end if;
4036
4037 end if;
4038 end if;
4039
4040 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4041 -- Warn if they are declared, as it is a common error to think that
4042 -- library are "linked" with Linker switches.
4043
4044 if Project.Library then
4045 declare
4046 Linker_Package_Id : constant Package_Id :=
4047 Util.Value_Of
4048 (Name_Linker,
4049 Project.Decl.Packages, In_Tree);
4050 Linker_Package : Package_Element;
4051 Switches : Array_Element_Id := No_Array_Element;
4052
4053 begin
4054 if Linker_Package_Id /= No_Package then
4055 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4056
4057 Switches :=
4058 Value_Of
4059 (Name => Name_Switches,
4060 In_Arrays => Linker_Package.Decl.Arrays,
4061 In_Tree => In_Tree);
4062
4063 if Switches = No_Array_Element then
4064 Switches :=
4065 Value_Of
4066 (Name => Name_Default_Switches,
4067 In_Arrays => Linker_Package.Decl.Arrays,
4068 In_Tree => In_Tree);
4069 end if;
4070
4071 if Switches /= No_Array_Element then
4072 Error_Msg
4073 (Project, In_Tree,
4074 "?Linker switches not taken into account in library " &
4075 "projects",
4076 No_Location);
4077 end if;
4078 end if;
4079 end;
4080 end if;
4081
4082 if Project.Extends /= No_Project then
4083 Project.Extends.Library := False;
4084 end if;
4085 end Check_Library_Attributes;
4086
4087 --------------------------
4088 -- Check_Package_Naming --
4089 --------------------------
4090
4091 procedure Check_Package_Naming
4092 (Project : Project_Id;
4093 In_Tree : Project_Tree_Ref)
4094 is
4095 Naming_Id : constant Package_Id :=
4096 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
4097
4098 Naming : Package_Element;
4099
4100 begin
4101 -- If there is a package Naming, we will put in Data.Naming
4102 -- what is in this package Naming.
4103
4104 if Naming_Id /= No_Package then
4105 Naming := In_Tree.Packages.Table (Naming_Id);
4106
4107 if Current_Verbosity = High then
4108 Write_Line ("Checking ""Naming"".");
4109 end if;
4110
4111 -- Check Spec_Suffix
4112
4113 declare
4114 Spec_Suffixs : Array_Element_Id :=
4115 Util.Value_Of
4116 (Name_Spec_Suffix,
4117 Naming.Decl.Arrays,
4118 In_Tree);
4119
4120 Suffix : Array_Element_Id;
4121 Element : Array_Element;
4122 Suffix2 : Array_Element_Id;
4123
4124 begin
4125 -- If some suffixes have been specified, we make sure that
4126 -- for each language for which a default suffix has been
4127 -- specified, there is a suffix specified, either the one
4128 -- in the project file or if there were none, the default.
4129
4130 if Spec_Suffixs /= No_Array_Element then
4131 Suffix := Project.Naming.Spec_Suffix;
4132
4133 while Suffix /= No_Array_Element loop
4134 Element :=
4135 In_Tree.Array_Elements.Table (Suffix);
4136 Suffix2 := Spec_Suffixs;
4137
4138 while Suffix2 /= No_Array_Element loop
4139 exit when In_Tree.Array_Elements.Table
4140 (Suffix2).Index = Element.Index;
4141 Suffix2 := In_Tree.Array_Elements.Table
4142 (Suffix2).Next;
4143 end loop;
4144
4145 -- There is a registered default suffix, but no
4146 -- suffix specified in the project file.
4147 -- Add the default to the array.
4148
4149 if Suffix2 = No_Array_Element then
4150 Array_Element_Table.Increment_Last
4151 (In_Tree.Array_Elements);
4152 In_Tree.Array_Elements.Table
4153 (Array_Element_Table.Last
4154 (In_Tree.Array_Elements)) :=
4155 (Index => Element.Index,
4156 Src_Index => Element.Src_Index,
4157 Index_Case_Sensitive => False,
4158 Value => Element.Value,
4159 Next => Spec_Suffixs);
4160 Spec_Suffixs := Array_Element_Table.Last
4161 (In_Tree.Array_Elements);
4162 end if;
4163
4164 Suffix := Element.Next;
4165 end loop;
4166
4167 -- Put the resulting array as the Spec suffixes
4168
4169 Project.Naming.Spec_Suffix := Spec_Suffixs;
4170 end if;
4171 end;
4172
4173 -- Check Body_Suffix
4174
4175 declare
4176 Impl_Suffixs : Array_Element_Id :=
4177 Util.Value_Of
4178 (Name_Body_Suffix,
4179 Naming.Decl.Arrays,
4180 In_Tree);
4181
4182 Suffix : Array_Element_Id;
4183 Element : Array_Element;
4184 Suffix2 : Array_Element_Id;
4185
4186 begin
4187 -- If some suffixes have been specified, we make sure that
4188 -- for each language for which a default suffix has been
4189 -- specified, there is a suffix specified, either the one
4190 -- in the project file or if there were none, the default.
4191
4192 if Impl_Suffixs /= No_Array_Element then
4193 Suffix := Project.Naming.Body_Suffix;
4194 while Suffix /= No_Array_Element loop
4195 Element :=
4196 In_Tree.Array_Elements.Table (Suffix);
4197
4198 Suffix2 := Impl_Suffixs;
4199 while Suffix2 /= No_Array_Element loop
4200 exit when In_Tree.Array_Elements.Table
4201 (Suffix2).Index = Element.Index;
4202 Suffix2 := In_Tree.Array_Elements.Table
4203 (Suffix2).Next;
4204 end loop;
4205
4206 -- There is a registered default suffix, but no suffix was
4207 -- specified in the project file. Add default to the array.
4208
4209 if Suffix2 = No_Array_Element then
4210 Array_Element_Table.Increment_Last
4211 (In_Tree.Array_Elements);
4212 In_Tree.Array_Elements.Table
4213 (Array_Element_Table.Last
4214 (In_Tree.Array_Elements)) :=
4215 (Index => Element.Index,
4216 Src_Index => Element.Src_Index,
4217 Index_Case_Sensitive => False,
4218 Value => Element.Value,
4219 Next => Impl_Suffixs);
4220 Impl_Suffixs := Array_Element_Table.Last
4221 (In_Tree.Array_Elements);
4222 end if;
4223
4224 Suffix := Element.Next;
4225 end loop;
4226
4227 -- Put the resulting array as the implementation suffixes
4228
4229 Project.Naming.Body_Suffix := Impl_Suffixs;
4230 end if;
4231 end;
4232
4233 -- Get the exceptions, if any
4234
4235 Project.Naming.Specification_Exceptions :=
4236 Util.Value_Of
4237 (Name_Specification_Exceptions,
4238 In_Arrays => Naming.Decl.Arrays,
4239 In_Tree => In_Tree);
4240
4241 Project.Naming.Implementation_Exceptions :=
4242 Util.Value_Of
4243 (Name_Implementation_Exceptions,
4244 In_Arrays => Naming.Decl.Arrays,
4245 In_Tree => In_Tree);
4246 end if;
4247 end Check_Package_Naming;
4248
4249 ---------------------------------
4250 -- Check_Programming_Languages --
4251 ---------------------------------
4252
4253 procedure Check_Programming_Languages
4254 (In_Tree : Project_Tree_Ref;
4255 Project : Project_Id)
4256 is
4257 Languages : Variable_Value := Nil_Variable_Value;
4258 Def_Lang : Variable_Value := Nil_Variable_Value;
4259 Def_Lang_Id : Name_Id;
4260
4261 begin
4262 Project.Languages := No_Language_Index;
4263 Languages :=
4264 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, In_Tree);
4265 Def_Lang :=
4266 Prj.Util.Value_Of
4267 (Name_Default_Language, Project.Decl.Attributes, In_Tree);
4268
4269 -- Shouldn't these be set to False by default, and only set to True when
4270 -- we actually find some source file???
4271
4272 if Project.Source_Dirs /= Nil_String then
4273
4274 -- Check if languages are specified in this project
4275
4276 if Languages.Default then
4277
4278 -- In Ada_Only mode, the default language is Ada
4279
4280 if Get_Mode = Ada_Only then
4281 Def_Lang_Id := Name_Ada;
4282
4283 else
4284 -- Fail if there is no default language defined
4285
4286 if Def_Lang.Default then
4287 if not Default_Language_Is_Ada then
4288 Error_Msg
4289 (Project,
4290 In_Tree,
4291 "no languages defined for this project",
4292 Project.Location);
4293 Def_Lang_Id := No_Name;
4294 else
4295 Def_Lang_Id := Name_Ada;
4296 end if;
4297
4298 else
4299 Get_Name_String (Def_Lang.Value);
4300 To_Lower (Name_Buffer (1 .. Name_Len));
4301 Def_Lang_Id := Name_Find;
4302 end if;
4303 end if;
4304
4305 if Def_Lang_Id /= No_Name then
4306 Project.Languages := new Language_Data'(No_Language_Data);
4307 Project.Languages.Name := Def_Lang_Id;
4308 Get_Name_String (Def_Lang_Id);
4309 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4310 Project.Languages.Display_Name := Name_Find;
4311
4312 if Def_Lang_Id = Name_Ada then
4313 Project.Languages.Config.Kind := Unit_Based;
4314 Project.Languages.Config.Dependency_Kind := ALI_File;
4315 else
4316 Project.Languages.Config.Kind := File_Based;
4317 end if;
4318 end if;
4319
4320 else
4321 declare
4322 Current : String_List_Id := Languages.Values;
4323 Element : String_Element;
4324 Lang_Name : Name_Id;
4325 Index : Language_Ptr;
4326 NL_Id : Language_Ptr;
4327
4328 begin
4329 -- If there are no languages declared, there are no sources
4330
4331 if Current = Nil_String then
4332 Project.Source_Dirs := Nil_String;
4333
4334 if Project.Qualifier = Standard then
4335 Error_Msg
4336 (Project,
4337 In_Tree,
4338 "a standard project must have at least one language",
4339 Languages.Location);
4340 end if;
4341
4342 else
4343 -- Look through all the languages specified in attribute
4344 -- Languages.
4345
4346 while Current /= Nil_String loop
4347 Element := In_Tree.String_Elements.Table (Current);
4348 Get_Name_String (Element.Value);
4349 To_Lower (Name_Buffer (1 .. Name_Len));
4350 Lang_Name := Name_Find;
4351
4352 -- If the language was not already specified (duplicates
4353 -- are simply ignored).
4354
4355 NL_Id := Project.Languages;
4356 while NL_Id /= No_Language_Index loop
4357 exit when Lang_Name = NL_Id.Name;
4358 NL_Id := NL_Id.Next;
4359 end loop;
4360
4361 if NL_Id = No_Language_Index then
4362 Index := new Language_Data'(No_Language_Data);
4363 Index.Name := Lang_Name;
4364 Index.Display_Name := Element.Value;
4365 Index.Next := Project.Languages;
4366
4367 if Lang_Name = Name_Ada then
4368 Index.Config.Kind := Unit_Based;
4369 Index.Config.Dependency_Kind := ALI_File;
4370
4371 else
4372 Index.Config.Kind := File_Based;
4373 Index.Config.Dependency_Kind := None;
4374 end if;
4375
4376 Project.Languages := Index;
4377 end if;
4378
4379 Current := Element.Next;
4380 end loop;
4381 end if;
4382 end;
4383 end if;
4384 end if;
4385 end Check_Programming_Languages;
4386
4387 -------------------
4388 -- Check_Project --
4389 -------------------
4390
4391 function Check_Project
4392 (P : Project_Id;
4393 Root_Project : Project_Id;
4394 Extending : Boolean) return Boolean
4395 is
4396 Prj : Project_Id;
4397 begin
4398 if P = Root_Project then
4399 return True;
4400
4401 elsif Extending then
4402 Prj := Root_Project;
4403 while Prj.Extends /= No_Project loop
4404 if P = Prj.Extends then
4405 return True;
4406 end if;
4407
4408 Prj := Prj.Extends;
4409 end loop;
4410 end if;
4411
4412 return False;
4413 end Check_Project;
4414
4415 -------------------------------
4416 -- Check_Stand_Alone_Library --
4417 -------------------------------
4418
4419 procedure Check_Stand_Alone_Library
4420 (Project : Project_Id;
4421 In_Tree : Project_Tree_Ref;
4422 Current_Dir : String;
4423 Extending : Boolean)
4424 is
4425 Lib_Interfaces : constant Prj.Variable_Value :=
4426 Prj.Util.Value_Of
4427 (Snames.Name_Library_Interface,
4428 Project.Decl.Attributes,
4429 In_Tree);
4430
4431 Lib_Auto_Init : constant Prj.Variable_Value :=
4432 Prj.Util.Value_Of
4433 (Snames.Name_Library_Auto_Init,
4434 Project.Decl.Attributes,
4435 In_Tree);
4436
4437 Lib_Src_Dir : constant Prj.Variable_Value :=
4438 Prj.Util.Value_Of
4439 (Snames.Name_Library_Src_Dir,
4440 Project.Decl.Attributes,
4441 In_Tree);
4442
4443 Lib_Symbol_File : constant Prj.Variable_Value :=
4444 Prj.Util.Value_Of
4445 (Snames.Name_Library_Symbol_File,
4446 Project.Decl.Attributes,
4447 In_Tree);
4448
4449 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4450 Prj.Util.Value_Of
4451 (Snames.Name_Library_Symbol_Policy,
4452 Project.Decl.Attributes,
4453 In_Tree);
4454
4455 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4456 Prj.Util.Value_Of
4457 (Snames.Name_Library_Reference_Symbol_File,
4458 Project.Decl.Attributes,
4459 In_Tree);
4460
4461 Auto_Init_Supported : Boolean;
4462 OK : Boolean := True;
4463 Source : Source_Id;
4464 Next_Proj : Project_Id;
4465 Iter : Source_Iterator;
4466
4467 begin
4468 if Get_Mode = Multi_Language then
4469 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4470 else
4471 Auto_Init_Supported :=
4472 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4473 end if;
4474
4475 pragma Assert (Lib_Interfaces.Kind = List);
4476
4477 -- It is a stand-alone library project file if attribute
4478 -- Library_Interface is defined.
4479
4480 if not Lib_Interfaces.Default then
4481 SAL_Library : declare
4482 Interfaces : String_List_Id := Lib_Interfaces.Values;
4483 Interface_ALIs : String_List_Id := Nil_String;
4484 Unit : Name_Id;
4485 UData : Unit_Index;
4486
4487 procedure Add_ALI_For (Source : File_Name_Type);
4488 -- Add an ALI file name to the list of Interface ALIs
4489
4490 -----------------
4491 -- Add_ALI_For --
4492 -----------------
4493
4494 procedure Add_ALI_For (Source : File_Name_Type) is
4495 begin
4496 Get_Name_String (Source);
4497
4498 declare
4499 ALI : constant String :=
4500 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4501 ALI_Name_Id : Name_Id;
4502
4503 begin
4504 Name_Len := ALI'Length;
4505 Name_Buffer (1 .. Name_Len) := ALI;
4506 ALI_Name_Id := Name_Find;
4507
4508 String_Element_Table.Increment_Last
4509 (In_Tree.String_Elements);
4510 In_Tree.String_Elements.Table
4511 (String_Element_Table.Last
4512 (In_Tree.String_Elements)) :=
4513 (Value => ALI_Name_Id,
4514 Index => 0,
4515 Display_Value => ALI_Name_Id,
4516 Location =>
4517 In_Tree.String_Elements.Table
4518 (Interfaces).Location,
4519 Flag => False,
4520 Next => Interface_ALIs);
4521 Interface_ALIs := String_Element_Table.Last
4522 (In_Tree.String_Elements);
4523 end;
4524 end Add_ALI_For;
4525
4526 -- Start of processing for SAL_Library
4527
4528 begin
4529 Project.Standalone_Library := True;
4530
4531 -- Library_Interface cannot be an empty list
4532
4533 if Interfaces = Nil_String then
4534 Error_Msg
4535 (Project, In_Tree,
4536 "Library_Interface cannot be an empty list",
4537 Lib_Interfaces.Location);
4538 end if;
4539
4540 -- Process each unit name specified in the attribute
4541 -- Library_Interface.
4542
4543 while Interfaces /= Nil_String loop
4544 Get_Name_String
4545 (In_Tree.String_Elements.Table (Interfaces).Value);
4546 To_Lower (Name_Buffer (1 .. Name_Len));
4547
4548 if Name_Len = 0 then
4549 Error_Msg
4550 (Project, In_Tree,
4551 "an interface cannot be an empty string",
4552 In_Tree.String_Elements.Table (Interfaces).Location);
4553
4554 else
4555 Unit := Name_Find;
4556 Error_Msg_Name_1 := Unit;
4557
4558 if Get_Mode = Ada_Only then
4559 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
4560
4561 if UData = No_Unit_Index then
4562 Error_Msg
4563 (Project, In_Tree,
4564 "unknown unit %%",
4565 In_Tree.String_Elements.Table
4566 (Interfaces).Location);
4567
4568 else
4569 -- Check that the unit is part of the project
4570
4571 if UData.File_Names (Impl) /= null
4572 and then not UData.File_Names (Impl).Locally_Removed
4573 then
4574 if Check_Project
4575 (UData.File_Names (Impl).Project,
4576 Project, Extending)
4577 then
4578 -- There is a body for this unit.
4579 -- If there is no spec, we need to check that it
4580 -- is not a subunit.
4581
4582 if UData.File_Names (Spec) = null then
4583 declare
4584 Src_Ind : Source_File_Index;
4585
4586 begin
4587 Src_Ind :=
4588 Sinput.P.Load_Project_File
4589 (Get_Name_String (UData.File_Names
4590 (Impl).Path.Name));
4591
4592 if Sinput.P.Source_File_Is_Subunit
4593 (Src_Ind)
4594 then
4595 Error_Msg
4596 (Project, In_Tree,
4597 "%% is a subunit; " &
4598 "it cannot be an interface",
4599 In_Tree.
4600 String_Elements.Table
4601 (Interfaces).Location);
4602 end if;
4603 end;
4604 end if;
4605
4606 -- The unit is not a subunit, so we add the
4607 -- ALI file for its body to the Interface ALIs.
4608
4609 Add_ALI_For
4610 (UData.File_Names (Impl).File);
4611
4612 else
4613 Error_Msg
4614 (Project, In_Tree,
4615 "%% is not an unit of this project",
4616 In_Tree.String_Elements.Table
4617 (Interfaces).Location);
4618 end if;
4619
4620 elsif UData.File_Names (Spec) /= null
4621 and then not UData.File_Names (Spec).Locally_Removed
4622 and then Check_Project
4623 (UData.File_Names (Spec).Project,
4624 Project, Extending)
4625
4626 then
4627 -- The unit is part of the project, it has a spec,
4628 -- but no body. We add the ALI for its spec to the
4629 -- Interface ALIs.
4630
4631 Add_ALI_For
4632 (UData.File_Names (Spec).File);
4633
4634 else
4635 Error_Msg
4636 (Project, In_Tree,
4637 "%% is not an unit of this project",
4638 In_Tree.String_Elements.Table
4639 (Interfaces).Location);
4640 end if;
4641 end if;
4642
4643 else
4644 -- Multi_Language mode
4645
4646 Next_Proj := Project.Extends;
4647 Iter := For_Each_Source (In_Tree, Project);
4648 loop
4649 while Prj.Element (Iter) /= No_Source
4650 and then
4651 (Prj.Element (Iter).Unit = null
4652 or else Prj.Element (Iter).Unit.Name /= Unit)
4653 loop
4654 Next (Iter);
4655 end loop;
4656
4657 Source := Prj.Element (Iter);
4658 exit when Source /= No_Source
4659 or else Next_Proj = No_Project;
4660
4661 Iter := For_Each_Source (In_Tree, Next_Proj);
4662 Next_Proj := Next_Proj.Extends;
4663 end loop;
4664
4665 if Source /= No_Source then
4666 if Source.Kind = Sep then
4667 Source := No_Source;
4668 elsif Source.Kind = Spec
4669 and then Other_Part (Source) /= No_Source
4670 then
4671 Source := Other_Part (Source);
4672 end if;
4673 end if;
4674
4675 if Source /= No_Source then
4676 if Source.Project /= Project
4677 and then not Is_Extending (Project, Source.Project)
4678 then
4679 Source := No_Source;
4680 end if;
4681 end if;
4682
4683 if Source = No_Source then
4684 Error_Msg
4685 (Project, In_Tree,
4686 "%% is not an unit of this project",
4687 In_Tree.String_Elements.Table
4688 (Interfaces).Location);
4689
4690 else
4691 if Source.Kind = Spec
4692 and then Other_Part (Source) /= No_Source
4693 then
4694 Source := Other_Part (Source);
4695 end if;
4696
4697 String_Element_Table.Increment_Last
4698 (In_Tree.String_Elements);
4699
4700 In_Tree.String_Elements.Table
4701 (String_Element_Table.Last
4702 (In_Tree.String_Elements)) :=
4703 (Value => Name_Id (Source.Dep_Name),
4704 Index => 0,
4705 Display_Value => Name_Id (Source.Dep_Name),
4706 Location =>
4707 In_Tree.String_Elements.Table
4708 (Interfaces).Location,
4709 Flag => False,
4710 Next => Interface_ALIs);
4711
4712 Interface_ALIs :=
4713 String_Element_Table.Last (In_Tree.String_Elements);
4714 end if;
4715
4716 end if;
4717
4718 end if;
4719
4720 Interfaces :=
4721 In_Tree.String_Elements.Table (Interfaces).Next;
4722 end loop;
4723
4724 -- Put the list of Interface ALIs in the project data
4725
4726 Project.Lib_Interface_ALIs := Interface_ALIs;
4727
4728 -- Check value of attribute Library_Auto_Init and set
4729 -- Lib_Auto_Init accordingly.
4730
4731 if Lib_Auto_Init.Default then
4732
4733 -- If no attribute Library_Auto_Init is declared, then set auto
4734 -- init only if it is supported.
4735
4736 Project.Lib_Auto_Init := Auto_Init_Supported;
4737
4738 else
4739 Get_Name_String (Lib_Auto_Init.Value);
4740 To_Lower (Name_Buffer (1 .. Name_Len));
4741
4742 if Name_Buffer (1 .. Name_Len) = "false" then
4743 Project.Lib_Auto_Init := False;
4744
4745 elsif Name_Buffer (1 .. Name_Len) = "true" then
4746 if Auto_Init_Supported then
4747 Project.Lib_Auto_Init := True;
4748
4749 else
4750 -- Library_Auto_Init cannot be "true" if auto init is not
4751 -- supported.
4752
4753 Error_Msg
4754 (Project, In_Tree,
4755 "library auto init not supported " &
4756 "on this platform",
4757 Lib_Auto_Init.Location);
4758 end if;
4759
4760 else
4761 Error_Msg
4762 (Project, In_Tree,
4763 "invalid value for attribute Library_Auto_Init",
4764 Lib_Auto_Init.Location);
4765 end if;
4766 end if;
4767 end SAL_Library;
4768
4769 -- If attribute Library_Src_Dir is defined and not the empty string,
4770 -- check if the directory exist and is not the object directory or
4771 -- one of the source directories. This is the directory where copies
4772 -- of the interface sources will be copied. Note that this directory
4773 -- may be the library directory.
4774
4775 if Lib_Src_Dir.Value /= Empty_String then
4776 declare
4777 Dir_Id : constant File_Name_Type :=
4778 File_Name_Type (Lib_Src_Dir.Value);
4779 Dir_Exists : Boolean;
4780
4781 begin
4782 Locate_Directory
4783 (Project,
4784 In_Tree,
4785 Dir_Id,
4786 Path => Project.Library_Src_Dir,
4787 Dir_Exists => Dir_Exists,
4788 Must_Exist => False,
4789 Create => "library source copy",
4790 Location => Lib_Src_Dir.Location,
4791 Externally_Built => Project.Externally_Built);
4792
4793 -- If directory does not exist, report an error
4794
4795 if not Dir_Exists then
4796 -- Get the absolute name of the library directory that does
4797 -- not exist, to report an error.
4798
4799 Err_Vars.Error_Msg_File_1 :=
4800 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4801 Error_Msg
4802 (Project, In_Tree,
4803 "Directory { does not exist",
4804 Lib_Src_Dir.Location);
4805
4806 -- Report error if it is the same as the object directory
4807
4808 elsif Project.Library_Src_Dir = Project.Object_Directory then
4809 Error_Msg
4810 (Project, In_Tree,
4811 "directory to copy interfaces cannot be " &
4812 "the object directory",
4813 Lib_Src_Dir.Location);
4814 Project.Library_Src_Dir := No_Path_Information;
4815
4816 else
4817 declare
4818 Src_Dirs : String_List_Id;
4819 Src_Dir : String_Element;
4820 Pid : Project_List;
4821
4822 begin
4823 -- Interface copy directory cannot be one of the source
4824 -- directory of the current project.
4825
4826 Src_Dirs := Project.Source_Dirs;
4827 while Src_Dirs /= Nil_String loop
4828 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4829
4830 -- Report error if it is one of the source directories
4831
4832 if Project.Library_Src_Dir.Name =
4833 Path_Name_Type (Src_Dir.Value)
4834 then
4835 Error_Msg
4836 (Project, In_Tree,
4837 "directory to copy interfaces cannot " &
4838 "be one of the source directories",
4839 Lib_Src_Dir.Location);
4840 Project.Library_Src_Dir := No_Path_Information;
4841 exit;
4842 end if;
4843
4844 Src_Dirs := Src_Dir.Next;
4845 end loop;
4846
4847 if Project.Library_Src_Dir /= No_Path_Information then
4848
4849 -- It cannot be a source directory of any other
4850 -- project either.
4851
4852 Pid := In_Tree.Projects;
4853 Project_Loop : loop
4854 exit Project_Loop when Pid = null;
4855
4856 Src_Dirs := Pid.Project.Source_Dirs;
4857 Dir_Loop : while Src_Dirs /= Nil_String loop
4858 Src_Dir :=
4859 In_Tree.String_Elements.Table (Src_Dirs);
4860
4861 -- Report error if it is one of the source
4862 -- directories
4863
4864 if Project.Library_Src_Dir.Name =
4865 Path_Name_Type (Src_Dir.Value)
4866 then
4867 Error_Msg_File_1 :=
4868 File_Name_Type (Src_Dir.Value);
4869 Error_Msg_Name_1 := Pid.Project.Name;
4870 Error_Msg
4871 (Project, In_Tree,
4872 "directory to copy interfaces cannot " &
4873 "be the same as source directory { of " &
4874 "project %%",
4875 Lib_Src_Dir.Location);
4876 Project.Library_Src_Dir :=
4877 No_Path_Information;
4878 exit Project_Loop;
4879 end if;
4880
4881 Src_Dirs := Src_Dir.Next;
4882 end loop Dir_Loop;
4883
4884 Pid := Pid.Next;
4885 end loop Project_Loop;
4886 end if;
4887 end;
4888
4889 -- In high verbosity, if there is a valid Library_Src_Dir,
4890 -- display its path name.
4891
4892 if Project.Library_Src_Dir /= No_Path_Information
4893 and then Current_Verbosity = High
4894 then
4895 Write_Attr
4896 ("Directory to copy interfaces",
4897 Get_Name_String (Project.Library_Src_Dir.Name));
4898 end if;
4899 end if;
4900 end;
4901 end if;
4902
4903 -- Check the symbol related attributes
4904
4905 -- First, the symbol policy
4906
4907 if not Lib_Symbol_Policy.Default then
4908 declare
4909 Value : constant String :=
4910 To_Lower
4911 (Get_Name_String (Lib_Symbol_Policy.Value));
4912
4913 begin
4914 -- Symbol policy must hove one of a limited number of values
4915
4916 if Value = "autonomous" or else Value = "default" then
4917 Project.Symbol_Data.Symbol_Policy := Autonomous;
4918
4919 elsif Value = "compliant" then
4920 Project.Symbol_Data.Symbol_Policy := Compliant;
4921
4922 elsif Value = "controlled" then
4923 Project.Symbol_Data.Symbol_Policy := Controlled;
4924
4925 elsif Value = "restricted" then
4926 Project.Symbol_Data.Symbol_Policy := Restricted;
4927
4928 elsif Value = "direct" then
4929 Project.Symbol_Data.Symbol_Policy := Direct;
4930
4931 else
4932 Error_Msg
4933 (Project, In_Tree,
4934 "illegal value for Library_Symbol_Policy",
4935 Lib_Symbol_Policy.Location);
4936 end if;
4937 end;
4938 end if;
4939
4940 -- If attribute Library_Symbol_File is not specified, symbol policy
4941 -- cannot be Restricted.
4942
4943 if Lib_Symbol_File.Default then
4944 if Project.Symbol_Data.Symbol_Policy = Restricted then
4945 Error_Msg
4946 (Project, In_Tree,
4947 "Library_Symbol_File needs to be defined when " &
4948 "symbol policy is Restricted",
4949 Lib_Symbol_Policy.Location);
4950 end if;
4951
4952 else
4953 -- Library_Symbol_File is defined
4954
4955 Project.Symbol_Data.Symbol_File :=
4956 Path_Name_Type (Lib_Symbol_File.Value);
4957
4958 Get_Name_String (Lib_Symbol_File.Value);
4959
4960 if Name_Len = 0 then
4961 Error_Msg
4962 (Project, In_Tree,
4963 "symbol file name cannot be an empty string",
4964 Lib_Symbol_File.Location);
4965
4966 else
4967 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4968
4969 if OK then
4970 for J in 1 .. Name_Len loop
4971 if Name_Buffer (J) = '/'
4972 or else Name_Buffer (J) = Directory_Separator
4973 then
4974 OK := False;
4975 exit;
4976 end if;
4977 end loop;
4978 end if;
4979
4980 if not OK then
4981 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4982 Error_Msg
4983 (Project, In_Tree,
4984 "symbol file name { is illegal. " &
4985 "Name cannot include directory info.",
4986 Lib_Symbol_File.Location);
4987 end if;
4988 end if;
4989 end if;
4990
4991 -- If attribute Library_Reference_Symbol_File is not defined,
4992 -- symbol policy cannot be Compliant or Controlled.
4993
4994 if Lib_Ref_Symbol_File.Default then
4995 if Project.Symbol_Data.Symbol_Policy = Compliant
4996 or else Project.Symbol_Data.Symbol_Policy = Controlled
4997 then
4998 Error_Msg
4999 (Project, In_Tree,
5000 "a reference symbol file needs to be defined",
5001 Lib_Symbol_Policy.Location);
5002 end if;
5003
5004 else
5005 -- Library_Reference_Symbol_File is defined, check file exists
5006
5007 Project.Symbol_Data.Reference :=
5008 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5009
5010 Get_Name_String (Lib_Ref_Symbol_File.Value);
5011
5012 if Name_Len = 0 then
5013 Error_Msg
5014 (Project, In_Tree,
5015 "reference symbol file name cannot be an empty string",
5016 Lib_Symbol_File.Location);
5017
5018 else
5019 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5020 Name_Len := 0;
5021 Add_Str_To_Name_Buffer
5022 (Get_Name_String (Project.Directory.Name));
5023 Add_Char_To_Name_Buffer (Directory_Separator);
5024 Add_Str_To_Name_Buffer
5025 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5026 Project.Symbol_Data.Reference := Name_Find;
5027 end if;
5028
5029 if not Is_Regular_File
5030 (Get_Name_String (Project.Symbol_Data.Reference))
5031 then
5032 Error_Msg_File_1 :=
5033 File_Name_Type (Lib_Ref_Symbol_File.Value);
5034
5035 -- For controlled and direct symbol policies, it is an error
5036 -- if the reference symbol file does not exist. For other
5037 -- symbol policies, this is just a warning
5038
5039 Error_Msg_Warn :=
5040 Project.Symbol_Data.Symbol_Policy /= Controlled
5041 and then Project.Symbol_Data.Symbol_Policy /= Direct;
5042
5043 Error_Msg
5044 (Project, In_Tree,
5045 "<library reference symbol file { does not exist",
5046 Lib_Ref_Symbol_File.Location);
5047
5048 -- In addition in the non-controlled case, if symbol policy
5049 -- is Compliant, it is changed to Autonomous, because there
5050 -- is no reference to check against, and we don't want to
5051 -- fail in this case.
5052
5053 if Project.Symbol_Data.Symbol_Policy /= Controlled then
5054 if Project.Symbol_Data.Symbol_Policy = Compliant then
5055 Project.Symbol_Data.Symbol_Policy := Autonomous;
5056 end if;
5057 end if;
5058 end if;
5059
5060 -- If both the reference symbol file and the symbol file are
5061 -- defined, then check that they are not the same file.
5062
5063 if Project.Symbol_Data.Symbol_File /= No_Path then
5064 Get_Name_String (Project.Symbol_Data.Symbol_File);
5065
5066 if Name_Len > 0 then
5067 declare
5068 Symb_Path : constant String :=
5069 Normalize_Pathname
5070 (Get_Name_String
5071 (Project.Object_Directory.Name) &
5072 Directory_Separator &
5073 Name_Buffer (1 .. Name_Len),
5074 Directory => Current_Dir,
5075 Resolve_Links =>
5076 Opt.Follow_Links_For_Files);
5077 Ref_Path : constant String :=
5078 Normalize_Pathname
5079 (Get_Name_String
5080 (Project.Symbol_Data.Reference),
5081 Directory => Current_Dir,
5082 Resolve_Links =>
5083 Opt.Follow_Links_For_Files);
5084 begin
5085 if Symb_Path = Ref_Path then
5086 Error_Msg
5087 (Project, In_Tree,
5088 "library reference symbol file and library" &
5089 " symbol file cannot be the same file",
5090 Lib_Ref_Symbol_File.Location);
5091 end if;
5092 end;
5093 end if;
5094 end if;
5095 end if;
5096 end if;
5097 end if;
5098 end Check_Stand_Alone_Library;
5099
5100 ----------------------------
5101 -- Compute_Directory_Last --
5102 ----------------------------
5103
5104 function Compute_Directory_Last (Dir : String) return Natural is
5105 begin
5106 if Dir'Length > 1
5107 and then (Dir (Dir'Last - 1) = Directory_Separator
5108 or else Dir (Dir'Last - 1) = '/')
5109 then
5110 return Dir'Last - 1;
5111 else
5112 return Dir'Last;
5113 end if;
5114 end Compute_Directory_Last;
5115
5116 ---------------
5117 -- Error_Msg --
5118 ---------------
5119
5120 procedure Error_Msg
5121 (Project : Project_Id;
5122 In_Tree : Project_Tree_Ref;
5123 Msg : String;
5124 Flag_Location : Source_Ptr)
5125 is
5126 Real_Location : Source_Ptr := Flag_Location;
5127 Error_Buffer : String (1 .. 5_000);
5128 Error_Last : Natural := 0;
5129 Name_Number : Natural := 0;
5130 File_Number : Natural := 0;
5131 First : Positive := Msg'First;
5132 Index : Positive;
5133
5134 procedure Add (C : Character);
5135 -- Add a character to the buffer
5136
5137 procedure Add (S : String);
5138 -- Add a string to the buffer
5139
5140 procedure Add_Name;
5141 -- Add a name to the buffer
5142
5143 procedure Add_File;
5144 -- Add a file name to the buffer
5145
5146 ---------
5147 -- Add --
5148 ---------
5149
5150 procedure Add (C : Character) is
5151 begin
5152 Error_Last := Error_Last + 1;
5153 Error_Buffer (Error_Last) := C;
5154 end Add;
5155
5156 procedure Add (S : String) is
5157 begin
5158 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5159 Error_Last := Error_Last + S'Length;
5160 end Add;
5161
5162 --------------
5163 -- Add_File --
5164 --------------
5165
5166 procedure Add_File is
5167 File : File_Name_Type;
5168
5169 begin
5170 Add ('"');
5171 File_Number := File_Number + 1;
5172
5173 case File_Number is
5174 when 1 =>
5175 File := Err_Vars.Error_Msg_File_1;
5176 when 2 =>
5177 File := Err_Vars.Error_Msg_File_2;
5178 when 3 =>
5179 File := Err_Vars.Error_Msg_File_3;
5180 when others =>
5181 null;
5182 end case;
5183
5184 Get_Name_String (File);
5185 Add (Name_Buffer (1 .. Name_Len));
5186 Add ('"');
5187 end Add_File;
5188
5189 --------------
5190 -- Add_Name --
5191 --------------
5192
5193 procedure Add_Name is
5194 Name : Name_Id;
5195
5196 begin
5197 Add ('"');
5198 Name_Number := Name_Number + 1;
5199
5200 case Name_Number is
5201 when 1 =>
5202 Name := Err_Vars.Error_Msg_Name_1;
5203 when 2 =>
5204 Name := Err_Vars.Error_Msg_Name_2;
5205 when 3 =>
5206 Name := Err_Vars.Error_Msg_Name_3;
5207 when others =>
5208 null;
5209 end case;
5210
5211 Get_Name_String (Name);
5212 Add (Name_Buffer (1 .. Name_Len));
5213 Add ('"');
5214 end Add_Name;
5215
5216 -- Start of processing for Error_Msg
5217
5218 begin
5219 -- If location of error is unknown, use the location of the project
5220
5221 if Real_Location = No_Location then
5222 Real_Location := Project.Location;
5223 end if;
5224
5225 if Error_Report = null then
5226 Prj.Err.Error_Msg (Msg, Real_Location);
5227 return;
5228 end if;
5229
5230 -- Ignore continuation character
5231
5232 if Msg (First) = '\' then
5233 First := First + 1;
5234 end if;
5235
5236 -- Warning character is always the first one in this package
5237 -- this is an undocumented kludge???
5238
5239 if Msg (First) = '?' then
5240 First := First + 1;
5241 Add ("Warning: ");
5242
5243 elsif Msg (First) = '<' then
5244 First := First + 1;
5245
5246 if Err_Vars.Error_Msg_Warn then
5247 Add ("Warning: ");
5248 end if;
5249 end if;
5250
5251 Index := First;
5252 while Index <= Msg'Last loop
5253 if Msg (Index) = '{' then
5254 Add_File;
5255
5256 elsif Msg (Index) = '%' then
5257 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5258 Index := Index + 1;
5259 end if;
5260
5261 Add_Name;
5262 else
5263 Add (Msg (Index));
5264 end if;
5265 Index := Index + 1;
5266
5267 end loop;
5268
5269 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5270 end Error_Msg;
5271
5272 --------------------------------
5273 -- Free_Ada_Naming_Exceptions --
5274 --------------------------------
5275
5276 procedure Free_Ada_Naming_Exceptions is
5277 begin
5278 Ada_Naming_Exception_Table.Set_Last (0);
5279 Ada_Naming_Exceptions.Reset;
5280 Reverse_Ada_Naming_Exceptions.Reset;
5281 end Free_Ada_Naming_Exceptions;
5282
5283 ---------------------
5284 -- Get_Directories --
5285 ---------------------
5286
5287 procedure Get_Directories
5288 (Project : Project_Id;
5289 In_Tree : Project_Tree_Ref;
5290 Current_Dir : String)
5291 is
5292 Object_Dir : constant Variable_Value :=
5293 Util.Value_Of
5294 (Name_Object_Dir, Project.Decl.Attributes, In_Tree);
5295
5296 Exec_Dir : constant Variable_Value :=
5297 Util.Value_Of
5298 (Name_Exec_Dir, Project.Decl.Attributes, In_Tree);
5299
5300 Source_Dirs : constant Variable_Value :=
5301 Util.Value_Of
5302 (Name_Source_Dirs, Project.Decl.Attributes, In_Tree);
5303
5304 Excluded_Source_Dirs : constant Variable_Value :=
5305 Util.Value_Of
5306 (Name_Excluded_Source_Dirs,
5307 Project.Decl.Attributes,
5308 In_Tree);
5309
5310 Source_Files : constant Variable_Value :=
5311 Util.Value_Of
5312 (Name_Source_Files, Project.Decl.Attributes, In_Tree);
5313
5314 Last_Source_Dir : String_List_Id := Nil_String;
5315
5316 Languages : constant Variable_Value :=
5317 Prj.Util.Value_Of
5318 (Name_Languages, Project.Decl.Attributes, In_Tree);
5319
5320 procedure Find_Source_Dirs
5321 (From : File_Name_Type;
5322 Location : Source_Ptr;
5323 Removed : Boolean := False);
5324 -- Find one or several source directories, and add (or remove, if
5325 -- Removed is True) them to list of source directories of the project.
5326
5327 ----------------------
5328 -- Find_Source_Dirs --
5329 ----------------------
5330
5331 procedure Find_Source_Dirs
5332 (From : File_Name_Type;
5333 Location : Source_Ptr;
5334 Removed : Boolean := False)
5335 is
5336 Directory : constant String := Get_Name_String (From);
5337 Element : String_Element;
5338
5339 procedure Recursive_Find_Dirs (Path : Name_Id);
5340 -- Find all the subdirectories (recursively) of Path and add them
5341 -- to the list of source directories of the project.
5342
5343 -------------------------
5344 -- Recursive_Find_Dirs --
5345 -------------------------
5346
5347 procedure Recursive_Find_Dirs (Path : Name_Id) is
5348 Dir : Dir_Type;
5349 Name : String (1 .. 250);
5350 Last : Natural;
5351 List : String_List_Id;
5352 Prev : String_List_Id;
5353 Element : String_Element;
5354 Found : Boolean := False;
5355
5356 Non_Canonical_Path : Name_Id := No_Name;
5357 Canonical_Path : Name_Id := No_Name;
5358
5359 The_Path : constant String :=
5360 Normalize_Pathname
5361 (Get_Name_String (Path),
5362 Directory => Current_Dir,
5363 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5364 Directory_Separator;
5365
5366 The_Path_Last : constant Natural :=
5367 Compute_Directory_Last (The_Path);
5368
5369 begin
5370 Name_Len := The_Path_Last - The_Path'First + 1;
5371 Name_Buffer (1 .. Name_Len) :=
5372 The_Path (The_Path'First .. The_Path_Last);
5373 Non_Canonical_Path := Name_Find;
5374 Canonical_Path :=
5375 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5376
5377 -- To avoid processing the same directory several times, check
5378 -- if the directory is already in Recursive_Dirs. If it is, then
5379 -- there is nothing to do, just return. If it is not, put it there
5380 -- and continue recursive processing.
5381
5382 if not Removed then
5383 if Recursive_Dirs.Get (Canonical_Path) then
5384 return;
5385 else
5386 Recursive_Dirs.Set (Canonical_Path, True);
5387 end if;
5388 end if;
5389
5390 -- Check if directory is already in list
5391
5392 List := Project.Source_Dirs;
5393 Prev := Nil_String;
5394 while List /= Nil_String loop
5395 Element := In_Tree.String_Elements.Table (List);
5396
5397 if Element.Value /= No_Name then
5398 Found := Element.Value = Canonical_Path;
5399 exit when Found;
5400 end if;
5401
5402 Prev := List;
5403 List := Element.Next;
5404 end loop;
5405
5406 -- If directory is not already in list, put it there
5407
5408 if (not Removed) and (not Found) then
5409 if Current_Verbosity = High then
5410 Write_Str (" ");
5411 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5412 end if;
5413
5414 String_Element_Table.Increment_Last
5415 (In_Tree.String_Elements);
5416 Element :=
5417 (Value => Canonical_Path,
5418 Display_Value => Non_Canonical_Path,
5419 Location => No_Location,
5420 Flag => False,
5421 Next => Nil_String,
5422 Index => 0);
5423
5424 -- Case of first source directory
5425
5426 if Last_Source_Dir = Nil_String then
5427 Project.Source_Dirs := String_Element_Table.Last
5428 (In_Tree.String_Elements);
5429
5430 -- Here we already have source directories
5431
5432 else
5433 -- Link the previous last to the new one
5434
5435 In_Tree.String_Elements.Table
5436 (Last_Source_Dir).Next :=
5437 String_Element_Table.Last
5438 (In_Tree.String_Elements);
5439 end if;
5440
5441 -- And register this source directory as the new last
5442
5443 Last_Source_Dir := String_Element_Table.Last
5444 (In_Tree.String_Elements);
5445 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5446 Element;
5447
5448 elsif Removed and Found then
5449 if Prev = Nil_String then
5450 Project.Source_Dirs :=
5451 In_Tree.String_Elements.Table (List).Next;
5452 else
5453 In_Tree.String_Elements.Table (Prev).Next :=
5454 In_Tree.String_Elements.Table (List).Next;
5455 end if;
5456 end if;
5457
5458 -- Now look for subdirectories. We do that even when this
5459 -- directory is already in the list, because some of its
5460 -- subdirectories may not be in the list yet.
5461
5462 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5463
5464 loop
5465 Read (Dir, Name, Last);
5466 exit when Last = 0;
5467
5468 if Name (1 .. Last) /= "."
5469 and then Name (1 .. Last) /= ".."
5470 then
5471 -- Avoid . and .. directories
5472
5473 if Current_Verbosity = High then
5474 Write_Str (" Checking ");
5475 Write_Line (Name (1 .. Last));
5476 end if;
5477
5478 declare
5479 Path_Name : constant String :=
5480 Normalize_Pathname
5481 (Name => Name (1 .. Last),
5482 Directory =>
5483 The_Path (The_Path'First .. The_Path_Last),
5484 Resolve_Links => Opt.Follow_Links_For_Dirs,
5485 Case_Sensitive => True);
5486
5487 begin
5488 if Is_Directory (Path_Name) then
5489 -- We have found a new subdirectory, call self
5490
5491 Name_Len := Path_Name'Length;
5492 Name_Buffer (1 .. Name_Len) := Path_Name;
5493 Recursive_Find_Dirs (Name_Find);
5494 end if;
5495 end;
5496 end if;
5497 end loop;
5498
5499 Close (Dir);
5500
5501 exception
5502 when Directory_Error =>
5503 null;
5504 end Recursive_Find_Dirs;
5505
5506 -- Start of processing for Find_Source_Dirs
5507
5508 begin
5509 if Current_Verbosity = High and then not Removed then
5510 Write_Str ("Find_Source_Dirs (""");
5511 Write_Str (Directory);
5512 Write_Line (""")");
5513 end if;
5514
5515 -- First, check if we are looking for a directory tree, indicated
5516 -- by "/**" at the end.
5517
5518 if Directory'Length >= 3
5519 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5520 and then (Directory (Directory'Last - 2) = '/'
5521 or else
5522 Directory (Directory'Last - 2) = Directory_Separator)
5523 then
5524 if not Removed then
5525 Project.Known_Order_Of_Source_Dirs := False;
5526 end if;
5527
5528 Name_Len := Directory'Length - 3;
5529
5530 if Name_Len = 0 then
5531
5532 -- Case of "/**": all directories in file system
5533
5534 Name_Len := 1;
5535 Name_Buffer (1) := Directory (Directory'First);
5536
5537 else
5538 Name_Buffer (1 .. Name_Len) :=
5539 Directory (Directory'First .. Directory'Last - 3);
5540 end if;
5541
5542 if Current_Verbosity = High then
5543 Write_Str ("Looking for all subdirectories of """);
5544 Write_Str (Name_Buffer (1 .. Name_Len));
5545 Write_Line ("""");
5546 end if;
5547
5548 declare
5549 Base_Dir : constant File_Name_Type := Name_Find;
5550 Root_Dir : constant String :=
5551 Normalize_Pathname
5552 (Name => Get_Name_String (Base_Dir),
5553 Directory =>
5554 Get_Name_String
5555 (Project.Directory.Display_Name),
5556 Resolve_Links => False,
5557 Case_Sensitive => True);
5558
5559 begin
5560 if Root_Dir'Length = 0 then
5561 Err_Vars.Error_Msg_File_1 := Base_Dir;
5562
5563 if Location = No_Location then
5564 Error_Msg
5565 (Project, In_Tree,
5566 "{ is not a valid directory.",
5567 Project.Location);
5568 else
5569 Error_Msg
5570 (Project, In_Tree,
5571 "{ is not a valid directory.",
5572 Location);
5573 end if;
5574
5575 else
5576 -- We have an existing directory, we register it and all of
5577 -- its subdirectories.
5578
5579 if Current_Verbosity = High then
5580 Write_Line ("Looking for source directories:");
5581 end if;
5582
5583 Name_Len := Root_Dir'Length;
5584 Name_Buffer (1 .. Name_Len) := Root_Dir;
5585 Recursive_Find_Dirs (Name_Find);
5586
5587 if Current_Verbosity = High then
5588 Write_Line ("End of looking for source directories.");
5589 end if;
5590 end if;
5591 end;
5592
5593 -- We have a single directory
5594
5595 else
5596 declare
5597 Path_Name : Path_Information;
5598 List : String_List_Id;
5599 Prev : String_List_Id;
5600 Dir_Exists : Boolean;
5601
5602 begin
5603 Locate_Directory
5604 (Project => Project,
5605 In_Tree => In_Tree,
5606 Name => From,
5607 Path => Path_Name,
5608 Dir_Exists => Dir_Exists,
5609 Must_Exist => False);
5610
5611 if not Dir_Exists then
5612 Err_Vars.Error_Msg_File_1 := From;
5613
5614 if Location = No_Location then
5615 Error_Msg
5616 (Project, In_Tree,
5617 "{ is not a valid directory",
5618 Project.Location);
5619 else
5620 Error_Msg
5621 (Project, In_Tree,
5622 "{ is not a valid directory",
5623 Location);
5624 end if;
5625
5626 else
5627 declare
5628 Path : constant String :=
5629 Get_Name_String (Path_Name.Name) &
5630 Directory_Separator;
5631 Last_Path : constant Natural :=
5632 Compute_Directory_Last (Path);
5633 Path_Id : Name_Id;
5634 Display_Path : constant String :=
5635 Get_Name_String
5636 (Path_Name.Display_Name) &
5637 Directory_Separator;
5638 Last_Display_Path : constant Natural :=
5639 Compute_Directory_Last
5640 (Display_Path);
5641 Display_Path_Id : Name_Id;
5642
5643 begin
5644 Name_Len := 0;
5645 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5646 Path_Id := Name_Find;
5647 Name_Len := 0;
5648 Add_Str_To_Name_Buffer
5649 (Display_Path
5650 (Display_Path'First .. Last_Display_Path));
5651 Display_Path_Id := Name_Find;
5652
5653 if not Removed then
5654
5655 -- As it is an existing directory, we add it to the
5656 -- list of directories.
5657
5658 String_Element_Table.Increment_Last
5659 (In_Tree.String_Elements);
5660 Element :=
5661 (Value => Path_Id,
5662 Index => 0,
5663 Display_Value => Display_Path_Id,
5664 Location => No_Location,
5665 Flag => False,
5666 Next => Nil_String);
5667
5668 if Last_Source_Dir = Nil_String then
5669
5670 -- This is the first source directory
5671
5672 Project.Source_Dirs := String_Element_Table.Last
5673 (In_Tree.String_Elements);
5674
5675 else
5676 -- We already have source directories, link the
5677 -- previous last to the new one.
5678
5679 In_Tree.String_Elements.Table
5680 (Last_Source_Dir).Next :=
5681 String_Element_Table.Last
5682 (In_Tree.String_Elements);
5683 end if;
5684
5685 -- And register this source directory as the new last
5686
5687 Last_Source_Dir := String_Element_Table.Last
5688 (In_Tree.String_Elements);
5689 In_Tree.String_Elements.Table
5690 (Last_Source_Dir) := Element;
5691
5692 else
5693 -- Remove source dir, if present
5694
5695 Prev := Nil_String;
5696
5697 -- Look for source dir in current list
5698
5699 List := Project.Source_Dirs;
5700 while List /= Nil_String loop
5701 Element := In_Tree.String_Elements.Table (List);
5702 exit when Element.Value = Path_Id;
5703 Prev := List;
5704 List := Element.Next;
5705 end loop;
5706
5707 if List /= Nil_String then
5708 -- Source dir was found, remove it from the list
5709
5710 if Prev = Nil_String then
5711 Project.Source_Dirs :=
5712 In_Tree.String_Elements.Table (List).Next;
5713
5714 else
5715 In_Tree.String_Elements.Table (Prev).Next :=
5716 In_Tree.String_Elements.Table (List).Next;
5717 end if;
5718 end if;
5719 end if;
5720 end;
5721 end if;
5722 end;
5723 end if;
5724 end Find_Source_Dirs;
5725
5726 -- Start of processing for Get_Directories
5727
5728 Dir_Exists : Boolean;
5729
5730 begin
5731 if Current_Verbosity = High then
5732 Write_Line ("Starting to look for directories");
5733 end if;
5734
5735 -- Set the object directory to its default which may be nil, if there
5736 -- is no sources in the project.
5737
5738 if (((not Source_Files.Default)
5739 and then Source_Files.Values = Nil_String)
5740 or else
5741 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5742 or else
5743 ((not Languages.Default) and then Languages.Values = Nil_String))
5744 and then Project.Extends = No_Project
5745 then
5746 Project.Object_Directory := No_Path_Information;
5747 else
5748 Project.Object_Directory := Project.Directory;
5749 end if;
5750
5751 -- Check the object directory
5752
5753 if Object_Dir.Value /= Empty_String then
5754 Get_Name_String (Object_Dir.Value);
5755
5756 if Name_Len = 0 then
5757 Error_Msg
5758 (Project, In_Tree,
5759 "Object_Dir cannot be empty",
5760 Object_Dir.Location);
5761
5762 else
5763 -- We check that the specified object directory does exist.
5764 -- However, even when it doesn't exist, we set it to a default
5765 -- value. This is for the benefit of tools that recover from
5766 -- errors; for example, these tools could create the non existent
5767 -- directory.
5768 -- We always return an absolute directory name though
5769
5770 Locate_Directory
5771 (Project,
5772 In_Tree,
5773 File_Name_Type (Object_Dir.Value),
5774 Path => Project.Object_Directory,
5775 Create => "object",
5776 Dir_Exists => Dir_Exists,
5777 Location => Object_Dir.Location,
5778 Must_Exist => False,
5779 Externally_Built => Project.Externally_Built);
5780
5781 if not Dir_Exists
5782 and then not Project.Externally_Built
5783 then
5784 -- The object directory does not exist, report an error if
5785 -- the project is not externally built.
5786
5787 Err_Vars.Error_Msg_File_1 :=
5788 File_Name_Type (Object_Dir.Value);
5789 Error_Msg
5790 (Project, In_Tree,
5791 "object directory { not found",
5792 Project.Location);
5793 end if;
5794 end if;
5795
5796 elsif Project.Object_Directory /= No_Path_Information
5797 and then Subdirs /= null
5798 then
5799 Name_Len := 1;
5800 Name_Buffer (1) := '.';
5801 Locate_Directory
5802 (Project,
5803 In_Tree,
5804 Name_Find,
5805 Path => Project.Object_Directory,
5806 Create => "object",
5807 Dir_Exists => Dir_Exists,
5808 Location => Object_Dir.Location,
5809 Externally_Built => Project.Externally_Built);
5810 end if;
5811
5812 if Current_Verbosity = High then
5813 if Project.Object_Directory = No_Path_Information then
5814 Write_Line ("No object directory");
5815 else
5816 Write_Attr
5817 ("Object directory",
5818 Get_Name_String (Project.Object_Directory.Display_Name));
5819 end if;
5820 end if;
5821
5822 -- Check the exec directory
5823
5824 -- We set the object directory to its default
5825
5826 Project.Exec_Directory := Project.Object_Directory;
5827
5828 if Exec_Dir.Value /= Empty_String then
5829 Get_Name_String (Exec_Dir.Value);
5830
5831 if Name_Len = 0 then
5832 Error_Msg
5833 (Project, In_Tree,
5834 "Exec_Dir cannot be empty",
5835 Exec_Dir.Location);
5836
5837 else
5838 -- We check that the specified exec directory does exist
5839
5840 Locate_Directory
5841 (Project,
5842 In_Tree,
5843 File_Name_Type (Exec_Dir.Value),
5844 Path => Project.Exec_Directory,
5845 Dir_Exists => Dir_Exists,
5846 Create => "exec",
5847 Location => Exec_Dir.Location,
5848 Externally_Built => Project.Externally_Built);
5849
5850 if not Dir_Exists then
5851 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5852 Error_Msg
5853 (Project, In_Tree,
5854 "exec directory { not found",
5855 Project.Location);
5856 end if;
5857 end if;
5858 end if;
5859
5860 if Current_Verbosity = High then
5861 if Project.Exec_Directory = No_Path_Information then
5862 Write_Line ("No exec directory");
5863 else
5864 Write_Str ("Exec directory: """);
5865 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5866 Write_Line ("""");
5867 end if;
5868 end if;
5869
5870 -- Look for the source directories
5871
5872 if Current_Verbosity = High then
5873 Write_Line ("Starting to look for source directories");
5874 end if;
5875
5876 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5877
5878 if (not Source_Files.Default) and then
5879 Source_Files.Values = Nil_String
5880 then
5881 Project.Source_Dirs := Nil_String;
5882
5883 if Project.Qualifier = Standard then
5884 Error_Msg
5885 (Project,
5886 In_Tree,
5887 "a standard project cannot have no sources",
5888 Source_Files.Location);
5889 end if;
5890
5891 elsif Source_Dirs.Default then
5892
5893 -- No Source_Dirs specified: the single source directory is the one
5894 -- containing the project file
5895
5896 String_Element_Table.Append (In_Tree.String_Elements,
5897 (Value => Name_Id (Project.Directory.Name),
5898 Display_Value => Name_Id (Project.Directory.Display_Name),
5899 Location => No_Location,
5900 Flag => False,
5901 Next => Nil_String,
5902 Index => 0));
5903 Project.Source_Dirs := String_Element_Table.Last
5904 (In_Tree.String_Elements);
5905
5906 if Current_Verbosity = High then
5907 Write_Attr
5908 ("Default source directory",
5909 Get_Name_String (Project.Directory.Display_Name));
5910 end if;
5911
5912 elsif Source_Dirs.Values = Nil_String then
5913 if Project.Qualifier = Standard then
5914 Error_Msg
5915 (Project,
5916 In_Tree,
5917 "a standard project cannot have no source directories",
5918 Source_Dirs.Location);
5919 end if;
5920
5921 Project.Source_Dirs := Nil_String;
5922
5923 else
5924 declare
5925 Source_Dir : String_List_Id;
5926 Element : String_Element;
5927
5928 begin
5929 -- Process the source directories for each element of the list
5930
5931 Source_Dir := Source_Dirs.Values;
5932 while Source_Dir /= Nil_String loop
5933 Element := In_Tree.String_Elements.Table (Source_Dir);
5934 Find_Source_Dirs
5935 (File_Name_Type (Element.Value), Element.Location);
5936 Source_Dir := Element.Next;
5937 end loop;
5938 end;
5939 end if;
5940
5941 if not Excluded_Source_Dirs.Default
5942 and then Excluded_Source_Dirs.Values /= Nil_String
5943 then
5944 declare
5945 Source_Dir : String_List_Id;
5946 Element : String_Element;
5947
5948 begin
5949 -- Process the source directories for each element of the list
5950
5951 Source_Dir := Excluded_Source_Dirs.Values;
5952 while Source_Dir /= Nil_String loop
5953 Element := In_Tree.String_Elements.Table (Source_Dir);
5954 Find_Source_Dirs
5955 (File_Name_Type (Element.Value),
5956 Element.Location,
5957 Removed => True);
5958 Source_Dir := Element.Next;
5959 end loop;
5960 end;
5961 end if;
5962
5963 if Current_Verbosity = High then
5964 Write_Line ("Putting source directories in canonical cases");
5965 end if;
5966
5967 declare
5968 Current : String_List_Id := Project.Source_Dirs;
5969 Element : String_Element;
5970
5971 begin
5972 while Current /= Nil_String loop
5973 Element := In_Tree.String_Elements.Table (Current);
5974 if Element.Value /= No_Name then
5975 Element.Value :=
5976 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5977 In_Tree.String_Elements.Table (Current) := Element;
5978 end if;
5979
5980 Current := Element.Next;
5981 end loop;
5982 end;
5983 end Get_Directories;
5984
5985 ---------------
5986 -- Get_Mains --
5987 ---------------
5988
5989 procedure Get_Mains
5990 (Project : Project_Id;
5991 In_Tree : Project_Tree_Ref)
5992 is
5993 Mains : constant Variable_Value :=
5994 Prj.Util.Value_Of (Name_Main, Project.Decl.Attributes, In_Tree);
5995 List : String_List_Id;
5996 Elem : String_Element;
5997
5998 begin
5999 Project.Mains := Mains.Values;
6000
6001 -- If no Mains were specified, and if we are an extending project,
6002 -- inherit the Mains from the project we are extending.
6003
6004 if Mains.Default then
6005 if not Project.Library and then Project.Extends /= No_Project then
6006 Project.Mains := Project.Extends.Mains;
6007 end if;
6008
6009 -- In a library project file, Main cannot be specified
6010
6011 elsif Project.Library then
6012 Error_Msg
6013 (Project, In_Tree,
6014 "a library project file cannot have Main specified",
6015 Mains.Location);
6016
6017 else
6018 List := Mains.Values;
6019 while List /= Nil_String loop
6020 Elem := In_Tree.String_Elements.Table (List);
6021
6022 if Length_Of_Name (Elem.Value) = 0 then
6023 Error_Msg
6024 (Project, In_Tree,
6025 "?a main cannot have an empty name",
6026 Elem.Location);
6027 exit;
6028 end if;
6029
6030 List := Elem.Next;
6031 end loop;
6032 end if;
6033 end Get_Mains;
6034
6035 ---------------------------
6036 -- Get_Sources_From_File --
6037 ---------------------------
6038
6039 procedure Get_Sources_From_File
6040 (Path : String;
6041 Location : Source_Ptr;
6042 Project : Project_Id;
6043 In_Tree : Project_Tree_Ref)
6044 is
6045 File : Prj.Util.Text_File;
6046 Line : String (1 .. 250);
6047 Last : Natural;
6048 Source_Name : File_Name_Type;
6049 Name_Loc : Name_Location;
6050
6051 begin
6052 if Get_Mode = Ada_Only then
6053 Source_Names.Reset;
6054 end if;
6055
6056 if Current_Verbosity = High then
6057 Write_Str ("Opening """);
6058 Write_Str (Path);
6059 Write_Line (""".");
6060 end if;
6061
6062 -- Open the file
6063
6064 Prj.Util.Open (File, Path);
6065
6066 if not Prj.Util.Is_Valid (File) then
6067 Error_Msg (Project, In_Tree, "file does not exist", Location);
6068
6069 else
6070 -- Read the lines one by one
6071
6072 while not Prj.Util.End_Of_File (File) loop
6073 Prj.Util.Get_Line (File, Line, Last);
6074
6075 -- A non empty, non comment line should contain a file name
6076
6077 if Last /= 0
6078 and then (Last = 1 or else Line (1 .. 2) /= "--")
6079 then
6080 Name_Len := Last;
6081 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6082 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6083 Source_Name := Name_Find;
6084
6085 -- Check that there is no directory information
6086
6087 for J in 1 .. Last loop
6088 if Line (J) = '/' or else Line (J) = Directory_Separator then
6089 Error_Msg_File_1 := Source_Name;
6090 Error_Msg
6091 (Project,
6092 In_Tree,
6093 "file name cannot include directory information ({)",
6094 Location);
6095 exit;
6096 end if;
6097 end loop;
6098
6099 Name_Loc := Source_Names.Get (Source_Name);
6100
6101 if Name_Loc = No_Name_Location then
6102 Name_Loc :=
6103 (Name => Source_Name,
6104 Location => Location,
6105 Source => No_Source,
6106 Except => False,
6107 Found => False);
6108 end if;
6109
6110 Source_Names.Set (Source_Name, Name_Loc);
6111 end if;
6112 end loop;
6113
6114 Prj.Util.Close (File);
6115
6116 end if;
6117 end Get_Sources_From_File;
6118
6119 -----------------------
6120 -- Compute_Unit_Name --
6121 -----------------------
6122
6123 procedure Compute_Unit_Name
6124 (File_Name : File_Name_Type;
6125 Dot_Replacement : File_Name_Type;
6126 Separate_Suffix : File_Name_Type;
6127 Body_Suffix : File_Name_Type;
6128 Spec_Suffix : File_Name_Type;
6129 Casing : Casing_Type;
6130 Kind : out Source_Kind;
6131 Unit : out Name_Id;
6132 In_Tree : Project_Tree_Ref)
6133 is
6134 Filename : constant String := Get_Name_String (File_Name);
6135 Last : Integer := Filename'Last;
6136 Sep_Len : constant Integer :=
6137 Integer (Length_Of_Name (Separate_Suffix));
6138 Body_Len : constant Integer :=
6139 Integer (Length_Of_Name (Body_Suffix));
6140 Spec_Len : constant Integer :=
6141 Integer (Length_Of_Name (Spec_Suffix));
6142
6143 Standard_GNAT : constant Boolean :=
6144 Spec_Suffix = Default_Ada_Spec_Suffix
6145 and then
6146 Body_Suffix = Default_Ada_Body_Suffix;
6147
6148 Unit_Except : Unit_Exception;
6149 Masked : Boolean := False;
6150 begin
6151 Unit := No_Name;
6152 Kind := Spec;
6153
6154 if Dot_Replacement = No_File then
6155 if Current_Verbosity = High then
6156 Write_Line (" No dot_replacement specified");
6157 end if;
6158 return;
6159 end if;
6160
6161 -- Choose the longest suffix that matches. If there are several matches,
6162 -- give priority to specs, then bodies, then separates.
6163
6164 if Separate_Suffix /= Body_Suffix
6165 and then Suffix_Matches (Filename, Separate_Suffix)
6166 then
6167 Last := Filename'Last - Sep_Len;
6168 Kind := Sep;
6169 end if;
6170
6171 if Filename'Last - Body_Len <= Last
6172 and then Suffix_Matches (Filename, Body_Suffix)
6173 then
6174 Last := Natural'Min (Last, Filename'Last - Body_Len);
6175 Kind := Impl;
6176 end if;
6177
6178 if Filename'Last - Spec_Len <= Last
6179 and then Suffix_Matches (Filename, Spec_Suffix)
6180 then
6181 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6182 Kind := Spec;
6183 end if;
6184
6185 if Last = Filename'Last then
6186 if Current_Verbosity = High then
6187 Write_Line (" No matching suffix");
6188 end if;
6189 return;
6190 end if;
6191
6192 -- Check that the casing matches
6193
6194 if File_Names_Case_Sensitive then
6195 case Casing is
6196 when All_Lower_Case =>
6197 for J in Filename'First .. Last loop
6198 if Is_Letter (Filename (J))
6199 and then not Is_Lower (Filename (J))
6200 then
6201 if Current_Verbosity = High then
6202 Write_Line (" Invalid casing");
6203 end if;
6204 return;
6205 end if;
6206 end loop;
6207
6208 when All_Upper_Case =>
6209 for J in Filename'First .. Last loop
6210 if Is_Letter (Filename (J))
6211 and then not Is_Upper (Filename (J))
6212 then
6213 if Current_Verbosity = High then
6214 Write_Line (" Invalid casing");
6215 end if;
6216 return;
6217 end if;
6218 end loop;
6219
6220 when Mixed_Case | Unknown =>
6221 null;
6222 end case;
6223 end if;
6224
6225 -- If Dot_Replacement is not a single dot, then there should not
6226 -- be any dot in the name.
6227
6228 declare
6229 Dot_Repl : constant String := Get_Name_String (Dot_Replacement);
6230
6231 begin
6232 if Dot_Repl /= "." then
6233 for Index in Filename'First .. Last loop
6234 if Filename (Index) = '.' then
6235 if Current_Verbosity = High then
6236 Write_Line (" Invalid name, contains dot");
6237 end if;
6238 return;
6239 end if;
6240 end loop;
6241
6242 Replace_Into_Name_Buffer
6243 (Filename (Filename'First .. Last), Dot_Repl, '.');
6244 else
6245 Name_Len := Last - Filename'First + 1;
6246 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6247 Fixed.Translate
6248 (Source => Name_Buffer (1 .. Name_Len),
6249 Mapping => Lower_Case_Map);
6250 end if;
6251 end;
6252
6253 -- In the standard GNAT naming scheme, check for special cases: children
6254 -- or separates of A, G, I or S, and run time sources.
6255
6256 if Standard_GNAT and then Name_Len >= 3 then
6257 declare
6258 S1 : constant Character := Name_Buffer (1);
6259 S2 : constant Character := Name_Buffer (2);
6260 S3 : constant Character := Name_Buffer (3);
6261
6262 begin
6263 if S1 = 'a'
6264 or else S1 = 'g'
6265 or else S1 = 'i'
6266 or else S1 = 's'
6267 then
6268 -- Children or separates of packages A, G, I or S. These names
6269 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6270 -- versions (x__... and x~...) are allowed in all platforms,
6271 -- because it is not possible to know the platform before
6272 -- processing of the project files.
6273
6274 if S2 = '_' and then S3 = '_' then
6275 Name_Buffer (2) := '.';
6276 Name_Buffer (3 .. Name_Len - 1) :=
6277 Name_Buffer (4 .. Name_Len);
6278 Name_Len := Name_Len - 1;
6279
6280 elsif S2 = '~' then
6281 Name_Buffer (2) := '.';
6282
6283 elsif S2 = '.' then
6284
6285 -- If it is potentially a run time source, disable filling
6286 -- of the mapping file to avoid warnings.
6287
6288 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6289 end if;
6290 end if;
6291 end;
6292 end if;
6293
6294 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6295 -- that this is a valid unit name
6296
6297 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6298
6299 -- If there is a naming exception for the same unit, the file is not
6300 -- a source for the unit. Currently, this only applies in multi_lang
6301 -- mode, since Unit_Exceptions is no set in ada_only mode.
6302
6303 if Unit /= No_Name then
6304 Unit_Except := Unit_Exceptions.Get (Unit);
6305
6306 if Kind = Spec then
6307 Masked := Unit_Except.Spec /= No_File
6308 and then
6309 Unit_Except.Spec /= File_Name;
6310 else
6311 Masked := Unit_Except.Impl /= No_File
6312 and then
6313 Unit_Except.Impl /= File_Name;
6314 end if;
6315
6316 if Masked then
6317 if Current_Verbosity = High then
6318 Write_Str (" """ & Filename & """ contains the ");
6319
6320 if Kind = Spec then
6321 Write_Str ("spec of a unit found in """);
6322 Write_Str (Get_Name_String (Unit_Except.Spec));
6323 else
6324 Write_Str ("body of a unit found in """);
6325 Write_Str (Get_Name_String (Unit_Except.Impl));
6326 end if;
6327
6328 Write_Line (""" (ignored)");
6329 end if;
6330
6331 Unit := No_Name;
6332 end if;
6333 end if;
6334
6335 if Unit /= No_Name
6336 and then Current_Verbosity = High
6337 then
6338 case Kind is
6339 when Spec => Write_Str (" spec of ");
6340 when Impl => Write_Str (" body of ");
6341 when Sep => Write_Str (" sep of ");
6342 end case;
6343
6344 Write_Line (Get_Name_String (Unit));
6345 end if;
6346 end Compute_Unit_Name;
6347
6348 --------------
6349 -- Get_Unit --
6350 --------------
6351
6352 procedure Get_Unit
6353 (In_Tree : Project_Tree_Ref;
6354 Canonical_File_Name : File_Name_Type;
6355 Naming : Naming_Data;
6356 Exception_Id : out Ada_Naming_Exception_Id;
6357 Unit_Name : out Name_Id;
6358 Unit_Kind : out Spec_Or_Body)
6359 is
6360 Info_Id : Ada_Naming_Exception_Id :=
6361 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6362 VMS_Name : File_Name_Type;
6363 Kind : Source_Kind;
6364
6365 begin
6366 if Info_Id = No_Ada_Naming_Exception
6367 and then Hostparm.OpenVMS
6368 then
6369 VMS_Name := Canonical_File_Name;
6370 Get_Name_String (VMS_Name);
6371
6372 if Name_Buffer (Name_Len) = '.' then
6373 Name_Len := Name_Len - 1;
6374 VMS_Name := Name_Find;
6375 end if;
6376
6377 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6378 end if;
6379
6380 if Info_Id /= No_Ada_Naming_Exception then
6381 Exception_Id := Info_Id;
6382 Unit_Name := No_Name;
6383 Unit_Kind := Spec;
6384
6385 else
6386 Exception_Id := No_Ada_Naming_Exception;
6387 Compute_Unit_Name
6388 (File_Name => Canonical_File_Name,
6389 Dot_Replacement => Naming.Dot_Replacement,
6390 Separate_Suffix => Naming.Separate_Suffix,
6391 Body_Suffix => Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6392 Spec_Suffix => Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6393 Casing => Naming.Casing,
6394 Kind => Kind,
6395 Unit => Unit_Name,
6396 In_Tree => In_Tree);
6397
6398 case Kind is
6399 when Spec => Unit_Kind := Spec;
6400 when Impl | Sep => Unit_Kind := Impl;
6401 end case;
6402 end if;
6403 end Get_Unit;
6404
6405 ----------
6406 -- Hash --
6407 ----------
6408
6409 function Hash (Unit : Unit_Info) return Header_Num is
6410 begin
6411 return Header_Num (Unit.Unit mod 2048);
6412 end Hash;
6413
6414 -----------------------
6415 -- Is_Illegal_Suffix --
6416 -----------------------
6417
6418 function Is_Illegal_Suffix
6419 (Suffix : File_Name_Type;
6420 Dot_Replacement : File_Name_Type) return Boolean
6421 is
6422 Suffix_Str : constant String := Get_Name_String (Suffix);
6423
6424 begin
6425 if Suffix_Str'Length = 0 then
6426 return False;
6427 elsif Index (Suffix_Str, ".") = 0 then
6428 return True;
6429 end if;
6430
6431 -- Case of dot replacement is a single dot, and first character of
6432 -- suffix is also a dot.
6433
6434 if Get_Name_String (Dot_Replacement) = "."
6435 and then Suffix_Str (Suffix_Str'First) = '.'
6436 then
6437 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6438
6439 -- Case of following dot
6440
6441 if Suffix_Str (Index) = '.' then
6442
6443 -- It is illegal to have a letter following the initial dot
6444
6445 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6446 end if;
6447 end loop;
6448 end if;
6449
6450 return False;
6451 end Is_Illegal_Suffix;
6452
6453 ----------------------
6454 -- Locate_Directory --
6455 ----------------------
6456
6457 procedure Locate_Directory
6458 (Project : Project_Id;
6459 In_Tree : Project_Tree_Ref;
6460 Name : File_Name_Type;
6461 Path : out Path_Information;
6462 Dir_Exists : out Boolean;
6463 Create : String := "";
6464 Location : Source_Ptr := No_Location;
6465 Must_Exist : Boolean := True;
6466 Externally_Built : Boolean := False)
6467 is
6468 Parent : constant Path_Name_Type :=
6469 Project.Directory.Display_Name;
6470 The_Parent : constant String :=
6471 Get_Name_String (Parent) & Directory_Separator;
6472 The_Parent_Last : constant Natural :=
6473 Compute_Directory_Last (The_Parent);
6474 Full_Name : File_Name_Type;
6475 The_Name : File_Name_Type;
6476
6477 begin
6478 Get_Name_String (Name);
6479
6480 -- Add Subdirs.all if it is a directory that may be created and
6481 -- Subdirs is not null;
6482
6483 if Create /= "" and then Subdirs /= null then
6484 if Name_Buffer (Name_Len) /= Directory_Separator then
6485 Add_Char_To_Name_Buffer (Directory_Separator);
6486 end if;
6487
6488 Add_Str_To_Name_Buffer (Subdirs.all);
6489 end if;
6490
6491 -- Convert '/' to directory separator (for Windows)
6492
6493 for J in 1 .. Name_Len loop
6494 if Name_Buffer (J) = '/' then
6495 Name_Buffer (J) := Directory_Separator;
6496 end if;
6497 end loop;
6498
6499 The_Name := Name_Find;
6500
6501 if Current_Verbosity = High then
6502 Write_Str ("Locate_Directory (""");
6503 Write_Str (Get_Name_String (The_Name));
6504 Write_Str (""", """);
6505 Write_Str (The_Parent);
6506 Write_Line (""")");
6507 end if;
6508
6509 Path := No_Path_Information;
6510 Dir_Exists := False;
6511
6512 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6513 Full_Name := The_Name;
6514
6515 else
6516 Name_Len := 0;
6517 Add_Str_To_Name_Buffer
6518 (The_Parent (The_Parent'First .. The_Parent_Last));
6519 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6520 Full_Name := Name_Find;
6521 end if;
6522
6523 declare
6524 Full_Path_Name : String_Access :=
6525 new String'(Get_Name_String (Full_Name));
6526
6527 begin
6528 if (Setup_Projects or else Subdirs /= null)
6529 and then Create'Length > 0
6530 then
6531 if not Is_Directory (Full_Path_Name.all) then
6532
6533 -- If project is externally built, do not create a subdir,
6534 -- use the specified directory, without the subdir.
6535
6536 if Externally_Built then
6537 if Is_Absolute_Path (Get_Name_String (Name)) then
6538 Get_Name_String (Name);
6539
6540 else
6541 Name_Len := 0;
6542 Add_Str_To_Name_Buffer
6543 (The_Parent (The_Parent'First .. The_Parent_Last));
6544 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6545 end if;
6546
6547 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6548
6549 else
6550 begin
6551 Create_Path (Full_Path_Name.all);
6552
6553 if not Quiet_Output then
6554 Write_Str (Create);
6555 Write_Str (" directory """);
6556 Write_Str (Full_Path_Name.all);
6557 Write_Str (""" created for project ");
6558 Write_Line (Get_Name_String (Project.Name));
6559 end if;
6560
6561 exception
6562 when Use_Error =>
6563 Error_Msg
6564 (Project, In_Tree,
6565 "could not create " & Create &
6566 " directory " & Full_Path_Name.all,
6567 Location);
6568 end;
6569 end if;
6570 end if;
6571 end if;
6572
6573 Dir_Exists := Is_Directory (Full_Path_Name.all);
6574
6575 if not Must_Exist or else Dir_Exists then
6576 declare
6577 Normed : constant String :=
6578 Normalize_Pathname
6579 (Full_Path_Name.all,
6580 Directory =>
6581 The_Parent (The_Parent'First .. The_Parent_Last),
6582 Resolve_Links => False,
6583 Case_Sensitive => True);
6584
6585 Canonical_Path : constant String :=
6586 Normalize_Pathname
6587 (Normed,
6588 Directory =>
6589 The_Parent
6590 (The_Parent'First .. The_Parent_Last),
6591 Resolve_Links =>
6592 Opt.Follow_Links_For_Dirs,
6593 Case_Sensitive => False);
6594
6595 begin
6596 Name_Len := Normed'Length;
6597 Name_Buffer (1 .. Name_Len) := Normed;
6598 Path.Display_Name := Name_Find;
6599
6600 Name_Len := Canonical_Path'Length;
6601 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6602 Path.Name := Name_Find;
6603 end;
6604 end if;
6605
6606 Free (Full_Path_Name);
6607 end;
6608 end Locate_Directory;
6609
6610 ---------------------------
6611 -- Find_Excluded_Sources --
6612 ---------------------------
6613
6614 procedure Find_Excluded_Sources
6615 (Project : Project_Id;
6616 In_Tree : Project_Tree_Ref)
6617 is
6618 Excluded_Source_List_File : constant Variable_Value :=
6619 Util.Value_Of
6620 (Name_Excluded_Source_List_File,
6621 Project.Decl.Attributes,
6622 In_Tree);
6623
6624 Excluded_Sources : Variable_Value := Util.Value_Of
6625 (Name_Excluded_Source_Files,
6626 Project.Decl.Attributes,
6627 In_Tree);
6628
6629 Current : String_List_Id;
6630 Element : String_Element;
6631 Location : Source_Ptr;
6632 Name : File_Name_Type;
6633 File : Prj.Util.Text_File;
6634 Line : String (1 .. 300);
6635 Last : Natural;
6636 Locally_Removed : Boolean := False;
6637
6638 begin
6639 -- If Excluded_Source_Files is not declared, check
6640 -- Locally_Removed_Files.
6641
6642 if Excluded_Sources.Default then
6643 Locally_Removed := True;
6644 Excluded_Sources :=
6645 Util.Value_Of
6646 (Name_Locally_Removed_Files, Project.Decl.Attributes, In_Tree);
6647 end if;
6648
6649 Excluded_Sources_Htable.Reset;
6650
6651 -- If there are excluded sources, put them in the table
6652
6653 if not Excluded_Sources.Default then
6654 if not Excluded_Source_List_File.Default then
6655 if Locally_Removed then
6656 Error_Msg
6657 (Project, In_Tree,
6658 "?both attributes Locally_Removed_Files and " &
6659 "Excluded_Source_List_File are present",
6660 Excluded_Source_List_File.Location);
6661 else
6662 Error_Msg
6663 (Project, In_Tree,
6664 "?both attributes Excluded_Source_Files and " &
6665 "Excluded_Source_List_File are present",
6666 Excluded_Source_List_File.Location);
6667 end if;
6668 end if;
6669
6670 Current := Excluded_Sources.Values;
6671 while Current /= Nil_String loop
6672 Element := In_Tree.String_Elements.Table (Current);
6673 Name := Canonical_Case_File_Name (Element.Value);
6674
6675 -- If the element has no location, then use the location of
6676 -- Excluded_Sources to report possible errors.
6677
6678 if Element.Location = No_Location then
6679 Location := Excluded_Sources.Location;
6680 else
6681 Location := Element.Location;
6682 end if;
6683
6684 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6685 Current := Element.Next;
6686 end loop;
6687
6688 elsif not Excluded_Source_List_File.Default then
6689 Location := Excluded_Source_List_File.Location;
6690
6691 declare
6692 Source_File_Path_Name : constant String :=
6693 Path_Name_Of
6694 (File_Name_Type
6695 (Excluded_Source_List_File.Value),
6696 Project.Directory.Name);
6697
6698 begin
6699 if Source_File_Path_Name'Length = 0 then
6700 Err_Vars.Error_Msg_File_1 :=
6701 File_Name_Type (Excluded_Source_List_File.Value);
6702 Error_Msg
6703 (Project, In_Tree,
6704 "file with excluded sources { does not exist",
6705 Excluded_Source_List_File.Location);
6706
6707 else
6708 -- Open the file
6709
6710 Prj.Util.Open (File, Source_File_Path_Name);
6711
6712 if not Prj.Util.Is_Valid (File) then
6713 Error_Msg
6714 (Project, In_Tree, "file does not exist", Location);
6715 else
6716 -- Read the lines one by one
6717
6718 while not Prj.Util.End_Of_File (File) loop
6719 Prj.Util.Get_Line (File, Line, Last);
6720
6721 -- Non empty, non comment line should contain a file name
6722
6723 if Last /= 0
6724 and then (Last = 1 or else Line (1 .. 2) /= "--")
6725 then
6726 Name_Len := Last;
6727 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6728 Canonical_Case_File_Name
6729 (Name_Buffer (1 .. Name_Len));
6730 Name := Name_Find;
6731
6732 -- Check that there is no directory information
6733
6734 for J in 1 .. Last loop
6735 if Line (J) = '/'
6736 or else Line (J) = Directory_Separator
6737 then
6738 Error_Msg_File_1 := Name;
6739 Error_Msg
6740 (Project,
6741 In_Tree,
6742 "file name cannot include " &
6743 "directory information ({)",
6744 Location);
6745 exit;
6746 end if;
6747 end loop;
6748
6749 Excluded_Sources_Htable.Set
6750 (Name, (Name, False, Location));
6751 end if;
6752 end loop;
6753
6754 Prj.Util.Close (File);
6755 end if;
6756 end if;
6757 end;
6758 end if;
6759 end Find_Excluded_Sources;
6760
6761 ------------------
6762 -- Find_Sources --
6763 ------------------
6764
6765 procedure Find_Sources
6766 (Project : Project_Id;
6767 In_Tree : Project_Tree_Ref;
6768 Proc_Data : in out Processing_Data;
6769 Allow_Duplicate_Basenames : Boolean)
6770 is
6771 Sources : constant Variable_Value :=
6772 Util.Value_Of
6773 (Name_Source_Files,
6774 Project.Decl.Attributes,
6775 In_Tree);
6776 Source_List_File : constant Variable_Value :=
6777 Util.Value_Of
6778 (Name_Source_List_File,
6779 Project.Decl.Attributes,
6780 In_Tree);
6781 Name_Loc : Name_Location;
6782
6783 Has_Explicit_Sources : Boolean;
6784
6785 begin
6786 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6787 pragma Assert
6788 (Source_List_File.Kind = Single,
6789 "Source_List_File is not a single string");
6790
6791 -- If the user has specified a Source_Files attribute
6792
6793 if not Sources.Default then
6794 if not Source_List_File.Default then
6795 Error_Msg
6796 (Project, In_Tree,
6797 "?both attributes source_files and " &
6798 "source_list_file are present",
6799 Source_List_File.Location);
6800 end if;
6801
6802 -- Sources is a list of file names
6803
6804 declare
6805 Current : String_List_Id := Sources.Values;
6806 Element : String_Element;
6807 Location : Source_Ptr;
6808 Name : File_Name_Type;
6809
6810 begin
6811 if Get_Mode = Multi_Language then
6812 if Current = Nil_String then
6813 Project.Languages := No_Language_Index;
6814
6815 -- This project contains no source. For projects that don't
6816 -- extend other projects, this also means that there is no
6817 -- need for an object directory, if not specified.
6818
6819 if Project.Extends = No_Project
6820 and then Project.Object_Directory = Project.Directory
6821 then
6822 Project.Object_Directory := No_Path_Information;
6823 end if;
6824 end if;
6825 end if;
6826
6827 while Current /= Nil_String loop
6828 Element := In_Tree.String_Elements.Table (Current);
6829 Name := Canonical_Case_File_Name (Element.Value);
6830 Get_Name_String (Element.Value);
6831
6832 -- If the element has no location, then use the location of
6833 -- Sources to report possible errors.
6834
6835 if Element.Location = No_Location then
6836 Location := Sources.Location;
6837 else
6838 Location := Element.Location;
6839 end if;
6840
6841 -- Check that there is no directory information
6842
6843 for J in 1 .. Name_Len loop
6844 if Name_Buffer (J) = '/'
6845 or else Name_Buffer (J) = Directory_Separator
6846 then
6847 Error_Msg_File_1 := Name;
6848 Error_Msg
6849 (Project,
6850 In_Tree,
6851 "file name cannot include directory " &
6852 "information ({)",
6853 Location);
6854 exit;
6855 end if;
6856 end loop;
6857
6858 -- In Multi_Language mode, check whether the file is already
6859 -- there: the same file name may be in the list. If the source
6860 -- is missing, the error will be on the first mention of the
6861 -- source file name.
6862
6863 case Get_Mode is
6864 when Ada_Only =>
6865 Name_Loc := No_Name_Location;
6866 when Multi_Language =>
6867 Name_Loc := Source_Names.Get (Name);
6868 end case;
6869
6870 if Name_Loc = No_Name_Location then
6871 Name_Loc :=
6872 (Name => Name,
6873 Location => Location,
6874 Source => No_Source,
6875 Except => False,
6876 Found => False);
6877 Source_Names.Set (Name, Name_Loc);
6878 end if;
6879
6880 Current := Element.Next;
6881 end loop;
6882
6883 Has_Explicit_Sources := True;
6884 end;
6885
6886 -- If we have no Source_Files attribute, check the Source_List_File
6887 -- attribute.
6888
6889 elsif not Source_List_File.Default then
6890
6891 -- Source_List_File is the name of the file that contains the source
6892 -- file names.
6893
6894 declare
6895 Source_File_Path_Name : constant String :=
6896 Path_Name_Of
6897 (File_Name_Type (Source_List_File.Value),
6898 Project.Directory.Name);
6899
6900 begin
6901 Has_Explicit_Sources := True;
6902
6903 if Source_File_Path_Name'Length = 0 then
6904 Err_Vars.Error_Msg_File_1 :=
6905 File_Name_Type (Source_List_File.Value);
6906 Error_Msg
6907 (Project, In_Tree,
6908 "file with sources { does not exist",
6909 Source_List_File.Location);
6910
6911 else
6912 Get_Sources_From_File
6913 (Source_File_Path_Name, Source_List_File.Location,
6914 Project, In_Tree);
6915 end if;
6916 end;
6917
6918 else
6919 -- Neither Source_Files nor Source_List_File has been specified. Find
6920 -- all the files that satisfy the naming scheme in all the source
6921 -- directories.
6922
6923 Has_Explicit_Sources := False;
6924 end if;
6925
6926 if Get_Mode = Ada_Only then
6927 Find_Ada_Sources
6928 (Project, In_Tree,
6929 Explicit_Sources_Only => Has_Explicit_Sources,
6930 Proc_Data => Proc_Data);
6931
6932 else
6933 Search_Directories
6934 (Project, In_Tree,
6935 For_All_Sources =>
6936 Sources.Default and then Source_List_File.Default,
6937 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames);
6938 end if;
6939
6940 -- Check if all exceptions have been found. For Ada, it is an error if
6941 -- an exception is not found. For other language, the source is simply
6942 -- removed.
6943
6944 declare
6945 Source : Source_Id;
6946 Iter : Source_Iterator;
6947
6948 begin
6949 Iter := For_Each_Source (In_Tree, Project);
6950 loop
6951 Source := Prj.Element (Iter);
6952 exit when Source = No_Source;
6953
6954 if Source.Naming_Exception
6955 and then Source.Path = No_Path_Information
6956 then
6957 if Source.Unit /= No_Unit_Index then
6958 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6959 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6960 Error_Msg
6961 (Project, In_Tree,
6962 "source file %% for unit %% not found",
6963 No_Location);
6964 end if;
6965
6966 Remove_Source (Source, No_Source);
6967 end if;
6968
6969 Next (Iter);
6970 end loop;
6971 end;
6972
6973 -- It is an error if a source file name in a source list or in a source
6974 -- list file is not found.
6975
6976 if Has_Explicit_Sources then
6977 declare
6978 NL : Name_Location;
6979 First_Error : Boolean;
6980
6981 begin
6982 NL := Source_Names.Get_First;
6983 First_Error := True;
6984 while NL /= No_Name_Location loop
6985 if not NL.Found then
6986 Err_Vars.Error_Msg_File_1 := NL.Name;
6987
6988 if First_Error then
6989 Error_Msg
6990 (Project, In_Tree,
6991 "source file { not found",
6992 NL.Location);
6993 First_Error := False;
6994
6995 else
6996 Error_Msg
6997 (Project, In_Tree,
6998 "\source file { not found",
6999 NL.Location);
7000 end if;
7001 end if;
7002
7003 NL := Source_Names.Get_Next;
7004 end loop;
7005 end;
7006 end if;
7007
7008 if Get_Mode = Ada_Only
7009 and then Project.Extends = No_Project
7010 then
7011 -- We should have found at least one source, if not report an error
7012
7013 if not Has_Ada_Sources (Project) then
7014 Report_No_Sources
7015 (Project, "Ada", In_Tree, Source_List_File.Location);
7016 end if;
7017 end if;
7018 end Find_Sources;
7019
7020 ----------------
7021 -- Initialize --
7022 ----------------
7023
7024 procedure Initialize (Proc_Data : in out Processing_Data) is
7025 begin
7026 Files_Htable.Reset (Proc_Data.Units);
7027 end Initialize;
7028
7029 ----------
7030 -- Free --
7031 ----------
7032
7033 procedure Free (Proc_Data : in out Processing_Data) is
7034 begin
7035 Files_Htable.Reset (Proc_Data.Units);
7036 end Free;
7037
7038 ----------------------
7039 -- Find_Ada_Sources --
7040 ----------------------
7041
7042 procedure Find_Ada_Sources
7043 (Project : Project_Id;
7044 In_Tree : Project_Tree_Ref;
7045 Explicit_Sources_Only : Boolean;
7046 Proc_Data : in out Processing_Data)
7047 is
7048 Source_Dir : String_List_Id;
7049 Element : String_Element;
7050 Dir : Dir_Type;
7051 Dir_Has_Source : Boolean := False;
7052 NL : Name_Location;
7053 Ada_Language : Language_Ptr;
7054
7055 begin
7056 if Current_Verbosity = High then
7057 Write_Line ("Looking for Ada sources:");
7058 end if;
7059
7060 Ada_Language := Project.Languages;
7061 while Ada_Language /= No_Language_Index
7062 and then Ada_Language.Name /= Name_Ada
7063 loop
7064 Ada_Language := Ada_Language.Next;
7065 end loop;
7066
7067 -- We look in all source directories for the file names in the hash
7068 -- table Source_Names.
7069
7070 Source_Dir := Project.Source_Dirs;
7071 while Source_Dir /= Nil_String loop
7072 Dir_Has_Source := False;
7073 Element := In_Tree.String_Elements.Table (Source_Dir);
7074
7075 declare
7076 Dir_Path : constant String :=
7077 Get_Name_String (Element.Display_Value) &
7078 Directory_Separator;
7079 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
7080
7081 begin
7082 if Current_Verbosity = High then
7083 Write_Line ("checking directory """ & Dir_Path & """");
7084 end if;
7085
7086 -- Look for all files in the current source directory
7087
7088 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
7089
7090 loop
7091 Read (Dir, Name_Buffer, Name_Len);
7092 exit when Name_Len = 0;
7093
7094 if Current_Verbosity = High then
7095 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7096 end if;
7097
7098 declare
7099 Name : constant File_Name_Type := Name_Find;
7100 Canonical_Name : File_Name_Type;
7101
7102 -- ??? We could probably optimize the following call: we
7103 -- need to resolve links only once for the directory itself,
7104 -- and then do a single call to readlink() for each file.
7105 -- Unfortunately that would require a change in
7106 -- Normalize_Pathname so that it has the option of not
7107 -- resolving links for its Directory parameter, only for
7108 -- Name.
7109
7110 Path : constant String :=
7111 Normalize_Pathname
7112 (Name => Name_Buffer (1 .. Name_Len),
7113 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7114 Resolve_Links => Opt.Follow_Links_For_Files,
7115 Case_Sensitive => True); -- no case folding
7116
7117 Path_Name : Path_Name_Type;
7118 To_Record : Boolean := False;
7119 Location : Source_Ptr;
7120
7121 begin
7122 -- If the file was listed in the explicit list of sources,
7123 -- mark it as such (since we'll need to report an error when
7124 -- an explicit source was not found)
7125
7126 if Explicit_Sources_Only then
7127 Canonical_Name :=
7128 Canonical_Case_File_Name (Name_Id (Name));
7129 NL := Source_Names.Get (Canonical_Name);
7130 To_Record := NL /= No_Name_Location and then not NL.Found;
7131
7132 if To_Record then
7133 NL.Found := True;
7134 Location := NL.Location;
7135 Source_Names.Set (Canonical_Name, NL);
7136 end if;
7137
7138 else
7139 To_Record := True;
7140 Location := No_Location;
7141 end if;
7142
7143 if To_Record then
7144 Name_Len := Path'Length;
7145 Name_Buffer (1 .. Name_Len) := Path;
7146 Path_Name := Name_Find;
7147
7148 if Current_Verbosity = High then
7149 Write_Line (" recording " & Get_Name_String (Name));
7150 end if;
7151
7152 -- Register the source if it is an Ada compilation unit
7153
7154 Record_Ada_Source
7155 (File_Name => Name,
7156 Path_Name => Path_Name,
7157 Project => Project,
7158 In_Tree => In_Tree,
7159 Proc_Data => Proc_Data,
7160 Ada_Language => Ada_Language,
7161 Location => Location,
7162 Source_Recorded => Dir_Has_Source);
7163 end if;
7164 end;
7165 end loop;
7166
7167 Close (Dir);
7168
7169 exception
7170 when others =>
7171 Close (Dir);
7172 raise;
7173 end;
7174
7175 if Dir_Has_Source then
7176 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7177 end if;
7178
7179 Source_Dir := Element.Next;
7180 end loop;
7181
7182 if Current_Verbosity = High then
7183 Write_Line ("End looking for sources");
7184 end if;
7185 end Find_Ada_Sources;
7186
7187 -------------------------------
7188 -- Check_File_Naming_Schemes --
7189 -------------------------------
7190
7191 procedure Check_File_Naming_Schemes
7192 (In_Tree : Project_Tree_Ref;
7193 Project : Project_Id;
7194 File_Name : File_Name_Type;
7195 Alternate_Languages : out Language_List;
7196 Language : out Language_Ptr;
7197 Display_Language_Name : out Name_Id;
7198 Unit : out Name_Id;
7199 Lang_Kind : out Language_Kind;
7200 Kind : out Source_Kind)
7201 is
7202 Filename : constant String := Get_Name_String (File_Name);
7203 Config : Language_Config;
7204 Tmp_Lang : Language_Ptr;
7205
7206 Header_File : Boolean := False;
7207 -- True if we found at least one language for which the file is a header
7208 -- In such a case, we search for all possible languages where this is
7209 -- also a header (C and C++ for instance), since the file might be used
7210 -- for several such languages.
7211
7212 procedure Check_File_Based_Lang;
7213 -- Does the naming scheme test for file-based languages. For those,
7214 -- there is no Unit. Just check if the file name has the implementation
7215 -- or, if it is specified, the template suffix of the language.
7216 --
7217 -- Returns True if the file belongs to the current language and we
7218 -- should stop searching for matching languages. Not that a given header
7219 -- file could belong to several languages (C and C++ for instance). Thus
7220 -- if we found a header we'll check whether it matches other languages.
7221
7222 ---------------------------
7223 -- Check_File_Based_Lang --
7224 ---------------------------
7225
7226 procedure Check_File_Based_Lang is
7227 begin
7228 if not Header_File
7229 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7230 then
7231 Unit := No_Name;
7232 Kind := Impl;
7233 Language := Tmp_Lang;
7234
7235 if Current_Verbosity = High then
7236 Write_Str (" implementation of language ");
7237 Write_Line (Get_Name_String (Display_Language_Name));
7238 end if;
7239
7240 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7241 if Current_Verbosity = High then
7242 Write_Str (" header of language ");
7243 Write_Line (Get_Name_String (Display_Language_Name));
7244 end if;
7245
7246 if Header_File then
7247 Alternate_Languages := new Language_List_Element'
7248 (Language => Language,
7249 Next => Alternate_Languages);
7250
7251 else
7252 Header_File := True;
7253 Kind := Spec;
7254 Unit := No_Name;
7255 Language := Tmp_Lang;
7256 end if;
7257 end if;
7258 end Check_File_Based_Lang;
7259
7260 -- Start of processing for Check_File_Naming_Schemes
7261
7262 begin
7263 Language := No_Language_Index;
7264 Alternate_Languages := null;
7265 Display_Language_Name := No_Name;
7266 Unit := No_Name;
7267 Lang_Kind := File_Based;
7268 Kind := Spec;
7269
7270 Tmp_Lang := Project.Languages;
7271 while Tmp_Lang /= No_Language_Index loop
7272 if Current_Verbosity = High then
7273 Write_Line
7274 (" Testing language "
7275 & Get_Name_String (Tmp_Lang.Name)
7276 & " Header_File=" & Header_File'Img);
7277 end if;
7278
7279 Display_Language_Name := Tmp_Lang.Display_Name;
7280 Config := Tmp_Lang.Config;
7281 Lang_Kind := Config.Kind;
7282
7283 case Config.Kind is
7284 when File_Based =>
7285 Check_File_Based_Lang;
7286 exit when Kind = Impl;
7287
7288 when Unit_Based =>
7289
7290 -- We know it belongs to a least a file_based language, no
7291 -- need to check unit-based ones.
7292
7293 if not Header_File then
7294 Compute_Unit_Name
7295 (File_Name => File_Name,
7296 Dot_Replacement => Config.Naming_Data.Dot_Replacement,
7297 Separate_Suffix => Config.Naming_Data.Separate_Suffix,
7298 Body_Suffix => Config.Naming_Data.Body_Suffix,
7299 Spec_Suffix => Config.Naming_Data.Spec_Suffix,
7300 Casing => Config.Naming_Data.Casing,
7301 Kind => Kind,
7302 Unit => Unit,
7303 In_Tree => In_Tree);
7304
7305 if Unit /= No_Name then
7306 Language := Tmp_Lang;
7307 exit;
7308 end if;
7309 end if;
7310 end case;
7311
7312 Tmp_Lang := Tmp_Lang.Next;
7313 end loop;
7314
7315 if Language = No_Language_Index
7316 and then Current_Verbosity = High
7317 then
7318 Write_Line (" not a source of any language");
7319 end if;
7320 end Check_File_Naming_Schemes;
7321
7322 -------------------
7323 -- Override_Kind --
7324 -------------------
7325
7326 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
7327 begin
7328 -- Remove reference in the unit, if necessary
7329
7330 if Source.Unit /= null
7331 and then Source.Kind in Spec_Or_Body
7332 then
7333 Source.Unit.File_Names (Source.Kind) := null;
7334 end if;
7335
7336 Source.Kind := Kind;
7337
7338 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
7339 Source.Unit.File_Names (Source.Kind) := Source;
7340 end if;
7341 end Override_Kind;
7342
7343 ----------------
7344 -- Check_File --
7345 ----------------
7346
7347 procedure Check_File
7348 (Project : Project_Id;
7349 In_Tree : Project_Tree_Ref;
7350 Path : Path_Name_Type;
7351 File_Name : File_Name_Type;
7352 Display_File_Name : File_Name_Type;
7353 For_All_Sources : Boolean;
7354 Allow_Duplicate_Basenames : Boolean)
7355 is
7356 Canonical_Path : constant Path_Name_Type :=
7357 Path_Name_Type
7358 (Canonical_Case_File_Name (Name_Id (Path)));
7359
7360 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7361 Check_Name : Boolean := False;
7362 Alternate_Languages : Language_List;
7363 Language : Language_Ptr;
7364 Source : Source_Id;
7365 Add_Src : Boolean;
7366 Src_Ind : Source_File_Index;
7367 Unit : Name_Id;
7368 Source_To_Replace : Source_Id := No_Source;
7369 Display_Language_Name : Name_Id;
7370 Lang_Kind : Language_Kind;
7371 Kind : Source_Kind := Spec;
7372 Iter : Source_Iterator;
7373
7374 begin
7375 if Name_Loc = No_Name_Location then
7376 Check_Name := For_All_Sources;
7377
7378 else
7379 if Name_Loc.Found then
7380
7381 -- Check if it is OK to have the same file name in several
7382 -- source directories.
7383
7384 if not Project.Known_Order_Of_Source_Dirs then
7385 Error_Msg_File_1 := File_Name;
7386 Error_Msg
7387 (Project, In_Tree,
7388 "{ is found in several source directories",
7389 Name_Loc.Location);
7390 end if;
7391
7392 else
7393 Name_Loc.Found := True;
7394
7395 Source_Names.Set (File_Name, Name_Loc);
7396
7397 if Name_Loc.Source = No_Source then
7398 Check_Name := True;
7399
7400 else
7401 Name_Loc.Source.Path := (Canonical_Path, Path);
7402
7403 Source_Paths_Htable.Set
7404 (In_Tree.Source_Paths_HT,
7405 Canonical_Path,
7406 Name_Loc.Source);
7407
7408 -- Check if this is a subunit
7409
7410 if Name_Loc.Source.Unit /= No_Unit_Index
7411 and then Name_Loc.Source.Kind = Impl
7412 then
7413 Src_Ind := Sinput.P.Load_Project_File
7414 (Get_Name_String (Canonical_Path));
7415
7416 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7417 Override_Kind (Name_Loc.Source, Sep);
7418 end if;
7419 end if;
7420 end if;
7421 end if;
7422 end if;
7423
7424 if Check_Name then
7425 Check_File_Naming_Schemes
7426 (In_Tree => In_Tree,
7427 Project => Project,
7428 File_Name => File_Name,
7429 Alternate_Languages => Alternate_Languages,
7430 Language => Language,
7431 Display_Language_Name => Display_Language_Name,
7432 Unit => Unit,
7433 Lang_Kind => Lang_Kind,
7434 Kind => Kind);
7435
7436 if Language = No_Language_Index then
7437
7438 -- A file name in a list must be a source of a language
7439
7440 if Name_Loc.Found then
7441 Error_Msg_File_1 := File_Name;
7442 Error_Msg
7443 (Project,
7444 In_Tree,
7445 "language unknown for {",
7446 Name_Loc.Location);
7447 end if;
7448
7449 else
7450 -- Check if the same file name or unit is used in the prj tree
7451
7452 Iter := For_Each_Source (In_Tree);
7453 Add_Src := True;
7454 loop
7455 Source := Prj.Element (Iter);
7456 exit when Source = No_Source;
7457
7458 if Unit /= No_Name
7459 and then Source.Unit /= No_Unit_Index
7460 and then Source.Unit.Name = Unit
7461 and then
7462 ((Source.Kind = Spec and then Kind = Impl)
7463 or else
7464 (Source.Kind = Impl and then Kind = Spec))
7465 then
7466 -- We found the "other_part (source)"
7467
7468 null;
7469
7470 elsif (Unit /= No_Name
7471 and then Source.Unit /= No_Unit_Index
7472 and then Source.Unit.Name = Unit
7473 and then
7474 (Source.Kind = Kind
7475 or else
7476 (Source.Kind = Sep and then Kind = Impl)
7477 or else
7478 (Source.Kind = Impl and then Kind = Sep)))
7479 or else
7480 (Unit = No_Name and then Source.File = File_Name)
7481 then
7482 -- Duplication of file/unit in same project is only
7483 -- allowed if order of source directories is known.
7484
7485 if Project = Source.Project then
7486 if Unit = No_Name then
7487 if Allow_Duplicate_Basenames then
7488 Add_Src := True;
7489 elsif Project.Known_Order_Of_Source_Dirs then
7490 Add_Src := False;
7491 else
7492 Error_Msg_File_1 := File_Name;
7493 Error_Msg
7494 (Project, In_Tree, "duplicate source file name {",
7495 No_Location);
7496 Add_Src := False;
7497 end if;
7498
7499 else
7500 if Project.Known_Order_Of_Source_Dirs then
7501 Add_Src := False;
7502 else
7503 Error_Msg_Name_1 := Unit;
7504 Error_Msg
7505 (Project, In_Tree, "duplicate unit %%",
7506 No_Location);
7507 Add_Src := False;
7508 end if;
7509 end if;
7510
7511 -- Do not allow the same unit name in different projects,
7512 -- except if one is extending the other.
7513
7514 -- For a file based language, the same file name replaces
7515 -- a file in a project being extended, but it is allowed
7516 -- to have the same file name in unrelated projects.
7517
7518 elsif Is_Extending (Project, Source.Project) then
7519 Source_To_Replace := Source;
7520
7521 elsif Unit /= No_Name
7522 and then not Source.Locally_Removed
7523 then
7524 Error_Msg_Name_1 := Unit;
7525 Error_Msg
7526 (Project, In_Tree,
7527 "unit %% cannot belong to several projects",
7528 No_Location);
7529
7530 Error_Msg_Name_1 := Project.Name;
7531 Error_Msg_Name_2 := Name_Id (Path);
7532 Error_Msg
7533 (Project, In_Tree, "\ project %%, %%", No_Location);
7534
7535 Error_Msg_Name_1 := Source.Project.Name;
7536 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7537 Error_Msg
7538 (Project, In_Tree, "\ project %%, %%", No_Location);
7539
7540 Add_Src := False;
7541 end if;
7542 end if;
7543
7544 Next (Iter);
7545 end loop;
7546
7547 if Add_Src then
7548 Add_Source
7549 (Id => Source,
7550 In_Tree => In_Tree,
7551 Project => Project,
7552 Lang_Id => Language,
7553 Kind => Kind,
7554 Alternate_Languages => Alternate_Languages,
7555 File_Name => File_Name,
7556 Display_File => Display_File_Name,
7557 Unit => Unit,
7558 Path => (Canonical_Path, Path),
7559 Source_To_Replace => Source_To_Replace);
7560 end if;
7561 end if;
7562 end if;
7563 end Check_File;
7564
7565 ------------------------
7566 -- Search_Directories --
7567 ------------------------
7568
7569 procedure Search_Directories
7570 (Project : Project_Id;
7571 In_Tree : Project_Tree_Ref;
7572 For_All_Sources : Boolean;
7573 Allow_Duplicate_Basenames : Boolean)
7574 is
7575 Source_Dir : String_List_Id;
7576 Element : String_Element;
7577 Dir : Dir_Type;
7578 Name : String (1 .. 1_000);
7579 Last : Natural;
7580 File_Name : File_Name_Type;
7581 Display_File_Name : File_Name_Type;
7582
7583 begin
7584 if Current_Verbosity = High then
7585 Write_Line ("Looking for sources:");
7586 end if;
7587
7588 -- Loop through subdirectories
7589
7590 Source_Dir := Project.Source_Dirs;
7591 while Source_Dir /= Nil_String loop
7592 begin
7593 Element := In_Tree.String_Elements.Table (Source_Dir);
7594 if Element.Value /= No_Name then
7595 Get_Name_String (Element.Display_Value);
7596
7597 declare
7598 Source_Directory : constant String :=
7599 Name_Buffer (1 .. Name_Len) &
7600 Directory_Separator;
7601
7602 Dir_Last : constant Natural :=
7603 Compute_Directory_Last
7604 (Source_Directory);
7605
7606 begin
7607 if Current_Verbosity = High then
7608 Write_Attr ("Source_Dir", Source_Directory);
7609 end if;
7610
7611 -- We look to every entry in the source directory
7612
7613 Open (Dir, Source_Directory);
7614
7615 loop
7616 Read (Dir, Name, Last);
7617
7618 exit when Last = 0;
7619
7620 -- ??? Duplicate system call here, we just did a
7621 -- a similar one. Maybe Ada.Directories would be more
7622 -- appropriate here
7623
7624 if Is_Regular_File
7625 (Source_Directory & Name (1 .. Last))
7626 then
7627 if Current_Verbosity = High then
7628 Write_Str (" Checking ");
7629 Write_Line (Name (1 .. Last));
7630 end if;
7631
7632 Name_Len := Last;
7633 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7634 Display_File_Name := Name_Find;
7635
7636 if Osint.File_Names_Case_Sensitive then
7637 File_Name := Display_File_Name;
7638 else
7639 Canonical_Case_File_Name
7640 (Name_Buffer (1 .. Name_Len));
7641 File_Name := Name_Find;
7642 end if;
7643
7644 declare
7645 Path_Name : constant String :=
7646 Normalize_Pathname
7647 (Name (1 .. Last),
7648 Directory =>
7649 Source_Directory
7650 (Source_Directory'First ..
7651 Dir_Last),
7652 Resolve_Links =>
7653 Opt.Follow_Links_For_Files,
7654 Case_Sensitive => True);
7655 -- Case_Sensitive set True (no folding)
7656
7657 Path : Path_Name_Type;
7658 FF : File_Found :=
7659 Excluded_Sources_Htable.Get (File_Name);
7660
7661 begin
7662 Name_Len := Path_Name'Length;
7663 Name_Buffer (1 .. Name_Len) := Path_Name;
7664 Path := Name_Find;
7665
7666 if FF /= No_File_Found then
7667 if not FF.Found then
7668 FF.Found := True;
7669 Excluded_Sources_Htable.Set (File_Name, FF);
7670
7671 if Current_Verbosity = High then
7672 Write_Str (" excluded source """);
7673 Write_Str (Get_Name_String (File_Name));
7674 Write_Line ("""");
7675 end if;
7676 end if;
7677
7678 else
7679 Check_File
7680 (Project => Project,
7681 In_Tree => In_Tree,
7682 Path => Path,
7683 File_Name => File_Name,
7684 Display_File_Name =>
7685 Display_File_Name,
7686 For_All_Sources => For_All_Sources,
7687 Allow_Duplicate_Basenames =>
7688 Allow_Duplicate_Basenames);
7689 end if;
7690 end;
7691 end if;
7692 end loop;
7693
7694 Close (Dir);
7695 end;
7696 end if;
7697
7698 exception
7699 when Directory_Error =>
7700 null;
7701 end;
7702
7703 Source_Dir := Element.Next;
7704 end loop;
7705
7706 if Current_Verbosity = High then
7707 Write_Line ("end Looking for sources.");
7708 end if;
7709 end Search_Directories;
7710
7711 ----------------------------
7712 -- Load_Naming_Exceptions --
7713 ----------------------------
7714
7715 procedure Load_Naming_Exceptions
7716 (Project : Project_Id;
7717 In_Tree : Project_Tree_Ref)
7718 is
7719 Source : Source_Id;
7720 Iter : Source_Iterator;
7721
7722 begin
7723 Unit_Exceptions.Reset;
7724
7725 Iter := For_Each_Source (In_Tree, Project);
7726 loop
7727 Source := Prj.Element (Iter);
7728 exit when Source = No_Source;
7729
7730 -- An excluded file cannot also be an exception file name
7731
7732 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7733 Error_Msg_File_1 := Source.File;
7734 Error_Msg
7735 (Project, In_Tree,
7736 "{ cannot be both excluded and an exception file name",
7737 No_Location);
7738 end if;
7739
7740 if Current_Verbosity = High then
7741 Write_Str ("Naming exception: Putting source file ");
7742 Write_Str (Get_Name_String (Source.File));
7743 Write_Line (" in Source_Names");
7744 end if;
7745
7746 Source_Names.Set
7747 (K => Source.File,
7748 E => Name_Location'
7749 (Name => Source.File,
7750 Location => No_Location,
7751 Source => Source,
7752 Except => Source.Unit /= No_Unit_Index,
7753 Found => False));
7754
7755 -- If this is an Ada exception, record in table Unit_Exceptions
7756
7757 if Source.Unit /= No_Unit_Index then
7758 declare
7759 Unit_Except : Unit_Exception :=
7760 Unit_Exceptions.Get (Source.Unit.Name);
7761
7762 begin
7763 Unit_Except.Name := Source.Unit.Name;
7764
7765 if Source.Kind = Spec then
7766 Unit_Except.Spec := Source.File;
7767 else
7768 Unit_Except.Impl := Source.File;
7769 end if;
7770
7771 Unit_Exceptions.Set (Source.Unit.Name, Unit_Except);
7772 end;
7773 end if;
7774
7775 Next (Iter);
7776 end loop;
7777 end Load_Naming_Exceptions;
7778
7779 ----------------------
7780 -- Look_For_Sources --
7781 ----------------------
7782
7783 procedure Look_For_Sources
7784 (Project : Project_Id;
7785 In_Tree : Project_Tree_Ref;
7786 Proc_Data : in out Processing_Data;
7787 Allow_Duplicate_Basenames : Boolean)
7788 is
7789 Iter : Source_Iterator;
7790
7791 procedure Process_Sources_In_Multi_Language_Mode;
7792 -- Find all source files when in multi language mode
7793
7794 procedure Mark_Excluded_Sources;
7795 -- Mark as such the sources that are declared as excluded
7796
7797 ---------------------------
7798 -- Mark_Excluded_Sources --
7799 ---------------------------
7800
7801 procedure Mark_Excluded_Sources is
7802 Source : Source_Id := No_Source;
7803 OK : Boolean;
7804 Excluded : File_Found;
7805
7806 begin
7807 Excluded := Excluded_Sources_Htable.Get_First;
7808 while Excluded /= No_File_Found loop
7809 OK := False;
7810
7811 -- ??? Don't we have a hash table to map files to Source_Id?
7812
7813 Iter := For_Each_Source (In_Tree);
7814 loop
7815 Source := Prj.Element (Iter);
7816 exit when Source = No_Source;
7817
7818 if Source.File = Excluded.File then
7819 if Source.Project = Project
7820 or else Is_Extending (Project, Source.Project)
7821 then
7822 OK := True;
7823 Source.Locally_Removed := True;
7824
7825 Name_Len := 1;
7826 Name_Buffer (1 .. Name_Len) := "/";
7827 Source.Path.Name := Name_Find;
7828 Source.In_Interfaces := False;
7829
7830 if Current_Verbosity = High then
7831 Write_Str ("Removing file ");
7832 Write_Line (Get_Name_String (Excluded.File));
7833 end if;
7834
7835 Add_Forbidden_File_Name (Excluded.File);
7836
7837 else
7838 Error_Msg
7839 (Project, In_Tree,
7840 "cannot remove a source from another project",
7841 Excluded.Location);
7842 end if;
7843
7844 exit;
7845 end if;
7846
7847 Next (Iter);
7848 end loop;
7849
7850 OK := OK or Excluded.Found;
7851
7852 if not OK then
7853 Err_Vars.Error_Msg_File_1 := Excluded.File;
7854 Error_Msg
7855 (Project, In_Tree, "unknown file {", Excluded.Location);
7856 end if;
7857
7858 Excluded := Excluded_Sources_Htable.Get_Next;
7859 end loop;
7860 end Mark_Excluded_Sources;
7861
7862 --------------------------------------------
7863 -- Process_Sources_In_Multi_Language_Mode --
7864 --------------------------------------------
7865
7866 procedure Process_Sources_In_Multi_Language_Mode is
7867 Iter : Source_Iterator;
7868
7869 begin
7870 -- Check that two sources of this project do not have the same object
7871 -- file name.
7872
7873 Check_Object_File_Names : declare
7874 Src_Id : Source_Id;
7875 Source_Name : File_Name_Type;
7876
7877 procedure Check_Object (Src : Source_Id);
7878 -- Check if object file name of the current source is already in
7879 -- hash table Object_File_Names. If it is, report an error. If it
7880 -- is not, put it there with the file name of the current source.
7881
7882 ------------------
7883 -- Check_Object --
7884 ------------------
7885
7886 procedure Check_Object (Src : Source_Id) is
7887 begin
7888 Source_Name := Object_File_Names.Get (Src.Object);
7889
7890 if Source_Name /= No_File then
7891 Error_Msg_File_1 := Src.File;
7892 Error_Msg_File_2 := Source_Name;
7893 Error_Msg
7894 (Project,
7895 In_Tree,
7896 "{ and { have the same object file name",
7897 No_Location);
7898
7899 else
7900 Object_File_Names.Set (Src.Object, Src.File);
7901 end if;
7902 end Check_Object;
7903
7904 -- Start of processing for Check_Object_File_Names
7905
7906 begin
7907 Object_File_Names.Reset;
7908 Iter := For_Each_Source (In_Tree);
7909 loop
7910 Src_Id := Prj.Element (Iter);
7911 exit when Src_Id = No_Source;
7912
7913 if Is_Compilable (Src_Id)
7914 and then Src_Id.Language.Config.Object_Generated
7915 and then Is_Extending (Project, Src_Id.Project)
7916 then
7917 if Src_Id.Unit = No_Unit_Index then
7918 if Src_Id.Kind = Impl then
7919 Check_Object (Src_Id);
7920 end if;
7921
7922 else
7923 case Src_Id.Kind is
7924 when Spec =>
7925 if Other_Part (Src_Id) = No_Source then
7926 Check_Object (Src_Id);
7927 end if;
7928
7929 when Sep =>
7930 null;
7931
7932 when Impl =>
7933 if Other_Part (Src_Id) /= No_Source then
7934 Check_Object (Src_Id);
7935
7936 else
7937 -- Check if it is a subunit
7938
7939 declare
7940 Src_Ind : constant Source_File_Index :=
7941 Sinput.P.Load_Project_File
7942 (Get_Name_String
7943 (Src_Id.Path.Name));
7944 begin
7945 if Sinput.P.Source_File_Is_Subunit
7946 (Src_Ind)
7947 then
7948 Override_Kind (Src_Id, Sep);
7949 else
7950 Check_Object (Src_Id);
7951 end if;
7952 end;
7953 end if;
7954 end case;
7955 end if;
7956 end if;
7957
7958 Next (Iter);
7959 end loop;
7960 end Check_Object_File_Names;
7961 end Process_Sources_In_Multi_Language_Mode;
7962
7963 -- Start of processing for Look_For_Sources
7964
7965 begin
7966 Source_Names.Reset;
7967 Find_Excluded_Sources (Project, In_Tree);
7968
7969 if (Get_Mode = Ada_Only and then Is_A_Language (Project, Name_Ada))
7970 or else (Get_Mode = Multi_Language
7971 and then Project.Languages /= No_Language_Index)
7972 then
7973 if Get_Mode = Multi_Language then
7974 Load_Naming_Exceptions (Project, In_Tree);
7975 end if;
7976
7977 Find_Sources (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
7978 Mark_Excluded_Sources;
7979
7980 if Get_Mode = Multi_Language then
7981 Process_Sources_In_Multi_Language_Mode;
7982 end if;
7983 end if;
7984 end Look_For_Sources;
7985
7986 ------------------
7987 -- Path_Name_Of --
7988 ------------------
7989
7990 function Path_Name_Of
7991 (File_Name : File_Name_Type;
7992 Directory : Path_Name_Type) return String
7993 is
7994 Result : String_Access;
7995 The_Directory : constant String := Get_Name_String (Directory);
7996
7997 begin
7998 Get_Name_String (File_Name);
7999 Result :=
8000 Locate_Regular_File
8001 (File_Name => Name_Buffer (1 .. Name_Len),
8002 Path => The_Directory);
8003
8004 if Result = null then
8005 return "";
8006 else
8007 declare
8008 R : String := Result.all;
8009 begin
8010 Free (Result);
8011 Canonical_Case_File_Name (R);
8012 return R;
8013 end;
8014 end if;
8015 end Path_Name_Of;
8016
8017 -----------------------------------
8018 -- Prepare_Ada_Naming_Exceptions --
8019 -----------------------------------
8020
8021 procedure Prepare_Ada_Naming_Exceptions
8022 (List : Array_Element_Id;
8023 In_Tree : Project_Tree_Ref;
8024 Kind : Spec_Or_Body)
8025 is
8026 Current : Array_Element_Id;
8027 Element : Array_Element;
8028 Unit : Unit_Info;
8029
8030 begin
8031 -- Traverse the list
8032
8033 Current := List;
8034 while Current /= No_Array_Element loop
8035 Element := In_Tree.Array_Elements.Table (Current);
8036
8037 if Element.Index /= No_Name then
8038 Unit :=
8039 (Kind => Kind,
8040 Unit => Element.Index,
8041 Next => No_Ada_Naming_Exception);
8042 Reverse_Ada_Naming_Exceptions.Set
8043 (Unit, (Element.Value.Value, Element.Value.Index));
8044 Unit.Next :=
8045 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8046 Ada_Naming_Exception_Table.Increment_Last;
8047 Ada_Naming_Exception_Table.Table
8048 (Ada_Naming_Exception_Table.Last) := Unit;
8049 Ada_Naming_Exceptions.Set
8050 (File_Name_Type (Element.Value.Value),
8051 Ada_Naming_Exception_Table.Last);
8052 end if;
8053
8054 Current := Element.Next;
8055 end loop;
8056 end Prepare_Ada_Naming_Exceptions;
8057
8058 -----------------------
8059 -- Record_Ada_Source --
8060 -----------------------
8061
8062 procedure Record_Ada_Source
8063 (File_Name : File_Name_Type;
8064 Path_Name : Path_Name_Type;
8065 Project : Project_Id;
8066 In_Tree : Project_Tree_Ref;
8067 Proc_Data : in out Processing_Data;
8068 Ada_Language : Language_Ptr;
8069 Location : Source_Ptr;
8070 Source_Recorded : in out Boolean)
8071 is
8072 Canonical_File : File_Name_Type;
8073 Canonical_Path : Path_Name_Type;
8074
8075 File_Recorded : Boolean := False;
8076 -- True when at least one file has been recorded
8077
8078 procedure Record_Unit
8079 (Unit_Name : Name_Id;
8080 Unit_Ind : Int := 0;
8081 Unit_Kind : Spec_Or_Body;
8082 Needs_Pragma : Boolean);
8083 -- Register of the units contained in the source file (there is in
8084 -- general a single such unit except when exceptions to the naming
8085 -- scheme indicate there are several such units)
8086
8087 -----------------
8088 -- Record_Unit --
8089 -----------------
8090
8091 procedure Record_Unit
8092 (Unit_Name : Name_Id;
8093 Unit_Ind : Int := 0;
8094 Unit_Kind : Spec_Or_Body;
8095 Needs_Pragma : Boolean)
8096 is
8097 UData : constant Unit_Index :=
8098 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8099 -- ??? Add_Source will look it up again, can we do that only once ?
8100
8101 Source : Source_Id;
8102 To_Record : Boolean := False;
8103 The_Location : Source_Ptr := Location;
8104 Unit_Prj : Project_Id;
8105
8106 begin
8107 if Current_Verbosity = High then
8108 Write_Str (" Putting ");
8109 Write_Str (Get_Name_String (Unit_Name));
8110 Write_Line (" in the unit list.");
8111 end if;
8112
8113 -- The unit is already in the list, but may be it is only the other
8114 -- unit kind (spec or body), or what is in the unit list is a unit of
8115 -- a project we are extending.
8116
8117 if UData /= No_Unit_Index then
8118 if UData.File_Names (Unit_Kind) = null
8119 or else
8120 (UData.File_Names (Unit_Kind).File = Canonical_File
8121 and then UData.File_Names (Unit_Kind).Locally_Removed)
8122 or else Is_Extending
8123 (Project.Extends, UData.File_Names (Unit_Kind).Project)
8124 then
8125 if UData.File_Names (Unit_Kind) /= null
8126 and then UData.File_Names (Unit_Kind).Locally_Removed
8127 then
8128 Remove_Forbidden_File_Name
8129 (UData.File_Names (Unit_Kind).File);
8130 end if;
8131
8132 To_Record := True;
8133
8134 -- If the same file is already in the list, do not add it again
8135
8136 elsif UData.File_Names (Unit_Kind).Project = Project
8137 and then
8138 (Project.Known_Order_Of_Source_Dirs
8139 or else
8140 UData.File_Names (Unit_Kind).Path.Name = Canonical_Path)
8141 then
8142 To_Record := False;
8143
8144 -- Else, same unit but not same file => It is an error to have two
8145 -- units with the same name and the same kind (spec or body).
8146
8147 else
8148 if The_Location = No_Location then
8149 The_Location := Project.Location;
8150 end if;
8151
8152 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8153 Error_Msg
8154 (Project, In_Tree, "duplicate unit %%", The_Location);
8155
8156 Err_Vars.Error_Msg_Name_1 :=
8157 UData.File_Names (Unit_Kind).Project.Name;
8158 Err_Vars.Error_Msg_File_1 :=
8159 File_Name_Type (UData.File_Names (Unit_Kind).Path.Name);
8160 Error_Msg
8161 (Project, In_Tree,
8162 "\ project file %%, {", The_Location);
8163
8164 Err_Vars.Error_Msg_Name_1 := Project.Name;
8165 Err_Vars.Error_Msg_File_1 := File_Name_Type (Canonical_Path);
8166 Error_Msg
8167 (Project, In_Tree, "\ project file %%, {", The_Location);
8168
8169 To_Record := False;
8170 end if;
8171
8172 -- It is a new unit, create a new record
8173
8174 else
8175 -- First, check if there is no other unit with this file name in
8176 -- another project. If it is, report error but note we do that
8177 -- only for the first unit in the source file.
8178
8179 Unit_Prj := Files_Htable.Get (Proc_Data.Units, Canonical_File);
8180
8181 if not File_Recorded
8182 and then Unit_Prj /= No_Project
8183 then
8184 Error_Msg_File_1 := File_Name;
8185 Error_Msg_Name_1 := Unit_Prj.Name;
8186 Error_Msg
8187 (Project, In_Tree,
8188 "{ is already a source of project %%",
8189 Location);
8190
8191 else
8192 To_Record := True;
8193 end if;
8194 end if;
8195
8196 if To_Record then
8197 Files_Htable.Set (Proc_Data.Units, Canonical_File, Project);
8198 Add_Source
8199 (Id => Source,
8200 In_Tree => In_Tree,
8201 Project => Project,
8202 Lang_Id => Ada_Language,
8203 File_Name => Canonical_File,
8204 Display_File => File_Name,
8205 Unit => Unit_Name,
8206 Path => (Canonical_Path, Path_Name),
8207 Naming_Exception => Needs_Pragma,
8208 Kind => Unit_Kind,
8209 Index => Unit_Ind);
8210 Source_Recorded := True;
8211 end if;
8212 end Record_Unit;
8213
8214 Exception_Id : Ada_Naming_Exception_Id;
8215 Unit_Name : Name_Id;
8216 Unit_Kind : Spec_Or_Body;
8217 Unit_Ind : Int := 0;
8218 Info : Unit_Info;
8219 Name_Index : Name_And_Index;
8220 Except_Name : Name_And_Index := No_Name_And_Index;
8221 Needs_Pragma : Boolean;
8222
8223 begin
8224 Canonical_File := Canonical_Case_File_Name (Name_Id (File_Name));
8225 Canonical_Path :=
8226 Path_Name_Type (Canonical_Case_File_Name (Name_Id (Path_Name)));
8227
8228 -- Check the naming scheme to get extra file properties
8229
8230 Get_Unit
8231 (In_Tree => In_Tree,
8232 Canonical_File_Name => Canonical_File,
8233 Naming => Project.Naming,
8234 Exception_Id => Exception_Id,
8235 Unit_Name => Unit_Name,
8236 Unit_Kind => Unit_Kind);
8237
8238 Needs_Pragma := Exception_Id /= No_Ada_Naming_Exception;
8239
8240 if Exception_Id = No_Ada_Naming_Exception
8241 and then Unit_Name = No_Name
8242 then
8243 if Current_Verbosity = High then
8244 Write_Str (" """);
8245 Write_Str (Get_Name_String (Canonical_File));
8246 Write_Line (""" is not a valid source file name (ignored).");
8247 end if;
8248 return;
8249 end if;
8250
8251 -- Check to see if the source has been hidden by an exception,
8252 -- but only if it is not an exception.
8253
8254 if not Needs_Pragma then
8255 Except_Name :=
8256 Reverse_Ada_Naming_Exceptions.Get
8257 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8258
8259 if Except_Name /= No_Name_And_Index then
8260 if Current_Verbosity = High then
8261 Write_Str (" """);
8262 Write_Str (Get_Name_String (Canonical_File));
8263 Write_Str (""" contains a unit that is found in """);
8264 Write_Str (Get_Name_String (Except_Name.Name));
8265 Write_Line (""" (ignored).");
8266 end if;
8267
8268 -- The file is not included in the source of the project since it
8269 -- is hidden by the exception. So, nothing else to do.
8270
8271 return;
8272 end if;
8273 end if;
8274
8275 -- The following loop registers the unit in the appropriate table. It
8276 -- will be executed multiple times when the file is a multi-unit file,
8277 -- in which case Exception_Id initially points to the first file and
8278 -- then to each other unit in the file.
8279
8280 loop
8281 if Exception_Id /= No_Ada_Naming_Exception then
8282 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8283 Exception_Id := Info.Next;
8284 Info.Next := No_Ada_Naming_Exception;
8285 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8286
8287 Unit_Name := Info.Unit;
8288 Unit_Ind := Name_Index.Index;
8289 Unit_Kind := Info.Kind;
8290 end if;
8291
8292 Record_Unit (Unit_Name, Unit_Ind, Unit_Kind, Needs_Pragma);
8293 File_Recorded := True;
8294
8295 exit when Exception_Id = No_Ada_Naming_Exception;
8296 end loop;
8297 end Record_Ada_Source;
8298
8299 -------------------
8300 -- Remove_Source --
8301 -------------------
8302
8303 procedure Remove_Source
8304 (Id : Source_Id;
8305 Replaced_By : Source_Id)
8306 is
8307 Source : Source_Id;
8308
8309 begin
8310 if Current_Verbosity = High then
8311 Write_Str ("Removing source ");
8312 Write_Line (Get_Name_String (Id.File));
8313 end if;
8314
8315 if Replaced_By /= No_Source then
8316 Id.Replaced_By := Replaced_By;
8317 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8318 end if;
8319
8320 Source := Id.Language.First_Source;
8321
8322 if Source = Id then
8323 Id.Language.First_Source := Id.Next_In_Lang;
8324
8325 else
8326 while Source.Next_In_Lang /= Id loop
8327 Source := Source.Next_In_Lang;
8328 end loop;
8329
8330 Source.Next_In_Lang := Id.Next_In_Lang;
8331 end if;
8332 end Remove_Source;
8333
8334 -----------------------
8335 -- Report_No_Sources --
8336 -----------------------
8337
8338 procedure Report_No_Sources
8339 (Project : Project_Id;
8340 Lang_Name : String;
8341 In_Tree : Project_Tree_Ref;
8342 Location : Source_Ptr;
8343 Continuation : Boolean := False)
8344 is
8345 begin
8346 case When_No_Sources is
8347 when Silent =>
8348 null;
8349
8350 when Warning | Error =>
8351 declare
8352 Msg : constant String :=
8353 "<there are no " &
8354 Lang_Name &
8355 " sources in this project";
8356
8357 begin
8358 Error_Msg_Warn := When_No_Sources = Warning;
8359
8360 if Continuation then
8361 Error_Msg (Project, In_Tree, "\" & Msg, Location);
8362 else
8363 Error_Msg (Project, In_Tree, Msg, Location);
8364 end if;
8365 end;
8366 end case;
8367 end Report_No_Sources;
8368
8369 ----------------------
8370 -- Show_Source_Dirs --
8371 ----------------------
8372
8373 procedure Show_Source_Dirs
8374 (Project : Project_Id;
8375 In_Tree : Project_Tree_Ref)
8376 is
8377 Current : String_List_Id;
8378 Element : String_Element;
8379
8380 begin
8381 Write_Line ("Source_Dirs:");
8382
8383 Current := Project.Source_Dirs;
8384 while Current /= Nil_String loop
8385 Element := In_Tree.String_Elements.Table (Current);
8386 Write_Str (" ");
8387 Write_Line (Get_Name_String (Element.Value));
8388 Current := Element.Next;
8389 end loop;
8390
8391 Write_Line ("end Source_Dirs.");
8392 end Show_Source_Dirs;
8393
8394 -------------------------
8395 -- Warn_If_Not_Sources --
8396 -------------------------
8397
8398 -- comments needed in this body ???
8399
8400 procedure Warn_If_Not_Sources
8401 (Project : Project_Id;
8402 In_Tree : Project_Tree_Ref;
8403 Conventions : Array_Element_Id;
8404 Specs : Boolean;
8405 Extending : Boolean)
8406 is
8407 Conv : Array_Element_Id;
8408 Unit : Name_Id;
8409 The_Unit_Data : Unit_Index;
8410 Location : Source_Ptr;
8411
8412 begin
8413 Conv := Conventions;
8414 while Conv /= No_Array_Element loop
8415 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8416 Error_Msg_Name_1 := Unit;
8417 Get_Name_String (Unit);
8418 To_Lower (Name_Buffer (1 .. Name_Len));
8419 Unit := Name_Find;
8420 The_Unit_Data := Units_Htable.Get (In_Tree.Units_HT, Unit);
8421 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8422
8423 if The_Unit_Data = No_Unit_Index then
8424 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8425
8426 else
8427 Error_Msg_Name_2 :=
8428 In_Tree.Array_Elements.Table (Conv).Value.Value;
8429
8430 if Specs then
8431 if not Check_Project
8432 (The_Unit_Data.File_Names (Spec).Project,
8433 Project, Extending)
8434 then
8435 Error_Msg
8436 (Project, In_Tree,
8437 "?source of spec of unit %% (%%)" &
8438 " not found in this project",
8439 Location);
8440 end if;
8441
8442 else
8443 if The_Unit_Data.File_Names (Impl) = null
8444 or else not Check_Project
8445 (The_Unit_Data.File_Names (Impl).Project,
8446 Project, Extending)
8447 then
8448 Error_Msg
8449 (Project, In_Tree,
8450 "?source of body of unit %% (%%)" &
8451 " not found in this project",
8452 Location);
8453 end if;
8454 end if;
8455 end if;
8456
8457 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8458 end loop;
8459 end Warn_If_Not_Sources;
8460
8461 end Prj.Nmsc;