1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
10 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 ------------------------------------------------------------------------------
28 with GNAT.OS_Lib; use GNAT.OS_Lib;
29 with Namet; use Namet;
31 with Osint; use Osint;
32 with Output; use Output;
33 with Prj.Com; use Prj.Com;
35 with Snames; use Snames;
36 with Stringt; use Stringt;
39 package body Prj.Env is
41 type Naming_Id is new Nat;
43 Ada_Path_Buffer : String_Access := new String (1 .. 1_000);
44 -- A buffer where values for ADA_INCLUDE_PATH
45 -- and ADA_OBJECTS_PATH are stored.
47 Ada_Path_Length : Natural := 0;
48 -- Index of the last valid character in Ada_Path_Buffer.
50 package Namings is new Table.Table (
51 Table_Component_Type => Naming_Data,
52 Table_Index_Type => Naming_Id,
55 Table_Increment => 100,
56 Table_Name => "Prj.Env.Namings");
58 Default_Naming : constant Naming_Id := Namings.First;
60 Global_Configuration_Pragmas : Name_Id;
61 Local_Configuration_Pragmas : Name_Id;
63 Fill_Mapping_File : Boolean := True;
65 -----------------------
66 -- Local Subprograms --
67 -----------------------
69 function Body_Path_Name_Of (Unit : Unit_Id) return String;
70 -- Returns the path name of the body of a unit.
71 -- Compute it first, if necessary.
73 function Spec_Path_Name_Of (Unit : Unit_Id) return String;
74 -- Returns the path name of the spec of a unit.
75 -- Compute it first, if necessary.
77 procedure Add_To_Path (Source_Dirs : String_List_Id);
78 -- Add to Ada_Path_Buffer all the source directories in string list
79 -- Source_Dirs, if any. Increment Ada_Path_Length.
81 procedure Add_To_Path (Path : String);
82 -- Add Path to global variable Ada_Path_Buffer
83 -- Increment Ada_Path_Length
85 ----------------------
86 -- Ada_Include_Path --
87 ----------------------
89 function Ada_Include_Path (Project : Project_Id) return String_Access is
91 procedure Add (Project : Project_Id);
92 -- Add all the source directories of a project to the path only if
93 -- this project has not been visited. Calls itself recursively for
94 -- projects being modified, and imported projects. Adds the project
95 -- to the list Seen if this is the call to Add for this project.
101 procedure Add (Project : Project_Id) is
103 -- If Seen is empty, then the project cannot have been visited
105 if not Projects.Table (Project).Seen then
106 Projects.Table (Project).Seen := True;
109 Data : Project_Data := Projects.Table (Project);
110 List : Project_List := Data.Imported_Projects;
113 -- Add to path all source directories of this project
115 Add_To_Path (Data.Source_Dirs);
117 -- Call Add to the project being modified, if any
119 if Data.Modifies /= No_Project then
123 -- Call Add for each imported project, if any
125 while List /= Empty_Project_List loop
126 Add (Project_Lists.Table (List).Project);
127 List := Project_Lists.Table (List).Next;
133 -- Start of processing for Ada_Include_Path
136 -- If it is the first time we call this function for
137 -- this project, compute the source path
139 if Projects.Table (Project).Include_Path = null then
140 Ada_Path_Length := 0;
142 for Index in 1 .. Projects.Last loop
143 Projects.Table (Index).Seen := False;
147 Projects.Table (Project).Include_Path :=
148 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
151 return Projects.Table (Project).Include_Path;
152 end Ada_Include_Path;
154 function Ada_Include_Path
155 (Project : Project_Id;
161 return Ada_Include_Path (Project).all;
163 Ada_Path_Length := 0;
164 Add_To_Path (Projects.Table (Project).Source_Dirs);
165 return Ada_Path_Buffer (1 .. Ada_Path_Length);
167 end Ada_Include_Path;
169 ----------------------
170 -- Ada_Objects_Path --
171 ----------------------
173 function Ada_Objects_Path
174 (Project : Project_Id;
175 Including_Libraries : Boolean := True)
178 procedure Add (Project : Project_Id);
179 -- Add all the object directories of a project to the path only if
180 -- this project has not been visited. Calls itself recursively for
181 -- projects being modified, and imported projects. Adds the project
182 -- to the list Seen if this is the first call to Add for this project.
188 procedure Add (Project : Project_Id) is
190 -- If this project has not been seen yet
192 if not Projects.Table (Project).Seen then
193 Projects.Table (Project).Seen := True;
196 Data : Project_Data := Projects.Table (Project);
197 List : Project_List := Data.Imported_Projects;
200 -- Add to path the object directory of this project
201 -- except if we don't include library project and
202 -- this is a library project.
204 if (Data.Library and then Including_Libraries)
206 (Data.Object_Directory /= No_Name
208 (not Including_Libraries or else not Data.Library))
210 if Ada_Path_Length > 0 then
211 Add_To_Path (Path => (1 => Path_Separator));
214 -- For a library project, att the library directory
218 New_Path : constant String :=
219 Get_Name_String (Data.Library_Dir);
221 Add_To_Path (New_Path);
225 -- For a non library project, add the object directory
227 New_Path : constant String :=
228 Get_Name_String (Data.Object_Directory);
230 Add_To_Path (New_Path);
235 -- Call Add to the project being modified, if any
237 if Data.Modifies /= No_Project then
241 -- Call Add for each imported project, if any
243 while List /= Empty_Project_List loop
244 Add (Project_Lists.Table (List).Project);
245 List := Project_Lists.Table (List).Next;
252 -- Start of processing for Ada_Objects_Path
255 -- If it is the first time we call this function for
256 -- this project, compute the objects path
258 if Projects.Table (Project).Objects_Path = null then
259 Ada_Path_Length := 0;
261 for Index in 1 .. Projects.Last loop
262 Projects.Table (Index).Seen := False;
266 Projects.Table (Project).Objects_Path :=
267 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
270 return Projects.Table (Project).Objects_Path;
271 end Ada_Objects_Path;
277 procedure Add_To_Path (Source_Dirs : String_List_Id) is
278 Current : String_List_Id := Source_Dirs;
279 Source_Dir : String_Element;
282 while Current /= Nil_String loop
283 if Ada_Path_Length > 0 then
284 Add_To_Path (Path => (1 => Path_Separator));
287 Source_Dir := String_Elements.Table (Current);
288 String_To_Name_Buffer (Source_Dir.Value);
291 New_Path : constant String :=
292 Name_Buffer (1 .. Name_Len);
294 Add_To_Path (New_Path);
297 Current := Source_Dir.Next;
301 procedure Add_To_Path (Path : String) is
303 -- If Ada_Path_Buffer is too small, double it
305 if Ada_Path_Length + Path'Length > Ada_Path_Buffer'Last then
307 New_Ada_Path_Buffer : constant String_Access :=
309 (1 .. Ada_Path_Buffer'Last +
310 Ada_Path_Buffer'Last);
313 New_Ada_Path_Buffer (1 .. Ada_Path_Length) :=
314 Ada_Path_Buffer (1 .. Ada_Path_Length);
315 Ada_Path_Buffer := New_Ada_Path_Buffer;
320 (Ada_Path_Length + 1 .. Ada_Path_Length + Path'Length) := Path;
321 Ada_Path_Length := Ada_Path_Length + Path'Length;
324 -----------------------
325 -- Body_Path_Name_Of --
326 -----------------------
328 function Body_Path_Name_Of (Unit : Unit_Id) return String is
329 Data : Unit_Data := Units.Table (Unit);
332 -- If we don't know the path name of the body of this unit,
333 -- we compute it, and we store it.
335 if Data.File_Names (Body_Part).Path = No_Name then
337 Current_Source : String_List_Id :=
338 Projects.Table (Data.File_Names (Body_Part).Project).Sources;
339 Path : GNAT.OS_Lib.String_Access;
342 -- By default, put the file name
344 Data.File_Names (Body_Part).Path :=
345 Data.File_Names (Body_Part).Name;
347 -- For each source directory
349 while Current_Source /= Nil_String loop
350 String_To_Name_Buffer
351 (String_Elements.Table (Current_Source).Value);
354 (Namet.Get_Name_String
355 (Data.File_Names (Body_Part).Name),
356 Name_Buffer (1 .. Name_Len));
358 -- If the file is in this directory,
359 -- then we store the path, and we are done.
362 Name_Len := Path'Length;
363 Name_Buffer (1 .. Name_Len) := Path.all;
364 Data.File_Names (Body_Part).Path := Name_Enter;
369 String_Elements.Table (Current_Source).Next;
373 Units.Table (Unit) := Data;
377 -- Returned the value stored
379 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
380 end Body_Path_Name_Of;
382 --------------------------------
383 -- Create_Config_Pragmas_File --
384 --------------------------------
386 procedure Create_Config_Pragmas_File
387 (For_Project : Project_Id;
388 Main_Project : Project_Id)
390 File_Name : Temp_File_Name;
391 File : File_Descriptor := Invalid_FD;
393 The_Packages : Package_Id;
394 Gnatmake : Prj.Package_Id;
395 Compiler : Prj.Package_Id;
397 Current_Unit : Unit_Id := Units.First;
399 First_Project : Project_List := Empty_Project_List;
401 Current_Project : Project_List;
402 Current_Naming : Naming_Id;
404 Global_Attribute : Variable_Value := Nil_Variable_Value;
405 Local_Attribute : Variable_Value := Nil_Variable_Value;
407 Global_Attribute_Present : Boolean := False;
408 Local_Attribute_Present : Boolean := False;
410 procedure Check (Project : Project_Id);
412 procedure Check_Temp_File;
413 -- Check that a temporary file has been opened.
414 -- If not, create one, and put its name in the project data,
415 -- with the indication that it is a temporary file.
417 procedure Copy_File (Name : String_Id);
418 -- Copy a configuration pragmas file into the temp file.
421 (Unit_Name : Name_Id;
423 Unit_Kind : Spec_Or_Body);
424 -- Put an SFN pragma in the temporary file.
426 procedure Put (File : File_Descriptor; S : String);
428 procedure Put_Line (File : File_Descriptor; S : String);
434 procedure Check (Project : Project_Id) is
435 Data : constant Project_Data := Projects.Table (Project);
438 if Current_Verbosity = High then
439 Write_Str ("Checking project file """);
440 Write_Str (Namet.Get_Name_String (Data.Name));
445 -- Is this project in the list of the visited project?
447 Current_Project := First_Project;
448 while Current_Project /= Empty_Project_List
449 and then Project_Lists.Table (Current_Project).Project /= Project
451 Current_Project := Project_Lists.Table (Current_Project).Next;
454 -- If it is not, put it in the list, and visit it
456 if Current_Project = Empty_Project_List then
457 Project_Lists.Increment_Last;
458 Project_Lists.Table (Project_Lists.Last) :=
459 (Project => Project, Next => First_Project);
460 First_Project := Project_Lists.Last;
462 -- Is the naming scheme of this project one that we know?
464 Current_Naming := Default_Naming;
465 while Current_Naming <= Namings.Last and then
466 not Same_Naming_Scheme
467 (Left => Namings.Table (Current_Naming),
468 Right => Data.Naming) loop
469 Current_Naming := Current_Naming + 1;
472 -- If we don't know it, add it
474 if Current_Naming > Namings.Last then
475 Namings.Increment_Last;
476 Namings.Table (Namings.Last) := Data.Naming;
478 -- We need a temporary file to be created
482 -- Put the SFN pragmas for the naming scheme
487 (File, "pragma Source_File_Name");
489 (File, " (Spec_File_Name => ""*" &
490 Namet.Get_Name_String (Data.Naming.Current_Spec_Suffix) &
493 (File, " Casing => " &
494 Image (Data.Naming.Casing) & ",");
496 (File, " Dot_Replacement => """ &
497 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
503 (File, "pragma Source_File_Name");
505 (File, " (Body_File_Name => ""*" &
506 Namet.Get_Name_String (Data.Naming.Current_Impl_Suffix) &
509 (File, " Casing => " &
510 Image (Data.Naming.Casing) & ",");
512 (File, " Dot_Replacement => """ &
513 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
516 -- and maybe separate
519 Data.Naming.Current_Impl_Suffix /= Data.Naming.Separate_Suffix
522 (File, "pragma Source_File_Name");
524 (File, " (Subunit_File_Name => ""*" &
525 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
528 (File, " Casing => " &
529 Image (Data.Naming.Casing) &
532 (File, " Dot_Replacement => """ &
533 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
538 if Data.Modifies /= No_Project then
539 Check (Data.Modifies);
543 Current : Project_List := Data.Imported_Projects;
546 while Current /= Empty_Project_List loop
547 Check (Project_Lists.Table (Current).Project);
548 Current := Project_Lists.Table (Current).Next;
554 ---------------------
555 -- Check_Temp_File --
556 ---------------------
558 procedure Check_Temp_File is
560 if File = Invalid_FD then
561 GNAT.OS_Lib.Create_Temp_File (File, Name => File_Name);
562 if File = Invalid_FD then
564 ("unable to create temporary configuration pragmas file");
565 elsif Opt.Verbose_Mode then
566 Write_Str ("Creating temp file """);
567 Write_Str (File_Name);
577 procedure Copy_File (Name : in String_Id) is
578 Input : File_Descriptor;
579 Buffer : String (1 .. 1_000);
580 Input_Length : Integer;
581 Output_Length : Integer;
585 String_To_Name_Buffer (Name);
587 if Opt.Verbose_Mode then
588 Write_Str ("Copying config pragmas file """);
589 Write_Str (Name_Buffer (1 .. Name_Len));
590 Write_Line (""" into temp file");
594 Name : constant String :=
595 Name_Buffer (1 .. Name_Len) & ASCII.NUL;
597 Input := Open_Read (Name'Address, Binary);
600 if Input = Invalid_FD then
602 ("cannot open configuration pragmas file " &
603 Name_Buffer (1 .. Name_Len));
607 Input_Length := Read (Input, Buffer'Address, Buffer'Length);
608 Output_Length := Write (File, Buffer'Address, Input_Length);
610 if Output_Length /= Input_Length then
611 Osint.Fail ("disk full");
614 exit when Input_Length < Buffer'Length;
626 (Unit_Name : Name_Id;
628 Unit_Kind : Spec_Or_Body)
631 -- A temporary file needs to be open
635 -- Put the pragma SFN for the unit kind (spec or body)
637 Put (File, "pragma Source_File_Name (");
638 Put (File, Namet.Get_Name_String (Unit_Name));
640 if Unit_Kind = Specification then
641 Put (File, ", Spec_File_Name => """);
643 Put (File, ", Body_File_Name => """);
646 Put (File, Namet.Get_Name_String (File_Name));
647 Put_Line (File, """);");
650 procedure Put (File : File_Descriptor; S : String) is
654 Last := Write (File, S (S'First)'Address, S'Length);
656 if Last /= S'Length then
657 Osint.Fail ("Disk full");
660 if Current_Verbosity = High then
669 procedure Put_Line (File : File_Descriptor; S : String) is
670 S0 : String (1 .. S'Length + 1);
674 -- Add an ASCII.LF to the string. As this gnat.adc is supposed to
675 -- be used only by the compiler, we don't care about the characters
676 -- for the end of line. In fact we could have put a space, but
677 -- it is more convenient to be able to read gnat.adc during
678 -- development, for which the ASCII.LF is fine.
680 S0 (1 .. S'Length) := S;
681 S0 (S0'Last) := ASCII.LF;
682 Last := Write (File, S0'Address, S0'Length);
684 if Last /= S'Length + 1 then
685 Osint.Fail ("Disk full");
688 if Current_Verbosity = High then
693 -- Start of processing for Create_Config_Pragmas_File
696 if not Projects.Table (For_Project).Config_Checked then
698 -- Remove any memory of processed naming schemes, if any
700 Namings.Set_Last (Default_Naming);
702 -- Check the naming schemes
706 -- Visit all the units and process those that need an SFN pragma
708 while Current_Unit <= Units.Last loop
710 Unit : constant Unit_Data :=
711 Units.Table (Current_Unit);
714 if Unit.File_Names (Specification).Needs_Pragma then
716 Unit.File_Names (Specification).Name,
720 if Unit.File_Names (Body_Part).Needs_Pragma then
722 Unit.File_Names (Body_Part).Name,
726 Current_Unit := Current_Unit + 1;
730 The_Packages := Projects.Table (Main_Project).Decl.Packages;
733 (Name => Name_Builder,
734 In_Packages => The_Packages);
736 if Gnatmake /= No_Package then
737 Global_Attribute := Prj.Util.Value_Of
738 (Variable_Name => Global_Configuration_Pragmas,
739 In_Variables => Packages.Table (Gnatmake).Decl.Attributes);
740 Global_Attribute_Present :=
741 Global_Attribute /= Nil_Variable_Value
742 and then String_Length (Global_Attribute.Value) > 0;
745 The_Packages := Projects.Table (For_Project).Decl.Packages;
748 (Name => Name_Compiler,
749 In_Packages => The_Packages);
751 if Compiler /= No_Package then
752 Local_Attribute := Prj.Util.Value_Of
753 (Variable_Name => Local_Configuration_Pragmas,
754 In_Variables => Packages.Table (Compiler).Decl.Attributes);
755 Local_Attribute_Present :=
756 Local_Attribute /= Nil_Variable_Value
757 and then String_Length (Local_Attribute.Value) > 0;
760 if Global_Attribute_Present then
761 if File /= Invalid_FD
762 or else Local_Attribute_Present
764 Copy_File (Global_Attribute.Value);
767 String_To_Name_Buffer (Global_Attribute.Value);
768 Projects.Table (For_Project).Config_File_Name := Name_Find;
772 if Local_Attribute_Present then
773 if File /= Invalid_FD then
774 Copy_File (Local_Attribute.Value);
777 String_To_Name_Buffer (Local_Attribute.Value);
778 Projects.Table (For_Project).Config_File_Name := Name_Find;
782 if File /= Invalid_FD then
783 GNAT.OS_Lib.Close (File);
785 if Opt.Verbose_Mode then
786 Write_Str ("Closing configuration file """);
787 Write_Str (File_Name);
791 Name_Len := File_Name'Length;
792 Name_Buffer (1 .. Name_Len) := File_Name;
793 Projects.Table (For_Project).Config_File_Name := Name_Find;
794 Projects.Table (For_Project).Config_File_Temp := True;
797 Projects.Table (For_Project).Config_Checked := True;
799 end Create_Config_Pragmas_File;
801 -------------------------
802 -- Create_Mapping_File --
803 -------------------------
805 procedure Create_Mapping_File (Name : in out Temp_File_Name) is
806 File : File_Descriptor := Invalid_FD;
807 The_Unit_Data : Unit_Data;
808 Data : File_Name_Data;
810 procedure Put_Name_Buffer;
811 -- Put the line contained in the Name_Buffer in the mapping file
813 procedure Put_Data (Spec : Boolean);
814 -- Put the mapping of the spec or body contained in Data in the file
821 procedure Put_Name_Buffer is
825 Name_Len := Name_Len + 1;
826 Name_Buffer (Name_Len) := ASCII.LF;
827 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
829 if Last /= Name_Len then
830 Osint.Fail ("Disk full");
838 procedure Put_Data (Spec : Boolean) is
840 -- Line with the unit name
842 Get_Name_String (The_Unit_Data.Name);
843 Name_Len := Name_Len + 1;
844 Name_Buffer (Name_Len) := '%';
845 Name_Len := Name_Len + 1;
848 Name_Buffer (Name_Len) := 's';
850 Name_Buffer (Name_Len) := 'b';
855 -- Line with the file nale
857 Get_Name_String (Data.Name);
860 -- Line with the path name
862 Get_Name_String (Data.Path);
867 -- Start of processing for Create_Mapping_File
870 GNAT.OS_Lib.Create_Temp_File (File, Name => Name);
872 if File = Invalid_FD then
874 ("unable to create temporary mapping file");
876 elsif Opt.Verbose_Mode then
877 Write_Str ("Creating temp mapping file """);
882 if Fill_Mapping_File then
883 -- For all units in table Units
885 for Unit in 1 .. Units.Last loop
886 The_Unit_Data := Units.Table (Unit);
888 -- If the unit has a valid name
890 if The_Unit_Data.Name /= No_Name then
891 Data := The_Unit_Data.File_Names (Specification);
893 -- If there is a spec, put it mapping in the file
895 if Data.Name /= No_Name then
896 Put_Data (Spec => True);
899 Data := The_Unit_Data.File_Names (Body_Part);
901 -- If there is a body (or subunit) put its mapping in the file
903 if Data.Name /= No_Name then
904 Put_Data (Spec => False);
911 GNAT.OS_Lib.Close (File);
913 end Create_Mapping_File;
915 ------------------------------------
916 -- File_Name_Of_Library_Unit_Body --
917 ------------------------------------
919 function File_Name_Of_Library_Unit_Body
921 Project : Project_Id)
924 Data : constant Project_Data := Projects.Table (Project);
925 Original_Name : String := Name;
927 Extended_Spec_Name : String :=
928 Name & Namet.Get_Name_String
929 (Data.Naming.Current_Spec_Suffix);
930 Extended_Body_Name : String :=
931 Name & Namet.Get_Name_String
932 (Data.Naming.Current_Impl_Suffix);
936 The_Original_Name : Name_Id;
937 The_Spec_Name : Name_Id;
938 The_Body_Name : Name_Id;
941 Canonical_Case_File_Name (Original_Name);
942 Name_Len := Original_Name'Length;
943 Name_Buffer (1 .. Name_Len) := Original_Name;
944 The_Original_Name := Name_Find;
946 Canonical_Case_File_Name (Extended_Spec_Name);
947 Name_Len := Extended_Spec_Name'Length;
948 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
949 The_Spec_Name := Name_Find;
951 Canonical_Case_File_Name (Extended_Body_Name);
952 Name_Len := Extended_Body_Name'Length;
953 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
954 The_Body_Name := Name_Find;
956 if Current_Verbosity = High then
957 Write_Str ("Looking for file name of """);
961 Write_Str (" Extended Spec Name = """);
962 Write_Str (Extended_Spec_Name);
965 Write_Str (" Extended Body Name = """);
966 Write_Str (Extended_Body_Name);
973 for Current in reverse Units.First .. Units.Last loop
974 Unit := Units.Table (Current);
976 -- Case of unit of the same project
978 if Unit.File_Names (Body_Part).Project = Project then
980 Current_Name : constant Name_Id :=
981 Unit.File_Names (Body_Part).Name;
984 -- Case of a body present
986 if Current_Name /= No_Name then
987 if Current_Verbosity = High then
988 Write_Str (" Comparing with """);
989 Write_Str (Get_Name_String (Current_Name));
994 -- If it has the name of the original name,
995 -- return the original name
997 if Unit.Name = The_Original_Name
998 or else Current_Name = The_Original_Name
1000 if Current_Verbosity = High then
1004 return Get_Name_String (Current_Name);
1006 -- If it has the name of the extended body name,
1007 -- return the extended body name
1009 elsif Current_Name = The_Body_Name then
1010 if Current_Verbosity = High then
1014 return Extended_Body_Name;
1017 if Current_Verbosity = High then
1018 Write_Line (" not good");
1025 -- Case of a unit of the same project
1027 if Units.Table (Current).File_Names (Specification).Project =
1031 Current_Name : constant Name_Id :=
1032 Unit.File_Names (Specification).Name;
1035 -- Case of spec present
1037 if Current_Name /= No_Name then
1038 if Current_Verbosity = High then
1039 Write_Str (" Comparing with """);
1040 Write_Str (Get_Name_String (Current_Name));
1045 -- If name same as the original name, return original name
1047 if Unit.Name = The_Original_Name
1048 or else Current_Name = The_Original_Name
1050 if Current_Verbosity = High then
1054 return Get_Name_String (Current_Name);
1056 -- If it has the same name as the extended spec name,
1057 -- return the extended spec name.
1059 elsif Current_Name = The_Spec_Name then
1060 if Current_Verbosity = High then
1064 return Extended_Spec_Name;
1067 if Current_Verbosity = High then
1068 Write_Line (" not good");
1076 -- We don't know this file name, return an empty string
1079 end File_Name_Of_Library_Unit_Body;
1081 -------------------------
1082 -- For_All_Object_Dirs --
1083 -------------------------
1085 procedure For_All_Object_Dirs (Project : Project_Id) is
1086 Seen : Project_List := Empty_Project_List;
1088 procedure Add (Project : Project_Id);
1089 -- Process a project. Remember the processes visited to avoid
1090 -- processing a project twice. Recursively process an eventual
1091 -- modified project, and all imported projects.
1097 procedure Add (Project : Project_Id) is
1098 Data : constant Project_Data := Projects.Table (Project);
1099 List : Project_List := Data.Imported_Projects;
1102 -- If the list of visited project is empty, then
1103 -- for sure we never visited this project.
1105 if Seen = Empty_Project_List then
1106 Project_Lists.Increment_Last;
1107 Seen := Project_Lists.Last;
1108 Project_Lists.Table (Seen) :=
1109 (Project => Project, Next => Empty_Project_List);
1112 -- Check if the project is in the list
1115 Current : Project_List := Seen;
1119 -- If it is, then there is nothing else to do
1121 if Project_Lists.Table (Current).Project = Project then
1125 exit when Project_Lists.Table (Current).Next =
1127 Current := Project_Lists.Table (Current).Next;
1130 -- This project has never been visited, add it
1133 Project_Lists.Increment_Last;
1134 Project_Lists.Table (Current).Next := Project_Lists.Last;
1135 Project_Lists.Table (Project_Lists.Last) :=
1136 (Project => Project, Next => Empty_Project_List);
1140 -- If there is an object directory, call Action
1143 if Data.Object_Directory /= No_Name then
1144 Get_Name_String (Data.Object_Directory);
1145 Action (Name_Buffer (1 .. Name_Len));
1148 -- If we are extending a project, visit it
1150 if Data.Modifies /= No_Project then
1151 Add (Data.Modifies);
1154 -- And visit all imported projects
1156 while List /= Empty_Project_List loop
1157 Add (Project_Lists.Table (List).Project);
1158 List := Project_Lists.Table (List).Next;
1162 -- Start of processing for For_All_Object_Dirs
1165 -- Visit this project, and its imported projects,
1169 end For_All_Object_Dirs;
1171 -------------------------
1172 -- For_All_Source_Dirs --
1173 -------------------------
1175 procedure For_All_Source_Dirs (Project : Project_Id) is
1176 Seen : Project_List := Empty_Project_List;
1178 procedure Add (Project : Project_Id);
1179 -- Process a project. Remember the processes visited to avoid
1180 -- processing a project twice. Recursively process an eventual
1181 -- modified project, and all imported projects.
1187 procedure Add (Project : Project_Id) is
1188 Data : constant Project_Data := Projects.Table (Project);
1189 List : Project_List := Data.Imported_Projects;
1192 -- If the list of visited project is empty, then
1193 -- for sure we never visited this project.
1195 if Seen = Empty_Project_List then
1196 Project_Lists.Increment_Last;
1197 Seen := Project_Lists.Last;
1198 Project_Lists.Table (Seen) :=
1199 (Project => Project, Next => Empty_Project_List);
1202 -- Check if the project is in the list
1205 Current : Project_List := Seen;
1209 -- If it is, then there is nothing else to do
1211 if Project_Lists.Table (Current).Project = Project then
1215 exit when Project_Lists.Table (Current).Next =
1217 Current := Project_Lists.Table (Current).Next;
1220 -- This project has never been visited, add it
1223 Project_Lists.Increment_Last;
1224 Project_Lists.Table (Current).Next := Project_Lists.Last;
1225 Project_Lists.Table (Project_Lists.Last) :=
1226 (Project => Project, Next => Empty_Project_List);
1231 Current : String_List_Id := Data.Source_Dirs;
1232 The_String : String_Element;
1235 -- Call action with the name of every source directorie
1237 while Current /= Nil_String loop
1238 The_String := String_Elements.Table (Current);
1239 String_To_Name_Buffer (The_String.Value);
1240 Action (Name_Buffer (1 .. Name_Len));
1241 Current := The_String.Next;
1245 -- If we are extending a project, visit it
1247 if Data.Modifies /= No_Project then
1248 Add (Data.Modifies);
1251 -- And visit all imported projects
1253 while List /= Empty_Project_List loop
1254 Add (Project_Lists.Table (List).Project);
1255 List := Project_Lists.Table (List).Next;
1259 -- Start of processing for For_All_Source_Dirs
1262 -- Visit this project, and its imported projects recursively
1265 end For_All_Source_Dirs;
1271 procedure Get_Reference
1272 (Source_File_Name : String;
1273 Project : out Project_Id;
1277 if Current_Verbosity > Default then
1278 Write_Str ("Getting Reference_Of (""");
1279 Write_Str (Source_File_Name);
1280 Write_Str (""") ... ");
1284 Original_Name : String := Source_File_Name;
1288 Canonical_Case_File_Name (Original_Name);
1290 for Id in Units.First .. Units.Last loop
1291 Unit := Units.Table (Id);
1293 if (Unit.File_Names (Specification).Name /= No_Name
1295 Namet.Get_Name_String
1296 (Unit.File_Names (Specification).Name) = Original_Name)
1297 or else (Unit.File_Names (Specification).Path /= No_Name
1299 Namet.Get_Name_String
1300 (Unit.File_Names (Specification).Path) =
1303 Project := Unit.File_Names (Specification).Project;
1304 Path := Unit.File_Names (Specification).Path;
1306 if Current_Verbosity > Default then
1307 Write_Str ("Done: Specification.");
1313 elsif (Unit.File_Names (Body_Part).Name /= No_Name
1315 Namet.Get_Name_String
1316 (Unit.File_Names (Body_Part).Name) = Original_Name)
1317 or else (Unit.File_Names (Body_Part).Path /= No_Name
1318 and then Namet.Get_Name_String
1319 (Unit.File_Names (Body_Part).Path) =
1322 Project := Unit.File_Names (Body_Part).Project;
1323 Path := Unit.File_Names (Body_Part).Path;
1325 if Current_Verbosity > Default then
1326 Write_Str ("Done: Body.");
1336 Project := No_Project;
1339 if Current_Verbosity > Default then
1340 Write_Str ("Cannot be found.");
1349 procedure Initialize is
1350 Global : constant String := "global_configuration_pragmas";
1351 Local : constant String := "local_configuration_pragmas";
1354 -- Put the standard GNAT naming scheme in the Namings table
1356 Namings.Increment_Last;
1357 Namings.Table (Namings.Last) := Standard_Naming_Data;
1358 Name_Len := Global'Length;
1359 Name_Buffer (1 .. Name_Len) := Global;
1360 Global_Configuration_Pragmas := Name_Find;
1361 Name_Len := Local'Length;
1362 Name_Buffer (1 .. Name_Len) := Local;
1363 Local_Configuration_Pragmas := Name_Find;
1366 ------------------------------------
1367 -- Path_Name_Of_Library_Unit_Body --
1368 ------------------------------------
1370 function Path_Name_Of_Library_Unit_Body
1372 Project : Project_Id)
1375 Data : constant Project_Data := Projects.Table (Project);
1376 Original_Name : String := Name;
1378 Extended_Spec_Name : String :=
1379 Name & Namet.Get_Name_String
1380 (Data.Naming.Current_Spec_Suffix);
1381 Extended_Body_Name : String :=
1382 Name & Namet.Get_Name_String
1383 (Data.Naming.Current_Impl_Suffix);
1385 First : Unit_Id := Units.First;
1390 Canonical_Case_File_Name (Original_Name);
1391 Canonical_Case_File_Name (Extended_Spec_Name);
1392 Canonical_Case_File_Name (Extended_Spec_Name);
1394 if Current_Verbosity = High then
1395 Write_Str ("Looking for path name of """);
1399 Write_Str (" Extended Spec Name = """);
1400 Write_Str (Extended_Spec_Name);
1403 Write_Str (" Extended Body Name = """);
1404 Write_Str (Extended_Body_Name);
1409 while First <= Units.Last
1410 and then Units.Table (First).File_Names (Body_Part).Project /= Project
1416 while Current <= Units.Last loop
1417 Unit := Units.Table (Current);
1419 if Unit.File_Names (Body_Part).Project = Project
1420 and then Unit.File_Names (Body_Part).Name /= No_Name
1423 Current_Name : constant String :=
1424 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1426 if Current_Verbosity = High then
1427 Write_Str (" Comparing with """);
1428 Write_Str (Current_Name);
1433 if Current_Name = Original_Name then
1434 if Current_Verbosity = High then
1438 return Body_Path_Name_Of (Current);
1440 elsif Current_Name = Extended_Body_Name then
1441 if Current_Verbosity = High then
1445 return Body_Path_Name_Of (Current);
1448 if Current_Verbosity = High then
1449 Write_Line (" not good");
1454 elsif Unit.File_Names (Specification).Name /= No_Name then
1456 Current_Name : constant String :=
1457 Namet.Get_Name_String
1458 (Unit.File_Names (Specification).Name);
1461 if Current_Verbosity = High then
1462 Write_Str (" Comparing with """);
1463 Write_Str (Current_Name);
1468 if Current_Name = Original_Name then
1469 if Current_Verbosity = High then
1473 return Spec_Path_Name_Of (Current);
1475 elsif Current_Name = Extended_Spec_Name then
1477 if Current_Verbosity = High then
1481 return Spec_Path_Name_Of (Current);
1484 if Current_Verbosity = High then
1485 Write_Line (" not good");
1490 Current := Current + 1;
1494 end Path_Name_Of_Library_Unit_Body;
1500 procedure Print_Sources is
1504 Write_Line ("List of Sources:");
1506 for Id in Units.First .. Units.Last loop
1507 Unit := Units.Table (Id);
1509 Write_Line (Namet.Get_Name_String (Unit.Name));
1511 if Unit.File_Names (Specification).Name /= No_Name then
1512 if Unit.File_Names (Specification).Project = No_Project then
1513 Write_Line (" No project");
1516 Write_Str (" Project: ");
1519 (Unit.File_Names (Specification).Project).Path_Name);
1520 Write_Line (Name_Buffer (1 .. Name_Len));
1523 Write_Str (" spec: ");
1525 (Namet.Get_Name_String
1526 (Unit.File_Names (Specification).Name));
1529 if Unit.File_Names (Body_Part).Name /= No_Name then
1530 if Unit.File_Names (Body_Part).Project = No_Project then
1531 Write_Line (" No project");
1534 Write_Str (" Project: ");
1537 (Unit.File_Names (Body_Part).Project).Path_Name);
1538 Write_Line (Name_Buffer (1 .. Name_Len));
1541 Write_Str (" body: ");
1543 (Namet.Get_Name_String
1544 (Unit.File_Names (Body_Part).Name));
1549 Write_Line ("end of List of Sources.");
1552 ---------------------------------------------
1553 -- Set_Mapping_File_Initial_State_To_Empty --
1554 ---------------------------------------------
1556 procedure Set_Mapping_File_Initial_State_To_Empty is
1558 Fill_Mapping_File := False;
1559 end Set_Mapping_File_Initial_State_To_Empty;
1561 -----------------------
1562 -- Spec_Path_Name_Of --
1563 -----------------------
1565 function Spec_Path_Name_Of (Unit : Unit_Id) return String is
1566 Data : Unit_Data := Units.Table (Unit);
1569 if Data.File_Names (Specification).Path = No_Name then
1571 Current_Source : String_List_Id :=
1572 Projects.Table (Data.File_Names (Specification).Project).Sources;
1573 Path : GNAT.OS_Lib.String_Access;
1576 Data.File_Names (Specification).Path :=
1577 Data.File_Names (Specification).Name;
1579 while Current_Source /= Nil_String loop
1580 String_To_Name_Buffer
1581 (String_Elements.Table (Current_Source).Value);
1582 Path := Locate_Regular_File
1583 (Namet.Get_Name_String
1584 (Data.File_Names (Specification).Name),
1585 Name_Buffer (1 .. Name_Len));
1587 if Path /= null then
1588 Name_Len := Path'Length;
1589 Name_Buffer (1 .. Name_Len) := Path.all;
1590 Data.File_Names (Specification).Path := Name_Enter;
1594 String_Elements.Table (Current_Source).Next;
1598 Units.Table (Unit) := Data;
1602 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
1603 end Spec_Path_Name_Of;