1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
27 ------------------------------------------------------------------------------
29 with GNAT.OS_Lib; use GNAT.OS_Lib;
30 with Namet; use Namet;
32 with Osint; use Osint;
33 with Output; use Output;
34 with Prj.Com; use Prj.Com;
36 with Snames; use Snames;
37 with Stringt; use Stringt;
40 package body Prj.Env is
42 type Naming_Id is new Nat;
44 Ada_Path_Buffer : String_Access := new String (1 .. 1_000);
45 -- A buffer where values for ADA_INCLUDE_PATH
46 -- and ADA_OBJECTS_PATH are stored.
48 Ada_Path_Length : Natural := 0;
49 -- Index of the last valid character in Ada_Path_Buffer.
51 package Namings is new Table.Table (
52 Table_Component_Type => Naming_Data,
53 Table_Index_Type => Naming_Id,
56 Table_Increment => 100,
57 Table_Name => "Prj.Env.Namings");
59 Default_Naming : constant Naming_Id := Namings.First;
61 Global_Configuration_Pragmas : Name_Id;
62 Local_Configuration_Pragmas : Name_Id;
64 Fill_Mapping_File : Boolean := True;
66 -----------------------
67 -- Local Subprograms --
68 -----------------------
70 function Body_Path_Name_Of (Unit : Unit_Id) return String;
71 -- Returns the path name of the body of a unit.
72 -- Compute it first, if necessary.
74 function Spec_Path_Name_Of (Unit : Unit_Id) return String;
75 -- Returns the path name of the spec of a unit.
76 -- Compute it first, if necessary.
78 procedure Add_To_Path (Source_Dirs : String_List_Id);
79 -- Add to Ada_Path_Buffer all the source directories in string list
80 -- Source_Dirs, if any. Increment Ada_Path_Length.
82 procedure Add_To_Path (Path : String);
83 -- Add Path to global variable Ada_Path_Buffer
84 -- Increment Ada_Path_Length
86 ----------------------
87 -- Ada_Include_Path --
88 ----------------------
90 function Ada_Include_Path (Project : Project_Id) return String_Access is
92 procedure Add (Project : Project_Id);
93 -- Add all the source directories of a project to the path only if
94 -- this project has not been visited. Calls itself recursively for
95 -- projects being modified, and imported projects. Adds the project
96 -- to the list Seen if this is the call to Add for this project.
102 procedure Add (Project : Project_Id) is
104 -- If Seen is empty, then the project cannot have been visited
106 if not Projects.Table (Project).Seen then
107 Projects.Table (Project).Seen := True;
110 Data : Project_Data := Projects.Table (Project);
111 List : Project_List := Data.Imported_Projects;
114 -- Add to path all source directories of this project
116 Add_To_Path (Data.Source_Dirs);
118 -- Call Add to the project being modified, if any
120 if Data.Modifies /= No_Project then
124 -- Call Add for each imported project, if any
126 while List /= Empty_Project_List loop
127 Add (Project_Lists.Table (List).Project);
128 List := Project_Lists.Table (List).Next;
134 -- Start of processing for Ada_Include_Path
137 -- If it is the first time we call this function for
138 -- this project, compute the source path
140 if Projects.Table (Project).Include_Path = null then
141 Ada_Path_Length := 0;
143 for Index in 1 .. Projects.Last loop
144 Projects.Table (Index).Seen := False;
148 Projects.Table (Project).Include_Path :=
149 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
152 return Projects.Table (Project).Include_Path;
153 end Ada_Include_Path;
155 function Ada_Include_Path
156 (Project : Project_Id;
162 return Ada_Include_Path (Project).all;
164 Ada_Path_Length := 0;
165 Add_To_Path (Projects.Table (Project).Source_Dirs);
166 return Ada_Path_Buffer (1 .. Ada_Path_Length);
168 end Ada_Include_Path;
170 ----------------------
171 -- Ada_Objects_Path --
172 ----------------------
174 function Ada_Objects_Path
175 (Project : Project_Id;
176 Including_Libraries : Boolean := True)
179 procedure Add (Project : Project_Id);
180 -- Add all the object directories of a project to the path only if
181 -- this project has not been visited. Calls itself recursively for
182 -- projects being modified, and imported projects. Adds the project
183 -- to the list Seen if this is the first call to Add for this project.
189 procedure Add (Project : Project_Id) is
191 -- If this project has not been seen yet
193 if not Projects.Table (Project).Seen then
194 Projects.Table (Project).Seen := True;
197 Data : Project_Data := Projects.Table (Project);
198 List : Project_List := Data.Imported_Projects;
201 -- Add to path the object directory of this project
202 -- except if we don't include library project and
203 -- this is a library project.
205 if (Data.Library and then Including_Libraries)
207 (Data.Object_Directory /= No_Name
209 (not Including_Libraries or else not Data.Library))
211 if Ada_Path_Length > 0 then
212 Add_To_Path (Path => (1 => Path_Separator));
215 -- For a library project, att the library directory
219 New_Path : constant String :=
220 Get_Name_String (Data.Library_Dir);
222 Add_To_Path (New_Path);
226 -- For a non library project, add the object directory
228 New_Path : constant String :=
229 Get_Name_String (Data.Object_Directory);
231 Add_To_Path (New_Path);
236 -- Call Add to the project being modified, if any
238 if Data.Modifies /= No_Project then
242 -- Call Add for each imported project, if any
244 while List /= Empty_Project_List loop
245 Add (Project_Lists.Table (List).Project);
246 List := Project_Lists.Table (List).Next;
253 -- Start of processing for Ada_Objects_Path
256 -- If it is the first time we call this function for
257 -- this project, compute the objects path
259 if Projects.Table (Project).Objects_Path = null then
260 Ada_Path_Length := 0;
262 for Index in 1 .. Projects.Last loop
263 Projects.Table (Index).Seen := False;
267 Projects.Table (Project).Objects_Path :=
268 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
271 return Projects.Table (Project).Objects_Path;
272 end Ada_Objects_Path;
278 procedure Add_To_Path (Source_Dirs : String_List_Id) is
279 Current : String_List_Id := Source_Dirs;
280 Source_Dir : String_Element;
283 while Current /= Nil_String loop
284 if Ada_Path_Length > 0 then
285 Add_To_Path (Path => (1 => Path_Separator));
288 Source_Dir := String_Elements.Table (Current);
289 String_To_Name_Buffer (Source_Dir.Value);
292 New_Path : constant String :=
293 Name_Buffer (1 .. Name_Len);
295 Add_To_Path (New_Path);
298 Current := Source_Dir.Next;
302 procedure Add_To_Path (Path : String) is
304 -- If Ada_Path_Buffer is too small, double it
306 if Ada_Path_Length + Path'Length > Ada_Path_Buffer'Last then
308 New_Ada_Path_Buffer : constant String_Access :=
310 (1 .. Ada_Path_Buffer'Last +
311 Ada_Path_Buffer'Last);
314 New_Ada_Path_Buffer (1 .. Ada_Path_Length) :=
315 Ada_Path_Buffer (1 .. Ada_Path_Length);
316 Ada_Path_Buffer := New_Ada_Path_Buffer;
321 (Ada_Path_Length + 1 .. Ada_Path_Length + Path'Length) := Path;
322 Ada_Path_Length := Ada_Path_Length + Path'Length;
325 -----------------------
326 -- Body_Path_Name_Of --
327 -----------------------
329 function Body_Path_Name_Of (Unit : Unit_Id) return String is
330 Data : Unit_Data := Units.Table (Unit);
333 -- If we don't know the path name of the body of this unit,
334 -- we compute it, and we store it.
336 if Data.File_Names (Body_Part).Path = No_Name then
338 Current_Source : String_List_Id :=
339 Projects.Table (Data.File_Names (Body_Part).Project).Sources;
340 Path : GNAT.OS_Lib.String_Access;
343 -- By default, put the file name
345 Data.File_Names (Body_Part).Path :=
346 Data.File_Names (Body_Part).Name;
348 -- For each source directory
350 while Current_Source /= Nil_String loop
351 String_To_Name_Buffer
352 (String_Elements.Table (Current_Source).Value);
355 (Namet.Get_Name_String
356 (Data.File_Names (Body_Part).Name),
357 Name_Buffer (1 .. Name_Len));
359 -- If the file is in this directory,
360 -- then we store the path, and we are done.
363 Name_Len := Path'Length;
364 Name_Buffer (1 .. Name_Len) := Path.all;
365 Data.File_Names (Body_Part).Path := Name_Enter;
370 String_Elements.Table (Current_Source).Next;
374 Units.Table (Unit) := Data;
378 -- Returned the value stored
380 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
381 end Body_Path_Name_Of;
383 --------------------------------
384 -- Create_Config_Pragmas_File --
385 --------------------------------
387 procedure Create_Config_Pragmas_File
388 (For_Project : Project_Id;
389 Main_Project : Project_Id)
391 File_Name : Temp_File_Name;
392 File : File_Descriptor := Invalid_FD;
394 The_Packages : Package_Id;
395 Gnatmake : Prj.Package_Id;
396 Compiler : Prj.Package_Id;
398 Current_Unit : Unit_Id := Units.First;
400 First_Project : Project_List := Empty_Project_List;
402 Current_Project : Project_List;
403 Current_Naming : Naming_Id;
405 Global_Attribute : Variable_Value := Nil_Variable_Value;
406 Local_Attribute : Variable_Value := Nil_Variable_Value;
408 Global_Attribute_Present : Boolean := False;
409 Local_Attribute_Present : Boolean := False;
411 procedure Check (Project : Project_Id);
413 procedure Check_Temp_File;
414 -- Check that a temporary file has been opened.
415 -- If not, create one, and put its name in the project data,
416 -- with the indication that it is a temporary file.
418 procedure Copy_File (Name : String_Id);
419 -- Copy a configuration pragmas file into the temp file.
422 (Unit_Name : Name_Id;
424 Unit_Kind : Spec_Or_Body);
425 -- Put an SFN pragma in the temporary file.
427 procedure Put (File : File_Descriptor; S : String);
429 procedure Put_Line (File : File_Descriptor; S : String);
435 procedure Check (Project : Project_Id) is
436 Data : constant Project_Data := Projects.Table (Project);
439 if Current_Verbosity = High then
440 Write_Str ("Checking project file """);
441 Write_Str (Namet.Get_Name_String (Data.Name));
446 -- Is this project in the list of the visited project?
448 Current_Project := First_Project;
449 while Current_Project /= Empty_Project_List
450 and then Project_Lists.Table (Current_Project).Project /= Project
452 Current_Project := Project_Lists.Table (Current_Project).Next;
455 -- If it is not, put it in the list, and visit it
457 if Current_Project = Empty_Project_List then
458 Project_Lists.Increment_Last;
459 Project_Lists.Table (Project_Lists.Last) :=
460 (Project => Project, Next => First_Project);
461 First_Project := Project_Lists.Last;
463 -- Is the naming scheme of this project one that we know?
465 Current_Naming := Default_Naming;
466 while Current_Naming <= Namings.Last and then
467 not Same_Naming_Scheme
468 (Left => Namings.Table (Current_Naming),
469 Right => Data.Naming) loop
470 Current_Naming := Current_Naming + 1;
473 -- If we don't know it, add it
475 if Current_Naming > Namings.Last then
476 Namings.Increment_Last;
477 Namings.Table (Namings.Last) := Data.Naming;
479 -- We need a temporary file to be created
483 -- Put the SFN pragmas for the naming scheme
488 (File, "pragma Source_File_Name");
490 (File, " (Spec_File_Name => ""*" &
491 Namet.Get_Name_String (Data.Naming.Current_Spec_Suffix) &
494 (File, " Casing => " &
495 Image (Data.Naming.Casing) & ",");
497 (File, " Dot_Replacement => """ &
498 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
504 (File, "pragma Source_File_Name");
506 (File, " (Body_File_Name => ""*" &
507 Namet.Get_Name_String (Data.Naming.Current_Impl_Suffix) &
510 (File, " Casing => " &
511 Image (Data.Naming.Casing) & ",");
513 (File, " Dot_Replacement => """ &
514 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
517 -- and maybe separate
520 Data.Naming.Current_Impl_Suffix /= Data.Naming.Separate_Suffix
523 (File, "pragma Source_File_Name");
525 (File, " (Subunit_File_Name => ""*" &
526 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
529 (File, " Casing => " &
530 Image (Data.Naming.Casing) &
533 (File, " Dot_Replacement => """ &
534 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
539 if Data.Modifies /= No_Project then
540 Check (Data.Modifies);
544 Current : Project_List := Data.Imported_Projects;
547 while Current /= Empty_Project_List loop
548 Check (Project_Lists.Table (Current).Project);
549 Current := Project_Lists.Table (Current).Next;
555 ---------------------
556 -- Check_Temp_File --
557 ---------------------
559 procedure Check_Temp_File is
561 if File = Invalid_FD then
562 GNAT.OS_Lib.Create_Temp_File (File, Name => File_Name);
563 if File = Invalid_FD then
565 ("unable to create temporary configuration pragmas file");
566 elsif Opt.Verbose_Mode then
567 Write_Str ("Creating temp file """);
568 Write_Str (File_Name);
578 procedure Copy_File (Name : in String_Id) is
579 Input : File_Descriptor;
580 Buffer : String (1 .. 1_000);
581 Input_Length : Integer;
582 Output_Length : Integer;
586 String_To_Name_Buffer (Name);
588 if Opt.Verbose_Mode then
589 Write_Str ("Copying config pragmas file """);
590 Write_Str (Name_Buffer (1 .. Name_Len));
591 Write_Line (""" into temp file");
595 Name : constant String :=
596 Name_Buffer (1 .. Name_Len) & ASCII.NUL;
598 Input := Open_Read (Name'Address, Binary);
601 if Input = Invalid_FD then
603 ("cannot open configuration pragmas file " &
604 Name_Buffer (1 .. Name_Len));
608 Input_Length := Read (Input, Buffer'Address, Buffer'Length);
609 Output_Length := Write (File, Buffer'Address, Input_Length);
611 if Output_Length /= Input_Length then
612 Osint.Fail ("disk full");
615 exit when Input_Length < Buffer'Length;
627 (Unit_Name : Name_Id;
629 Unit_Kind : Spec_Or_Body)
632 -- A temporary file needs to be open
636 -- Put the pragma SFN for the unit kind (spec or body)
638 Put (File, "pragma Source_File_Name (");
639 Put (File, Namet.Get_Name_String (Unit_Name));
641 if Unit_Kind = Specification then
642 Put (File, ", Spec_File_Name => """);
644 Put (File, ", Body_File_Name => """);
647 Put (File, Namet.Get_Name_String (File_Name));
648 Put_Line (File, """);");
651 procedure Put (File : File_Descriptor; S : String) is
655 Last := Write (File, S (S'First)'Address, S'Length);
657 if Last /= S'Length then
658 Osint.Fail ("Disk full");
661 if Current_Verbosity = High then
670 procedure Put_Line (File : File_Descriptor; S : String) is
671 S0 : String (1 .. S'Length + 1);
675 -- Add an ASCII.LF to the string. As this gnat.adc is supposed to
676 -- be used only by the compiler, we don't care about the characters
677 -- for the end of line. In fact we could have put a space, but
678 -- it is more convenient to be able to read gnat.adc during
679 -- development, for which the ASCII.LF is fine.
681 S0 (1 .. S'Length) := S;
682 S0 (S0'Last) := ASCII.LF;
683 Last := Write (File, S0'Address, S0'Length);
685 if Last /= S'Length + 1 then
686 Osint.Fail ("Disk full");
689 if Current_Verbosity = High then
694 -- Start of processing for Create_Config_Pragmas_File
697 if not Projects.Table (For_Project).Config_Checked then
699 -- Remove any memory of processed naming schemes, if any
701 Namings.Set_Last (Default_Naming);
703 -- Check the naming schemes
707 -- Visit all the units and process those that need an SFN pragma
709 while Current_Unit <= Units.Last loop
711 Unit : constant Unit_Data :=
712 Units.Table (Current_Unit);
715 if Unit.File_Names (Specification).Needs_Pragma then
717 Unit.File_Names (Specification).Name,
721 if Unit.File_Names (Body_Part).Needs_Pragma then
723 Unit.File_Names (Body_Part).Name,
727 Current_Unit := Current_Unit + 1;
731 The_Packages := Projects.Table (Main_Project).Decl.Packages;
734 (Name => Name_Builder,
735 In_Packages => The_Packages);
737 if Gnatmake /= No_Package then
738 Global_Attribute := Prj.Util.Value_Of
739 (Variable_Name => Global_Configuration_Pragmas,
740 In_Variables => Packages.Table (Gnatmake).Decl.Attributes);
741 Global_Attribute_Present :=
742 Global_Attribute /= Nil_Variable_Value
743 and then String_Length (Global_Attribute.Value) > 0;
746 The_Packages := Projects.Table (For_Project).Decl.Packages;
749 (Name => Name_Compiler,
750 In_Packages => The_Packages);
752 if Compiler /= No_Package then
753 Local_Attribute := Prj.Util.Value_Of
754 (Variable_Name => Local_Configuration_Pragmas,
755 In_Variables => Packages.Table (Compiler).Decl.Attributes);
756 Local_Attribute_Present :=
757 Local_Attribute /= Nil_Variable_Value
758 and then String_Length (Local_Attribute.Value) > 0;
761 if Global_Attribute_Present then
762 if File /= Invalid_FD
763 or else Local_Attribute_Present
765 Copy_File (Global_Attribute.Value);
768 String_To_Name_Buffer (Global_Attribute.Value);
769 Projects.Table (For_Project).Config_File_Name := Name_Find;
773 if Local_Attribute_Present then
774 if File /= Invalid_FD then
775 Copy_File (Local_Attribute.Value);
778 String_To_Name_Buffer (Local_Attribute.Value);
779 Projects.Table (For_Project).Config_File_Name := Name_Find;
783 if File /= Invalid_FD then
784 GNAT.OS_Lib.Close (File);
786 if Opt.Verbose_Mode then
787 Write_Str ("Closing configuration file """);
788 Write_Str (File_Name);
792 Name_Len := File_Name'Length;
793 Name_Buffer (1 .. Name_Len) := File_Name;
794 Projects.Table (For_Project).Config_File_Name := Name_Find;
795 Projects.Table (For_Project).Config_File_Temp := True;
798 Projects.Table (For_Project).Config_Checked := True;
800 end Create_Config_Pragmas_File;
802 -------------------------
803 -- Create_Mapping_File --
804 -------------------------
806 procedure Create_Mapping_File (Name : in out Temp_File_Name) is
807 File : File_Descriptor := Invalid_FD;
808 The_Unit_Data : Unit_Data;
809 Data : File_Name_Data;
811 procedure Put_Name_Buffer;
812 -- Put the line contained in the Name_Buffer in the mapping file
814 procedure Put_Data (Spec : Boolean);
815 -- Put the mapping of the spec or body contained in Data in the file
822 procedure Put_Name_Buffer is
826 Name_Len := Name_Len + 1;
827 Name_Buffer (Name_Len) := ASCII.LF;
828 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
830 if Last /= Name_Len then
831 Osint.Fail ("Disk full");
839 procedure Put_Data (Spec : Boolean) is
841 -- Line with the unit name
843 Get_Name_String (The_Unit_Data.Name);
844 Name_Len := Name_Len + 1;
845 Name_Buffer (Name_Len) := '%';
846 Name_Len := Name_Len + 1;
849 Name_Buffer (Name_Len) := 's';
851 Name_Buffer (Name_Len) := 'b';
856 -- Line with the file nale
858 Get_Name_String (Data.Name);
861 -- Line with the path name
863 Get_Name_String (Data.Path);
868 -- Start of processing for Create_Mapping_File
871 GNAT.OS_Lib.Create_Temp_File (File, Name => Name);
873 if File = Invalid_FD then
875 ("unable to create temporary mapping file");
877 elsif Opt.Verbose_Mode then
878 Write_Str ("Creating temp mapping file """);
883 if Fill_Mapping_File then
884 -- For all units in table Units
886 for Unit in 1 .. Units.Last loop
887 The_Unit_Data := Units.Table (Unit);
889 -- If the unit has a valid name
891 if The_Unit_Data.Name /= No_Name then
892 Data := The_Unit_Data.File_Names (Specification);
894 -- If there is a spec, put it mapping in the file
896 if Data.Name /= No_Name then
897 Put_Data (Spec => True);
900 Data := The_Unit_Data.File_Names (Body_Part);
902 -- If there is a body (or subunit) put its mapping in the file
904 if Data.Name /= No_Name then
905 Put_Data (Spec => False);
912 GNAT.OS_Lib.Close (File);
914 end Create_Mapping_File;
916 ------------------------------------
917 -- File_Name_Of_Library_Unit_Body --
918 ------------------------------------
920 function File_Name_Of_Library_Unit_Body
922 Project : Project_Id)
925 Data : constant Project_Data := Projects.Table (Project);
926 Original_Name : String := Name;
928 Extended_Spec_Name : String :=
929 Name & Namet.Get_Name_String
930 (Data.Naming.Current_Spec_Suffix);
931 Extended_Body_Name : String :=
932 Name & Namet.Get_Name_String
933 (Data.Naming.Current_Impl_Suffix);
937 The_Original_Name : Name_Id;
938 The_Spec_Name : Name_Id;
939 The_Body_Name : Name_Id;
942 Canonical_Case_File_Name (Original_Name);
943 Name_Len := Original_Name'Length;
944 Name_Buffer (1 .. Name_Len) := Original_Name;
945 The_Original_Name := Name_Find;
947 Canonical_Case_File_Name (Extended_Spec_Name);
948 Name_Len := Extended_Spec_Name'Length;
949 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
950 The_Spec_Name := Name_Find;
952 Canonical_Case_File_Name (Extended_Body_Name);
953 Name_Len := Extended_Body_Name'Length;
954 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
955 The_Body_Name := Name_Find;
957 if Current_Verbosity = High then
958 Write_Str ("Looking for file name of """);
962 Write_Str (" Extended Spec Name = """);
963 Write_Str (Extended_Spec_Name);
966 Write_Str (" Extended Body Name = """);
967 Write_Str (Extended_Body_Name);
974 for Current in reverse Units.First .. Units.Last loop
975 Unit := Units.Table (Current);
977 -- Case of unit of the same project
979 if Unit.File_Names (Body_Part).Project = Project then
981 Current_Name : constant Name_Id :=
982 Unit.File_Names (Body_Part).Name;
985 -- Case of a body present
987 if Current_Name /= No_Name then
988 if Current_Verbosity = High then
989 Write_Str (" Comparing with """);
990 Write_Str (Get_Name_String (Current_Name));
995 -- If it has the name of the original name,
996 -- return the original name
998 if Unit.Name = The_Original_Name
999 or else Current_Name = The_Original_Name
1001 if Current_Verbosity = High then
1005 return Get_Name_String (Current_Name);
1007 -- If it has the name of the extended body name,
1008 -- return the extended body name
1010 elsif Current_Name = The_Body_Name then
1011 if Current_Verbosity = High then
1015 return Extended_Body_Name;
1018 if Current_Verbosity = High then
1019 Write_Line (" not good");
1026 -- Case of a unit of the same project
1028 if Units.Table (Current).File_Names (Specification).Project =
1032 Current_Name : constant Name_Id :=
1033 Unit.File_Names (Specification).Name;
1036 -- Case of spec present
1038 if Current_Name /= No_Name then
1039 if Current_Verbosity = High then
1040 Write_Str (" Comparing with """);
1041 Write_Str (Get_Name_String (Current_Name));
1046 -- If name same as the original name, return original name
1048 if Unit.Name = The_Original_Name
1049 or else Current_Name = The_Original_Name
1051 if Current_Verbosity = High then
1055 return Get_Name_String (Current_Name);
1057 -- If it has the same name as the extended spec name,
1058 -- return the extended spec name.
1060 elsif Current_Name = The_Spec_Name then
1061 if Current_Verbosity = High then
1065 return Extended_Spec_Name;
1068 if Current_Verbosity = High then
1069 Write_Line (" not good");
1077 -- We don't know this file name, return an empty string
1080 end File_Name_Of_Library_Unit_Body;
1082 -------------------------
1083 -- For_All_Object_Dirs --
1084 -------------------------
1086 procedure For_All_Object_Dirs (Project : Project_Id) is
1087 Seen : Project_List := Empty_Project_List;
1089 procedure Add (Project : Project_Id);
1090 -- Process a project. Remember the processes visited to avoid
1091 -- processing a project twice. Recursively process an eventual
1092 -- modified project, and all imported projects.
1098 procedure Add (Project : Project_Id) is
1099 Data : constant Project_Data := Projects.Table (Project);
1100 List : Project_List := Data.Imported_Projects;
1103 -- If the list of visited project is empty, then
1104 -- for sure we never visited this project.
1106 if Seen = Empty_Project_List then
1107 Project_Lists.Increment_Last;
1108 Seen := Project_Lists.Last;
1109 Project_Lists.Table (Seen) :=
1110 (Project => Project, Next => Empty_Project_List);
1113 -- Check if the project is in the list
1116 Current : Project_List := Seen;
1120 -- If it is, then there is nothing else to do
1122 if Project_Lists.Table (Current).Project = Project then
1126 exit when Project_Lists.Table (Current).Next =
1128 Current := Project_Lists.Table (Current).Next;
1131 -- This project has never been visited, add it
1134 Project_Lists.Increment_Last;
1135 Project_Lists.Table (Current).Next := Project_Lists.Last;
1136 Project_Lists.Table (Project_Lists.Last) :=
1137 (Project => Project, Next => Empty_Project_List);
1141 -- If there is an object directory, call Action
1144 if Data.Object_Directory /= No_Name then
1145 Get_Name_String (Data.Object_Directory);
1146 Action (Name_Buffer (1 .. Name_Len));
1149 -- If we are extending a project, visit it
1151 if Data.Modifies /= No_Project then
1152 Add (Data.Modifies);
1155 -- And visit all imported projects
1157 while List /= Empty_Project_List loop
1158 Add (Project_Lists.Table (List).Project);
1159 List := Project_Lists.Table (List).Next;
1163 -- Start of processing for For_All_Object_Dirs
1166 -- Visit this project, and its imported projects,
1170 end For_All_Object_Dirs;
1172 -------------------------
1173 -- For_All_Source_Dirs --
1174 -------------------------
1176 procedure For_All_Source_Dirs (Project : Project_Id) is
1177 Seen : Project_List := Empty_Project_List;
1179 procedure Add (Project : Project_Id);
1180 -- Process a project. Remember the processes visited to avoid
1181 -- processing a project twice. Recursively process an eventual
1182 -- modified project, and all imported projects.
1188 procedure Add (Project : Project_Id) is
1189 Data : constant Project_Data := Projects.Table (Project);
1190 List : Project_List := Data.Imported_Projects;
1193 -- If the list of visited project is empty, then
1194 -- for sure we never visited this project.
1196 if Seen = Empty_Project_List then
1197 Project_Lists.Increment_Last;
1198 Seen := Project_Lists.Last;
1199 Project_Lists.Table (Seen) :=
1200 (Project => Project, Next => Empty_Project_List);
1203 -- Check if the project is in the list
1206 Current : Project_List := Seen;
1210 -- If it is, then there is nothing else to do
1212 if Project_Lists.Table (Current).Project = Project then
1216 exit when Project_Lists.Table (Current).Next =
1218 Current := Project_Lists.Table (Current).Next;
1221 -- This project has never been visited, add it
1224 Project_Lists.Increment_Last;
1225 Project_Lists.Table (Current).Next := Project_Lists.Last;
1226 Project_Lists.Table (Project_Lists.Last) :=
1227 (Project => Project, Next => Empty_Project_List);
1232 Current : String_List_Id := Data.Source_Dirs;
1233 The_String : String_Element;
1236 -- Call action with the name of every source directorie
1238 while Current /= Nil_String loop
1239 The_String := String_Elements.Table (Current);
1240 String_To_Name_Buffer (The_String.Value);
1241 Action (Name_Buffer (1 .. Name_Len));
1242 Current := The_String.Next;
1246 -- If we are extending a project, visit it
1248 if Data.Modifies /= No_Project then
1249 Add (Data.Modifies);
1252 -- And visit all imported projects
1254 while List /= Empty_Project_List loop
1255 Add (Project_Lists.Table (List).Project);
1256 List := Project_Lists.Table (List).Next;
1260 -- Start of processing for For_All_Source_Dirs
1263 -- Visit this project, and its imported projects recursively
1266 end For_All_Source_Dirs;
1272 procedure Get_Reference
1273 (Source_File_Name : String;
1274 Project : out Project_Id;
1278 if Current_Verbosity > Default then
1279 Write_Str ("Getting Reference_Of (""");
1280 Write_Str (Source_File_Name);
1281 Write_Str (""") ... ");
1285 Original_Name : String := Source_File_Name;
1289 Canonical_Case_File_Name (Original_Name);
1291 for Id in Units.First .. Units.Last loop
1292 Unit := Units.Table (Id);
1294 if (Unit.File_Names (Specification).Name /= No_Name
1296 Namet.Get_Name_String
1297 (Unit.File_Names (Specification).Name) = Original_Name)
1298 or else (Unit.File_Names (Specification).Path /= No_Name
1300 Namet.Get_Name_String
1301 (Unit.File_Names (Specification).Path) =
1304 Project := Unit.File_Names (Specification).Project;
1305 Path := Unit.File_Names (Specification).Path;
1307 if Current_Verbosity > Default then
1308 Write_Str ("Done: Specification.");
1314 elsif (Unit.File_Names (Body_Part).Name /= No_Name
1316 Namet.Get_Name_String
1317 (Unit.File_Names (Body_Part).Name) = Original_Name)
1318 or else (Unit.File_Names (Body_Part).Path /= No_Name
1319 and then Namet.Get_Name_String
1320 (Unit.File_Names (Body_Part).Path) =
1323 Project := Unit.File_Names (Body_Part).Project;
1324 Path := Unit.File_Names (Body_Part).Path;
1326 if Current_Verbosity > Default then
1327 Write_Str ("Done: Body.");
1337 Project := No_Project;
1340 if Current_Verbosity > Default then
1341 Write_Str ("Cannot be found.");
1350 procedure Initialize is
1351 Global : constant String := "global_configuration_pragmas";
1352 Local : constant String := "local_configuration_pragmas";
1355 -- Put the standard GNAT naming scheme in the Namings table
1357 Namings.Increment_Last;
1358 Namings.Table (Namings.Last) := Standard_Naming_Data;
1359 Name_Len := Global'Length;
1360 Name_Buffer (1 .. Name_Len) := Global;
1361 Global_Configuration_Pragmas := Name_Find;
1362 Name_Len := Local'Length;
1363 Name_Buffer (1 .. Name_Len) := Local;
1364 Local_Configuration_Pragmas := Name_Find;
1367 ------------------------------------
1368 -- Path_Name_Of_Library_Unit_Body --
1369 ------------------------------------
1371 function Path_Name_Of_Library_Unit_Body
1373 Project : Project_Id)
1376 Data : constant Project_Data := Projects.Table (Project);
1377 Original_Name : String := Name;
1379 Extended_Spec_Name : String :=
1380 Name & Namet.Get_Name_String
1381 (Data.Naming.Current_Spec_Suffix);
1382 Extended_Body_Name : String :=
1383 Name & Namet.Get_Name_String
1384 (Data.Naming.Current_Impl_Suffix);
1386 First : Unit_Id := Units.First;
1391 Canonical_Case_File_Name (Original_Name);
1392 Canonical_Case_File_Name (Extended_Spec_Name);
1393 Canonical_Case_File_Name (Extended_Spec_Name);
1395 if Current_Verbosity = High then
1396 Write_Str ("Looking for path name of """);
1400 Write_Str (" Extended Spec Name = """);
1401 Write_Str (Extended_Spec_Name);
1404 Write_Str (" Extended Body Name = """);
1405 Write_Str (Extended_Body_Name);
1410 while First <= Units.Last
1411 and then Units.Table (First).File_Names (Body_Part).Project /= Project
1417 while Current <= Units.Last loop
1418 Unit := Units.Table (Current);
1420 if Unit.File_Names (Body_Part).Project = Project
1421 and then Unit.File_Names (Body_Part).Name /= No_Name
1424 Current_Name : constant String :=
1425 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1427 if Current_Verbosity = High then
1428 Write_Str (" Comparing with """);
1429 Write_Str (Current_Name);
1434 if Current_Name = Original_Name then
1435 if Current_Verbosity = High then
1439 return Body_Path_Name_Of (Current);
1441 elsif Current_Name = Extended_Body_Name then
1442 if Current_Verbosity = High then
1446 return Body_Path_Name_Of (Current);
1449 if Current_Verbosity = High then
1450 Write_Line (" not good");
1455 elsif Unit.File_Names (Specification).Name /= No_Name then
1457 Current_Name : constant String :=
1458 Namet.Get_Name_String
1459 (Unit.File_Names (Specification).Name);
1462 if Current_Verbosity = High then
1463 Write_Str (" Comparing with """);
1464 Write_Str (Current_Name);
1469 if Current_Name = Original_Name then
1470 if Current_Verbosity = High then
1474 return Spec_Path_Name_Of (Current);
1476 elsif Current_Name = Extended_Spec_Name then
1478 if Current_Verbosity = High then
1482 return Spec_Path_Name_Of (Current);
1485 if Current_Verbosity = High then
1486 Write_Line (" not good");
1491 Current := Current + 1;
1495 end Path_Name_Of_Library_Unit_Body;
1501 procedure Print_Sources is
1505 Write_Line ("List of Sources:");
1507 for Id in Units.First .. Units.Last loop
1508 Unit := Units.Table (Id);
1510 Write_Line (Namet.Get_Name_String (Unit.Name));
1512 if Unit.File_Names (Specification).Name /= No_Name then
1513 if Unit.File_Names (Specification).Project = No_Project then
1514 Write_Line (" No project");
1517 Write_Str (" Project: ");
1520 (Unit.File_Names (Specification).Project).Path_Name);
1521 Write_Line (Name_Buffer (1 .. Name_Len));
1524 Write_Str (" spec: ");
1526 (Namet.Get_Name_String
1527 (Unit.File_Names (Specification).Name));
1530 if Unit.File_Names (Body_Part).Name /= No_Name then
1531 if Unit.File_Names (Body_Part).Project = No_Project then
1532 Write_Line (" No project");
1535 Write_Str (" Project: ");
1538 (Unit.File_Names (Body_Part).Project).Path_Name);
1539 Write_Line (Name_Buffer (1 .. Name_Len));
1542 Write_Str (" body: ");
1544 (Namet.Get_Name_String
1545 (Unit.File_Names (Body_Part).Name));
1550 Write_Line ("end of List of Sources.");
1553 ---------------------------------------------
1554 -- Set_Mapping_File_Initial_State_To_Empty --
1555 ---------------------------------------------
1557 procedure Set_Mapping_File_Initial_State_To_Empty is
1559 Fill_Mapping_File := False;
1560 end Set_Mapping_File_Initial_State_To_Empty;
1562 -----------------------
1563 -- Spec_Path_Name_Of --
1564 -----------------------
1566 function Spec_Path_Name_Of (Unit : Unit_Id) return String is
1567 Data : Unit_Data := Units.Table (Unit);
1570 if Data.File_Names (Specification).Path = No_Name then
1572 Current_Source : String_List_Id :=
1573 Projects.Table (Data.File_Names (Specification).Project).Sources;
1574 Path : GNAT.OS_Lib.String_Access;
1577 Data.File_Names (Specification).Path :=
1578 Data.File_Names (Specification).Name;
1580 while Current_Source /= Nil_String loop
1581 String_To_Name_Buffer
1582 (String_Elements.Table (Current_Source).Value);
1583 Path := Locate_Regular_File
1584 (Namet.Get_Name_String
1585 (Data.File_Names (Specification).Name),
1586 Name_Buffer (1 .. Name_Len));
1588 if Path /= null then
1589 Name_Len := Path'Length;
1590 Name_Buffer (1 .. Name_Len) := Path.all;
1591 Data.File_Names (Specification).Path := Name_Enter;
1595 String_Elements.Table (Current_Source).Next;
1599 Units.Table (Unit) := Data;
1603 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
1604 end Spec_Path_Name_Of;