1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2003 Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Namet; use Namet;
29 with Osint; use Osint;
30 with Output; use Output;
31 with Prj.Com; use Prj.Com;
35 with GNAT.OS_Lib; use GNAT.OS_Lib;
37 package body Prj.Env is
39 type Naming_Id is new Nat;
41 Current_Source_Path_File : Name_Id := No_Name;
42 -- Current value of project source path file env var.
43 -- Used to avoid setting the env var to the same value.
45 Current_Object_Path_File : Name_Id := No_Name;
46 -- Current value of project object path file env var.
47 -- Used to avoid setting the env var to the same value.
49 Ada_Path_Buffer : String_Access := new String (1 .. 1024);
50 -- A buffer where values for ADA_INCLUDE_PATH
51 -- and ADA_OBJECTS_PATH are stored.
53 Ada_Path_Length : Natural := 0;
54 -- Index of the last valid character in Ada_Path_Buffer.
56 Ada_Prj_Include_File_Set : Boolean := False;
57 Ada_Prj_Objects_File_Set : Boolean := False;
58 -- These flags are set to True when the corresponding environment variables
59 -- are set and are used to give these environment variables an empty string
60 -- value at the end of the program. This has no practical effect on most
61 -- platforms, except on VMS where the logical names are deassigned, thus
62 -- avoiding the pollution of the environment of the caller.
64 package Namings is new Table.Table (
65 Table_Component_Type => Naming_Data,
66 Table_Index_Type => Naming_Id,
69 Table_Increment => 100,
70 Table_Name => "Prj.Env.Namings");
72 Default_Naming : constant Naming_Id := Namings.First;
74 Fill_Mapping_File : Boolean := True;
76 package Path_Files is new Table.Table (
77 Table_Component_Type => Name_Id,
78 Table_Index_Type => Natural,
81 Table_Increment => 50,
82 Table_Name => "Prj.Env.Path_Files");
83 -- Table storing all the temp path file names.
84 -- Used by Delete_All_Path_Files.
86 type Project_Flags is array (Project_Id range <>) of Boolean;
87 -- A Boolean array type used in Create_Mapping_File to select the projects
88 -- in the closure of a specific project.
90 -----------------------
91 -- Local Subprograms --
92 -----------------------
94 function Body_Path_Name_Of (Unit : Unit_Id) return String;
95 -- Returns the path name of the body of a unit.
96 -- Compute it first, if necessary.
98 function Spec_Path_Name_Of (Unit : Unit_Id) return String;
99 -- Returns the path name of the spec of a unit.
100 -- Compute it first, if necessary.
102 procedure Add_To_Path (Source_Dirs : String_List_Id);
103 -- Add to Ada_Path_Buffer all the source directories in string list
104 -- Source_Dirs, if any. Increment Ada_Path_Length.
106 procedure Add_To_Path (Dir : String);
107 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
108 -- Increment Ada_Path_Length.
109 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
112 procedure Add_To_Path_File
113 (Source_Dirs : String_List_Id;
114 Path_File : File_Descriptor);
115 -- Add to Ada_Path_Buffer all the source directories in string list
116 -- Source_Dirs, if any. Increment Ada_Path_Length.
118 procedure Add_To_Path_File
120 Path_File : File_Descriptor);
121 -- Add Path to path file
123 procedure Create_New_Path_File
124 (Path_FD : out File_Descriptor;
125 Path_Name : out Name_Id);
126 -- Create a new temporary path file. Get the file name in Path_Name.
127 -- The name is normally obtained by increasing the number in
128 -- Temp_Path_File_Name by 1.
130 procedure Set_Path_File_Var (Name : String; Value : String);
131 -- Call Setenv, after calling To_Host_File_Spec
133 function Ultimate_Extension_Of (Project : in Project_Id) return Project_Id;
134 -- Return a project that is either Project or an extended ancestor of
135 -- Project that itself is not extended.
137 ----------------------
138 -- Ada_Include_Path --
139 ----------------------
141 function Ada_Include_Path (Project : Project_Id) return String_Access is
143 procedure Add (Project : Project_Id);
144 -- Add all the source directories of a project to the path only if
145 -- this project has not been visited. Calls itself recursively for
146 -- projects being extended, and imported projects. Adds the project
147 -- to the list Seen if this is the call to Add for this project.
153 procedure Add (Project : Project_Id) is
155 -- If Seen is empty, then the project cannot have been visited
157 if not Projects.Table (Project).Seen then
158 Projects.Table (Project).Seen := True;
161 Data : constant Project_Data := Projects.Table (Project);
162 List : Project_List := Data.Imported_Projects;
165 -- Add to path all source directories of this project
167 Add_To_Path (Data.Source_Dirs);
169 -- Call Add to the project being extended, if any
171 if Data.Extends /= No_Project then
175 -- Call Add for each imported project, if any
177 while List /= Empty_Project_List loop
178 Add (Project_Lists.Table (List).Project);
179 List := Project_Lists.Table (List).Next;
185 -- Start of processing for Ada_Include_Path
188 -- If it is the first time we call this function for
189 -- this project, compute the source path
191 if Projects.Table (Project).Ada_Include_Path = null then
192 Ada_Path_Length := 0;
194 for Index in 1 .. Projects.Last loop
195 Projects.Table (Index).Seen := False;
199 Projects.Table (Project).Ada_Include_Path :=
200 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
203 return Projects.Table (Project).Ada_Include_Path;
204 end Ada_Include_Path;
206 ----------------------
207 -- Ada_Include_Path --
208 ----------------------
210 function Ada_Include_Path
211 (Project : Project_Id;
212 Recursive : Boolean) return String
216 return Ada_Include_Path (Project).all;
218 Ada_Path_Length := 0;
219 Add_To_Path (Projects.Table (Project).Source_Dirs);
220 return Ada_Path_Buffer (1 .. Ada_Path_Length);
222 end Ada_Include_Path;
224 ----------------------
225 -- Ada_Objects_Path --
226 ----------------------
228 function Ada_Objects_Path
229 (Project : Project_Id;
230 Including_Libraries : Boolean := True) return String_Access
232 procedure Add (Project : Project_Id);
233 -- Add all the object directories of a project to the path only if
234 -- this project has not been visited. Calls itself recursively for
235 -- projects being extended, and imported projects. Adds the project
236 -- to the list Seen if this is the first call to Add for this project.
242 procedure Add (Project : Project_Id) is
244 -- If this project has not been seen yet
246 if not Projects.Table (Project).Seen then
247 Projects.Table (Project).Seen := True;
250 Data : constant Project_Data := Projects.Table (Project);
251 List : Project_List := Data.Imported_Projects;
254 -- Add to path the object directory of this project
255 -- except if we don't include library project and
256 -- this is a library project.
258 if (Data.Library and then Including_Libraries)
260 (Data.Object_Directory /= No_Name
262 (not Including_Libraries or else not Data.Library))
264 -- For a library project, add the library directory
267 Add_To_Path (Get_Name_String (Data.Library_Dir));
270 -- For a non library project, add the object directory
272 Add_To_Path (Get_Name_String (Data.Object_Directory));
276 -- Call Add to the project being extended, if any
278 if Data.Extends /= No_Project then
282 -- Call Add for each imported project, if any
284 while List /= Empty_Project_List loop
285 Add (Project_Lists.Table (List).Project);
286 List := Project_Lists.Table (List).Next;
293 -- Start of processing for Ada_Objects_Path
296 -- If it is the first time we call this function for
297 -- this project, compute the objects path
299 if Projects.Table (Project).Ada_Objects_Path = null then
300 Ada_Path_Length := 0;
302 for Index in 1 .. Projects.Last loop
303 Projects.Table (Index).Seen := False;
307 Projects.Table (Project).Ada_Objects_Path :=
308 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
311 return Projects.Table (Project).Ada_Objects_Path;
312 end Ada_Objects_Path;
318 procedure Add_To_Path (Source_Dirs : String_List_Id) is
319 Current : String_List_Id := Source_Dirs;
320 Source_Dir : String_Element;
323 while Current /= Nil_String loop
324 Source_Dir := String_Elements.Table (Current);
325 Add_To_Path (Get_Name_String (Source_Dir.Value));
326 Current := Source_Dir.Next;
330 procedure Add_To_Path (Dir : String) is
332 New_Buffer : String_Access;
335 function Is_Present (Path : String; Dir : String) return Boolean;
336 -- Return True if Dir is part of Path
342 function Is_Present (Path : String; Dir : String) return Boolean is
343 Last : constant Integer := Path'Last - Dir'Length + 1;
345 for J in Path'First .. Last loop
346 -- Note: the order of the conditions below is important, since
347 -- it ensures a minimal number of string comparisons.
350 or else Path (J - 1) = Path_Separator)
352 (J + Dir'Length > Path'Last
353 or else Path (J + Dir'Length) = Path_Separator)
354 and then Dir = Path (J .. J + Dir'Length - 1)
364 if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
365 -- Dir is already in the path, nothing to do
370 Min_Len := Ada_Path_Length + Dir'Length;
372 if Ada_Path_Length > 0 then
373 -- Add 1 for the Path_Separator character
375 Min_Len := Min_Len + 1;
378 -- If Ada_Path_Buffer is too small, increase it
380 Len := Ada_Path_Buffer'Last;
382 if Len < Min_Len then
385 exit when Len >= Min_Len;
388 New_Buffer := new String (1 .. Len);
389 New_Buffer (1 .. Ada_Path_Length) :=
390 Ada_Path_Buffer (1 .. Ada_Path_Length);
391 Free (Ada_Path_Buffer);
392 Ada_Path_Buffer := New_Buffer;
395 if Ada_Path_Length > 0 then
396 Ada_Path_Length := Ada_Path_Length + 1;
397 Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
401 (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
402 Ada_Path_Length := Ada_Path_Length + Dir'Length;
405 ----------------------
406 -- Add_To_Path_File --
407 ----------------------
409 procedure Add_To_Path_File
410 (Source_Dirs : String_List_Id;
411 Path_File : File_Descriptor)
413 Current : String_List_Id := Source_Dirs;
414 Source_Dir : String_Element;
417 while Current /= Nil_String loop
418 Source_Dir := String_Elements.Table (Current);
419 Add_To_Path_File (Get_Name_String (Source_Dir.Value), Path_File);
420 Current := Source_Dir.Next;
422 end Add_To_Path_File;
424 procedure Add_To_Path_File
426 Path_File : File_Descriptor)
428 Line : String (1 .. Path'Length + 1);
432 Line (1 .. Path'Length) := Path;
433 Line (Line'Last) := ASCII.LF;
434 Len := Write (Path_File, Line (1)'Address, Line'Length);
436 if Len /= Line'Length then
437 Prj.Com.Fail ("disk full");
439 end Add_To_Path_File;
441 -----------------------
442 -- Body_Path_Name_Of --
443 -----------------------
445 function Body_Path_Name_Of (Unit : Unit_Id) return String is
446 Data : Unit_Data := Units.Table (Unit);
449 -- If we don't know the path name of the body of this unit,
450 -- we compute it, and we store it.
452 if Data.File_Names (Body_Part).Path = No_Name then
454 Current_Source : String_List_Id :=
455 Projects.Table (Data.File_Names (Body_Part).Project).Sources;
456 Path : GNAT.OS_Lib.String_Access;
459 -- By default, put the file name
461 Data.File_Names (Body_Part).Path :=
462 Data.File_Names (Body_Part).Name;
464 -- For each source directory
466 while Current_Source /= Nil_String loop
469 (Namet.Get_Name_String
470 (Data.File_Names (Body_Part).Name),
471 Namet.Get_Name_String
472 (String_Elements.Table (Current_Source).Value));
474 -- If the file is in this directory,
475 -- then we store the path, and we are done.
478 Name_Len := Path'Length;
479 Name_Buffer (1 .. Name_Len) := Path.all;
480 Data.File_Names (Body_Part).Path := Name_Enter;
485 String_Elements.Table (Current_Source).Next;
489 Units.Table (Unit) := Data;
493 -- Returned the value stored
495 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
496 end Body_Path_Name_Of;
498 --------------------------------
499 -- Create_Config_Pragmas_File --
500 --------------------------------
502 procedure Create_Config_Pragmas_File
503 (For_Project : Project_Id;
504 Main_Project : Project_Id;
505 Include_Config_Files : Boolean := True)
507 pragma Unreferenced (Main_Project);
508 pragma Unreferenced (Include_Config_Files);
510 File_Name : Name_Id := No_Name;
511 File : File_Descriptor := Invalid_FD;
513 Current_Unit : Unit_Id := Units.First;
515 First_Project : Project_List := Empty_Project_List;
517 Current_Project : Project_List;
518 Current_Naming : Naming_Id;
523 procedure Check (Project : Project_Id);
525 procedure Check_Temp_File;
526 -- Check that a temporary file has been opened.
527 -- If not, create one, and put its name in the project data,
528 -- with the indication that it is a temporary file.
531 (Unit_Name : Name_Id;
533 Unit_Kind : Spec_Or_Body);
534 -- Put an SFN pragma in the temporary file.
536 procedure Put (File : File_Descriptor; S : String);
538 procedure Put_Line (File : File_Descriptor; S : String);
544 procedure Check (Project : Project_Id) is
545 Data : constant Project_Data := Projects.Table (Project);
548 if Current_Verbosity = High then
549 Write_Str ("Checking project file """);
550 Write_Str (Namet.Get_Name_String (Data.Name));
555 -- Is this project in the list of the visited project?
557 Current_Project := First_Project;
558 while Current_Project /= Empty_Project_List
559 and then Project_Lists.Table (Current_Project).Project /= Project
561 Current_Project := Project_Lists.Table (Current_Project).Next;
564 -- If it is not, put it in the list, and visit it
566 if Current_Project = Empty_Project_List then
567 Project_Lists.Increment_Last;
568 Project_Lists.Table (Project_Lists.Last) :=
569 (Project => Project, Next => First_Project);
570 First_Project := Project_Lists.Last;
572 -- Is the naming scheme of this project one that we know?
574 Current_Naming := Default_Naming;
575 while Current_Naming <= Namings.Last and then
576 not Same_Naming_Scheme
577 (Left => Namings.Table (Current_Naming),
578 Right => Data.Naming) loop
579 Current_Naming := Current_Naming + 1;
582 -- If we don't know it, add it
584 if Current_Naming > Namings.Last then
585 Namings.Increment_Last;
586 Namings.Table (Namings.Last) := Data.Naming;
588 -- We need a temporary file to be created
592 -- Put the SFN pragmas for the naming scheme
597 (File, "pragma Source_File_Name_Project");
599 (File, " (Spec_File_Name => ""*" &
600 Namet.Get_Name_String (Data.Naming.Current_Spec_Suffix) &
603 (File, " Casing => " &
604 Image (Data.Naming.Casing) & ",");
606 (File, " Dot_Replacement => """ &
607 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
613 (File, "pragma Source_File_Name_Project");
615 (File, " (Body_File_Name => ""*" &
616 Namet.Get_Name_String (Data.Naming.Current_Body_Suffix) &
619 (File, " Casing => " &
620 Image (Data.Naming.Casing) & ",");
622 (File, " Dot_Replacement => """ &
623 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
626 -- and maybe separate
629 Data.Naming.Current_Body_Suffix /= Data.Naming.Separate_Suffix
632 (File, "pragma Source_File_Name_Project");
634 (File, " (Subunit_File_Name => ""*" &
635 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
638 (File, " Casing => " &
639 Image (Data.Naming.Casing) &
642 (File, " Dot_Replacement => """ &
643 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
648 if Data.Extends /= No_Project then
649 Check (Data.Extends);
653 Current : Project_List := Data.Imported_Projects;
656 while Current /= Empty_Project_List loop
657 Check (Project_Lists.Table (Current).Project);
658 Current := Project_Lists.Table (Current).Next;
664 ---------------------
665 -- Check_Temp_File --
666 ---------------------
668 procedure Check_Temp_File is
670 if File = Invalid_FD then
671 Tempdir.Create_Temp_File (File, Name => File_Name);
673 if File = Invalid_FD then
675 ("unable to create temporary configuration pragmas file");
676 elsif Opt.Verbose_Mode then
677 Write_Str ("Creating temp file """);
678 Write_Str (Get_Name_String (File_Name));
689 (Unit_Name : Name_Id;
691 Unit_Kind : Spec_Or_Body)
694 -- A temporary file needs to be open
698 -- Put the pragma SFN for the unit kind (spec or body)
700 Put (File, "pragma Source_File_Name_Project (");
701 Put (File, Namet.Get_Name_String (Unit_Name));
703 if Unit_Kind = Specification then
704 Put (File, ", Spec_File_Name => """);
706 Put (File, ", Body_File_Name => """);
709 Put (File, Namet.Get_Name_String (File_Name));
710 Put_Line (File, """);");
713 procedure Put (File : File_Descriptor; S : String) is
717 Last := Write (File, S (S'First)'Address, S'Length);
719 if Last /= S'Length then
720 Prj.Com.Fail ("Disk full");
723 if Current_Verbosity = High then
732 procedure Put_Line (File : File_Descriptor; S : String) is
733 S0 : String (1 .. S'Length + 1);
737 -- Add an ASCII.LF to the string. As this gnat.adc is supposed to
738 -- be used only by the compiler, we don't care about the characters
739 -- for the end of line. In fact we could have put a space, but
740 -- it is more convenient to be able to read gnat.adc during
741 -- development, for which the ASCII.LF is fine.
743 S0 (1 .. S'Length) := S;
744 S0 (S0'Last) := ASCII.LF;
745 Last := Write (File, S0'Address, S0'Length);
747 if Last /= S'Length + 1 then
748 Prj.Com.Fail ("Disk full");
751 if Current_Verbosity = High then
756 -- Start of processing for Create_Config_Pragmas_File
759 if not Projects.Table (For_Project).Config_Checked then
761 -- Remove any memory of processed naming schemes, if any
763 Namings.Set_Last (Default_Naming);
765 -- Check the naming schemes
769 -- Visit all the units and process those that need an SFN pragma
771 while Current_Unit <= Units.Last loop
773 Unit : constant Unit_Data :=
774 Units.Table (Current_Unit);
777 if Unit.File_Names (Specification).Needs_Pragma then
779 Unit.File_Names (Specification).Name,
783 if Unit.File_Names (Body_Part).Needs_Pragma then
785 Unit.File_Names (Body_Part).Name,
789 Current_Unit := Current_Unit + 1;
793 -- If there are no non standard naming scheme, issue the GNAT
794 -- standard naming scheme. This will tell the compiler that
795 -- a project file is used and will forbid any pragma SFN.
797 if File = Invalid_FD then
800 Put_Line (File, "pragma Source_File_Name_Project");
801 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
802 Put_Line (File, " Dot_Replacement => ""-"",");
803 Put_Line (File, " Casing => lowercase);");
805 Put_Line (File, "pragma Source_File_Name_Project");
806 Put_Line (File, " (Body_File_Name => ""*.adb"",");
807 Put_Line (File, " Dot_Replacement => ""-"",");
808 Put_Line (File, " Casing => lowercase);");
811 -- Close the temporary file
813 GNAT.OS_Lib.Close (File, Status);
816 Prj.Com.Fail ("disk full");
819 if Opt.Verbose_Mode then
820 Write_Str ("Closing configuration file """);
821 Write_Str (Get_Name_String (File_Name));
825 Projects.Table (For_Project).Config_File_Name := File_Name;
826 Projects.Table (For_Project).Config_File_Temp := True;
828 Projects.Table (For_Project).Config_Checked := True;
830 end Create_Config_Pragmas_File;
832 -------------------------
833 -- Create_Mapping_File --
834 -------------------------
836 procedure Create_Mapping_File
837 (Project : Project_Id;
840 File : File_Descriptor := Invalid_FD;
841 The_Unit_Data : Unit_Data;
842 Data : File_Name_Data;
847 Present : Project_Flags (No_Project .. Projects.Last) :=
849 -- For each project in the closure of Project, the corresponding flag
850 -- will be set to True;
852 procedure Put_Name_Buffer;
853 -- Put the line contained in the Name_Buffer in the mapping file
855 procedure Put_Data (Spec : Boolean);
856 -- Put the mapping of the spec or body contained in Data in the file
859 procedure Recursive_Flag (Prj : Project_Id);
860 -- Set the flags corresponding to Prj, the projects it imports
861 -- (directly or indirectly) or extends to True. Call itself recursively.
867 procedure Put_Name_Buffer is
871 Name_Len := Name_Len + 1;
872 Name_Buffer (Name_Len) := ASCII.LF;
873 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
875 if Last /= Name_Len then
876 Prj.Com.Fail ("Disk full");
884 procedure Put_Data (Spec : Boolean) is
886 -- Line with the unit name
888 Get_Name_String (The_Unit_Data.Name);
889 Name_Len := Name_Len + 1;
890 Name_Buffer (Name_Len) := '%';
891 Name_Len := Name_Len + 1;
894 Name_Buffer (Name_Len) := 's';
896 Name_Buffer (Name_Len) := 'b';
901 -- Line with the file name
903 Get_Name_String (Data.Name);
906 -- Line with the path name
908 Get_Name_String (Data.Path);
917 procedure Recursive_Flag (Prj : Project_Id) is
918 Imported : Project_List;
922 -- Nothing to do for non existent project or project that has
923 -- already been flagged.
925 if Prj = No_Project or else Present (Prj) then
929 -- Flag the current project
931 Present (Prj) := True;
932 Imported := Projects.Table (Prj).Imported_Projects;
934 -- Call itself for each project directly imported
936 while Imported /= Empty_Project_List loop
937 Proj := Project_Lists.Table (Imported).Project;
938 Imported := Project_Lists.Table (Imported).Next;
939 Recursive_Flag (Proj);
942 -- Call itself for an eventual project being extended
944 Recursive_Flag (Projects.Table (Prj).Extends);
947 -- Start of processing for Create_Mapping_File
950 -- Flag the necessary projects
952 Recursive_Flag (Project);
954 -- Create the temporary file
956 Tempdir.Create_Temp_File (File, Name => Name);
958 if File = Invalid_FD then
959 Prj.Com.Fail ("unable to create temporary mapping file");
961 elsif Opt.Verbose_Mode then
962 Write_Str ("Creating temp mapping file """);
963 Write_Str (Get_Name_String (Name));
967 if Fill_Mapping_File then
968 -- For all units in table Units
970 for Unit in 1 .. Units.Last loop
971 The_Unit_Data := Units.Table (Unit);
973 -- If the unit has a valid name
975 if The_Unit_Data.Name /= No_Name then
976 Data := The_Unit_Data.File_Names (Specification);
978 -- If there is a spec, put it mapping in the file if it is
979 -- from a project in the closure of Project.
981 if Data.Name /= No_Name and then Present (Data.Project) then
982 Put_Data (Spec => True);
985 Data := The_Unit_Data.File_Names (Body_Part);
987 -- If there is a body (or subunit) put its mapping in the file
988 -- if it is from a project in the closure of Project.
990 if Data.Name /= No_Name and then Present (Data.Project) then
991 Put_Data (Spec => False);
998 GNAT.OS_Lib.Close (File, Status);
1001 Prj.Com.Fail ("disk full");
1004 end Create_Mapping_File;
1006 --------------------------
1007 -- Create_New_Path_File --
1008 --------------------------
1010 procedure Create_New_Path_File
1011 (Path_FD : out File_Descriptor;
1012 Path_Name : out Name_Id)
1015 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1017 if Path_Name /= No_Name then
1019 -- Record the name, so that the temp path file will be deleted
1020 -- at the end of the program.
1022 Path_Files.Increment_Last;
1023 Path_Files.Table (Path_Files.Last) := Path_Name;
1025 end Create_New_Path_File;
1027 ---------------------------
1028 -- Delete_All_Path_Files --
1029 ---------------------------
1031 procedure Delete_All_Path_Files is
1032 Disregard : Boolean := True;
1035 for Index in 1 .. Path_Files.Last loop
1036 if Path_Files.Table (Index) /= No_Name then
1038 (Get_Name_String (Path_Files.Table (Index)), Disregard);
1042 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1043 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1044 -- the empty string. On VMS, this has the effect of deassigning
1045 -- the logical names.
1047 if Ada_Prj_Include_File_Set then
1048 Setenv (Project_Include_Path_File, "");
1049 Ada_Prj_Include_File_Set := False;
1052 if Ada_Prj_Objects_File_Set then
1053 Setenv (Project_Objects_Path_File, "");
1054 Ada_Prj_Objects_File_Set := False;
1056 end Delete_All_Path_Files;
1058 ------------------------------------
1059 -- File_Name_Of_Library_Unit_Body --
1060 ------------------------------------
1062 function File_Name_Of_Library_Unit_Body
1064 Project : Project_Id;
1065 Main_Project_Only : Boolean := True;
1066 Full_Path : Boolean := False) return String
1068 The_Project : Project_Id := Project;
1069 Data : Project_Data := Projects.Table (Project);
1070 Original_Name : String := Name;
1072 Extended_Spec_Name : String :=
1073 Name & Namet.Get_Name_String
1074 (Data.Naming.Current_Spec_Suffix);
1075 Extended_Body_Name : String :=
1076 Name & Namet.Get_Name_String
1077 (Data.Naming.Current_Body_Suffix);
1081 The_Original_Name : Name_Id;
1082 The_Spec_Name : Name_Id;
1083 The_Body_Name : Name_Id;
1086 Canonical_Case_File_Name (Original_Name);
1087 Name_Len := Original_Name'Length;
1088 Name_Buffer (1 .. Name_Len) := Original_Name;
1089 The_Original_Name := Name_Find;
1091 Canonical_Case_File_Name (Extended_Spec_Name);
1092 Name_Len := Extended_Spec_Name'Length;
1093 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1094 The_Spec_Name := Name_Find;
1096 Canonical_Case_File_Name (Extended_Body_Name);
1097 Name_Len := Extended_Body_Name'Length;
1098 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1099 The_Body_Name := Name_Find;
1101 if Current_Verbosity = High then
1102 Write_Str ("Looking for file name of """);
1106 Write_Str (" Extended Spec Name = """);
1107 Write_Str (Extended_Spec_Name);
1110 Write_Str (" Extended Body Name = """);
1111 Write_Str (Extended_Body_Name);
1116 -- For extending project, search in the extended project
1117 -- if the source is not found. For non extending projects,
1118 -- this loop will be run only once.
1123 for Current in reverse Units.First .. Units.Last loop
1124 Unit := Units.Table (Current);
1128 if not Main_Project_Only
1129 or else Unit.File_Names (Body_Part).Project = The_Project
1132 Current_Name : constant Name_Id :=
1133 Unit.File_Names (Body_Part).Name;
1136 -- Case of a body present
1138 if Current_Name /= No_Name then
1139 if Current_Verbosity = High then
1140 Write_Str (" Comparing with """);
1141 Write_Str (Get_Name_String (Current_Name));
1146 -- If it has the name of the original name,
1147 -- return the original name
1149 if Unit.Name = The_Original_Name
1150 or else Current_Name = The_Original_Name
1152 if Current_Verbosity = High then
1157 return Get_Name_String
1158 (Unit.File_Names (Body_Part).Path);
1161 return Get_Name_String (Current_Name);
1164 -- If it has the name of the extended body name,
1165 -- return the extended body name
1167 elsif Current_Name = The_Body_Name then
1168 if Current_Verbosity = High then
1173 return Get_Name_String
1174 (Unit.File_Names (Body_Part).Path);
1177 return Extended_Body_Name;
1181 if Current_Verbosity = High then
1182 Write_Line (" not good");
1191 if not Main_Project_Only
1192 or else Unit.File_Names (Specification).Project = The_Project
1195 Current_Name : constant Name_Id :=
1196 Unit.File_Names (Specification).Name;
1199 -- Case of spec present
1201 if Current_Name /= No_Name then
1202 if Current_Verbosity = High then
1203 Write_Str (" Comparing with """);
1204 Write_Str (Get_Name_String (Current_Name));
1209 -- If name same as the original name, return original
1212 if Unit.Name = The_Original_Name
1213 or else Current_Name = The_Original_Name
1215 if Current_Verbosity = High then
1221 return Get_Name_String
1222 (Unit.File_Names (Specification).Path);
1225 return Get_Name_String (Current_Name);
1228 -- If it has the same name as the extended spec name,
1229 -- return the extended spec name.
1231 elsif Current_Name = The_Spec_Name then
1232 if Current_Verbosity = High then
1237 return Get_Name_String
1238 (Unit.File_Names (Specification).Path);
1241 return Extended_Spec_Name;
1245 if Current_Verbosity = High then
1246 Write_Line (" not good");
1254 -- If we are not in an extending project, give up
1256 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1258 -- Otherwise, look in the project we are extending
1260 The_Project := Data.Extends;
1261 Data := Projects.Table (The_Project);
1264 -- We don't know this file name, return an empty string
1267 end File_Name_Of_Library_Unit_Body;
1269 -------------------------
1270 -- For_All_Object_Dirs --
1271 -------------------------
1273 procedure For_All_Object_Dirs (Project : Project_Id) is
1274 Seen : Project_List := Empty_Project_List;
1276 procedure Add (Project : Project_Id);
1277 -- Process a project. Remember the processes visited to avoid
1278 -- processing a project twice. Recursively process an eventual
1279 -- extended project, and all imported projects.
1285 procedure Add (Project : Project_Id) is
1286 Data : constant Project_Data := Projects.Table (Project);
1287 List : Project_List := Data.Imported_Projects;
1290 -- If the list of visited project is empty, then
1291 -- for sure we never visited this project.
1293 if Seen = Empty_Project_List then
1294 Project_Lists.Increment_Last;
1295 Seen := Project_Lists.Last;
1296 Project_Lists.Table (Seen) :=
1297 (Project => Project, Next => Empty_Project_List);
1300 -- Check if the project is in the list
1303 Current : Project_List := Seen;
1307 -- If it is, then there is nothing else to do
1309 if Project_Lists.Table (Current).Project = Project then
1313 exit when Project_Lists.Table (Current).Next =
1315 Current := Project_Lists.Table (Current).Next;
1318 -- This project has never been visited, add it
1321 Project_Lists.Increment_Last;
1322 Project_Lists.Table (Current).Next := Project_Lists.Last;
1323 Project_Lists.Table (Project_Lists.Last) :=
1324 (Project => Project, Next => Empty_Project_List);
1328 -- If there is an object directory, call Action
1331 if Data.Object_Directory /= No_Name then
1332 Get_Name_String (Data.Object_Directory);
1333 Action (Name_Buffer (1 .. Name_Len));
1336 -- If we are extending a project, visit it
1338 if Data.Extends /= No_Project then
1342 -- And visit all imported projects
1344 while List /= Empty_Project_List loop
1345 Add (Project_Lists.Table (List).Project);
1346 List := Project_Lists.Table (List).Next;
1350 -- Start of processing for For_All_Object_Dirs
1353 -- Visit this project, and its imported projects,
1357 end For_All_Object_Dirs;
1359 -------------------------
1360 -- For_All_Source_Dirs --
1361 -------------------------
1363 procedure For_All_Source_Dirs (Project : Project_Id) is
1364 Seen : Project_List := Empty_Project_List;
1366 procedure Add (Project : Project_Id);
1367 -- Process a project. Remember the processes visited to avoid
1368 -- processing a project twice. Recursively process an eventual
1369 -- extended project, and all imported projects.
1375 procedure Add (Project : Project_Id) is
1376 Data : constant Project_Data := Projects.Table (Project);
1377 List : Project_List := Data.Imported_Projects;
1380 -- If the list of visited project is empty, then
1381 -- for sure we never visited this project.
1383 if Seen = Empty_Project_List then
1384 Project_Lists.Increment_Last;
1385 Seen := Project_Lists.Last;
1386 Project_Lists.Table (Seen) :=
1387 (Project => Project, Next => Empty_Project_List);
1390 -- Check if the project is in the list
1393 Current : Project_List := Seen;
1397 -- If it is, then there is nothing else to do
1399 if Project_Lists.Table (Current).Project = Project then
1403 exit when Project_Lists.Table (Current).Next =
1405 Current := Project_Lists.Table (Current).Next;
1408 -- This project has never been visited, add it
1411 Project_Lists.Increment_Last;
1412 Project_Lists.Table (Current).Next := Project_Lists.Last;
1413 Project_Lists.Table (Project_Lists.Last) :=
1414 (Project => Project, Next => Empty_Project_List);
1419 Current : String_List_Id := Data.Source_Dirs;
1420 The_String : String_Element;
1423 -- Call action with the name of every source directorie
1425 while Current /= Nil_String loop
1426 The_String := String_Elements.Table (Current);
1427 Action (Get_Name_String (The_String.Value));
1428 Current := The_String.Next;
1432 -- If we are extending a project, visit it
1434 if Data.Extends /= No_Project then
1438 -- And visit all imported projects
1440 while List /= Empty_Project_List loop
1441 Add (Project_Lists.Table (List).Project);
1442 List := Project_Lists.Table (List).Next;
1446 -- Start of processing for For_All_Source_Dirs
1449 -- Visit this project, and its imported projects recursively
1452 end For_All_Source_Dirs;
1458 procedure Get_Reference
1459 (Source_File_Name : String;
1460 Project : out Project_Id;
1464 if Current_Verbosity > Default then
1465 Write_Str ("Getting Reference_Of (""");
1466 Write_Str (Source_File_Name);
1467 Write_Str (""") ... ");
1471 Original_Name : String := Source_File_Name;
1475 Canonical_Case_File_Name (Original_Name);
1477 for Id in Units.First .. Units.Last loop
1478 Unit := Units.Table (Id);
1480 if (Unit.File_Names (Specification).Name /= No_Name
1482 Namet.Get_Name_String
1483 (Unit.File_Names (Specification).Name) = Original_Name)
1484 or else (Unit.File_Names (Specification).Path /= No_Name
1486 Namet.Get_Name_String
1487 (Unit.File_Names (Specification).Path) =
1490 Project := Ultimate_Extension_Of
1491 (Unit.File_Names (Specification).Project);
1492 Path := Unit.File_Names (Specification).Display_Path;
1494 if Current_Verbosity > Default then
1495 Write_Str ("Done: Specification.");
1501 elsif (Unit.File_Names (Body_Part).Name /= No_Name
1503 Namet.Get_Name_String
1504 (Unit.File_Names (Body_Part).Name) = Original_Name)
1505 or else (Unit.File_Names (Body_Part).Path /= No_Name
1506 and then Namet.Get_Name_String
1507 (Unit.File_Names (Body_Part).Path) =
1510 Project := Ultimate_Extension_Of
1511 (Unit.File_Names (Body_Part).Project);
1512 Path := Unit.File_Names (Body_Part).Display_Path;
1514 if Current_Verbosity > Default then
1515 Write_Str ("Done: Body.");
1525 Project := No_Project;
1528 if Current_Verbosity > Default then
1529 Write_Str ("Cannot be found.");
1538 procedure Initialize is
1540 -- There is nothing to do anymore
1545 ------------------------------------
1546 -- Path_Name_Of_Library_Unit_Body --
1547 ------------------------------------
1549 function Path_Name_Of_Library_Unit_Body
1551 Project : Project_Id) return String
1553 Data : constant Project_Data := Projects.Table (Project);
1554 Original_Name : String := Name;
1556 Extended_Spec_Name : String :=
1557 Name & Namet.Get_Name_String
1558 (Data.Naming.Current_Spec_Suffix);
1559 Extended_Body_Name : String :=
1560 Name & Namet.Get_Name_String
1561 (Data.Naming.Current_Body_Suffix);
1563 First : Unit_Id := Units.First;
1568 Canonical_Case_File_Name (Original_Name);
1569 Canonical_Case_File_Name (Extended_Spec_Name);
1570 Canonical_Case_File_Name (Extended_Body_Name);
1572 if Current_Verbosity = High then
1573 Write_Str ("Looking for path name of """);
1577 Write_Str (" Extended Spec Name = """);
1578 Write_Str (Extended_Spec_Name);
1581 Write_Str (" Extended Body Name = """);
1582 Write_Str (Extended_Body_Name);
1587 while First <= Units.Last
1588 and then Units.Table (First).File_Names (Body_Part).Project /= Project
1594 while Current <= Units.Last loop
1595 Unit := Units.Table (Current);
1597 if Unit.File_Names (Body_Part).Project = Project
1598 and then Unit.File_Names (Body_Part).Name /= No_Name
1601 Current_Name : constant String :=
1602 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1604 if Current_Verbosity = High then
1605 Write_Str (" Comparing with """);
1606 Write_Str (Current_Name);
1611 if Current_Name = Original_Name then
1612 if Current_Verbosity = High then
1616 return Body_Path_Name_Of (Current);
1618 elsif Current_Name = Extended_Body_Name then
1619 if Current_Verbosity = High then
1623 return Body_Path_Name_Of (Current);
1626 if Current_Verbosity = High then
1627 Write_Line (" not good");
1632 elsif Unit.File_Names (Specification).Name /= No_Name then
1634 Current_Name : constant String :=
1635 Namet.Get_Name_String
1636 (Unit.File_Names (Specification).Name);
1639 if Current_Verbosity = High then
1640 Write_Str (" Comparing with """);
1641 Write_Str (Current_Name);
1646 if Current_Name = Original_Name then
1647 if Current_Verbosity = High then
1651 return Spec_Path_Name_Of (Current);
1653 elsif Current_Name = Extended_Spec_Name then
1655 if Current_Verbosity = High then
1659 return Spec_Path_Name_Of (Current);
1662 if Current_Verbosity = High then
1663 Write_Line (" not good");
1668 Current := Current + 1;
1672 end Path_Name_Of_Library_Unit_Body;
1678 procedure Print_Sources is
1682 Write_Line ("List of Sources:");
1684 for Id in Units.First .. Units.Last loop
1685 Unit := Units.Table (Id);
1687 Write_Line (Namet.Get_Name_String (Unit.Name));
1689 if Unit.File_Names (Specification).Name /= No_Name then
1690 if Unit.File_Names (Specification).Project = No_Project then
1691 Write_Line (" No project");
1694 Write_Str (" Project: ");
1697 (Unit.File_Names (Specification).Project).Path_Name);
1698 Write_Line (Name_Buffer (1 .. Name_Len));
1701 Write_Str (" spec: ");
1703 (Namet.Get_Name_String
1704 (Unit.File_Names (Specification).Name));
1707 if Unit.File_Names (Body_Part).Name /= No_Name then
1708 if Unit.File_Names (Body_Part).Project = No_Project then
1709 Write_Line (" No project");
1712 Write_Str (" Project: ");
1715 (Unit.File_Names (Body_Part).Project).Path_Name);
1716 Write_Line (Name_Buffer (1 .. Name_Len));
1719 Write_Str (" body: ");
1721 (Namet.Get_Name_String
1722 (Unit.File_Names (Body_Part).Name));
1727 Write_Line ("end of List of Sources.");
1736 Main_Project : Project_Id) return Project_Id
1738 Result : Project_Id := No_Project;
1740 Original_Name : String := Name;
1742 Data : constant Project_Data := Projects.Table (Main_Project);
1744 Extended_Spec_Name : String :=
1745 Name & Namet.Get_Name_String
1746 (Data.Naming.Current_Spec_Suffix);
1747 Extended_Body_Name : String :=
1748 Name & Namet.Get_Name_String
1749 (Data.Naming.Current_Body_Suffix);
1753 Current_Name : Name_Id;
1755 The_Original_Name : Name_Id;
1756 The_Spec_Name : Name_Id;
1757 The_Body_Name : Name_Id;
1760 Canonical_Case_File_Name (Original_Name);
1761 Name_Len := Original_Name'Length;
1762 Name_Buffer (1 .. Name_Len) := Original_Name;
1763 The_Original_Name := Name_Find;
1765 Canonical_Case_File_Name (Extended_Spec_Name);
1766 Name_Len := Extended_Spec_Name'Length;
1767 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1768 The_Spec_Name := Name_Find;
1770 Canonical_Case_File_Name (Extended_Body_Name);
1771 Name_Len := Extended_Body_Name'Length;
1772 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1773 The_Body_Name := Name_Find;
1775 for Current in reverse Units.First .. Units.Last loop
1776 Unit := Units.Table (Current);
1780 Current_Name := Unit.File_Names (Body_Part).Name;
1782 -- Case of a body present
1784 if Current_Name /= No_Name then
1786 -- If it has the name of the original name or the body name,
1787 -- we have found the project.
1789 if Unit.Name = The_Original_Name
1790 or else Current_Name = The_Original_Name
1791 or else Current_Name = The_Body_Name
1793 Result := Unit.File_Names (Body_Part).Project;
1800 Current_Name := Unit.File_Names (Specification).Name;
1802 if Current_Name /= No_Name then
1804 -- If name same as the original name, or the spec name, we have
1805 -- found the project.
1807 if Unit.Name = The_Original_Name
1808 or else Current_Name = The_Original_Name
1809 or else Current_Name = The_Spec_Name
1811 Result := Unit.File_Names (Specification).Project;
1817 -- Get the ultimate extending project
1819 if Result /= No_Project then
1820 while Projects.Table (Result).Extended_By /= No_Project loop
1821 Result := Projects.Table (Result).Extended_By;
1832 procedure Set_Ada_Paths
1833 (Project : Project_Id;
1834 Including_Libraries : Boolean)
1836 Source_FD : File_Descriptor := Invalid_FD;
1837 Object_FD : File_Descriptor := Invalid_FD;
1839 Process_Source_Dirs : Boolean := False;
1840 Process_Object_Dirs : Boolean := False;
1843 -- For calls to Close
1845 procedure Add (Project : Project_Id);
1846 -- Add all the source/object directories of a project to the path only
1847 -- if this project has not been visited. Calls itself recursively for
1848 -- projects being extended, and imported projects.
1854 procedure Add (Project : Project_Id) is
1856 -- If Seen is False, then the project has not yet been visited
1858 if not Projects.Table (Project).Seen then
1859 Projects.Table (Project).Seen := True;
1862 Data : constant Project_Data := Projects.Table (Project);
1863 List : Project_List := Data.Imported_Projects;
1866 if Process_Source_Dirs then
1868 -- Add to path all source directories of this project
1870 Add_To_Path_File (Data.Source_Dirs, Source_FD);
1873 if Process_Object_Dirs then
1875 -- Add to path the object directory of this project
1876 -- except if we don't include library project and
1877 -- this is a library project.
1879 if (Data.Library and then Including_Libraries)
1881 (Data.Object_Directory /= No_Name
1883 (not Including_Libraries or else not Data.Library))
1885 -- For a library project, add the library directory
1887 if Data.Library then
1889 New_Path : constant String :=
1890 Get_Name_String (Data.Library_Dir);
1893 Add_To_Path_File (New_Path, Object_FD);
1897 -- For a non library project, add the object directory
1900 New_Path : constant String :=
1901 Get_Name_String (Data.Object_Directory);
1903 Add_To_Path_File (New_Path, Object_FD);
1909 -- Call Add to the project being extended, if any
1911 if Data.Extends /= No_Project then
1915 -- Call Add for each imported project, if any
1917 while List /= Empty_Project_List loop
1918 Add (Project_Lists.Table (List).Project);
1919 List := Project_Lists.Table (List).Next;
1925 -- Start of processing for Set_Ada_Paths
1928 -- If it is the first time we call this procedure for
1929 -- this project, compute the source path and/or the object path.
1931 if Projects.Table (Project).Include_Path_File = No_Name then
1932 Process_Source_Dirs := True;
1933 Create_New_Path_File
1934 (Source_FD, Projects.Table (Project).Include_Path_File);
1937 -- For the object path, we make a distinction depending on
1938 -- Including_Libraries.
1940 if Including_Libraries then
1941 if Projects.Table (Project).Objects_Path_File_With_Libs = No_Name then
1942 Process_Object_Dirs := True;
1943 Create_New_Path_File
1944 (Object_FD, Projects.Table (Project).
1945 Objects_Path_File_With_Libs);
1950 Projects.Table (Project).Objects_Path_File_Without_Libs = No_Name
1952 Process_Object_Dirs := True;
1953 Create_New_Path_File
1954 (Object_FD, Projects.Table (Project).
1955 Objects_Path_File_Without_Libs);
1959 -- If there is something to do, set Seen to False for all projects,
1960 -- then call the recursive procedure Add for Project.
1962 if Process_Source_Dirs or Process_Object_Dirs then
1963 for Index in 1 .. Projects.Last loop
1964 Projects.Table (Index).Seen := False;
1970 -- Close any file that has been created.
1972 if Source_FD /= Invalid_FD then
1973 Close (Source_FD, Status);
1976 Prj.Com.Fail ("disk full");
1980 if Object_FD /= Invalid_FD then
1981 Close (Object_FD, Status);
1984 Prj.Com.Fail ("disk full");
1988 -- Set the env vars, if they need to be changed, and set the
1989 -- corresponding flags.
1992 Current_Source_Path_File /= Projects.Table (Project).Include_Path_File
1994 Current_Source_Path_File :=
1995 Projects.Table (Project).Include_Path_File;
1997 (Project_Include_Path_File,
1998 Get_Name_String (Current_Source_Path_File));
1999 Ada_Prj_Include_File_Set := True;
2002 if Including_Libraries then
2003 if Current_Object_Path_File
2004 /= Projects.Table (Project).Objects_Path_File_With_Libs
2006 Current_Object_Path_File :=
2007 Projects.Table (Project).Objects_Path_File_With_Libs;
2009 (Project_Objects_Path_File,
2010 Get_Name_String (Current_Object_Path_File));
2011 Ada_Prj_Objects_File_Set := True;
2015 if Current_Object_Path_File
2016 /= Projects.Table (Project).Objects_Path_File_Without_Libs
2018 Current_Object_Path_File :=
2019 Projects.Table (Project).Objects_Path_File_Without_Libs;
2021 (Project_Objects_Path_File,
2022 Get_Name_String (Current_Object_Path_File));
2023 Ada_Prj_Objects_File_Set := True;
2028 ---------------------------------------------
2029 -- Set_Mapping_File_Initial_State_To_Empty --
2030 ---------------------------------------------
2032 procedure Set_Mapping_File_Initial_State_To_Empty is
2034 Fill_Mapping_File := False;
2035 end Set_Mapping_File_Initial_State_To_Empty;
2037 -----------------------
2038 -- Set_Path_File_Var --
2039 -----------------------
2041 procedure Set_Path_File_Var (Name : String; Value : String) is
2042 Host_Spec : String_Access := To_Host_File_Spec (Value);
2045 if Host_Spec = null then
2047 ("could not convert file name """, Value, """ to host spec");
2049 Setenv (Name, Host_Spec.all);
2052 end Set_Path_File_Var;
2054 -----------------------
2055 -- Spec_Path_Name_Of --
2056 -----------------------
2058 function Spec_Path_Name_Of (Unit : Unit_Id) return String is
2059 Data : Unit_Data := Units.Table (Unit);
2062 if Data.File_Names (Specification).Path = No_Name then
2064 Current_Source : String_List_Id :=
2065 Projects.Table (Data.File_Names (Specification).Project).Sources;
2066 Path : GNAT.OS_Lib.String_Access;
2069 Data.File_Names (Specification).Path :=
2070 Data.File_Names (Specification).Name;
2072 while Current_Source /= Nil_String loop
2073 Path := Locate_Regular_File
2074 (Namet.Get_Name_String
2075 (Data.File_Names (Specification).Name),
2076 Namet.Get_Name_String
2077 (String_Elements.Table (Current_Source).Value));
2079 if Path /= null then
2080 Name_Len := Path'Length;
2081 Name_Buffer (1 .. Name_Len) := Path.all;
2082 Data.File_Names (Specification).Path := Name_Enter;
2086 String_Elements.Table (Current_Source).Next;
2090 Units.Table (Unit) := Data;
2094 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
2095 end Spec_Path_Name_Of;
2097 ---------------------------
2098 -- Ultimate_Extension_Of --
2099 ---------------------------
2101 function Ultimate_Extension_Of (Project : in Project_Id) return Project_Id
2103 Result : Project_Id := Project;
2106 while Projects.Table (Result).Extended_By /= No_Project loop
2107 Result := Projects.Table (Result).Extended_By;
2111 end Ultimate_Extension_Of;
2114 Path_Files.Set_Last (0);