1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 2001 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 -- Extensive contributions were provided by Ada Core Technologies Inc. --
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
;
43 No_Naming
: constant Naming_Id
:= 0;
45 Ada_Path_Buffer
: String_Access
:= new String (1 .. 1_000
);
46 -- A buffer where values for ADA_INCLUDE_PATH
47 -- and ADA_OBJECTS_PATH are stored.
49 Ada_Path_Length
: Natural := 0;
50 -- Index of the last valid character in Ada_Path_Buffer.
52 package Namings
is new Table
.Table
(
53 Table_Component_Type
=> Naming_Data
,
54 Table_Index_Type
=> Naming_Id
,
57 Table_Increment
=> 100,
58 Table_Name
=> "Prj.Env.Namings");
60 Default_Naming
: constant Naming_Id
:= Namings
.First
;
62 Global_Configuration_Pragmas
: Name_Id
;
63 Local_Configuration_Pragmas
: Name_Id
;
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
(Path
: String);
78 -- Add Path to global variable Ada_Path_Buffer
79 -- Increment Ada_Path_Length
81 ----------------------
82 -- Ada_Include_Path --
83 ----------------------
85 function Ada_Include_Path
(Project
: Project_Id
) return String_Access
is
87 procedure Add
(Project
: Project_Id
);
88 -- Add all the source directories of a project to the path,
89 -- only if this project has not been visited.
90 -- Call itself recursively for projects being modified,
91 -- and imported projects.
92 -- Add the project to the list Seen if this is the first time
93 -- we call Add for this project.
99 procedure Add
(Project
: Project_Id
) is
101 -- If Seen is empty, then the project cannot have been
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
;
111 Current
: String_List_Id
:= Data
.Source_Dirs
;
112 Source_Dir
: String_Element
;
115 -- Add to path all source directories of this project
117 while Current
/= Nil_String
loop
118 if Ada_Path_Length
> 0 then
119 Add_To_Path
(Path
=> (1 => Path_Separator
));
122 Source_Dir
:= String_Elements
.Table
(Current
);
123 String_To_Name_Buffer
(Source_Dir
.Value
);
126 New_Path
: constant String :=
127 Name_Buffer
(1 .. Name_Len
);
129 Add_To_Path
(New_Path
);
132 Current
:= Source_Dir
.Next
;
135 -- Call Add to the project being modified, if any
137 if Data
.Modifies
/= No_Project
then
141 -- Call Add for each imported project, if any
143 while List
/= Empty_Project_List
loop
144 Add
(Project_Lists
.Table
(List
).Project
);
145 List
:= Project_Lists
.Table
(List
).Next
;
152 -- Start of processing for Ada_Include_Path
155 -- If it is the first time we call this function for
156 -- this project, compute the source path
158 if Projects
.Table
(Project
).Include_Path
= null then
159 Ada_Path_Length
:= 0;
161 for Index
in 1 .. Projects
.Last
loop
162 Projects
.Table
(Index
).Seen
:= False;
166 Projects
.Table
(Project
).Include_Path
:=
167 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
170 return Projects.Table (Project).Include_Path;
171 end Ada_Include_Path;
173 ----------------------
174 -- Ada_Objects_Path --
175 ----------------------
177 function Ada_Objects_Path
178 (Project : Project_Id;
179 Including_Libraries : Boolean := True)
180 return String_Access is
182 procedure Add (Project : Project_Id);
183 -- Add all the object directory of a project to the path,
184 -- only if this project has not been visited.
185 -- Call itself recursively for projects being modified,
186 -- and imported projects.
187 -- Add the project to the list Seen if this is the first time
188 -- we call Add for this project.
194 procedure Add (Project : Project_Id) is
197 -- If this project has not been seen yet
199 if not Projects.Table (Project).Seen then
200 Projects.Table (Project).Seen := True;
203 Data : Project_Data := Projects.Table (Project);
204 List : Project_List := Data.Imported_Projects;
207 -- Add to path the object directory of this project
208 -- except if we don't include library project and
209 -- this is a library project.
211 if (Data.Library and then Including_Libraries)
213 (Data.Object_Directory /= No_Name
215 (not Including_Libraries or else not Data.Library))
217 if Ada_Path_Length > 0 then
218 Add_To_Path (Path => (1 => Path_Separator));
221 -- For a library project, att the library directory
225 New_Path : constant String :=
226 Get_Name_String (Data.Library_Dir);
228 Add_To_Path (New_Path);
232 -- For a non library project, add the object directory
234 New_Path : constant String :=
235 Get_Name_String (Data.Object_Directory);
237 Add_To_Path (New_Path);
242 -- Call Add to the project being modified, if any
244 if Data.Modifies /= No_Project then
248 -- Call Add for each imported project, if any
250 while List /= Empty_Project_List loop
251 Add (Project_Lists.Table (List).Project);
252 List := Project_Lists.Table (List).Next;
259 -- Start of processing for Ada_Objects_Path
262 -- If it is the first time we call this function for
263 -- this project, compute the objects path
265 if Projects.Table (Project).Objects_Path = null then
266 Ada_Path_Length := 0;
268 for Index in 1 .. Projects.Last loop
269 Projects.Table (Index).Seen := False;
273 Projects.Table (Project).Objects_Path :=
274 new String'(Ada_Path_Buffer
(1 .. Ada_Path_Length
));
277 return Projects
.Table
(Project
).Objects_Path
;
278 end Ada_Objects_Path
;
284 procedure Add_To_Path
(Path
: String) is
286 -- If Ada_Path_Buffer is too small, double it
288 if Ada_Path_Length
+ Path
'Length > Ada_Path_Buffer
'Last then
290 New_Ada_Path_Buffer
: constant String_Access
:=
292 (1 .. Ada_Path_Buffer
'Last +
293 Ada_Path_Buffer
'Last);
296 New_Ada_Path_Buffer
(1 .. Ada_Path_Length
) :=
297 Ada_Path_Buffer
(1 .. Ada_Path_Length
);
298 Ada_Path_Buffer
:= New_Ada_Path_Buffer
;
303 (Ada_Path_Length
+ 1 .. Ada_Path_Length
+ Path
'Length) := Path
;
304 Ada_Path_Length
:= Ada_Path_Length
+ Path
'Length;
307 -----------------------
308 -- Body_Path_Name_Of --
309 -----------------------
311 function Body_Path_Name_Of
(Unit
: Unit_Id
) return String is
312 Data
: Unit_Data
:= Units
.Table
(Unit
);
315 -- If we don't know the path name of the body of this unit,
316 -- we compute it, and we store it.
318 if Data
.File_Names
(Body_Part
).Path
= No_Name
then
320 Current_Source
: String_List_Id
:=
321 Projects
.Table
(Data
.File_Names
(Body_Part
).Project
).Sources
;
322 Path
: GNAT
.OS_Lib
.String_Access
;
325 -- By default, put the file name
327 Data
.File_Names
(Body_Part
).Path
:=
328 Data
.File_Names
(Body_Part
).Name
;
330 -- For each source directory
332 while Current_Source
/= Nil_String
loop
333 String_To_Name_Buffer
334 (String_Elements
.Table
(Current_Source
).Value
);
337 (Namet
.Get_Name_String
338 (Data
.File_Names
(Body_Part
).Name
),
339 Name_Buffer
(1 .. Name_Len
));
341 -- If the file is in this directory,
342 -- then we store the path, and we are done.
345 Name_Len
:= Path
'Length;
346 Name_Buffer
(1 .. Name_Len
) := Path
.all;
347 Data
.File_Names
(Body_Part
).Path
:= Name_Enter
;
352 String_Elements
.Table
(Current_Source
).Next
;
356 Units
.Table
(Unit
) := Data
;
360 -- Returned the value stored
362 return Namet
.Get_Name_String
(Data
.File_Names
(Body_Part
).Path
);
363 end Body_Path_Name_Of
;
365 --------------------------------
366 -- Create_Config_Pragmas_File --
367 --------------------------------
369 procedure Create_Config_Pragmas_File
370 (For_Project
: Project_Id
;
371 Main_Project
: Project_Id
)
373 File_Name
: Temp_File_Name
;
374 File
: File_Descriptor
:= Invalid_FD
;
376 The_Packages
: Package_Id
;
377 Gnatmake
: Prj
.Package_Id
;
378 Compiler
: Prj
.Package_Id
;
380 Current_Unit
: Unit_Id
:= Units
.First
;
382 First_Project
: Project_List
:= Empty_Project_List
;
384 Current_Project
: Project_List
;
385 Current_Naming
: Naming_Id
;
387 Global_Attribute
: Variable_Value
:= Nil_Variable_Value
;
388 Local_Attribute
: Variable_Value
:= Nil_Variable_Value
;
390 Global_Attribute_Present
: Boolean := False;
391 Local_Attribute_Present
: Boolean := False;
393 procedure Check
(Project
: Project_Id
);
395 procedure Check_Temp_File
;
396 -- Check that a temporary file has been opened.
397 -- If not, create one, and put its name in the project data,
398 -- with the indication that it is a temporary file.
400 procedure Copy_File
(Name
: String_Id
);
401 -- Copy a configuration pragmas file into the temp file.
404 (Unit_Name
: Name_Id
;
406 Unit_Kind
: Spec_Or_Body
);
407 -- Put an SFN pragma in the temporary file.
409 procedure Put
(File
: File_Descriptor
; S
: String);
411 procedure Put_Line
(File
: File_Descriptor
; S
: String);
417 procedure Check
(Project
: Project_Id
) is
418 Data
: constant Project_Data
:= Projects
.Table
(Project
);
421 if Current_Verbosity
= High
then
422 Write_Str
("Checking project file """);
423 Write_Str
(Namet
.Get_Name_String
(Data
.Name
));
428 -- Is this project in the list of the visited project?
430 Current_Project
:= First_Project
;
431 while Current_Project
/= Empty_Project_List
432 and then Project_Lists
.Table
(Current_Project
).Project
/= Project
434 Current_Project
:= Project_Lists
.Table
(Current_Project
).Next
;
437 -- If it is not, put it in the list, and visit it
439 if Current_Project
= Empty_Project_List
then
440 Project_Lists
.Increment_Last
;
441 Project_Lists
.Table
(Project_Lists
.Last
) :=
442 (Project
=> Project
, Next
=> First_Project
);
443 First_Project
:= Project_Lists
.Last
;
445 -- Is the naming scheme of this project one that we know?
447 Current_Naming
:= Default_Naming
;
448 while Current_Naming
<= Namings
.Last
and then
449 not Same_Naming_Scheme
450 (Left
=> Namings
.Table
(Current_Naming
),
451 Right
=> Data
.Naming
) loop
452 Current_Naming
:= Current_Naming
+ 1;
455 -- If we don't know it, add it
457 if Current_Naming
> Namings
.Last
then
458 Namings
.Increment_Last
;
459 Namings
.Table
(Namings
.Last
) := Data
.Naming
;
461 -- We need a temporary file to be created
465 -- Put the SFN pragmas for the naming scheme
470 (File
, "pragma Source_File_Name");
472 (File
, " (Spec_File_Name => ""*" &
473 Namet
.Get_Name_String
(Data
.Naming
.Current_Spec_Suffix
) &
476 (File
, " Casing => " &
477 Image
(Data
.Naming
.Casing
) & ",");
479 (File
, " Dot_Replacement => """ &
480 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
486 (File
, "pragma Source_File_Name");
488 (File
, " (Body_File_Name => ""*" &
489 Namet
.Get_Name_String
(Data
.Naming
.Current_Impl_Suffix
) &
492 (File
, " Casing => " &
493 Image
(Data
.Naming
.Casing
) & ",");
495 (File
, " Dot_Replacement => """ &
496 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
499 -- and maybe separate
502 Data
.Naming
.Current_Impl_Suffix
/= Data
.Naming
.Separate_Suffix
505 (File
, "pragma Source_File_Name");
507 (File
, " (Subunit_File_Name => ""*" &
508 Namet
.Get_Name_String
(Data
.Naming
.Separate_Suffix
) &
511 (File
, " Casing => " &
512 Image
(Data
.Naming
.Casing
) &
515 (File
, " Dot_Replacement => """ &
516 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
521 if Data
.Modifies
/= No_Project
then
522 Check
(Data
.Modifies
);
526 Current
: Project_List
:= Data
.Imported_Projects
;
529 while Current
/= Empty_Project_List
loop
530 Check
(Project_Lists
.Table
(Current
).Project
);
531 Current
:= Project_Lists
.Table
(Current
).Next
;
537 ---------------------
538 -- Check_Temp_File --
539 ---------------------
541 procedure Check_Temp_File
is
543 if File
= Invalid_FD
then
544 GNAT
.OS_Lib
.Create_Temp_File
(File
, Name
=> File_Name
);
545 if File
= Invalid_FD
then
547 ("unable to create temporary configuration pragmas file");
548 elsif Opt
.Verbose_Mode
then
549 Write_Str
("Creating temp file """);
550 Write_Str
(File_Name
);
560 procedure Copy_File
(Name
: in String_Id
) is
561 Input
: File_Descriptor
;
562 Buffer
: String (1 .. 1_000
);
563 Input_Length
: Integer;
564 Output_Length
: Integer;
568 String_To_Name_Buffer
(Name
);
570 if Opt
.Verbose_Mode
then
571 Write_Str
("Copying config pragmas file """);
572 Write_Str
(Name_Buffer
(1 .. Name_Len
));
573 Write_Line
(""" into temp file");
577 Name
: constant String :=
578 Name_Buffer
(1 .. Name_Len
) & ASCII
.NUL
;
580 Input
:= Open_Read
(Name
'Address, Binary
);
583 if Input
= Invalid_FD
then
585 ("cannot open configuration pragmas file " &
586 Name_Buffer
(1 .. Name_Len
));
590 Input_Length
:= Read
(Input
, Buffer
'Address, Buffer
'Length);
591 Output_Length
:= Write
(File
, Buffer
'Address, Input_Length
);
593 if Output_Length
/= Input_Length
then
594 Osint
.Fail
("disk full");
597 exit when Input_Length
< Buffer
'Length;
609 (Unit_Name
: Name_Id
;
611 Unit_Kind
: Spec_Or_Body
)
614 -- A temporary file needs to be open
618 -- Put the pragma SFN for the unit kind (spec or body)
620 Put
(File
, "pragma Source_File_Name (");
621 Put
(File
, Namet
.Get_Name_String
(Unit_Name
));
623 if Unit_Kind
= Specification
then
624 Put
(File
, ", Spec_File_Name => """);
626 Put
(File
, ", Body_File_Name => """);
629 Put
(File
, Namet
.Get_Name_String
(File_Name
));
630 Put_Line
(File
, """);");
633 procedure Put
(File
: File_Descriptor
; S
: String) is
637 Last
:= Write
(File
, S
(S
'First)'Address, S
'Length);
639 if Last
/= S
'Length then
640 Osint
.Fail
("Disk full");
643 if Current_Verbosity
= High
then
652 procedure Put_Line
(File
: File_Descriptor
; S
: String) is
653 S0
: String (1 .. S
'Length + 1);
657 -- Add an ASCII.LF to the string. As this gnat.adc
658 -- is supposed to be used only by the compiler, we don't
659 -- care about the characters for the end of line.
660 -- The truth is we could have put a space, but it is
661 -- more convenient to be able to read gnat.adc during
662 -- development. And the development was done under UNIX.
663 -- Hence the ASCII.LF.
665 S0
(1 .. S
'Length) := S
;
666 S0
(S0
'Last) := ASCII
.LF
;
667 Last
:= Write
(File
, S0
'Address, S0
'Length);
669 if Last
/= S
'Length + 1 then
670 Osint
.Fail
("Disk full");
673 if Current_Verbosity
= High
then
678 -- Start of processing for Create_Config_Pragmas_File
682 if not Projects
.Table
(For_Project
).Config_Checked
then
684 -- Remove any memory of processed naming schemes, if any
686 Namings
.Set_Last
(Default_Naming
);
688 -- Check the naming schemes
692 -- Visit all the units and process those that need an SFN pragma
694 while Current_Unit
<= Units
.Last
loop
696 Unit
: constant Unit_Data
:=
697 Units
.Table
(Current_Unit
);
700 if Unit
.File_Names
(Specification
).Needs_Pragma
then
702 Unit
.File_Names
(Specification
).Name
,
706 if Unit
.File_Names
(Body_Part
).Needs_Pragma
then
708 Unit
.File_Names
(Body_Part
).Name
,
712 Current_Unit
:= Current_Unit
+ 1;
716 The_Packages
:= Projects
.Table
(Main_Project
).Decl
.Packages
;
719 (Name
=> Name_Builder
,
720 In_Packages
=> The_Packages
);
722 if Gnatmake
/= No_Package
then
723 Global_Attribute
:= Prj
.Util
.Value_Of
724 (Variable_Name
=> Global_Configuration_Pragmas
,
725 In_Variables
=> Packages
.Table
(Gnatmake
).Decl
.Attributes
);
726 Global_Attribute_Present
:=
727 Global_Attribute
/= Nil_Variable_Value
728 and then String_Length
(Global_Attribute
.Value
) > 0;
731 The_Packages
:= Projects
.Table
(For_Project
).Decl
.Packages
;
734 (Name
=> Name_Compiler
,
735 In_Packages
=> The_Packages
);
737 if Compiler
/= No_Package
then
738 Local_Attribute
:= Prj
.Util
.Value_Of
739 (Variable_Name
=> Local_Configuration_Pragmas
,
740 In_Variables
=> Packages
.Table
(Compiler
).Decl
.Attributes
);
741 Local_Attribute_Present
:=
742 Local_Attribute
/= Nil_Variable_Value
743 and then String_Length
(Local_Attribute
.Value
) > 0;
746 if Global_Attribute_Present
then
748 if File
/= Invalid_FD
749 or else Local_Attribute_Present
751 Copy_File
(Global_Attribute
.Value
);
753 String_To_Name_Buffer
(Global_Attribute
.Value
);
754 Projects
.Table
(For_Project
).Config_File_Name
:= Name_Find
;
758 if Local_Attribute_Present
then
760 if File
/= Invalid_FD
then
761 Copy_File
(Local_Attribute
.Value
);
764 String_To_Name_Buffer
(Local_Attribute
.Value
);
765 Projects
.Table
(For_Project
).Config_File_Name
:= Name_Find
;
770 if File
/= Invalid_FD
then
771 GNAT
.OS_Lib
.Close
(File
);
773 if Opt
.Verbose_Mode
then
774 Write_Str
("Closing configuration file """);
775 Write_Str
(File_Name
);
779 Name_Len
:= File_Name
'Length;
780 Name_Buffer
(1 .. Name_Len
) := File_Name
;
781 Projects
.Table
(For_Project
).Config_File_Name
:= Name_Find
;
782 Projects
.Table
(For_Project
).Config_File_Temp
:= True;
785 Projects
.Table
(For_Project
).Config_Checked
:= True;
789 end Create_Config_Pragmas_File
;
791 -------------------------
792 -- Create_Mapping_File --
793 -------------------------
795 procedure Create_Mapping_File
(Name
: in out Temp_File_Name
) is
796 File
: File_Descriptor
:= Invalid_FD
;
797 The_Unit_Data
: Unit_Data
;
798 Data
: File_Name_Data
;
800 procedure Put
(S
: String);
801 -- Put a line in the mapping file
803 procedure Put_Data
(Spec
: Boolean);
804 -- Put the mapping of the spec or body contained in Data in the file
811 procedure Put
(S
: String) is
815 Last
:= Write
(File
, S
'Address, S
'Length);
817 if Last
/= S
'Length then
818 Osint
.Fail
("Disk full");
826 procedure Put_Data
(Spec
: Boolean) is
828 Put
(Get_Name_String
(The_Unit_Data
.Name
));
836 Put
(S
=> (1 => ASCII
.LF
));
837 Put
(Get_Name_String
(Data
.Name
));
838 Put
(S
=> (1 => ASCII
.LF
));
839 Put
(Get_Name_String
(Data
.Path
));
840 Put
(S
=> (1 => ASCII
.LF
));
843 -- Start of processing for Create_Mapping_File
846 GNAT
.OS_Lib
.Create_Temp_File
(File
, Name
=> Name
);
848 if File
= Invalid_FD
then
850 ("unable to create temporary mapping file");
852 elsif Opt
.Verbose_Mode
then
853 Write_Str
("Creating temp mapping file """);
858 -- For all units in table Units
860 for Unit
in 1 .. Units
.Last
loop
861 The_Unit_Data
:= Units
.Table
(Unit
);
863 -- If the unit has a valid name
865 if The_Unit_Data
.Name
/= No_Name
then
866 Data
:= The_Unit_Data
.File_Names
(Specification
);
868 -- If there is a spec, put it mapping in the file
870 if Data
.Name
/= No_Name
then
871 Put_Data
(Spec
=> True);
874 Data
:= The_Unit_Data
.File_Names
(Body_Part
);
876 -- If there is a body (or subunit) put its mapping in the file
878 if Data
.Name
/= No_Name
then
879 Put_Data
(Spec
=> False);
885 GNAT
.OS_Lib
.Close
(File
);
887 end Create_Mapping_File
;
889 ------------------------------------
890 -- File_Name_Of_Library_Unit_Body --
891 ------------------------------------
893 function File_Name_Of_Library_Unit_Body
895 Project
: Project_Id
)
898 Data
: constant Project_Data
:= Projects
.Table
(Project
);
899 Original_Name
: String := Name
;
901 Extended_Spec_Name
: String :=
902 Name
& Namet
.Get_Name_String
903 (Data
.Naming
.Current_Spec_Suffix
);
904 Extended_Body_Name
: String :=
905 Name
& Namet
.Get_Name_String
906 (Data
.Naming
.Current_Impl_Suffix
);
910 The_Original_Name
: Name_Id
;
911 The_Spec_Name
: Name_Id
;
912 The_Body_Name
: Name_Id
;
915 Canonical_Case_File_Name
(Original_Name
);
916 Name_Len
:= Original_Name
'Length;
917 Name_Buffer
(1 .. Name_Len
) := Original_Name
;
918 The_Original_Name
:= Name_Find
;
920 Canonical_Case_File_Name
(Extended_Spec_Name
);
921 Name_Len
:= Extended_Spec_Name
'Length;
922 Name_Buffer
(1 .. Name_Len
) := Extended_Spec_Name
;
923 The_Spec_Name
:= Name_Find
;
925 Canonical_Case_File_Name
(Extended_Body_Name
);
926 Name_Len
:= Extended_Body_Name
'Length;
927 Name_Buffer
(1 .. Name_Len
) := Extended_Body_Name
;
928 The_Body_Name
:= Name_Find
;
930 if Current_Verbosity
= High
then
931 Write_Str
("Looking for file name of """);
935 Write_Str
(" Extended Spec Name = """);
936 Write_Str
(Extended_Spec_Name
);
939 Write_Str
(" Extended Body Name = """);
940 Write_Str
(Extended_Body_Name
);
947 for Current
in reverse Units
.First
.. Units
.Last
loop
948 Unit
:= Units
.Table
(Current
);
950 -- Case of unit of the same project
952 if Unit
.File_Names
(Body_Part
).Project
= Project
then
954 Current_Name
: constant Name_Id
:=
955 Unit
.File_Names
(Body_Part
).Name
;
958 -- Case of a body present
960 if Current_Name
/= No_Name
then
961 if Current_Verbosity
= High
then
962 Write_Str
(" Comparing with """);
963 Write_Str
(Get_Name_String
(Current_Name
));
968 -- If it has the name of the original name,
969 -- return the original name
971 if Unit
.Name
= The_Original_Name
972 or else Current_Name
= The_Original_Name
974 if Current_Verbosity
= High
then
978 return Get_Name_String
(Current_Name
);
980 -- If it has the name of the extended body name,
981 -- return the extended body name
983 elsif Current_Name
= The_Body_Name
then
984 if Current_Verbosity
= High
then
988 return Extended_Body_Name
;
991 if Current_Verbosity
= High
then
992 Write_Line
(" not good");
999 -- Case of a unit of the same project
1001 if Units
.Table
(Current
).File_Names
(Specification
).Project
=
1005 Current_Name
: constant Name_Id
:=
1006 Unit
.File_Names
(Specification
).Name
;
1009 -- Case of spec present
1011 if Current_Name
/= No_Name
then
1012 if Current_Verbosity
= High
then
1013 Write_Str
(" Comparing with """);
1014 Write_Str
(Get_Name_String
(Current_Name
));
1019 -- If name same as the original name, return original name
1021 if Unit
.Name
= The_Original_Name
1022 or else Current_Name
= The_Original_Name
1024 if Current_Verbosity
= High
then
1028 return Get_Name_String
(Current_Name
);
1030 -- If it has the same name as the extended spec name,
1031 -- return the extended spec name.
1033 elsif Current_Name
= The_Spec_Name
then
1034 if Current_Verbosity
= High
then
1038 return Extended_Spec_Name
;
1041 if Current_Verbosity
= High
then
1042 Write_Line
(" not good");
1051 -- We don't know this file name, return an empty string
1054 end File_Name_Of_Library_Unit_Body
;
1056 -------------------------
1057 -- For_All_Object_Dirs --
1058 -------------------------
1060 procedure For_All_Object_Dirs
(Project
: Project_Id
) is
1061 Seen
: Project_List
:= Empty_Project_List
;
1063 procedure Add
(Project
: Project_Id
);
1064 -- Process a project. Remember the processes visited to avoid
1065 -- processing a project twice. Recursively process an eventual
1066 -- modified project, and all imported projects.
1072 procedure Add
(Project
: Project_Id
) is
1073 Data
: constant Project_Data
:= Projects
.Table
(Project
);
1074 List
: Project_List
:= Data
.Imported_Projects
;
1077 -- If the list of visited project is empty, then
1078 -- for sure we never visited this project.
1080 if Seen
= Empty_Project_List
then
1081 Project_Lists
.Increment_Last
;
1082 Seen
:= Project_Lists
.Last
;
1083 Project_Lists
.Table
(Seen
) :=
1084 (Project
=> Project
, Next
=> Empty_Project_List
);
1087 -- Check if the project is in the list
1090 Current
: Project_List
:= Seen
;
1094 -- If it is, then there is nothing else to do
1096 if Project_Lists
.Table
(Current
).Project
= Project
then
1100 exit when Project_Lists
.Table
(Current
).Next
=
1102 Current
:= Project_Lists
.Table
(Current
).Next
;
1105 -- This project has never been visited, add it
1108 Project_Lists
.Increment_Last
;
1109 Project_Lists
.Table
(Current
).Next
:= Project_Lists
.Last
;
1110 Project_Lists
.Table
(Project_Lists
.Last
) :=
1111 (Project
=> Project
, Next
=> Empty_Project_List
);
1115 -- If there is an object directory, call Action
1118 if Data
.Object_Directory
/= No_Name
then
1119 Get_Name_String
(Data
.Object_Directory
);
1120 Action
(Name_Buffer
(1 .. Name_Len
));
1123 -- If we are extending a project, visit it
1125 if Data
.Modifies
/= No_Project
then
1126 Add
(Data
.Modifies
);
1129 -- And visit all imported projects
1131 while List
/= Empty_Project_List
loop
1132 Add
(Project_Lists
.Table
(List
).Project
);
1133 List
:= Project_Lists
.Table
(List
).Next
;
1137 -- Start of processing for For_All_Object_Dirs
1140 -- Visit this project, and its imported projects,
1144 end For_All_Object_Dirs
;
1146 -------------------------
1147 -- For_All_Source_Dirs --
1148 -------------------------
1150 procedure For_All_Source_Dirs
(Project
: Project_Id
) is
1151 Seen
: Project_List
:= Empty_Project_List
;
1153 procedure Add
(Project
: Project_Id
);
1154 -- Process a project. Remember the processes visited to avoid
1155 -- processing a project twice. Recursively process an eventual
1156 -- modified project, and all imported projects.
1162 procedure Add
(Project
: Project_Id
) is
1163 Data
: constant Project_Data
:= Projects
.Table
(Project
);
1164 List
: Project_List
:= Data
.Imported_Projects
;
1167 -- If the list of visited project is empty, then
1168 -- for sure we never visited this project.
1170 if Seen
= Empty_Project_List
then
1171 Project_Lists
.Increment_Last
;
1172 Seen
:= Project_Lists
.Last
;
1173 Project_Lists
.Table
(Seen
) :=
1174 (Project
=> Project
, Next
=> Empty_Project_List
);
1177 -- Check if the project is in the list
1180 Current
: Project_List
:= Seen
;
1184 -- If it is, then there is nothing else to do
1186 if Project_Lists
.Table
(Current
).Project
= Project
then
1190 exit when Project_Lists
.Table
(Current
).Next
=
1192 Current
:= Project_Lists
.Table
(Current
).Next
;
1195 -- This project has never been visited, add it
1198 Project_Lists
.Increment_Last
;
1199 Project_Lists
.Table
(Current
).Next
:= Project_Lists
.Last
;
1200 Project_Lists
.Table
(Project_Lists
.Last
) :=
1201 (Project
=> Project
, Next
=> Empty_Project_List
);
1206 Current
: String_List_Id
:= Data
.Source_Dirs
;
1207 The_String
: String_Element
;
1210 -- Call action with the name of every source directorie
1212 while Current
/= Nil_String
loop
1213 The_String
:= String_Elements
.Table
(Current
);
1214 String_To_Name_Buffer
(The_String
.Value
);
1215 Action
(Name_Buffer
(1 .. Name_Len
));
1216 Current
:= The_String
.Next
;
1220 -- If we are extending a project, visit it
1222 if Data
.Modifies
/= No_Project
then
1223 Add
(Data
.Modifies
);
1226 -- And visit all imported projects
1228 while List
/= Empty_Project_List
loop
1229 Add
(Project_Lists
.Table
(List
).Project
);
1230 List
:= Project_Lists
.Table
(List
).Next
;
1234 -- Start of processing for For_All_Source_Dirs
1237 -- Visit this project, and its imported projects recursively
1240 end For_All_Source_Dirs
;
1246 procedure Get_Reference
1247 (Source_File_Name
: String;
1248 Project
: out Project_Id
;
1252 if Current_Verbosity
> Default
then
1253 Write_Str
("Getting Reference_Of (""");
1254 Write_Str
(Source_File_Name
);
1255 Write_Str
(""") ... ");
1259 Original_Name
: String := Source_File_Name
;
1263 Canonical_Case_File_Name
(Original_Name
);
1265 for Id
in Units
.First
.. Units
.Last
loop
1266 Unit
:= Units
.Table
(Id
);
1268 if (Unit
.File_Names
(Specification
).Name
/= No_Name
1270 Namet
.Get_Name_String
1271 (Unit
.File_Names
(Specification
).Name
) = Original_Name
)
1272 or else (Unit
.File_Names
(Specification
).Path
/= No_Name
1274 Namet
.Get_Name_String
1275 (Unit
.File_Names
(Specification
).Path
) =
1278 Project
:= Unit
.File_Names
(Specification
).Project
;
1279 Path
:= Unit
.File_Names
(Specification
).Path
;
1281 if Current_Verbosity
> Default
then
1282 Write_Str
("Done: Specification.");
1288 elsif (Unit
.File_Names
(Body_Part
).Name
/= No_Name
1290 Namet
.Get_Name_String
1291 (Unit
.File_Names
(Body_Part
).Name
) = Original_Name
)
1292 or else (Unit
.File_Names
(Body_Part
).Path
/= No_Name
1293 and then Namet
.Get_Name_String
1294 (Unit
.File_Names
(Body_Part
).Path
) =
1297 Project
:= Unit
.File_Names
(Body_Part
).Project
;
1298 Path
:= Unit
.File_Names
(Body_Part
).Path
;
1300 if Current_Verbosity
> Default
then
1301 Write_Str
("Done: Body.");
1311 Project
:= No_Project
;
1314 if Current_Verbosity
> Default
then
1315 Write_Str
("Cannot be found.");
1324 procedure Initialize
is
1325 Global
: constant String := "global_configuration_pragmas";
1326 Local
: constant String := "local_configuration_pragmas";
1328 -- Put the standard GNAT naming scheme in the Namings table
1330 Namings
.Increment_Last
;
1331 Namings
.Table
(Namings
.Last
) := Standard_Naming_Data
;
1332 Name_Len
:= Global
'Length;
1333 Name_Buffer
(1 .. Name_Len
) := Global
;
1334 Global_Configuration_Pragmas
:= Name_Find
;
1335 Name_Len
:= Local
'Length;
1336 Name_Buffer
(1 .. Name_Len
) := Local
;
1337 Local_Configuration_Pragmas
:= Name_Find
;
1340 ------------------------------------
1341 -- Path_Name_Of_Library_Unit_Body --
1342 ------------------------------------
1344 function Path_Name_Of_Library_Unit_Body
1346 Project
: Project_Id
)
1349 Data
: constant Project_Data
:= Projects
.Table
(Project
);
1350 Original_Name
: String := Name
;
1352 Extended_Spec_Name
: String :=
1353 Name
& Namet
.Get_Name_String
1354 (Data
.Naming
.Current_Spec_Suffix
);
1355 Extended_Body_Name
: String :=
1356 Name
& Namet
.Get_Name_String
1357 (Data
.Naming
.Current_Impl_Suffix
);
1359 First
: Unit_Id
:= Units
.First
;
1364 Canonical_Case_File_Name
(Original_Name
);
1365 Canonical_Case_File_Name
(Extended_Spec_Name
);
1366 Canonical_Case_File_Name
(Extended_Spec_Name
);
1368 if Current_Verbosity
= High
then
1369 Write_Str
("Looking for path name of """);
1373 Write_Str
(" Extended Spec Name = """);
1374 Write_Str
(Extended_Spec_Name
);
1377 Write_Str
(" Extended Body Name = """);
1378 Write_Str
(Extended_Body_Name
);
1383 while First
<= Units
.Last
1384 and then Units
.Table
(First
).File_Names
(Body_Part
).Project
/= Project
1390 while Current
<= Units
.Last
loop
1391 Unit
:= Units
.Table
(Current
);
1393 if Unit
.File_Names
(Body_Part
).Project
= Project
1394 and then Unit
.File_Names
(Body_Part
).Name
/= No_Name
1397 Current_Name
: constant String :=
1398 Namet
.Get_Name_String
(Unit
.File_Names
(Body_Part
).Name
);
1400 if Current_Verbosity
= High
then
1401 Write_Str
(" Comparing with """);
1402 Write_Str
(Current_Name
);
1407 if Current_Name
= Original_Name
then
1408 if Current_Verbosity
= High
then
1412 return Body_Path_Name_Of
(Current
);
1414 elsif Current_Name
= Extended_Body_Name
then
1415 if Current_Verbosity
= High
then
1419 return Body_Path_Name_Of
(Current
);
1422 if Current_Verbosity
= High
then
1423 Write_Line
(" not good");
1428 elsif Unit
.File_Names
(Specification
).Name
/= No_Name
then
1430 Current_Name
: constant String :=
1431 Namet
.Get_Name_String
1432 (Unit
.File_Names
(Specification
).Name
);
1435 if Current_Verbosity
= High
then
1436 Write_Str
(" Comparing with """);
1437 Write_Str
(Current_Name
);
1442 if Current_Name
= Original_Name
then
1443 if Current_Verbosity
= High
then
1447 return Spec_Path_Name_Of
(Current
);
1449 elsif Current_Name
= Extended_Spec_Name
then
1451 if Current_Verbosity
= High
then
1455 return Spec_Path_Name_Of
(Current
);
1458 if Current_Verbosity
= High
then
1459 Write_Line
(" not good");
1464 Current
:= Current
+ 1;
1468 end Path_Name_Of_Library_Unit_Body
;
1474 procedure Print_Sources
is
1478 Write_Line
("List of Sources:");
1480 for Id
in Units
.First
.. Units
.Last
loop
1481 Unit
:= Units
.Table
(Id
);
1483 Write_Line
(Namet
.Get_Name_String
(Unit
.Name
));
1485 if Unit
.File_Names
(Specification
).Name
/= No_Name
then
1486 if Unit
.File_Names
(Specification
).Project
= No_Project
then
1487 Write_Line
(" No project");
1490 Write_Str
(" Project: ");
1493 (Unit
.File_Names
(Specification
).Project
).Path_Name
);
1494 Write_Line
(Name_Buffer
(1 .. Name_Len
));
1497 Write_Str
(" spec: ");
1499 (Namet
.Get_Name_String
1500 (Unit
.File_Names
(Specification
).Name
));
1503 if Unit
.File_Names
(Body_Part
).Name
/= No_Name
then
1504 if Unit
.File_Names
(Body_Part
).Project
= No_Project
then
1505 Write_Line
(" No project");
1508 Write_Str
(" Project: ");
1511 (Unit
.File_Names
(Body_Part
).Project
).Path_Name
);
1512 Write_Line
(Name_Buffer
(1 .. Name_Len
));
1515 Write_Str
(" body: ");
1517 (Namet
.Get_Name_String
1518 (Unit
.File_Names
(Body_Part
).Name
));
1523 Write_Line
("end of List of Sources.");
1526 -----------------------
1527 -- Spec_Path_Name_Of --
1528 -----------------------
1530 function Spec_Path_Name_Of
(Unit
: Unit_Id
) return String is
1531 Data
: Unit_Data
:= Units
.Table
(Unit
);
1534 if Data
.File_Names
(Specification
).Path
= No_Name
then
1536 Current_Source
: String_List_Id
:=
1537 Projects
.Table
(Data
.File_Names
(Specification
).Project
).Sources
;
1538 Path
: GNAT
.OS_Lib
.String_Access
;
1541 Data
.File_Names
(Specification
).Path
:=
1542 Data
.File_Names
(Specification
).Name
;
1544 while Current_Source
/= Nil_String
loop
1545 String_To_Name_Buffer
1546 (String_Elements
.Table
(Current_Source
).Value
);
1547 Path
:= Locate_Regular_File
1548 (Namet
.Get_Name_String
1549 (Data
.File_Names
(Specification
).Name
),
1550 Name_Buffer
(1 .. Name_Len
));
1552 if Path
/= null then
1553 Name_Len
:= Path
'Length;
1554 Name_Buffer
(1 .. Name_Len
) := Path
.all;
1555 Data
.File_Names
(Specification
).Path
:= Name_Enter
;
1559 String_Elements
.Table
(Current_Source
).Next
;
1563 Units
.Table
(Unit
) := Data
;
1567 return Namet
.Get_Name_String
(Data
.File_Names
(Specification
).Path
);
1568 end Spec_Path_Name_Of
;