2008-05-30 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / ada / prj-env.adb
blobdd52f353287e8e073ebe26c511381d31637d09e6
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . E N V --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2008, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with Fmap;
27 with Opt;
28 with Osint; use Osint;
29 with Output; use Output;
30 with Prj.Com; use Prj.Com;
31 with Tempdir;
33 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
35 package body Prj.Env is
37 Current_Source_Path_File : Path_Name_Type := No_Path;
38 -- Current value of project source path file env var.
39 -- Used to avoid setting the env var to the same value.
41 Current_Object_Path_File : Path_Name_Type := No_Path;
42 -- Current value of project object path file env var.
43 -- Used to avoid setting the env var to the same value.
45 Ada_Path_Buffer : String_Access := new String (1 .. 1024);
46 -- A buffer where values for ADA_INCLUDE_PATH
47 -- and ADA_OBJECTS_PATH are stored.
49 Ada_Path_Length : Natural := 0;
50 -- Index of the last valid character in Ada_Path_Buffer
52 Ada_Prj_Include_File_Set : Boolean := False;
53 Ada_Prj_Objects_File_Set : Boolean := False;
54 -- These flags are set to True when the corresponding environment variables
55 -- are set and are used to give these environment variables an empty string
56 -- value at the end of the program. This has no practical effect on most
57 -- platforms, except on VMS where the logical names are deassigned, thus
58 -- avoiding the pollution of the environment of the caller.
60 Default_Naming : constant Naming_Id := Naming_Table.First;
62 Fill_Mapping_File : Boolean := True;
64 type Project_Flags is array (Project_Id range <>) of Boolean;
65 -- A Boolean array type used in Create_Mapping_File to select the projects
66 -- in the closure of a specific project.
68 -----------------------
69 -- Local Subprograms --
70 -----------------------
72 function Body_Path_Name_Of
73 (Unit : Unit_Index;
74 In_Tree : Project_Tree_Ref) return String;
75 -- Returns the path name of the body of a unit.
76 -- Compute it first, if necessary.
78 function Spec_Path_Name_Of
79 (Unit : Unit_Index;
80 In_Tree : Project_Tree_Ref) return String;
81 -- Returns the path name of the spec of a unit.
82 -- Compute it first, if necessary.
84 procedure Add_To_Path
85 (Source_Dirs : String_List_Id;
86 In_Tree : Project_Tree_Ref);
87 -- Add to Ada_Path_Buffer all the source directories in string list
88 -- Source_Dirs, if any. Increment Ada_Path_Length.
90 procedure Add_To_Path (Dir : String);
91 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
92 -- Increment Ada_Path_Length.
93 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
94 -- Path.
96 procedure Add_To_Source_Path
97 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
98 -- Add to Ada_Path_B all the source directories in string list
99 -- Source_Dirs, if any. Increment Ada_Path_Length.
101 procedure Add_To_Object_Path
102 (Object_Dir : Path_Name_Type;
103 In_Tree : Project_Tree_Ref);
104 -- Add Object_Dir to object path table. Make sure it is not duplicate
105 -- and it is the last one in the current table.
107 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
108 -- Return True if there is at least one ALI file in the directory Dir
110 procedure Set_Path_File_Var (Name : String; Value : String);
111 -- Call Setenv, after calling To_Host_File_Spec
113 function Ultimate_Extension_Of
114 (Project : Project_Id;
115 In_Tree : Project_Tree_Ref) return Project_Id;
116 -- Return a project that is either Project or an extended ancestor of
117 -- Project that itself is not extended.
119 ----------------------
120 -- Ada_Include_Path --
121 ----------------------
123 function Ada_Include_Path
124 (Project : Project_Id;
125 In_Tree : Project_Tree_Ref) return String_Access is
127 procedure Add (Project : Project_Id);
128 -- Add all the source directories of a project to the path only if
129 -- this project has not been visited. Calls itself recursively for
130 -- projects being extended, and imported projects. Adds the project
131 -- to the list Seen if this is the call to Add for this project.
133 ---------
134 -- Add --
135 ---------
137 procedure Add (Project : Project_Id) is
138 begin
139 -- If Seen is empty, then the project cannot have been visited
141 if not In_Tree.Projects.Table (Project).Seen then
142 In_Tree.Projects.Table (Project).Seen := True;
144 declare
145 Data : constant Project_Data :=
146 In_Tree.Projects.Table (Project);
147 List : Project_List := Data.Imported_Projects;
149 begin
150 -- Add to path all source directories of this project
152 Add_To_Path (Data.Source_Dirs, In_Tree);
154 -- Call Add to the project being extended, if any
156 if Data.Extends /= No_Project then
157 Add (Data.Extends);
158 end if;
160 -- Call Add for each imported project, if any
162 while List /= Empty_Project_List loop
164 (In_Tree.Project_Lists.Table (List).Project);
165 List := In_Tree.Project_Lists.Table (List).Next;
166 end loop;
167 end;
168 end if;
169 end Add;
171 -- Start of processing for Ada_Include_Path
173 begin
174 -- If it is the first time we call this function for
175 -- this project, compute the source path
178 In_Tree.Projects.Table (Project).Ada_Include_Path = null
179 then
180 Ada_Path_Length := 0;
182 for Index in Project_Table.First ..
183 Project_Table.Last (In_Tree.Projects)
184 loop
185 In_Tree.Projects.Table (Index).Seen := False;
186 end loop;
188 Add (Project);
189 In_Tree.Projects.Table (Project).Ada_Include_Path :=
190 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
191 end if;
193 return In_Tree.Projects.Table (Project).Ada_Include_Path;
194 end Ada_Include_Path;
196 ----------------------
197 -- Ada_Include_Path --
198 ----------------------
200 function Ada_Include_Path
201 (Project : Project_Id;
202 In_Tree : Project_Tree_Ref;
203 Recursive : Boolean) return String
205 begin
206 if Recursive then
207 return Ada_Include_Path (Project, In_Tree).all;
208 else
209 Ada_Path_Length := 0;
210 Add_To_Path
211 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
212 return Ada_Path_Buffer (1 .. Ada_Path_Length);
213 end if;
214 end Ada_Include_Path;
216 ----------------------
217 -- Ada_Objects_Path --
218 ----------------------
220 function Ada_Objects_Path
221 (Project : Project_Id;
222 In_Tree : Project_Tree_Ref;
223 Including_Libraries : Boolean := True) return String_Access
225 procedure Add (Project : Project_Id);
226 -- Add all the object directories of a project to the path only if
227 -- this project has not been visited. Calls itself recursively for
228 -- projects being extended, and imported projects. Adds the project
229 -- to the list Seen if this is the first call to Add for this project.
231 ---------
232 -- Add --
233 ---------
235 procedure Add (Project : Project_Id) is
236 begin
237 -- If this project has not been seen yet
239 if not In_Tree.Projects.Table (Project).Seen then
240 In_Tree.Projects.Table (Project).Seen := True;
242 declare
243 Data : constant Project_Data :=
244 In_Tree.Projects.Table (Project);
245 List : Project_List := Data.Imported_Projects;
247 begin
248 -- Add to path the object directory of this project
249 -- except if we don't include library project and
250 -- this is a library project.
252 if (Data.Library and then Including_Libraries)
253 or else
254 (Data.Object_Directory /= No_Path_Information
255 and then
256 (not Including_Libraries or else not Data.Library))
257 then
258 -- For a library project, add the library directory,
259 -- if there is no object directory or if it contains ALI
260 -- files; otherwise add the object directory.
262 if Data.Library then
263 if Data.Object_Directory = No_Path_Information
264 or else
265 Contains_ALI_Files (Data.Library_ALI_Dir.Name)
266 then
267 Add_To_Path
268 (Get_Name_String (Data.Library_ALI_Dir.Name));
269 else
270 Add_To_Path
271 (Get_Name_String (Data.Object_Directory.Name));
272 end if;
274 else
275 -- For a non library project, add the object directory
277 Add_To_Path
278 (Get_Name_String (Data.Object_Directory.Name));
279 end if;
280 end if;
282 -- Call Add to the project being extended, if any
284 if Data.Extends /= No_Project then
285 Add (Data.Extends);
286 end if;
288 -- Call Add for each imported project, if any
290 while List /= Empty_Project_List loop
292 (In_Tree.Project_Lists.Table (List).Project);
293 List := In_Tree.Project_Lists.Table (List).Next;
294 end loop;
295 end;
297 end if;
298 end Add;
300 -- Start of processing for Ada_Objects_Path
302 begin
303 -- If it is the first time we call this function for
304 -- this project, compute the objects path
307 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
308 then
309 Ada_Path_Length := 0;
311 for Index in Project_Table.First ..
312 Project_Table.Last (In_Tree.Projects)
313 loop
314 In_Tree.Projects.Table (Index).Seen := False;
315 end loop;
317 Add (Project);
318 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
319 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
320 end if;
322 return In_Tree.Projects.Table (Project).Ada_Objects_Path;
323 end Ada_Objects_Path;
325 ------------------------
326 -- Add_To_Object_Path --
327 ------------------------
329 procedure Add_To_Object_Path
330 (Object_Dir : Path_Name_Type; In_Tree : Project_Tree_Ref)
332 begin
333 -- Check if the directory is already in the table
335 for Index in Object_Path_Table.First ..
336 Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
337 loop
339 -- If it is, remove it, and add it as the last one
341 if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
342 for Index2 in Index + 1 ..
343 Object_Path_Table.Last
344 (In_Tree.Private_Part.Object_Paths)
345 loop
346 In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
347 In_Tree.Private_Part.Object_Paths.Table (Index2);
348 end loop;
350 In_Tree.Private_Part.Object_Paths.Table
351 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
352 Object_Dir;
353 return;
354 end if;
355 end loop;
357 -- The directory is not already in the table, add it
359 Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
360 In_Tree.Private_Part.Object_Paths.Table
361 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
362 Object_Dir;
363 end Add_To_Object_Path;
365 -----------------
366 -- Add_To_Path --
367 -----------------
369 procedure Add_To_Path
370 (Source_Dirs : String_List_Id;
371 In_Tree : Project_Tree_Ref)
373 Current : String_List_Id := Source_Dirs;
374 Source_Dir : String_Element;
375 begin
376 while Current /= Nil_String loop
377 Source_Dir := In_Tree.String_Elements.Table (Current);
378 Add_To_Path (Get_Name_String (Source_Dir.Display_Value));
379 Current := Source_Dir.Next;
380 end loop;
381 end Add_To_Path;
383 procedure Add_To_Path (Dir : String) is
384 Len : Natural;
385 New_Buffer : String_Access;
386 Min_Len : Natural;
388 function Is_Present (Path : String; Dir : String) return Boolean;
389 -- Return True if Dir is part of Path
391 ----------------
392 -- Is_Present --
393 ----------------
395 function Is_Present (Path : String; Dir : String) return Boolean is
396 Last : constant Integer := Path'Last - Dir'Length + 1;
398 begin
399 for J in Path'First .. Last loop
401 -- Note: the order of the conditions below is important, since
402 -- it ensures a minimal number of string comparisons.
404 if (J = Path'First
405 or else Path (J - 1) = Path_Separator)
406 and then
407 (J + Dir'Length > Path'Last
408 or else Path (J + Dir'Length) = Path_Separator)
409 and then Dir = Path (J .. J + Dir'Length - 1)
410 then
411 return True;
412 end if;
413 end loop;
415 return False;
416 end Is_Present;
418 -- Start of processing for Add_To_Path
420 begin
421 if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
423 -- Dir is already in the path, nothing to do
425 return;
426 end if;
428 Min_Len := Ada_Path_Length + Dir'Length;
430 if Ada_Path_Length > 0 then
432 -- Add 1 for the Path_Separator character
434 Min_Len := Min_Len + 1;
435 end if;
437 -- If Ada_Path_Buffer is too small, increase it
439 Len := Ada_Path_Buffer'Last;
441 if Len < Min_Len then
442 loop
443 Len := Len * 2;
444 exit when Len >= Min_Len;
445 end loop;
447 New_Buffer := new String (1 .. Len);
448 New_Buffer (1 .. Ada_Path_Length) :=
449 Ada_Path_Buffer (1 .. Ada_Path_Length);
450 Free (Ada_Path_Buffer);
451 Ada_Path_Buffer := New_Buffer;
452 end if;
454 if Ada_Path_Length > 0 then
455 Ada_Path_Length := Ada_Path_Length + 1;
456 Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
457 end if;
459 Ada_Path_Buffer
460 (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
461 Ada_Path_Length := Ada_Path_Length + Dir'Length;
462 end Add_To_Path;
464 ------------------------
465 -- Add_To_Source_Path --
466 ------------------------
468 procedure Add_To_Source_Path
469 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
471 Current : String_List_Id := Source_Dirs;
472 Source_Dir : String_Element;
473 Add_It : Boolean;
475 begin
476 -- Add each source directory
478 while Current /= Nil_String loop
479 Source_Dir := In_Tree.String_Elements.Table (Current);
480 Add_It := True;
482 -- Check if the source directory is already in the table
484 for Index in Source_Path_Table.First ..
485 Source_Path_Table.Last
486 (In_Tree.Private_Part.Source_Paths)
487 loop
488 -- If it is already, no need to add it
490 if In_Tree.Private_Part.Source_Paths.Table (Index) =
491 Source_Dir.Value
492 then
493 Add_It := False;
494 exit;
495 end if;
496 end loop;
498 if Add_It then
499 Source_Path_Table.Increment_Last
500 (In_Tree.Private_Part.Source_Paths);
501 In_Tree.Private_Part.Source_Paths.Table
502 (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
503 Source_Dir.Value;
504 end if;
506 -- Next source directory
508 Current := Source_Dir.Next;
509 end loop;
510 end Add_To_Source_Path;
512 -----------------------
513 -- Body_Path_Name_Of --
514 -----------------------
516 function Body_Path_Name_Of
517 (Unit : Unit_Index;
518 In_Tree : Project_Tree_Ref) return String
520 Data : Unit_Data := In_Tree.Units.Table (Unit);
522 begin
523 -- If we don't know the path name of the body of this unit,
524 -- we compute it, and we store it.
526 if Data.File_Names (Body_Part).Path = No_Path_Information then
527 declare
528 Current_Source : String_List_Id :=
529 In_Tree.Projects.Table
530 (Data.File_Names (Body_Part).Project).Ada_Sources;
531 Path : GNAT.OS_Lib.String_Access;
533 begin
534 -- By default, put the file name
536 Data.File_Names (Body_Part).Path.Name :=
537 Path_Name_Type (Data.File_Names (Body_Part).Name);
539 -- For each source directory
541 while Current_Source /= Nil_String loop
542 Path :=
543 Locate_Regular_File
544 (Namet.Get_Name_String
545 (Data.File_Names (Body_Part).Name),
546 Namet.Get_Name_String
547 (In_Tree.String_Elements.Table
548 (Current_Source).Value));
550 -- If the file is in this directory, then we store the path,
551 -- and we are done.
553 if Path /= null then
554 Name_Len := Path'Length;
555 Name_Buffer (1 .. Name_Len) := Path.all;
556 Data.File_Names (Body_Part).Path.Name := Name_Enter;
557 exit;
559 else
560 Current_Source :=
561 In_Tree.String_Elements.Table
562 (Current_Source).Next;
563 end if;
564 end loop;
566 In_Tree.Units.Table (Unit) := Data;
567 end;
568 end if;
570 -- Returned the stored value
572 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path.Name);
573 end Body_Path_Name_Of;
575 ------------------------
576 -- Contains_ALI_Files --
577 ------------------------
579 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
580 Dir_Name : constant String := Get_Name_String (Dir);
581 Direct : Dir_Type;
582 Name : String (1 .. 1_000);
583 Last : Natural;
584 Result : Boolean := False;
586 begin
587 Open (Direct, Dir_Name);
589 -- For each file in the directory, check if it is an ALI file
591 loop
592 Read (Direct, Name, Last);
593 exit when Last = 0;
594 Canonical_Case_File_Name (Name (1 .. Last));
595 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
596 exit when Result;
597 end loop;
599 Close (Direct);
600 return Result;
602 exception
603 -- If there is any problem, close the directory if open and return
604 -- True; the library directory will be added to the path.
606 when others =>
607 if Is_Open (Direct) then
608 Close (Direct);
609 end if;
611 return True;
612 end Contains_ALI_Files;
614 --------------------------------
615 -- Create_Config_Pragmas_File --
616 --------------------------------
618 procedure Create_Config_Pragmas_File
619 (For_Project : Project_Id;
620 Main_Project : Project_Id;
621 In_Tree : Project_Tree_Ref;
622 Include_Config_Files : Boolean := True)
624 pragma Unreferenced (Main_Project);
625 pragma Unreferenced (Include_Config_Files);
627 File_Name : Path_Name_Type := No_Path;
628 File : File_Descriptor := Invalid_FD;
630 Current_Unit : Unit_Index := Unit_Table.First;
632 First_Project : Project_List := Empty_Project_List;
634 Current_Project : Project_List;
635 Current_Naming : Naming_Id;
637 Status : Boolean;
638 -- For call to Close
640 procedure Check (Project : Project_Id);
641 -- Recursive procedure that put in the config pragmas file any non
642 -- standard naming schemes, if it is not already in the file, then call
643 -- itself for any imported project.
645 procedure Check_Temp_File;
646 -- Check that a temporary file has been opened.
647 -- If not, create one, and put its name in the project data,
648 -- with the indication that it is a temporary file.
650 procedure Put
651 (Unit_Name : Name_Id;
652 File_Name : File_Name_Type;
653 Unit_Kind : Spec_Or_Body;
654 Index : Int);
655 -- Put an SFN pragma in the temporary file
657 procedure Put (File : File_Descriptor; S : String);
658 procedure Put_Line (File : File_Descriptor; S : String);
659 -- Output procedures, analogous to normal Text_IO procs of same name
661 -----------
662 -- Check --
663 -----------
665 procedure Check (Project : Project_Id) is
666 Data : constant Project_Data :=
667 In_Tree.Projects.Table (Project);
669 begin
670 if Current_Verbosity = High then
671 Write_Str ("Checking project file """);
672 Write_Str (Namet.Get_Name_String (Data.Name));
673 Write_Str (""".");
674 Write_Eol;
675 end if;
677 -- Is this project in the list of the visited project?
679 Current_Project := First_Project;
680 while Current_Project /= Empty_Project_List
681 and then In_Tree.Project_Lists.Table
682 (Current_Project).Project /= Project
683 loop
684 Current_Project :=
685 In_Tree.Project_Lists.Table (Current_Project).Next;
686 end loop;
688 -- If it is not, put it in the list, and visit it
690 if Current_Project = Empty_Project_List then
691 Project_List_Table.Increment_Last
692 (In_Tree.Project_Lists);
693 In_Tree.Project_Lists.Table
694 (Project_List_Table.Last (In_Tree.Project_Lists)) :=
695 (Project => Project, Next => First_Project);
696 First_Project :=
697 Project_List_Table.Last (In_Tree.Project_Lists);
699 -- Is the naming scheme of this project one that we know?
701 Current_Naming := Default_Naming;
702 while Current_Naming <=
703 Naming_Table.Last (In_Tree.Private_Part.Namings)
704 and then not Same_Naming_Scheme
705 (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
706 Right => Data.Naming) loop
707 Current_Naming := Current_Naming + 1;
708 end loop;
710 -- If we don't know it, add it
712 if Current_Naming >
713 Naming_Table.Last (In_Tree.Private_Part.Namings)
714 then
715 Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
716 In_Tree.Private_Part.Namings.Table
717 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
718 Data.Naming;
720 -- We need a temporary file to be created
722 Check_Temp_File;
724 -- Put the SFN pragmas for the naming scheme
726 -- Spec
728 Put_Line
729 (File, "pragma Source_File_Name_Project");
730 Put_Line
731 (File, " (Spec_File_Name => ""*" &
732 Spec_Suffix_Of (In_Tree, "ada", Data.Naming) &
733 """,");
734 Put_Line
735 (File, " Casing => " &
736 Image (Data.Naming.Casing) & ",");
737 Put_Line
738 (File, " Dot_Replacement => """ &
739 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
740 """);");
742 -- and body
744 Put_Line
745 (File, "pragma Source_File_Name_Project");
746 Put_Line
747 (File, " (Body_File_Name => ""*" &
748 Body_Suffix_Of (In_Tree, "ada", Data.Naming) &
749 """,");
750 Put_Line
751 (File, " Casing => " &
752 Image (Data.Naming.Casing) & ",");
753 Put_Line
754 (File, " Dot_Replacement => """ &
755 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
756 """);");
758 -- and maybe separate
760 if Body_Suffix_Of (In_Tree, "ada", Data.Naming) /=
761 Get_Name_String (Data.Naming.Separate_Suffix)
762 then
763 Put_Line
764 (File, "pragma Source_File_Name_Project");
765 Put_Line
766 (File, " (Subunit_File_Name => ""*" &
767 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
768 """,");
769 Put_Line
770 (File, " Casing => " &
771 Image (Data.Naming.Casing) &
772 ",");
773 Put_Line
774 (File, " Dot_Replacement => """ &
775 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
776 """);");
777 end if;
778 end if;
780 if Data.Extends /= No_Project then
781 Check (Data.Extends);
782 end if;
784 declare
785 Current : Project_List := Data.Imported_Projects;
787 begin
788 while Current /= Empty_Project_List loop
789 Check
790 (In_Tree.Project_Lists.Table
791 (Current).Project);
792 Current := In_Tree.Project_Lists.Table
793 (Current).Next;
794 end loop;
795 end;
796 end if;
797 end Check;
799 ---------------------
800 -- Check_Temp_File --
801 ---------------------
803 procedure Check_Temp_File is
804 begin
805 if File = Invalid_FD then
806 Tempdir.Create_Temp_File (File, Name => File_Name);
808 if File = Invalid_FD then
809 Prj.Com.Fail
810 ("unable to create temporary configuration pragmas file");
812 else
813 Record_Temp_File (File_Name);
815 if Opt.Verbose_Mode then
816 Write_Str ("Creating temp file """);
817 Write_Str (Get_Name_String (File_Name));
818 Write_Line ("""");
819 end if;
820 end if;
821 end if;
822 end Check_Temp_File;
824 ---------
825 -- Put --
826 ---------
828 procedure Put
829 (Unit_Name : Name_Id;
830 File_Name : File_Name_Type;
831 Unit_Kind : Spec_Or_Body;
832 Index : Int)
834 begin
835 -- A temporary file needs to be open
837 Check_Temp_File;
839 -- Put the pragma SFN for the unit kind (spec or body)
841 Put (File, "pragma Source_File_Name_Project (");
842 Put (File, Namet.Get_Name_String (Unit_Name));
844 if Unit_Kind = Specification then
845 Put (File, ", Spec_File_Name => """);
846 else
847 Put (File, ", Body_File_Name => """);
848 end if;
850 Put (File, Namet.Get_Name_String (File_Name));
851 Put (File, """");
853 if Index /= 0 then
854 Put (File, ", Index =>");
855 Put (File, Index'Img);
856 end if;
858 Put_Line (File, ");");
859 end Put;
861 procedure Put (File : File_Descriptor; S : String) is
862 Last : Natural;
864 begin
865 Last := Write (File, S (S'First)'Address, S'Length);
867 if Last /= S'Length then
868 Prj.Com.Fail ("Disk full");
869 end if;
871 if Current_Verbosity = High then
872 Write_Str (S);
873 end if;
874 end Put;
876 --------------
877 -- Put_Line --
878 --------------
880 procedure Put_Line (File : File_Descriptor; S : String) is
881 S0 : String (1 .. S'Length + 1);
882 Last : Natural;
884 begin
885 -- Add an ASCII.LF to the string. As this config file is supposed to
886 -- be used only by the compiler, we don't care about the characters
887 -- for the end of line. In fact we could have put a space, but
888 -- it is more convenient to be able to read gnat.adc during
889 -- development, for which the ASCII.LF is fine.
891 S0 (1 .. S'Length) := S;
892 S0 (S0'Last) := ASCII.LF;
893 Last := Write (File, S0'Address, S0'Length);
895 if Last /= S'Length + 1 then
896 Prj.Com.Fail ("Disk full");
897 end if;
899 if Current_Verbosity = High then
900 Write_Line (S);
901 end if;
902 end Put_Line;
904 -- Start of processing for Create_Config_Pragmas_File
906 begin
907 if not
908 In_Tree.Projects.Table (For_Project).Config_Checked
909 then
911 -- Remove any memory of processed naming schemes, if any
913 Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
915 -- Check the naming schemes
917 Check (For_Project);
919 -- Visit all the units and process those that need an SFN pragma
921 while
922 Current_Unit <= Unit_Table.Last (In_Tree.Units)
923 loop
924 declare
925 Unit : constant Unit_Data :=
926 In_Tree.Units.Table (Current_Unit);
928 begin
929 if Unit.File_Names (Specification).Needs_Pragma then
930 Put (Unit.Name,
931 Unit.File_Names (Specification).Name,
932 Specification,
933 Unit.File_Names (Specification).Index);
934 end if;
936 if Unit.File_Names (Body_Part).Needs_Pragma then
937 Put (Unit.Name,
938 Unit.File_Names (Body_Part).Name,
939 Body_Part,
940 Unit.File_Names (Body_Part).Index);
941 end if;
943 Current_Unit := Current_Unit + 1;
944 end;
945 end loop;
947 -- If there are no non standard naming scheme, issue the GNAT
948 -- standard naming scheme. This will tell the compiler that
949 -- a project file is used and will forbid any pragma SFN.
951 if File = Invalid_FD then
952 Check_Temp_File;
954 Put_Line (File, "pragma Source_File_Name_Project");
955 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
956 Put_Line (File, " Dot_Replacement => ""-"",");
957 Put_Line (File, " Casing => lowercase);");
959 Put_Line (File, "pragma Source_File_Name_Project");
960 Put_Line (File, " (Body_File_Name => ""*.adb"",");
961 Put_Line (File, " Dot_Replacement => ""-"",");
962 Put_Line (File, " Casing => lowercase);");
963 end if;
965 -- Close the temporary file
967 GNAT.OS_Lib.Close (File, Status);
969 if not Status then
970 Prj.Com.Fail ("disk full");
971 end if;
973 if Opt.Verbose_Mode then
974 Write_Str ("Closing configuration file """);
975 Write_Str (Get_Name_String (File_Name));
976 Write_Line ("""");
977 end if;
979 In_Tree.Projects.Table (For_Project).Config_File_Name :=
980 File_Name;
981 In_Tree.Projects.Table (For_Project).Config_File_Temp :=
982 True;
984 In_Tree.Projects.Table (For_Project).Config_Checked :=
985 True;
986 end if;
987 end Create_Config_Pragmas_File;
989 --------------------
990 -- Create_Mapping --
991 --------------------
993 procedure Create_Mapping (In_Tree : Project_Tree_Ref) is
994 The_Unit_Data : Unit_Data;
995 Data : File_Name_Data;
997 begin
998 Fmap.Reset_Tables;
1000 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1001 The_Unit_Data := In_Tree.Units.Table (Unit);
1003 -- Process only if the unit has a valid name
1005 if The_Unit_Data.Name /= No_Name then
1006 Data := The_Unit_Data.File_Names (Specification);
1008 -- If there is a spec, put it in the mapping
1010 if Data.Name /= No_File then
1011 if Data.Path.Name = Slash then
1012 Fmap.Add_Forbidden_File_Name (Data.Name);
1013 else
1014 Fmap.Add_To_File_Map
1015 (Unit_Name => Unit_Name_Type (The_Unit_Data.Name),
1016 File_Name => Data.Name,
1017 Path_Name => File_Name_Type (Data.Path.Name));
1018 end if;
1019 end if;
1021 Data := The_Unit_Data.File_Names (Body_Part);
1023 -- If there is a body (or subunit) put it in the mapping
1025 if Data.Name /= No_File then
1026 if Data.Path.Name = Slash then
1027 Fmap.Add_Forbidden_File_Name (Data.Name);
1028 else
1029 Fmap.Add_To_File_Map
1030 (Unit_Name => Unit_Name_Type (The_Unit_Data.Name),
1031 File_Name => Data.Name,
1032 Path_Name => File_Name_Type (Data.Path.Name));
1033 end if;
1034 end if;
1035 end if;
1036 end loop;
1037 end Create_Mapping;
1039 -------------------------
1040 -- Create_Mapping_File --
1041 -------------------------
1043 procedure Create_Mapping_File
1044 (Project : Project_Id;
1045 In_Tree : Project_Tree_Ref;
1046 Name : out Path_Name_Type)
1048 File : File_Descriptor := Invalid_FD;
1049 The_Unit_Data : Unit_Data;
1050 Data : File_Name_Data;
1052 Status : Boolean;
1053 -- For call to Close
1055 Present : Project_Flags
1056 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1057 (others => False);
1058 -- For each project in the closure of Project, the corresponding flag
1059 -- will be set to True;
1061 procedure Put_Name_Buffer;
1062 -- Put the line contained in the Name_Buffer in the mapping file
1064 procedure Put_Data (Spec : Boolean);
1065 -- Put the mapping of the spec or body contained in Data in the file
1066 -- (3 lines).
1068 procedure Recursive_Flag (Prj : Project_Id);
1069 -- Set the flags corresponding to Prj, the projects it imports
1070 -- (directly or indirectly) or extends to True. Call itself recursively.
1072 ---------
1073 -- Put --
1074 ---------
1076 procedure Put_Name_Buffer is
1077 Last : Natural;
1079 begin
1080 Name_Len := Name_Len + 1;
1081 Name_Buffer (Name_Len) := ASCII.LF;
1082 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1084 if Last /= Name_Len then
1085 Prj.Com.Fail ("Disk full");
1086 end if;
1087 end Put_Name_Buffer;
1089 --------------
1090 -- Put_Data --
1091 --------------
1093 procedure Put_Data (Spec : Boolean) is
1094 begin
1095 -- Line with the unit name
1097 Get_Name_String (The_Unit_Data.Name);
1098 Name_Len := Name_Len + 1;
1099 Name_Buffer (Name_Len) := '%';
1100 Name_Len := Name_Len + 1;
1102 if Spec then
1103 Name_Buffer (Name_Len) := 's';
1104 else
1105 Name_Buffer (Name_Len) := 'b';
1106 end if;
1108 Put_Name_Buffer;
1110 -- Line with the file name
1112 Get_Name_String (Data.Name);
1113 Put_Name_Buffer;
1115 -- Line with the path name
1117 Get_Name_String (Data.Path.Name);
1118 Put_Name_Buffer;
1120 end Put_Data;
1122 --------------------
1123 -- Recursive_Flag --
1124 --------------------
1126 procedure Recursive_Flag (Prj : Project_Id) is
1127 Imported : Project_List;
1128 Proj : Project_Id;
1130 begin
1131 -- Nothing to do for non existent project or project that has
1132 -- already been flagged.
1134 if Prj = No_Project or else Present (Prj) then
1135 return;
1136 end if;
1138 -- Flag the current project
1140 Present (Prj) := True;
1141 Imported :=
1142 In_Tree.Projects.Table (Prj).Imported_Projects;
1144 -- Call itself for each project directly imported
1146 while Imported /= Empty_Project_List loop
1147 Proj :=
1148 In_Tree.Project_Lists.Table (Imported).Project;
1149 Imported :=
1150 In_Tree.Project_Lists.Table (Imported).Next;
1151 Recursive_Flag (Proj);
1152 end loop;
1154 -- Call itself for an eventual project being extended
1156 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1157 end Recursive_Flag;
1159 -- Start of processing for Create_Mapping_File
1161 begin
1162 -- Flag the necessary projects
1164 Recursive_Flag (Project);
1166 -- Create the temporary file
1168 Tempdir.Create_Temp_File (File, Name => Name);
1170 if File = Invalid_FD then
1171 Prj.Com.Fail ("unable to create temporary mapping file");
1173 else
1174 Record_Temp_File (Name);
1176 if Opt.Verbose_Mode then
1177 Write_Str ("Creating temp mapping file """);
1178 Write_Str (Get_Name_String (Name));
1179 Write_Line ("""");
1180 end if;
1181 end if;
1183 if Fill_Mapping_File then
1185 -- For all units in table Units
1187 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1188 The_Unit_Data := In_Tree.Units.Table (Unit);
1190 -- If the unit has a valid name
1192 if The_Unit_Data.Name /= No_Name then
1193 Data := The_Unit_Data.File_Names (Specification);
1195 -- If there is a spec, put it mapping in the file if it is
1196 -- from a project in the closure of Project.
1198 if Data.Name /= No_File and then Present (Data.Project) then
1199 Put_Data (Spec => True);
1200 end if;
1202 Data := The_Unit_Data.File_Names (Body_Part);
1204 -- If there is a body (or subunit) put its mapping in the file
1205 -- if it is from a project in the closure of Project.
1207 if Data.Name /= No_File and then Present (Data.Project) then
1208 Put_Data (Spec => False);
1209 end if;
1211 end if;
1212 end loop;
1213 end if;
1215 GNAT.OS_Lib.Close (File, Status);
1217 if not Status then
1218 Prj.Com.Fail ("disk full");
1219 end if;
1220 end Create_Mapping_File;
1222 procedure Create_Mapping_File
1223 (Project : Project_Id;
1224 Language : Name_Id;
1225 In_Tree : Project_Tree_Ref;
1226 Name : out Path_Name_Type)
1228 File : File_Descriptor := Invalid_FD;
1230 Status : Boolean;
1231 -- For call to Close
1233 Present : Project_Flags
1234 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1235 (others => False);
1236 -- For each project in the closure of Project, the corresponding flag
1237 -- will be set to True.
1239 Source : Source_Id;
1240 Src_Data : Source_Data;
1241 Suffix : File_Name_Type;
1243 procedure Put_Name_Buffer;
1244 -- Put the line contained in the Name_Buffer in the mapping file
1246 procedure Recursive_Flag (Prj : Project_Id);
1247 -- Set the flags corresponding to Prj, the projects it imports
1248 -- (directly or indirectly) or extends to True. Call itself recursively.
1250 ---------
1251 -- Put --
1252 ---------
1254 procedure Put_Name_Buffer is
1255 Last : Natural;
1257 begin
1258 Name_Len := Name_Len + 1;
1259 Name_Buffer (Name_Len) := ASCII.LF;
1260 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1262 if Last /= Name_Len then
1263 Prj.Com.Fail ("Disk full");
1264 end if;
1265 end Put_Name_Buffer;
1267 --------------------
1268 -- Recursive_Flag --
1269 --------------------
1271 procedure Recursive_Flag (Prj : Project_Id) is
1272 Imported : Project_List;
1273 Proj : Project_Id;
1275 begin
1276 -- Nothing to do for non existent project or project that has already
1277 -- been flagged.
1279 if Prj = No_Project or else Present (Prj) then
1280 return;
1281 end if;
1283 -- Flag the current project
1285 Present (Prj) := True;
1286 Imported :=
1287 In_Tree.Projects.Table (Prj).Imported_Projects;
1289 -- Call itself for each project directly imported
1291 while Imported /= Empty_Project_List loop
1292 Proj :=
1293 In_Tree.Project_Lists.Table (Imported).Project;
1294 Imported :=
1295 In_Tree.Project_Lists.Table (Imported).Next;
1296 Recursive_Flag (Proj);
1297 end loop;
1299 -- Call itself for an eventual project being extended
1301 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1302 end Recursive_Flag;
1304 -- Start of processing for Create_Mapping_File
1306 begin
1307 -- Flag the necessary projects
1309 Recursive_Flag (Project);
1311 -- Create the temporary file
1313 Tempdir.Create_Temp_File (File, Name => Name);
1315 if File = Invalid_FD then
1316 Prj.Com.Fail ("unable to create temporary mapping file");
1318 else
1319 Record_Temp_File (Name);
1321 if Opt.Verbose_Mode then
1322 Write_Str ("Creating temp mapping file """);
1323 Write_Str (Get_Name_String (Name));
1324 Write_Line ("""");
1325 end if;
1326 end if;
1328 -- For all source of the Language of all projects in the closure
1330 for Proj in Present'Range loop
1331 if Present (Proj) then
1332 Source := In_Tree.Projects.Table (Proj).First_Source;
1334 while Source /= No_Source loop
1335 Src_Data := In_Tree.Sources.Table (Source);
1337 if Src_Data.Language_Name = Language
1338 and then not Src_Data.Locally_Removed
1339 and then Src_Data.Replaced_By = No_Source
1340 and then Src_Data.Path.Name /= No_Path
1341 then
1342 if Src_Data.Unit /= No_Name then
1343 Get_Name_String (Src_Data.Unit);
1345 if Src_Data.Kind = Spec then
1346 Suffix :=
1347 In_Tree.Languages_Data.Table
1348 (Src_Data.Language).Config.Mapping_Spec_Suffix;
1349 else
1350 Suffix :=
1351 In_Tree.Languages_Data.Table
1352 (Src_Data.Language).Config.Mapping_Body_Suffix;
1353 end if;
1355 if Suffix /= No_File then
1356 Add_Str_To_Name_Buffer (Get_Name_String (Suffix));
1357 end if;
1359 Put_Name_Buffer;
1360 end if;
1362 Get_Name_String (Src_Data.File);
1363 Put_Name_Buffer;
1365 Get_Name_String (Src_Data.Path.Name);
1366 Put_Name_Buffer;
1367 end if;
1369 Source := Src_Data.Next_In_Project;
1370 end loop;
1371 end if;
1372 end loop;
1374 GNAT.OS_Lib.Close (File, Status);
1376 if not Status then
1377 Prj.Com.Fail ("disk full");
1378 end if;
1379 end Create_Mapping_File;
1381 --------------------------
1382 -- Create_New_Path_File --
1383 --------------------------
1385 procedure Create_New_Path_File
1386 (In_Tree : Project_Tree_Ref;
1387 Path_FD : out File_Descriptor;
1388 Path_Name : out Path_Name_Type)
1390 begin
1391 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1393 if Path_Name /= No_Path then
1394 Record_Temp_File (Path_Name);
1396 -- Record the name, so that the temp path file will be deleted at the
1397 -- end of the program.
1399 Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1400 In_Tree.Private_Part.Path_Files.Table
1401 (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1402 Path_Name;
1403 end if;
1404 end Create_New_Path_File;
1406 ---------------------------
1407 -- Delete_All_Path_Files --
1408 ---------------------------
1410 procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1411 Disregard : Boolean := True;
1412 pragma Warnings (Off, Disregard);
1414 begin
1415 for Index in Path_File_Table.First ..
1416 Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1417 loop
1418 if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Path then
1419 Delete_File
1420 (Get_Name_String
1421 (In_Tree.Private_Part.Path_Files.Table (Index)),
1422 Disregard);
1423 end if;
1424 end loop;
1426 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1427 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1428 -- the empty string. On VMS, this has the effect of deassigning
1429 -- the logical names.
1431 if Ada_Prj_Include_File_Set then
1432 Setenv (Project_Include_Path_File, "");
1433 Ada_Prj_Include_File_Set := False;
1434 end if;
1436 if Ada_Prj_Objects_File_Set then
1437 Setenv (Project_Objects_Path_File, "");
1438 Ada_Prj_Objects_File_Set := False;
1439 end if;
1440 end Delete_All_Path_Files;
1442 ------------------------------------
1443 -- File_Name_Of_Library_Unit_Body --
1444 ------------------------------------
1446 function File_Name_Of_Library_Unit_Body
1447 (Name : String;
1448 Project : Project_Id;
1449 In_Tree : Project_Tree_Ref;
1450 Main_Project_Only : Boolean := True;
1451 Full_Path : Boolean := False) return String
1453 The_Project : Project_Id := Project;
1454 Data : Project_Data :=
1455 In_Tree.Projects.Table (Project);
1456 Original_Name : String := Name;
1458 Extended_Spec_Name : String :=
1459 Name &
1460 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1461 Extended_Body_Name : String :=
1462 Name &
1463 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1465 Unit : Unit_Data;
1467 The_Original_Name : Name_Id;
1468 The_Spec_Name : Name_Id;
1469 The_Body_Name : Name_Id;
1471 begin
1472 Canonical_Case_File_Name (Original_Name);
1473 Name_Len := Original_Name'Length;
1474 Name_Buffer (1 .. Name_Len) := Original_Name;
1475 The_Original_Name := Name_Find;
1477 Canonical_Case_File_Name (Extended_Spec_Name);
1478 Name_Len := Extended_Spec_Name'Length;
1479 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1480 The_Spec_Name := Name_Find;
1482 Canonical_Case_File_Name (Extended_Body_Name);
1483 Name_Len := Extended_Body_Name'Length;
1484 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1485 The_Body_Name := Name_Find;
1487 if Current_Verbosity = High then
1488 Write_Str ("Looking for file name of """);
1489 Write_Str (Name);
1490 Write_Char ('"');
1491 Write_Eol;
1492 Write_Str (" Extended Spec Name = """);
1493 Write_Str (Extended_Spec_Name);
1494 Write_Char ('"');
1495 Write_Eol;
1496 Write_Str (" Extended Body Name = """);
1497 Write_Str (Extended_Body_Name);
1498 Write_Char ('"');
1499 Write_Eol;
1500 end if;
1502 -- For extending project, search in the extended project if the source
1503 -- is not found. For non extending projects, this loop will be run only
1504 -- once.
1506 loop
1507 -- Loop through units
1508 -- Should have comment explaining reverse ???
1510 for Current in reverse Unit_Table.First ..
1511 Unit_Table.Last (In_Tree.Units)
1512 loop
1513 Unit := In_Tree.Units.Table (Current);
1515 -- Check for body
1517 if not Main_Project_Only
1518 or else Unit.File_Names (Body_Part).Project = The_Project
1519 then
1520 declare
1521 Current_Name : constant File_Name_Type :=
1522 Unit.File_Names (Body_Part).Name;
1524 begin
1525 -- Case of a body present
1527 if Current_Name /= No_File then
1528 if Current_Verbosity = High then
1529 Write_Str (" Comparing with """);
1530 Write_Str (Get_Name_String (Current_Name));
1531 Write_Char ('"');
1532 Write_Eol;
1533 end if;
1535 -- If it has the name of the original name, return the
1536 -- original name.
1538 if Unit.Name = The_Original_Name
1539 or else
1540 Current_Name = File_Name_Type (The_Original_Name)
1541 then
1542 if Current_Verbosity = High then
1543 Write_Line (" OK");
1544 end if;
1546 if Full_Path then
1547 return Get_Name_String
1548 (Unit.File_Names (Body_Part).Path.Name);
1550 else
1551 return Get_Name_String (Current_Name);
1552 end if;
1554 -- If it has the name of the extended body name,
1555 -- return the extended body name
1557 elsif Current_Name = File_Name_Type (The_Body_Name) then
1558 if Current_Verbosity = High then
1559 Write_Line (" OK");
1560 end if;
1562 if Full_Path then
1563 return Get_Name_String
1564 (Unit.File_Names (Body_Part).Path.Name);
1566 else
1567 return Extended_Body_Name;
1568 end if;
1570 else
1571 if Current_Verbosity = High then
1572 Write_Line (" not good");
1573 end if;
1574 end if;
1575 end if;
1576 end;
1577 end if;
1579 -- Check for spec
1581 if not Main_Project_Only
1582 or else Unit.File_Names (Specification).Project = The_Project
1583 then
1584 declare
1585 Current_Name : constant File_Name_Type :=
1586 Unit.File_Names (Specification).Name;
1588 begin
1589 -- Case of spec present
1591 if Current_Name /= No_File then
1592 if Current_Verbosity = High then
1593 Write_Str (" Comparing with """);
1594 Write_Str (Get_Name_String (Current_Name));
1595 Write_Char ('"');
1596 Write_Eol;
1597 end if;
1599 -- If name same as original name, return original name
1601 if Unit.Name = The_Original_Name
1602 or else
1603 Current_Name = File_Name_Type (The_Original_Name)
1604 then
1605 if Current_Verbosity = High then
1606 Write_Line (" OK");
1607 end if;
1609 if Full_Path then
1610 return Get_Name_String
1611 (Unit.File_Names (Specification).Path.Name);
1612 else
1613 return Get_Name_String (Current_Name);
1614 end if;
1616 -- If it has the same name as the extended spec name,
1617 -- return the extended spec name.
1619 elsif Current_Name = File_Name_Type (The_Spec_Name) then
1620 if Current_Verbosity = High then
1621 Write_Line (" OK");
1622 end if;
1624 if Full_Path then
1625 return Get_Name_String
1626 (Unit.File_Names (Specification).Path.Name);
1627 else
1628 return Extended_Spec_Name;
1629 end if;
1631 else
1632 if Current_Verbosity = High then
1633 Write_Line (" not good");
1634 end if;
1635 end if;
1636 end if;
1637 end;
1638 end if;
1639 end loop;
1641 -- If we are not in an extending project, give up
1643 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1645 -- Otherwise, look in the project we are extending
1647 The_Project := Data.Extends;
1648 Data := In_Tree.Projects.Table (The_Project);
1649 end loop;
1651 -- We don't know this file name, return an empty string
1653 return "";
1654 end File_Name_Of_Library_Unit_Body;
1656 -------------------------
1657 -- For_All_Object_Dirs --
1658 -------------------------
1660 procedure For_All_Object_Dirs
1661 (Project : Project_Id;
1662 In_Tree : Project_Tree_Ref)
1664 Seen : Project_List := Empty_Project_List;
1666 procedure Add (Project : Project_Id);
1667 -- Process a project. Remember the processes visited to avoid processing
1668 -- a project twice. Recursively process an eventual extended project,
1669 -- and all imported projects.
1671 ---------
1672 -- Add --
1673 ---------
1675 procedure Add (Project : Project_Id) is
1676 Data : constant Project_Data :=
1677 In_Tree.Projects.Table (Project);
1678 List : Project_List := Data.Imported_Projects;
1680 begin
1681 -- If the list of visited project is empty, then
1682 -- for sure we never visited this project.
1684 if Seen = Empty_Project_List then
1685 Project_List_Table.Increment_Last (In_Tree.Project_Lists);
1686 Seen := Project_List_Table.Last (In_Tree.Project_Lists);
1687 In_Tree.Project_Lists.Table (Seen) :=
1688 (Project => Project, Next => Empty_Project_List);
1690 else
1691 -- Check if the project is in the list
1693 declare
1694 Current : Project_List := Seen;
1696 begin
1697 loop
1698 -- If it is, then there is nothing else to do
1700 if In_Tree.Project_Lists.Table
1701 (Current).Project = Project
1702 then
1703 return;
1704 end if;
1706 exit when
1707 In_Tree.Project_Lists.Table (Current).Next =
1708 Empty_Project_List;
1709 Current :=
1710 In_Tree.Project_Lists.Table (Current).Next;
1711 end loop;
1713 -- This project has never been visited, add it
1714 -- to the list.
1716 Project_List_Table.Increment_Last
1717 (In_Tree.Project_Lists);
1718 In_Tree.Project_Lists.Table (Current).Next :=
1719 Project_List_Table.Last (In_Tree.Project_Lists);
1720 In_Tree.Project_Lists.Table
1721 (Project_List_Table.Last
1722 (In_Tree.Project_Lists)) :=
1723 (Project => Project, Next => Empty_Project_List);
1724 end;
1725 end if;
1727 -- If there is an object directory, call Action with its name
1729 if Data.Object_Directory /= No_Path_Information then
1730 Get_Name_String (Data.Object_Directory.Display_Name);
1731 Action (Name_Buffer (1 .. Name_Len));
1732 end if;
1734 -- If we are extending a project, visit it
1736 if Data.Extends /= No_Project then
1737 Add (Data.Extends);
1738 end if;
1740 -- And visit all imported projects
1742 while List /= Empty_Project_List loop
1743 Add (In_Tree.Project_Lists.Table (List).Project);
1744 List := In_Tree.Project_Lists.Table (List).Next;
1745 end loop;
1746 end Add;
1748 -- Start of processing for For_All_Object_Dirs
1750 begin
1751 -- Visit this project, and its imported projects, recursively
1753 Add (Project);
1754 end For_All_Object_Dirs;
1756 -------------------------
1757 -- For_All_Source_Dirs --
1758 -------------------------
1760 procedure For_All_Source_Dirs
1761 (Project : Project_Id;
1762 In_Tree : Project_Tree_Ref)
1764 Seen : Project_List := Empty_Project_List;
1766 procedure Add (Project : Project_Id);
1767 -- Process a project. Remember the processes visited to avoid processing
1768 -- a project twice. Recursively process an eventual extended project,
1769 -- and all imported projects.
1771 ---------
1772 -- Add --
1773 ---------
1775 procedure Add (Project : Project_Id) is
1776 Data : constant Project_Data :=
1777 In_Tree.Projects.Table (Project);
1778 List : Project_List := Data.Imported_Projects;
1780 begin
1781 -- If the list of visited project is empty, then for sure we never
1782 -- visited this project.
1784 if Seen = Empty_Project_List then
1785 Project_List_Table.Increment_Last
1786 (In_Tree.Project_Lists);
1787 Seen := Project_List_Table.Last
1788 (In_Tree.Project_Lists);
1789 In_Tree.Project_Lists.Table (Seen) :=
1790 (Project => Project, Next => Empty_Project_List);
1792 else
1793 -- Check if the project is in the list
1795 declare
1796 Current : Project_List := Seen;
1798 begin
1799 loop
1800 -- If it is, then there is nothing else to do
1802 if In_Tree.Project_Lists.Table
1803 (Current).Project = Project
1804 then
1805 return;
1806 end if;
1808 exit when
1809 In_Tree.Project_Lists.Table (Current).Next =
1810 Empty_Project_List;
1811 Current :=
1812 In_Tree.Project_Lists.Table (Current).Next;
1813 end loop;
1815 -- This project has never been visited, add it to the list
1817 Project_List_Table.Increment_Last
1818 (In_Tree.Project_Lists);
1819 In_Tree.Project_Lists.Table (Current).Next :=
1820 Project_List_Table.Last (In_Tree.Project_Lists);
1821 In_Tree.Project_Lists.Table
1822 (Project_List_Table.Last
1823 (In_Tree.Project_Lists)) :=
1824 (Project => Project, Next => Empty_Project_List);
1825 end;
1826 end if;
1828 declare
1829 Current : String_List_Id := Data.Source_Dirs;
1830 The_String : String_Element;
1832 begin
1833 -- If there are Ada sources, call action with the name of every
1834 -- source directory.
1837 In_Tree.Projects.Table (Project).Ada_Sources /= Nil_String
1838 then
1839 while Current /= Nil_String loop
1840 The_String :=
1841 In_Tree.String_Elements.Table (Current);
1842 Action (Get_Name_String (The_String.Display_Value));
1843 Current := The_String.Next;
1844 end loop;
1845 end if;
1846 end;
1848 -- If we are extending a project, visit it
1850 if Data.Extends /= No_Project then
1851 Add (Data.Extends);
1852 end if;
1854 -- And visit all imported projects
1856 while List /= Empty_Project_List loop
1857 Add (In_Tree.Project_Lists.Table (List).Project);
1858 List := In_Tree.Project_Lists.Table (List).Next;
1859 end loop;
1860 end Add;
1862 -- Start of processing for For_All_Source_Dirs
1864 begin
1865 -- Visit this project, and its imported projects recursively
1867 Add (Project);
1868 end For_All_Source_Dirs;
1870 -------------------
1871 -- Get_Reference --
1872 -------------------
1874 procedure Get_Reference
1875 (Source_File_Name : String;
1876 In_Tree : Project_Tree_Ref;
1877 Project : out Project_Id;
1878 Path : out Path_Name_Type)
1880 begin
1881 -- Body below could use some comments ???
1883 if Current_Verbosity > Default then
1884 Write_Str ("Getting Reference_Of (""");
1885 Write_Str (Source_File_Name);
1886 Write_Str (""") ... ");
1887 end if;
1889 declare
1890 Original_Name : String := Source_File_Name;
1891 Unit : Unit_Data;
1893 begin
1894 Canonical_Case_File_Name (Original_Name);
1896 for Id in Unit_Table.First ..
1897 Unit_Table.Last (In_Tree.Units)
1898 loop
1899 Unit := In_Tree.Units.Table (Id);
1901 if (Unit.File_Names (Specification).Name /= No_File
1902 and then
1903 Namet.Get_Name_String
1904 (Unit.File_Names (Specification).Name) = Original_Name)
1905 or else (Unit.File_Names (Specification).Path /=
1906 No_Path_Information
1907 and then
1908 Namet.Get_Name_String
1909 (Unit.File_Names (Specification).Path.Name) =
1910 Original_Name)
1911 then
1912 Project := Ultimate_Extension_Of
1913 (Project => Unit.File_Names (Specification).Project,
1914 In_Tree => In_Tree);
1915 Path := Unit.File_Names (Specification).Path.Display_Name;
1917 if Current_Verbosity > Default then
1918 Write_Str ("Done: Specification.");
1919 Write_Eol;
1920 end if;
1922 return;
1924 elsif (Unit.File_Names (Body_Part).Name /= No_File
1925 and then
1926 Namet.Get_Name_String
1927 (Unit.File_Names (Body_Part).Name) = Original_Name)
1928 or else (Unit.File_Names (Body_Part).Path /= No_Path_Information
1929 and then Namet.Get_Name_String
1930 (Unit.File_Names (Body_Part).Path.Name) =
1931 Original_Name)
1932 then
1933 Project := Ultimate_Extension_Of
1934 (Project => Unit.File_Names (Body_Part).Project,
1935 In_Tree => In_Tree);
1936 Path := Unit.File_Names (Body_Part).Path.Display_Name;
1938 if Current_Verbosity > Default then
1939 Write_Str ("Done: Body.");
1940 Write_Eol;
1941 end if;
1943 return;
1944 end if;
1945 end loop;
1946 end;
1948 Project := No_Project;
1949 Path := No_Path;
1951 if Current_Verbosity > Default then
1952 Write_Str ("Cannot be found.");
1953 Write_Eol;
1954 end if;
1955 end Get_Reference;
1957 ----------------
1958 -- Initialize --
1959 ----------------
1961 procedure Initialize is
1962 begin
1963 Fill_Mapping_File := True;
1964 Current_Source_Path_File := No_Path;
1965 Current_Object_Path_File := No_Path;
1966 end Initialize;
1968 ------------------------------------
1969 -- Path_Name_Of_Library_Unit_Body --
1970 ------------------------------------
1972 -- Could use some comments in the body here ???
1974 function Path_Name_Of_Library_Unit_Body
1975 (Name : String;
1976 Project : Project_Id;
1977 In_Tree : Project_Tree_Ref) return String
1979 Data : constant Project_Data :=
1980 In_Tree.Projects.Table (Project);
1981 Original_Name : String := Name;
1983 Extended_Spec_Name : String :=
1984 Name &
1985 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1986 Extended_Body_Name : String :=
1987 Name &
1988 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1990 First : Unit_Index := Unit_Table.First;
1991 Current : Unit_Index;
1992 Unit : Unit_Data;
1994 begin
1995 Canonical_Case_File_Name (Original_Name);
1996 Canonical_Case_File_Name (Extended_Spec_Name);
1997 Canonical_Case_File_Name (Extended_Body_Name);
1999 if Current_Verbosity = High then
2000 Write_Str ("Looking for path name of """);
2001 Write_Str (Name);
2002 Write_Char ('"');
2003 Write_Eol;
2004 Write_Str (" Extended Spec Name = """);
2005 Write_Str (Extended_Spec_Name);
2006 Write_Char ('"');
2007 Write_Eol;
2008 Write_Str (" Extended Body Name = """);
2009 Write_Str (Extended_Body_Name);
2010 Write_Char ('"');
2011 Write_Eol;
2012 end if;
2014 while First <= Unit_Table.Last (In_Tree.Units)
2015 and then In_Tree.Units.Table
2016 (First).File_Names (Body_Part).Project /= Project
2017 loop
2018 First := First + 1;
2019 end loop;
2021 Current := First;
2022 while Current <= Unit_Table.Last (In_Tree.Units) loop
2023 Unit := In_Tree.Units.Table (Current);
2025 if Unit.File_Names (Body_Part).Project = Project
2026 and then Unit.File_Names (Body_Part).Name /= No_File
2027 then
2028 declare
2029 Current_Name : constant String :=
2030 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
2031 begin
2032 if Current_Verbosity = High then
2033 Write_Str (" Comparing with """);
2034 Write_Str (Current_Name);
2035 Write_Char ('"');
2036 Write_Eol;
2037 end if;
2039 if Current_Name = Original_Name then
2040 if Current_Verbosity = High then
2041 Write_Line (" OK");
2042 end if;
2044 return Body_Path_Name_Of (Current, In_Tree);
2046 elsif Current_Name = Extended_Body_Name then
2047 if Current_Verbosity = High then
2048 Write_Line (" OK");
2049 end if;
2051 return Body_Path_Name_Of (Current, In_Tree);
2053 else
2054 if Current_Verbosity = High then
2055 Write_Line (" not good");
2056 end if;
2057 end if;
2058 end;
2060 elsif Unit.File_Names (Specification).Name /= No_File then
2061 declare
2062 Current_Name : constant String :=
2063 Namet.Get_Name_String
2064 (Unit.File_Names (Specification).Name);
2066 begin
2067 if Current_Verbosity = High then
2068 Write_Str (" Comparing with """);
2069 Write_Str (Current_Name);
2070 Write_Char ('"');
2071 Write_Eol;
2072 end if;
2074 if Current_Name = Original_Name then
2075 if Current_Verbosity = High then
2076 Write_Line (" OK");
2077 end if;
2079 return Spec_Path_Name_Of (Current, In_Tree);
2081 elsif Current_Name = Extended_Spec_Name then
2082 if Current_Verbosity = High then
2083 Write_Line (" OK");
2084 end if;
2086 return Spec_Path_Name_Of (Current, In_Tree);
2088 else
2089 if Current_Verbosity = High then
2090 Write_Line (" not good");
2091 end if;
2092 end if;
2093 end;
2094 end if;
2095 Current := Current + 1;
2096 end loop;
2098 return "";
2099 end Path_Name_Of_Library_Unit_Body;
2101 -------------------
2102 -- Print_Sources --
2103 -------------------
2105 -- Could use some comments in this body ???
2107 procedure Print_Sources (In_Tree : Project_Tree_Ref) is
2108 Unit : Unit_Data;
2110 begin
2111 Write_Line ("List of Sources:");
2113 for Id in Unit_Table.First ..
2114 Unit_Table.Last (In_Tree.Units)
2115 loop
2116 Unit := In_Tree.Units.Table (Id);
2117 Write_Str (" ");
2118 Write_Line (Namet.Get_Name_String (Unit.Name));
2120 if Unit.File_Names (Specification).Name /= No_File then
2121 if Unit.File_Names (Specification).Project = No_Project then
2122 Write_Line (" No project");
2124 else
2125 Write_Str (" Project: ");
2126 Get_Name_String
2127 (In_Tree.Projects.Table
2128 (Unit.File_Names (Specification).Project).Path.Name);
2129 Write_Line (Name_Buffer (1 .. Name_Len));
2130 end if;
2132 Write_Str (" spec: ");
2133 Write_Line
2134 (Namet.Get_Name_String
2135 (Unit.File_Names (Specification).Name));
2136 end if;
2138 if Unit.File_Names (Body_Part).Name /= No_File then
2139 if Unit.File_Names (Body_Part).Project = No_Project then
2140 Write_Line (" No project");
2142 else
2143 Write_Str (" Project: ");
2144 Get_Name_String
2145 (In_Tree.Projects.Table
2146 (Unit.File_Names (Body_Part).Project).Path.Name);
2147 Write_Line (Name_Buffer (1 .. Name_Len));
2148 end if;
2150 Write_Str (" body: ");
2151 Write_Line
2152 (Namet.Get_Name_String
2153 (Unit.File_Names (Body_Part).Name));
2154 end if;
2155 end loop;
2157 Write_Line ("end of List of Sources.");
2158 end Print_Sources;
2160 ----------------
2161 -- Project_Of --
2162 ----------------
2164 function Project_Of
2165 (Name : String;
2166 Main_Project : Project_Id;
2167 In_Tree : Project_Tree_Ref) return Project_Id
2169 Result : Project_Id := No_Project;
2171 Original_Name : String := Name;
2173 Data : constant Project_Data :=
2174 In_Tree.Projects.Table (Main_Project);
2176 Extended_Spec_Name : String :=
2177 Name &
2178 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
2179 Extended_Body_Name : String :=
2180 Name &
2181 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
2183 Unit : Unit_Data;
2185 Current_Name : File_Name_Type;
2186 The_Original_Name : File_Name_Type;
2187 The_Spec_Name : File_Name_Type;
2188 The_Body_Name : File_Name_Type;
2190 begin
2191 Canonical_Case_File_Name (Original_Name);
2192 Name_Len := Original_Name'Length;
2193 Name_Buffer (1 .. Name_Len) := Original_Name;
2194 The_Original_Name := Name_Find;
2196 Canonical_Case_File_Name (Extended_Spec_Name);
2197 Name_Len := Extended_Spec_Name'Length;
2198 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
2199 The_Spec_Name := Name_Find;
2201 Canonical_Case_File_Name (Extended_Body_Name);
2202 Name_Len := Extended_Body_Name'Length;
2203 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
2204 The_Body_Name := Name_Find;
2206 for Current in reverse Unit_Table.First ..
2207 Unit_Table.Last (In_Tree.Units)
2208 loop
2209 Unit := In_Tree.Units.Table (Current);
2211 -- Check for body
2213 Current_Name := Unit.File_Names (Body_Part).Name;
2215 -- Case of a body present
2217 if Current_Name /= No_File then
2219 -- If it has the name of the original name or the body name,
2220 -- we have found the project.
2222 if Unit.Name = Name_Id (The_Original_Name)
2223 or else Current_Name = The_Original_Name
2224 or else Current_Name = The_Body_Name
2225 then
2226 Result := Unit.File_Names (Body_Part).Project;
2227 exit;
2228 end if;
2229 end if;
2231 -- Check for spec
2233 Current_Name := Unit.File_Names (Specification).Name;
2235 if Current_Name /= No_File then
2237 -- If name same as the original name, or the spec name, we have
2238 -- found the project.
2240 if Unit.Name = Name_Id (The_Original_Name)
2241 or else Current_Name = The_Original_Name
2242 or else Current_Name = The_Spec_Name
2243 then
2244 Result := Unit.File_Names (Specification).Project;
2245 exit;
2246 end if;
2247 end if;
2248 end loop;
2250 -- Get the ultimate extending project
2252 if Result /= No_Project then
2253 while In_Tree.Projects.Table (Result).Extended_By /=
2254 No_Project
2255 loop
2256 Result := In_Tree.Projects.Table (Result).Extended_By;
2257 end loop;
2258 end if;
2260 return Result;
2261 end Project_Of;
2263 -------------------
2264 -- Set_Ada_Paths --
2265 -------------------
2267 procedure Set_Ada_Paths
2268 (Project : Project_Id;
2269 In_Tree : Project_Tree_Ref;
2270 Including_Libraries : Boolean)
2272 Source_FD : File_Descriptor := Invalid_FD;
2273 Object_FD : File_Descriptor := Invalid_FD;
2275 Process_Source_Dirs : Boolean := False;
2276 Process_Object_Dirs : Boolean := False;
2278 Status : Boolean;
2279 -- For calls to Close
2281 Len : Natural;
2283 procedure Add (Proj : Project_Id);
2284 -- Add all the source/object directories of a project to the path only
2285 -- if this project has not been visited. Calls an internal procedure
2286 -- recursively for projects being extended, and imported projects.
2288 ---------
2289 -- Add --
2290 ---------
2292 procedure Add (Proj : Project_Id) is
2294 procedure Recursive_Add (Project : Project_Id);
2295 -- Recursive procedure to add the source/object paths of extended/
2296 -- imported projects.
2298 -------------------
2299 -- Recursive_Add --
2300 -------------------
2302 procedure Recursive_Add (Project : Project_Id) is
2303 begin
2304 -- If Seen is False, then the project has not yet been visited
2306 if not In_Tree.Projects.Table (Project).Seen then
2307 In_Tree.Projects.Table (Project).Seen := True;
2309 declare
2310 Data : constant Project_Data :=
2311 In_Tree.Projects.Table (Project);
2312 List : Project_List := Data.Imported_Projects;
2314 begin
2315 if Process_Source_Dirs then
2317 -- Add to path all source directories of this project if
2318 -- there are Ada sources.
2320 if In_Tree.Projects.Table (Project).Ada_Sources /=
2321 Nil_String
2322 then
2323 Add_To_Source_Path (Data.Source_Dirs, In_Tree);
2324 end if;
2325 end if;
2327 if Process_Object_Dirs then
2329 -- Add to path the object directory of this project
2330 -- except if we don't include library project and this
2331 -- is a library project.
2333 if (Data.Library and Including_Libraries)
2334 or else
2335 (Data.Object_Directory /= No_Path_Information
2336 and then
2337 (not Including_Libraries or else not Data.Library))
2338 then
2339 -- For a library project, add the library ALI
2340 -- directory if there is no object directory or
2341 -- if the library ALI directory contains ALI files;
2342 -- otherwise add the object directory.
2344 if Data.Library then
2345 if Data.Object_Directory = No_Path_Information
2346 or else Contains_ALI_Files
2347 (Data.Library_ALI_Dir.Name)
2348 then
2349 Add_To_Object_Path
2350 (Data.Library_ALI_Dir.Name, In_Tree);
2351 else
2352 Add_To_Object_Path
2353 (Data.Object_Directory.Name, In_Tree);
2354 end if;
2356 -- For a non-library project, add the object
2357 -- directory, if it is not a virtual project, and if
2358 -- there are Ada sources or if the project is an
2359 -- extending project. If there are no Ada sources,
2360 -- adding the object directory could disrupt the order
2361 -- of the object dirs in the path.
2363 elsif not Data.Virtual
2364 and then There_Are_Ada_Sources (In_Tree, Project)
2365 then
2366 Add_To_Object_Path
2367 (Data.Object_Directory.Name, In_Tree);
2368 end if;
2369 end if;
2370 end if;
2372 -- Call Add to the project being extended, if any
2374 if Data.Extends /= No_Project then
2375 Recursive_Add (Data.Extends);
2376 end if;
2378 -- Call Add for each imported project, if any
2380 while List /= Empty_Project_List loop
2381 Recursive_Add
2382 (In_Tree.Project_Lists.Table
2383 (List).Project);
2384 List :=
2385 In_Tree.Project_Lists.Table (List).Next;
2386 end loop;
2387 end;
2388 end if;
2389 end Recursive_Add;
2391 begin
2392 Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
2393 Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
2395 for Index in Project_Table.First ..
2396 Project_Table.Last (In_Tree.Projects)
2397 loop
2398 In_Tree.Projects.Table (Index).Seen := False;
2399 end loop;
2401 Recursive_Add (Proj);
2402 end Add;
2404 -- Start of processing for Set_Ada_Paths
2406 begin
2407 -- If it is the first time we call this procedure for
2408 -- this project, compute the source path and/or the object path.
2410 if In_Tree.Projects.Table (Project).Include_Path_File = No_Path then
2411 Process_Source_Dirs := True;
2412 Create_New_Path_File
2413 (In_Tree, Source_FD,
2414 In_Tree.Projects.Table (Project).Include_Path_File);
2415 end if;
2417 -- For the object path, we make a distinction depending on
2418 -- Including_Libraries.
2420 if Including_Libraries then
2421 if In_Tree.Projects.Table
2422 (Project).Objects_Path_File_With_Libs = No_Path
2423 then
2424 Process_Object_Dirs := True;
2425 Create_New_Path_File
2426 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2427 Objects_Path_File_With_Libs);
2428 end if;
2430 else
2431 if In_Tree.Projects.Table
2432 (Project).Objects_Path_File_Without_Libs = No_Path
2433 then
2434 Process_Object_Dirs := True;
2435 Create_New_Path_File
2436 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2437 Objects_Path_File_Without_Libs);
2438 end if;
2439 end if;
2441 -- If there is something to do, set Seen to False for all projects,
2442 -- then call the recursive procedure Add for Project.
2444 if Process_Source_Dirs or Process_Object_Dirs then
2445 Add (Project);
2446 end if;
2448 -- Write and close any file that has been created
2450 if Source_FD /= Invalid_FD then
2451 for Index in Source_Path_Table.First ..
2452 Source_Path_Table.Last
2453 (In_Tree.Private_Part.Source_Paths)
2454 loop
2455 Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2456 Name_Len := Name_Len + 1;
2457 Name_Buffer (Name_Len) := ASCII.LF;
2458 Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2460 if Len /= Name_Len then
2461 Prj.Com.Fail ("disk full");
2462 end if;
2463 end loop;
2465 Close (Source_FD, Status);
2467 if not Status then
2468 Prj.Com.Fail ("disk full");
2469 end if;
2470 end if;
2472 if Object_FD /= Invalid_FD then
2473 for Index in Object_Path_Table.First ..
2474 Object_Path_Table.Last
2475 (In_Tree.Private_Part.Object_Paths)
2476 loop
2477 Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2478 Name_Len := Name_Len + 1;
2479 Name_Buffer (Name_Len) := ASCII.LF;
2480 Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2482 if Len /= Name_Len then
2483 Prj.Com.Fail ("disk full");
2484 end if;
2485 end loop;
2487 Close (Object_FD, Status);
2489 if not Status then
2490 Prj.Com.Fail ("disk full");
2491 end if;
2492 end if;
2494 -- Set the env vars, if they need to be changed, and set the
2495 -- corresponding flags.
2497 if Current_Source_Path_File /=
2498 In_Tree.Projects.Table (Project).Include_Path_File
2499 then
2500 Current_Source_Path_File :=
2501 In_Tree.Projects.Table (Project).Include_Path_File;
2502 Set_Path_File_Var
2503 (Project_Include_Path_File,
2504 Get_Name_String (Current_Source_Path_File));
2505 Ada_Prj_Include_File_Set := True;
2506 end if;
2508 if Including_Libraries then
2509 if Current_Object_Path_File
2510 /= In_Tree.Projects.Table
2511 (Project).Objects_Path_File_With_Libs
2512 then
2513 Current_Object_Path_File :=
2514 In_Tree.Projects.Table
2515 (Project).Objects_Path_File_With_Libs;
2516 Set_Path_File_Var
2517 (Project_Objects_Path_File,
2518 Get_Name_String (Current_Object_Path_File));
2519 Ada_Prj_Objects_File_Set := True;
2520 end if;
2522 else
2523 if Current_Object_Path_File /=
2524 In_Tree.Projects.Table
2525 (Project).Objects_Path_File_Without_Libs
2526 then
2527 Current_Object_Path_File :=
2528 In_Tree.Projects.Table
2529 (Project).Objects_Path_File_Without_Libs;
2530 Set_Path_File_Var
2531 (Project_Objects_Path_File,
2532 Get_Name_String (Current_Object_Path_File));
2533 Ada_Prj_Objects_File_Set := True;
2534 end if;
2535 end if;
2536 end Set_Ada_Paths;
2538 ---------------------------------------------
2539 -- Set_Mapping_File_Initial_State_To_Empty --
2540 ---------------------------------------------
2542 procedure Set_Mapping_File_Initial_State_To_Empty is
2543 begin
2544 Fill_Mapping_File := False;
2545 end Set_Mapping_File_Initial_State_To_Empty;
2547 -----------------------
2548 -- Set_Path_File_Var --
2549 -----------------------
2551 procedure Set_Path_File_Var (Name : String; Value : String) is
2552 Host_Spec : String_Access := To_Host_File_Spec (Value);
2554 begin
2555 if Host_Spec = null then
2556 Prj.Com.Fail
2557 ("could not convert file name """, Value, """ to host spec");
2558 else
2559 Setenv (Name, Host_Spec.all);
2560 Free (Host_Spec);
2561 end if;
2562 end Set_Path_File_Var;
2564 -----------------------
2565 -- Spec_Path_Name_Of --
2566 -----------------------
2568 function Spec_Path_Name_Of
2569 (Unit : Unit_Index; In_Tree : Project_Tree_Ref) return String
2571 Data : Unit_Data := In_Tree.Units.Table (Unit);
2573 begin
2574 if Data.File_Names (Specification).Path.Name = No_Path then
2575 declare
2576 Current_Source : String_List_Id :=
2577 In_Tree.Projects.Table
2578 (Data.File_Names (Specification).Project).Ada_Sources;
2579 Path : GNAT.OS_Lib.String_Access;
2581 begin
2582 Data.File_Names (Specification).Path.Name :=
2583 Path_Name_Type (Data.File_Names (Specification).Name);
2585 while Current_Source /= Nil_String loop
2586 Path := Locate_Regular_File
2587 (Namet.Get_Name_String
2588 (Data.File_Names (Specification).Name),
2589 Namet.Get_Name_String
2590 (In_Tree.String_Elements.Table
2591 (Current_Source).Value));
2593 if Path /= null then
2594 Name_Len := Path'Length;
2595 Name_Buffer (1 .. Name_Len) := Path.all;
2596 Data.File_Names (Specification).Path.Name := Name_Enter;
2597 exit;
2598 else
2599 Current_Source :=
2600 In_Tree.String_Elements.Table
2601 (Current_Source).Next;
2602 end if;
2603 end loop;
2605 In_Tree.Units.Table (Unit) := Data;
2606 end;
2607 end if;
2609 return Namet.Get_Name_String (Data.File_Names (Specification).Path.Name);
2610 end Spec_Path_Name_Of;
2612 ---------------------------
2613 -- Ultimate_Extension_Of --
2614 ---------------------------
2616 function Ultimate_Extension_Of
2617 (Project : Project_Id;
2618 In_Tree : Project_Tree_Ref) return Project_Id
2620 Result : Project_Id := Project;
2622 begin
2623 while In_Tree.Projects.Table (Result).Extended_By /=
2624 No_Project
2625 loop
2626 Result := In_Tree.Projects.Table (Result).Extended_By;
2627 end loop;
2629 return Result;
2630 end Ultimate_Extension_Of;
2632 end Prj.Env;