1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2002 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 GNAT.OS_Lib; use GNAT.OS_Lib;
28 with Namet; use Namet;
30 with Osint; use Osint;
31 with Output; use Output;
32 with Prj.Com; use Prj.Com;
34 with Snames; use Snames;
35 with Stringt; use Stringt;
38 package body Prj.Env is
40 type Naming_Id is new Nat;
42 Ada_Path_Buffer : String_Access := new String (1 .. 1_000);
43 -- A buffer where values for ADA_INCLUDE_PATH
44 -- and ADA_OBJECTS_PATH are stored.
46 Ada_Path_Length : Natural := 0;
47 -- Index of the last valid character in Ada_Path_Buffer.
49 package Namings is new Table.Table (
50 Table_Component_Type => Naming_Data,
51 Table_Index_Type => Naming_Id,
54 Table_Increment => 100,
55 Table_Name => "Prj.Env.Namings");
57 Default_Naming : constant Naming_Id := Namings.First;
59 Global_Configuration_Pragmas : Name_Id;
60 Local_Configuration_Pragmas : Name_Id;
62 Fill_Mapping_File : Boolean := True;
64 -----------------------
65 -- Local Subprograms --
66 -----------------------
68 function Body_Path_Name_Of (Unit : Unit_Id) return String;
69 -- Returns the path name of the body of a unit.
70 -- Compute it first, if necessary.
72 function Spec_Path_Name_Of (Unit : Unit_Id) return String;
73 -- Returns the path name of the spec of a unit.
74 -- Compute it first, if necessary.
76 procedure Add_To_Path (Source_Dirs : String_List_Id);
77 -- Add to Ada_Path_Buffer all the source directories in string list
78 -- Source_Dirs, if any. Increment Ada_Path_Length.
80 procedure Add_To_Path (Path : String);
81 -- Add Path to global variable Ada_Path_Buffer
82 -- Increment Ada_Path_Length
84 ----------------------
85 -- Ada_Include_Path --
86 ----------------------
88 function Ada_Include_Path (Project : Project_Id) return String_Access is
90 procedure Add (Project : Project_Id);
91 -- Add all the source directories of a project to the path only if
92 -- this project has not been visited. Calls itself recursively for
93 -- projects being modified, and imported projects. Adds the project
94 -- to the list Seen if this is the call to Add for this project.
100 procedure Add (Project : Project_Id) is
102 -- If Seen is empty, then the project cannot have been visited
104 if not Projects.Table (Project).Seen then
105 Projects.Table (Project).Seen := True;
108 Data : Project_Data := Projects.Table (Project);
109 List : Project_List := Data.Imported_Projects;
112 -- Add to path all source directories of this project
114 Add_To_Path (Data.Source_Dirs);
116 -- Call Add to the project being modified, if any
118 if Data.Modifies /= No_Project then
122 -- Call Add for each imported project, if any
124 while List /= Empty_Project_List loop
125 Add (Project_Lists.Table (List).Project);
126 List := Project_Lists.Table (List).Next;
132 -- Start of processing for Ada_Include_Path
135 -- If it is the first time we call this function for
136 -- this project, compute the source path
138 if Projects.Table (Project).Include_Path = null then
139 Ada_Path_Length := 0;
141 for Index in 1 .. Projects.Last loop
142 Projects.Table (Index).Seen := False;
146 Projects.Table (Project).Include_Path :=
147 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
150 return Projects.Table (Project).Include_Path;
151 end Ada_Include_Path;
153 function Ada_Include_Path
154 (Project : Project_Id;
160 return Ada_Include_Path (Project).all;
162 Ada_Path_Length := 0;
163 Add_To_Path (Projects.Table (Project).Source_Dirs);
164 return Ada_Path_Buffer (1 .. Ada_Path_Length);
166 end Ada_Include_Path;
168 ----------------------
169 -- Ada_Objects_Path --
170 ----------------------
172 function Ada_Objects_Path
173 (Project : Project_Id;
174 Including_Libraries : Boolean := True)
177 procedure Add (Project : Project_Id);
178 -- Add all the object directories of a project to the path only if
179 -- this project has not been visited. Calls itself recursively for
180 -- projects being modified, and imported projects. Adds the project
181 -- to the list Seen if this is the first call to Add for this project.
187 procedure Add (Project : Project_Id) is
189 -- If this project has not been seen yet
191 if not Projects.Table (Project).Seen then
192 Projects.Table (Project).Seen := True;
195 Data : Project_Data := Projects.Table (Project);
196 List : Project_List := Data.Imported_Projects;
199 -- Add to path the object directory of this project
200 -- except if we don't include library project and
201 -- this is a library project.
203 if (Data.Library and then Including_Libraries)
205 (Data.Object_Directory /= No_Name
207 (not Including_Libraries or else not Data.Library))
209 if Ada_Path_Length > 0 then
210 Add_To_Path (Path => (1 => Path_Separator));
213 -- For a library project, att the library directory
217 New_Path : constant String :=
218 Get_Name_String (Data.Library_Dir);
220 Add_To_Path (New_Path);
224 -- For a non library project, add the object directory
226 New_Path : constant String :=
227 Get_Name_String (Data.Object_Directory);
229 Add_To_Path (New_Path);
234 -- Call Add to the project being modified, if any
236 if Data.Modifies /= No_Project then
240 -- Call Add for each imported project, if any
242 while List /= Empty_Project_List loop
243 Add (Project_Lists.Table (List).Project);
244 List := Project_Lists.Table (List).Next;
251 -- Start of processing for Ada_Objects_Path
254 -- If it is the first time we call this function for
255 -- this project, compute the objects path
257 if Projects.Table (Project).Objects_Path = null then
258 Ada_Path_Length := 0;
260 for Index in 1 .. Projects.Last loop
261 Projects.Table (Index).Seen := False;
265 Projects.Table (Project).Objects_Path :=
266 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
269 return Projects.Table (Project).Objects_Path;
270 end Ada_Objects_Path;
276 procedure Add_To_Path (Source_Dirs : String_List_Id) is
277 Current : String_List_Id := Source_Dirs;
278 Source_Dir : String_Element;
281 while Current /= Nil_String loop
282 if Ada_Path_Length > 0 then
283 Add_To_Path (Path => (1 => Path_Separator));
286 Source_Dir := String_Elements.Table (Current);
287 String_To_Name_Buffer (Source_Dir.Value);
290 New_Path : constant String :=
291 Name_Buffer (1 .. Name_Len);
293 Add_To_Path (New_Path);
296 Current := Source_Dir.Next;
300 procedure Add_To_Path (Path : String) is
302 -- If Ada_Path_Buffer is too small, double it
304 if Ada_Path_Length + Path'Length > Ada_Path_Buffer'Last then
306 New_Ada_Path_Buffer : constant String_Access :=
308 (1 .. Ada_Path_Buffer'Last +
309 Ada_Path_Buffer'Last);
312 New_Ada_Path_Buffer (1 .. Ada_Path_Length) :=
313 Ada_Path_Buffer (1 .. Ada_Path_Length);
314 Ada_Path_Buffer := New_Ada_Path_Buffer;
319 (Ada_Path_Length + 1 .. Ada_Path_Length + Path'Length) := Path;
320 Ada_Path_Length := Ada_Path_Length + Path'Length;
323 -----------------------
324 -- Body_Path_Name_Of --
325 -----------------------
327 function Body_Path_Name_Of (Unit : Unit_Id) return String is
328 Data : Unit_Data := Units.Table (Unit);
331 -- If we don't know the path name of the body of this unit,
332 -- we compute it, and we store it.
334 if Data.File_Names (Body_Part).Path = No_Name then
336 Current_Source : String_List_Id :=
337 Projects.Table (Data.File_Names (Body_Part).Project).Sources;
338 Path : GNAT.OS_Lib.String_Access;
341 -- By default, put the file name
343 Data.File_Names (Body_Part).Path :=
344 Data.File_Names (Body_Part).Name;
346 -- For each source directory
348 while Current_Source /= Nil_String loop
349 String_To_Name_Buffer
350 (String_Elements.Table (Current_Source).Value);
353 (Namet.Get_Name_String
354 (Data.File_Names (Body_Part).Name),
355 Name_Buffer (1 .. Name_Len));
357 -- If the file is in this directory,
358 -- then we store the path, and we are done.
361 Name_Len := Path'Length;
362 Name_Buffer (1 .. Name_Len) := Path.all;
363 Data.File_Names (Body_Part).Path := Name_Enter;
368 String_Elements.Table (Current_Source).Next;
372 Units.Table (Unit) := Data;
376 -- Returned the value stored
378 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
379 end Body_Path_Name_Of;
381 --------------------------------
382 -- Create_Config_Pragmas_File --
383 --------------------------------
385 procedure Create_Config_Pragmas_File
386 (For_Project : Project_Id;
387 Main_Project : Project_Id)
389 File_Name : Temp_File_Name;
390 File : File_Descriptor := Invalid_FD;
392 The_Packages : Package_Id;
393 Gnatmake : Prj.Package_Id;
394 Compiler : Prj.Package_Id;
396 Current_Unit : Unit_Id := Units.First;
398 First_Project : Project_List := Empty_Project_List;
400 Current_Project : Project_List;
401 Current_Naming : Naming_Id;
403 Global_Attribute : Variable_Value := Nil_Variable_Value;
404 Local_Attribute : Variable_Value := Nil_Variable_Value;
406 Global_Attribute_Present : Boolean := False;
407 Local_Attribute_Present : Boolean := False;
409 procedure Check (Project : Project_Id);
411 procedure Check_Temp_File;
412 -- Check that a temporary file has been opened.
413 -- If not, create one, and put its name in the project data,
414 -- with the indication that it is a temporary file.
416 procedure Copy_File (Name : String_Id);
417 -- Copy a configuration pragmas file into the temp file.
420 (Unit_Name : Name_Id;
422 Unit_Kind : Spec_Or_Body);
423 -- Put an SFN pragma in the temporary file.
425 procedure Put (File : File_Descriptor; S : String);
427 procedure Put_Line (File : File_Descriptor; S : String);
433 procedure Check (Project : Project_Id) is
434 Data : constant Project_Data := Projects.Table (Project);
437 if Current_Verbosity = High then
438 Write_Str ("Checking project file """);
439 Write_Str (Namet.Get_Name_String (Data.Name));
444 -- Is this project in the list of the visited project?
446 Current_Project := First_Project;
447 while Current_Project /= Empty_Project_List
448 and then Project_Lists.Table (Current_Project).Project /= Project
450 Current_Project := Project_Lists.Table (Current_Project).Next;
453 -- If it is not, put it in the list, and visit it
455 if Current_Project = Empty_Project_List then
456 Project_Lists.Increment_Last;
457 Project_Lists.Table (Project_Lists.Last) :=
458 (Project => Project, Next => First_Project);
459 First_Project := Project_Lists.Last;
461 -- Is the naming scheme of this project one that we know?
463 Current_Naming := Default_Naming;
464 while Current_Naming <= Namings.Last and then
465 not Same_Naming_Scheme
466 (Left => Namings.Table (Current_Naming),
467 Right => Data.Naming) loop
468 Current_Naming := Current_Naming + 1;
471 -- If we don't know it, add it
473 if Current_Naming > Namings.Last then
474 Namings.Increment_Last;
475 Namings.Table (Namings.Last) := Data.Naming;
477 -- We need a temporary file to be created
481 -- Put the SFN pragmas for the naming scheme
486 (File, "pragma Source_File_Name");
488 (File, " (Spec_File_Name => ""*" &
489 Namet.Get_Name_String (Data.Naming.Current_Spec_Suffix) &
492 (File, " Casing => " &
493 Image (Data.Naming.Casing) & ",");
495 (File, " Dot_Replacement => """ &
496 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
502 (File, "pragma Source_File_Name");
504 (File, " (Body_File_Name => ""*" &
505 Namet.Get_Name_String (Data.Naming.Current_Impl_Suffix) &
508 (File, " Casing => " &
509 Image (Data.Naming.Casing) & ",");
511 (File, " Dot_Replacement => """ &
512 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
515 -- and maybe separate
518 Data.Naming.Current_Impl_Suffix /= Data.Naming.Separate_Suffix
521 (File, "pragma Source_File_Name");
523 (File, " (Subunit_File_Name => ""*" &
524 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
527 (File, " Casing => " &
528 Image (Data.Naming.Casing) &
531 (File, " Dot_Replacement => """ &
532 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
537 if Data.Modifies /= No_Project then
538 Check (Data.Modifies);
542 Current : Project_List := Data.Imported_Projects;
545 while Current /= Empty_Project_List loop
546 Check (Project_Lists.Table (Current).Project);
547 Current := Project_Lists.Table (Current).Next;
553 ---------------------
554 -- Check_Temp_File --
555 ---------------------
557 procedure Check_Temp_File is
559 if File = Invalid_FD then
560 GNAT.OS_Lib.Create_Temp_File (File, Name => File_Name);
561 if File = Invalid_FD then
563 ("unable to create temporary configuration pragmas file");
564 elsif Opt.Verbose_Mode then
565 Write_Str ("Creating temp file """);
566 Write_Str (File_Name);
576 procedure Copy_File (Name : in String_Id) is
577 Input : File_Descriptor;
578 Buffer : String (1 .. 1_000);
579 Input_Length : Integer;
580 Output_Length : Integer;
584 String_To_Name_Buffer (Name);
586 if Opt.Verbose_Mode then
587 Write_Str ("Copying config pragmas file """);
588 Write_Str (Name_Buffer (1 .. Name_Len));
589 Write_Line (""" into temp file");
593 Name : constant String :=
594 Name_Buffer (1 .. Name_Len) & ASCII.NUL;
596 Input := Open_Read (Name'Address, Binary);
599 if Input = Invalid_FD then
601 ("cannot open configuration pragmas file " &
602 Name_Buffer (1 .. Name_Len));
606 Input_Length := Read (Input, Buffer'Address, Buffer'Length);
607 Output_Length := Write (File, Buffer'Address, Input_Length);
609 if Output_Length /= Input_Length then
610 Osint.Fail ("disk full");
613 exit when Input_Length < Buffer'Length;
625 (Unit_Name : Name_Id;
627 Unit_Kind : Spec_Or_Body)
630 -- A temporary file needs to be open
634 -- Put the pragma SFN for the unit kind (spec or body)
636 Put (File, "pragma Source_File_Name (");
637 Put (File, Namet.Get_Name_String (Unit_Name));
639 if Unit_Kind = Specification then
640 Put (File, ", Spec_File_Name => """);
642 Put (File, ", Body_File_Name => """);
645 Put (File, Namet.Get_Name_String (File_Name));
646 Put_Line (File, """);");
649 procedure Put (File : File_Descriptor; S : String) is
653 Last := Write (File, S (S'First)'Address, S'Length);
655 if Last /= S'Length then
656 Osint.Fail ("Disk full");
659 if Current_Verbosity = High then
668 procedure Put_Line (File : File_Descriptor; S : String) is
669 S0 : String (1 .. S'Length + 1);
673 -- Add an ASCII.LF to the string. As this gnat.adc is supposed to
674 -- be used only by the compiler, we don't care about the characters
675 -- for the end of line. In fact we could have put a space, but
676 -- it is more convenient to be able to read gnat.adc during
677 -- development, for which the ASCII.LF is fine.
679 S0 (1 .. S'Length) := S;
680 S0 (S0'Last) := ASCII.LF;
681 Last := Write (File, S0'Address, S0'Length);
683 if Last /= S'Length + 1 then
684 Osint.Fail ("Disk full");
687 if Current_Verbosity = High then
692 -- Start of processing for Create_Config_Pragmas_File
695 if not Projects.Table (For_Project).Config_Checked then
697 -- Remove any memory of processed naming schemes, if any
699 Namings.Set_Last (Default_Naming);
701 -- Check the naming schemes
705 -- Visit all the units and process those that need an SFN pragma
707 while Current_Unit <= Units.Last loop
709 Unit : constant Unit_Data :=
710 Units.Table (Current_Unit);
713 if Unit.File_Names (Specification).Needs_Pragma then
715 Unit.File_Names (Specification).Name,
719 if Unit.File_Names (Body_Part).Needs_Pragma then
721 Unit.File_Names (Body_Part).Name,
725 Current_Unit := Current_Unit + 1;
729 The_Packages := Projects.Table (Main_Project).Decl.Packages;
732 (Name => Name_Builder,
733 In_Packages => The_Packages);
735 if Gnatmake /= No_Package then
736 Global_Attribute := Prj.Util.Value_Of
737 (Variable_Name => Global_Configuration_Pragmas,
738 In_Variables => Packages.Table (Gnatmake).Decl.Attributes);
739 Global_Attribute_Present :=
740 Global_Attribute /= Nil_Variable_Value
741 and then String_Length (Global_Attribute.Value) > 0;
744 The_Packages := Projects.Table (For_Project).Decl.Packages;
747 (Name => Name_Compiler,
748 In_Packages => The_Packages);
750 if Compiler /= No_Package then
751 Local_Attribute := Prj.Util.Value_Of
752 (Variable_Name => Local_Configuration_Pragmas,
753 In_Variables => Packages.Table (Compiler).Decl.Attributes);
754 Local_Attribute_Present :=
755 Local_Attribute /= Nil_Variable_Value
756 and then String_Length (Local_Attribute.Value) > 0;
759 if Global_Attribute_Present then
760 if File /= Invalid_FD
761 or else Local_Attribute_Present
763 Copy_File (Global_Attribute.Value);
766 String_To_Name_Buffer (Global_Attribute.Value);
767 Projects.Table (For_Project).Config_File_Name := Name_Find;
771 if Local_Attribute_Present then
772 if File /= Invalid_FD then
773 Copy_File (Local_Attribute.Value);
776 String_To_Name_Buffer (Local_Attribute.Value);
777 Projects.Table (For_Project).Config_File_Name := Name_Find;
781 if File /= Invalid_FD then
782 GNAT.OS_Lib.Close (File);
784 if Opt.Verbose_Mode then
785 Write_Str ("Closing configuration file """);
786 Write_Str (File_Name);
790 Name_Len := File_Name'Length;
791 Name_Buffer (1 .. Name_Len) := File_Name;
792 Projects.Table (For_Project).Config_File_Name := Name_Find;
793 Projects.Table (For_Project).Config_File_Temp := True;
796 Projects.Table (For_Project).Config_Checked := True;
798 end Create_Config_Pragmas_File;
800 -------------------------
801 -- Create_Mapping_File --
802 -------------------------
804 procedure Create_Mapping_File (Name : in out Temp_File_Name) is
805 File : File_Descriptor := Invalid_FD;
806 The_Unit_Data : Unit_Data;
807 Data : File_Name_Data;
809 procedure Put_Name_Buffer;
810 -- Put the line contained in the Name_Buffer in the mapping file
812 procedure Put_Data (Spec : Boolean);
813 -- Put the mapping of the spec or body contained in Data in the file
820 procedure Put_Name_Buffer is
824 Name_Len := Name_Len + 1;
825 Name_Buffer (Name_Len) := ASCII.LF;
826 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
828 if Last /= Name_Len then
829 Osint.Fail ("Disk full");
837 procedure Put_Data (Spec : Boolean) is
839 -- Line with the unit name
841 Get_Name_String (The_Unit_Data.Name);
842 Name_Len := Name_Len + 1;
843 Name_Buffer (Name_Len) := '%';
844 Name_Len := Name_Len + 1;
847 Name_Buffer (Name_Len) := 's';
849 Name_Buffer (Name_Len) := 'b';
854 -- Line with the file nale
856 Get_Name_String (Data.Name);
859 -- Line with the path name
861 Get_Name_String (Data.Path);
866 -- Start of processing for Create_Mapping_File
869 GNAT.OS_Lib.Create_Temp_File (File, Name => Name);
871 if File = Invalid_FD then
873 ("unable to create temporary mapping file");
875 elsif Opt.Verbose_Mode then
876 Write_Str ("Creating temp mapping file """);
881 if Fill_Mapping_File then
882 -- For all units in table Units
884 for Unit in 1 .. Units.Last loop
885 The_Unit_Data := Units.Table (Unit);
887 -- If the unit has a valid name
889 if The_Unit_Data.Name /= No_Name then
890 Data := The_Unit_Data.File_Names (Specification);
892 -- If there is a spec, put it mapping in the file
894 if Data.Name /= No_Name then
895 Put_Data (Spec => True);
898 Data := The_Unit_Data.File_Names (Body_Part);
900 -- If there is a body (or subunit) put its mapping in the file
902 if Data.Name /= No_Name then
903 Put_Data (Spec => False);
910 GNAT.OS_Lib.Close (File);
912 end Create_Mapping_File;
914 ------------------------------------
915 -- File_Name_Of_Library_Unit_Body --
916 ------------------------------------
918 function File_Name_Of_Library_Unit_Body
920 Project : Project_Id)
923 Data : constant Project_Data := Projects.Table (Project);
924 Original_Name : String := Name;
926 Extended_Spec_Name : String :=
927 Name & Namet.Get_Name_String
928 (Data.Naming.Current_Spec_Suffix);
929 Extended_Body_Name : String :=
930 Name & Namet.Get_Name_String
931 (Data.Naming.Current_Impl_Suffix);
935 The_Original_Name : Name_Id;
936 The_Spec_Name : Name_Id;
937 The_Body_Name : Name_Id;
940 Canonical_Case_File_Name (Original_Name);
941 Name_Len := Original_Name'Length;
942 Name_Buffer (1 .. Name_Len) := Original_Name;
943 The_Original_Name := Name_Find;
945 Canonical_Case_File_Name (Extended_Spec_Name);
946 Name_Len := Extended_Spec_Name'Length;
947 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
948 The_Spec_Name := Name_Find;
950 Canonical_Case_File_Name (Extended_Body_Name);
951 Name_Len := Extended_Body_Name'Length;
952 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
953 The_Body_Name := Name_Find;
955 if Current_Verbosity = High then
956 Write_Str ("Looking for file name of """);
960 Write_Str (" Extended Spec Name = """);
961 Write_Str (Extended_Spec_Name);
964 Write_Str (" Extended Body Name = """);
965 Write_Str (Extended_Body_Name);
972 for Current in reverse Units.First .. Units.Last loop
973 Unit := Units.Table (Current);
975 -- Case of unit of the same project
977 if Unit.File_Names (Body_Part).Project = Project then
979 Current_Name : constant Name_Id :=
980 Unit.File_Names (Body_Part).Name;
983 -- Case of a body present
985 if Current_Name /= No_Name then
986 if Current_Verbosity = High then
987 Write_Str (" Comparing with """);
988 Write_Str (Get_Name_String (Current_Name));
993 -- If it has the name of the original name,
994 -- return the original name
996 if Unit.Name = The_Original_Name
997 or else Current_Name = The_Original_Name
999 if Current_Verbosity = High then
1003 return Get_Name_String (Current_Name);
1005 -- If it has the name of the extended body name,
1006 -- return the extended body name
1008 elsif Current_Name = The_Body_Name then
1009 if Current_Verbosity = High then
1013 return Extended_Body_Name;
1016 if Current_Verbosity = High then
1017 Write_Line (" not good");
1024 -- Case of a unit of the same project
1026 if Units.Table (Current).File_Names (Specification).Project =
1030 Current_Name : constant Name_Id :=
1031 Unit.File_Names (Specification).Name;
1034 -- Case of spec present
1036 if Current_Name /= No_Name then
1037 if Current_Verbosity = High then
1038 Write_Str (" Comparing with """);
1039 Write_Str (Get_Name_String (Current_Name));
1044 -- If name same as the original name, return original name
1046 if Unit.Name = The_Original_Name
1047 or else Current_Name = The_Original_Name
1049 if Current_Verbosity = High then
1053 return Get_Name_String (Current_Name);
1055 -- If it has the same name as the extended spec name,
1056 -- return the extended spec name.
1058 elsif Current_Name = The_Spec_Name then
1059 if Current_Verbosity = High then
1063 return Extended_Spec_Name;
1066 if Current_Verbosity = High then
1067 Write_Line (" not good");
1075 -- We don't know this file name, return an empty string
1078 end File_Name_Of_Library_Unit_Body;
1080 -------------------------
1081 -- For_All_Object_Dirs --
1082 -------------------------
1084 procedure For_All_Object_Dirs (Project : Project_Id) is
1085 Seen : Project_List := Empty_Project_List;
1087 procedure Add (Project : Project_Id);
1088 -- Process a project. Remember the processes visited to avoid
1089 -- processing a project twice. Recursively process an eventual
1090 -- modified project, and all imported projects.
1096 procedure Add (Project : Project_Id) is
1097 Data : constant Project_Data := Projects.Table (Project);
1098 List : Project_List := Data.Imported_Projects;
1101 -- If the list of visited project is empty, then
1102 -- for sure we never visited this project.
1104 if Seen = Empty_Project_List then
1105 Project_Lists.Increment_Last;
1106 Seen := Project_Lists.Last;
1107 Project_Lists.Table (Seen) :=
1108 (Project => Project, Next => Empty_Project_List);
1111 -- Check if the project is in the list
1114 Current : Project_List := Seen;
1118 -- If it is, then there is nothing else to do
1120 if Project_Lists.Table (Current).Project = Project then
1124 exit when Project_Lists.Table (Current).Next =
1126 Current := Project_Lists.Table (Current).Next;
1129 -- This project has never been visited, add it
1132 Project_Lists.Increment_Last;
1133 Project_Lists.Table (Current).Next := Project_Lists.Last;
1134 Project_Lists.Table (Project_Lists.Last) :=
1135 (Project => Project, Next => Empty_Project_List);
1139 -- If there is an object directory, call Action
1142 if Data.Object_Directory /= No_Name then
1143 Get_Name_String (Data.Object_Directory);
1144 Action (Name_Buffer (1 .. Name_Len));
1147 -- If we are extending a project, visit it
1149 if Data.Modifies /= No_Project then
1150 Add (Data.Modifies);
1153 -- And visit all imported projects
1155 while List /= Empty_Project_List loop
1156 Add (Project_Lists.Table (List).Project);
1157 List := Project_Lists.Table (List).Next;
1161 -- Start of processing for For_All_Object_Dirs
1164 -- Visit this project, and its imported projects,
1168 end For_All_Object_Dirs;
1170 -------------------------
1171 -- For_All_Source_Dirs --
1172 -------------------------
1174 procedure For_All_Source_Dirs (Project : Project_Id) is
1175 Seen : Project_List := Empty_Project_List;
1177 procedure Add (Project : Project_Id);
1178 -- Process a project. Remember the processes visited to avoid
1179 -- processing a project twice. Recursively process an eventual
1180 -- modified project, and all imported projects.
1186 procedure Add (Project : Project_Id) is
1187 Data : constant Project_Data := Projects.Table (Project);
1188 List : Project_List := Data.Imported_Projects;
1191 -- If the list of visited project is empty, then
1192 -- for sure we never visited this project.
1194 if Seen = Empty_Project_List then
1195 Project_Lists.Increment_Last;
1196 Seen := Project_Lists.Last;
1197 Project_Lists.Table (Seen) :=
1198 (Project => Project, Next => Empty_Project_List);
1201 -- Check if the project is in the list
1204 Current : Project_List := Seen;
1208 -- If it is, then there is nothing else to do
1210 if Project_Lists.Table (Current).Project = Project then
1214 exit when Project_Lists.Table (Current).Next =
1216 Current := Project_Lists.Table (Current).Next;
1219 -- This project has never been visited, add it
1222 Project_Lists.Increment_Last;
1223 Project_Lists.Table (Current).Next := Project_Lists.Last;
1224 Project_Lists.Table (Project_Lists.Last) :=
1225 (Project => Project, Next => Empty_Project_List);
1230 Current : String_List_Id := Data.Source_Dirs;
1231 The_String : String_Element;
1234 -- Call action with the name of every source directorie
1236 while Current /= Nil_String loop
1237 The_String := String_Elements.Table (Current);
1238 String_To_Name_Buffer (The_String.Value);
1239 Action (Name_Buffer (1 .. Name_Len));
1240 Current := The_String.Next;
1244 -- If we are extending a project, visit it
1246 if Data.Modifies /= No_Project then
1247 Add (Data.Modifies);
1250 -- And visit all imported projects
1252 while List /= Empty_Project_List loop
1253 Add (Project_Lists.Table (List).Project);
1254 List := Project_Lists.Table (List).Next;
1258 -- Start of processing for For_All_Source_Dirs
1261 -- Visit this project, and its imported projects recursively
1264 end For_All_Source_Dirs;
1270 procedure Get_Reference
1271 (Source_File_Name : String;
1272 Project : out Project_Id;
1276 if Current_Verbosity > Default then
1277 Write_Str ("Getting Reference_Of (""");
1278 Write_Str (Source_File_Name);
1279 Write_Str (""") ... ");
1283 Original_Name : String := Source_File_Name;
1287 Canonical_Case_File_Name (Original_Name);
1289 for Id in Units.First .. Units.Last loop
1290 Unit := Units.Table (Id);
1292 if (Unit.File_Names (Specification).Name /= No_Name
1294 Namet.Get_Name_String
1295 (Unit.File_Names (Specification).Name) = Original_Name)
1296 or else (Unit.File_Names (Specification).Path /= No_Name
1298 Namet.Get_Name_String
1299 (Unit.File_Names (Specification).Path) =
1302 Project := Unit.File_Names (Specification).Project;
1303 Path := Unit.File_Names (Specification).Path;
1305 if Current_Verbosity > Default then
1306 Write_Str ("Done: Specification.");
1312 elsif (Unit.File_Names (Body_Part).Name /= No_Name
1314 Namet.Get_Name_String
1315 (Unit.File_Names (Body_Part).Name) = Original_Name)
1316 or else (Unit.File_Names (Body_Part).Path /= No_Name
1317 and then Namet.Get_Name_String
1318 (Unit.File_Names (Body_Part).Path) =
1321 Project := Unit.File_Names (Body_Part).Project;
1322 Path := Unit.File_Names (Body_Part).Path;
1324 if Current_Verbosity > Default then
1325 Write_Str ("Done: Body.");
1335 Project := No_Project;
1338 if Current_Verbosity > Default then
1339 Write_Str ("Cannot be found.");
1348 procedure Initialize is
1349 Global : constant String := "global_configuration_pragmas";
1350 Local : constant String := "local_configuration_pragmas";
1353 -- Put the standard GNAT naming scheme in the Namings table
1355 Namings.Increment_Last;
1356 Namings.Table (Namings.Last) := Standard_Naming_Data;
1357 Name_Len := Global'Length;
1358 Name_Buffer (1 .. Name_Len) := Global;
1359 Global_Configuration_Pragmas := Name_Find;
1360 Name_Len := Local'Length;
1361 Name_Buffer (1 .. Name_Len) := Local;
1362 Local_Configuration_Pragmas := Name_Find;
1365 ------------------------------------
1366 -- Path_Name_Of_Library_Unit_Body --
1367 ------------------------------------
1369 function Path_Name_Of_Library_Unit_Body
1371 Project : Project_Id)
1374 Data : constant Project_Data := Projects.Table (Project);
1375 Original_Name : String := Name;
1377 Extended_Spec_Name : String :=
1378 Name & Namet.Get_Name_String
1379 (Data.Naming.Current_Spec_Suffix);
1380 Extended_Body_Name : String :=
1381 Name & Namet.Get_Name_String
1382 (Data.Naming.Current_Impl_Suffix);
1384 First : Unit_Id := Units.First;
1389 Canonical_Case_File_Name (Original_Name);
1390 Canonical_Case_File_Name (Extended_Spec_Name);
1391 Canonical_Case_File_Name (Extended_Spec_Name);
1393 if Current_Verbosity = High then
1394 Write_Str ("Looking for path name of """);
1398 Write_Str (" Extended Spec Name = """);
1399 Write_Str (Extended_Spec_Name);
1402 Write_Str (" Extended Body Name = """);
1403 Write_Str (Extended_Body_Name);
1408 while First <= Units.Last
1409 and then Units.Table (First).File_Names (Body_Part).Project /= Project
1415 while Current <= Units.Last loop
1416 Unit := Units.Table (Current);
1418 if Unit.File_Names (Body_Part).Project = Project
1419 and then Unit.File_Names (Body_Part).Name /= No_Name
1422 Current_Name : constant String :=
1423 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1425 if Current_Verbosity = High then
1426 Write_Str (" Comparing with """);
1427 Write_Str (Current_Name);
1432 if Current_Name = Original_Name then
1433 if Current_Verbosity = High then
1437 return Body_Path_Name_Of (Current);
1439 elsif Current_Name = Extended_Body_Name then
1440 if Current_Verbosity = High then
1444 return Body_Path_Name_Of (Current);
1447 if Current_Verbosity = High then
1448 Write_Line (" not good");
1453 elsif Unit.File_Names (Specification).Name /= No_Name then
1455 Current_Name : constant String :=
1456 Namet.Get_Name_String
1457 (Unit.File_Names (Specification).Name);
1460 if Current_Verbosity = High then
1461 Write_Str (" Comparing with """);
1462 Write_Str (Current_Name);
1467 if Current_Name = Original_Name then
1468 if Current_Verbosity = High then
1472 return Spec_Path_Name_Of (Current);
1474 elsif Current_Name = Extended_Spec_Name then
1476 if Current_Verbosity = High then
1480 return Spec_Path_Name_Of (Current);
1483 if Current_Verbosity = High then
1484 Write_Line (" not good");
1489 Current := Current + 1;
1493 end Path_Name_Of_Library_Unit_Body;
1499 procedure Print_Sources is
1503 Write_Line ("List of Sources:");
1505 for Id in Units.First .. Units.Last loop
1506 Unit := Units.Table (Id);
1508 Write_Line (Namet.Get_Name_String (Unit.Name));
1510 if Unit.File_Names (Specification).Name /= No_Name then
1511 if Unit.File_Names (Specification).Project = No_Project then
1512 Write_Line (" No project");
1515 Write_Str (" Project: ");
1518 (Unit.File_Names (Specification).Project).Path_Name);
1519 Write_Line (Name_Buffer (1 .. Name_Len));
1522 Write_Str (" spec: ");
1524 (Namet.Get_Name_String
1525 (Unit.File_Names (Specification).Name));
1528 if Unit.File_Names (Body_Part).Name /= No_Name then
1529 if Unit.File_Names (Body_Part).Project = No_Project then
1530 Write_Line (" No project");
1533 Write_Str (" Project: ");
1536 (Unit.File_Names (Body_Part).Project).Path_Name);
1537 Write_Line (Name_Buffer (1 .. Name_Len));
1540 Write_Str (" body: ");
1542 (Namet.Get_Name_String
1543 (Unit.File_Names (Body_Part).Name));
1548 Write_Line ("end of List of Sources.");
1551 ---------------------------------------------
1552 -- Set_Mapping_File_Initial_State_To_Empty --
1553 ---------------------------------------------
1555 procedure Set_Mapping_File_Initial_State_To_Empty is
1557 Fill_Mapping_File := False;
1558 end Set_Mapping_File_Initial_State_To_Empty;
1560 -----------------------
1561 -- Spec_Path_Name_Of --
1562 -----------------------
1564 function Spec_Path_Name_Of (Unit : Unit_Id) return String is
1565 Data : Unit_Data := Units.Table (Unit);
1568 if Data.File_Names (Specification).Path = No_Name then
1570 Current_Source : String_List_Id :=
1571 Projects.Table (Data.File_Names (Specification).Project).Sources;
1572 Path : GNAT.OS_Lib.String_Access;
1575 Data.File_Names (Specification).Path :=
1576 Data.File_Names (Specification).Name;
1578 while Current_Source /= Nil_String loop
1579 String_To_Name_Buffer
1580 (String_Elements.Table (Current_Source).Value);
1581 Path := Locate_Regular_File
1582 (Namet.Get_Name_String
1583 (Data.File_Names (Specification).Name),
1584 Name_Buffer (1 .. Name_Len));
1586 if Path /= null then
1587 Name_Len := Path'Length;
1588 Name_Buffer (1 .. Name_Len) := Path.all;
1589 Data.File_Names (Specification).Path := Name_Enter;
1593 String_Elements.Table (Current_Source).Next;
1597 Units.Table (Unit) := Data;
1601 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
1602 end Spec_Path_Name_Of;