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
;