1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2007, 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 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Osint
; use Osint
;
29 with Output
; use Output
;
30 with Prj
.Com
; use Prj
.Com
;
33 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
35 package body Prj
.Env
is
37 Current_Source_Path_File
: Path_Name_Type
:= No_Path
;
38 -- Current value of project source path file env var.
39 -- Used to avoid setting the env var to the same value.
41 Current_Object_Path_File
: Path_Name_Type
:= No_Path
;
42 -- Current value of project object path file env var.
43 -- Used to avoid setting the env var to the same value.
45 Ada_Path_Buffer
: String_Access
:= new String (1 .. 1024);
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 Ada_Prj_Include_File_Set
: Boolean := False;
53 Ada_Prj_Objects_File_Set
: Boolean := False;
54 -- These flags are set to True when the corresponding environment variables
55 -- are set and are used to give these environment variables an empty string
56 -- value at the end of the program. This has no practical effect on most
57 -- platforms, except on VMS where the logical names are deassigned, thus
58 -- avoiding the pollution of the environment of the caller.
60 Default_Naming
: constant Naming_Id
:= Naming_Table
.First
;
62 Fill_Mapping_File
: Boolean := True;
64 type Project_Flags
is array (Project_Id
range <>) of Boolean;
65 -- A Boolean array type used in Create_Mapping_File to select the projects
66 -- in the closure of a specific project.
68 -----------------------
69 -- Local Subprograms --
70 -----------------------
72 function Body_Path_Name_Of
74 In_Tree
: Project_Tree_Ref
) return String;
75 -- Returns the path name of the body of a unit.
76 -- Compute it first, if necessary.
78 function Spec_Path_Name_Of
80 In_Tree
: Project_Tree_Ref
) return String;
81 -- Returns the path name of the spec of a unit.
82 -- Compute it first, if necessary.
85 (Source_Dirs
: String_List_Id
;
86 In_Tree
: Project_Tree_Ref
);
87 -- Add to Ada_Path_Buffer all the source directories in string list
88 -- Source_Dirs, if any. Increment Ada_Path_Length.
90 procedure Add_To_Path
(Dir
: String);
91 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
92 -- Increment Ada_Path_Length.
93 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
96 procedure Add_To_Source_Path
97 (Source_Dirs
: String_List_Id
; In_Tree
: Project_Tree_Ref
);
98 -- Add to Ada_Path_B all the source directories in string list
99 -- Source_Dirs, if any. Increment Ada_Path_Length.
101 procedure Add_To_Object_Path
102 (Object_Dir
: Path_Name_Type
;
103 In_Tree
: Project_Tree_Ref
);
104 -- Add Object_Dir to object path table. Make sure it is not duplicate
105 -- and it is the last one in the current table.
107 function Contains_ALI_Files
(Dir
: Path_Name_Type
) return Boolean;
108 -- Return True if there is at least one ALI file in the directory Dir
110 procedure Set_Path_File_Var
(Name
: String; Value
: String);
111 -- Call Setenv, after calling To_Host_File_Spec
113 function Ultimate_Extension_Of
114 (Project
: Project_Id
;
115 In_Tree
: Project_Tree_Ref
) return Project_Id
;
116 -- Return a project that is either Project or an extended ancestor of
117 -- Project that itself is not extended.
119 ----------------------
120 -- Ada_Include_Path --
121 ----------------------
123 function Ada_Include_Path
124 (Project
: Project_Id
;
125 In_Tree
: Project_Tree_Ref
) return String_Access
is
127 procedure Add
(Project
: Project_Id
);
128 -- Add all the source directories of a project to the path only if
129 -- this project has not been visited. Calls itself recursively for
130 -- projects being extended, and imported projects. Adds the project
131 -- to the list Seen if this is the call to Add for this project.
137 procedure Add
(Project
: Project_Id
) is
139 -- If Seen is empty, then the project cannot have been visited
141 if not In_Tree
.Projects
.Table
(Project
).Seen
then
142 In_Tree
.Projects
.Table
(Project
).Seen
:= True;
145 Data
: constant Project_Data
:=
146 In_Tree
.Projects
.Table
(Project
);
147 List
: Project_List
:= Data
.Imported_Projects
;
150 -- Add to path all source directories of this project
152 Add_To_Path
(Data
.Source_Dirs
, In_Tree
);
154 -- Call Add to the project being extended, if any
156 if Data
.Extends
/= No_Project
then
160 -- Call Add for each imported project, if any
162 while List
/= Empty_Project_List
loop
164 (In_Tree
.Project_Lists
.Table
(List
).Project
);
165 List
:= In_Tree
.Project_Lists
.Table
(List
).Next
;
171 -- Start of processing for Ada_Include_Path
174 -- If it is the first time we call this function for
175 -- this project, compute the source path
178 In_Tree
.Projects
.Table
(Project
).Ada_Include_Path
= null
180 Ada_Path_Length
:= 0;
182 for Index
in Project_Table
.First
..
183 Project_Table
.Last
(In_Tree
.Projects
)
185 In_Tree
.Projects
.Table
(Index
).Seen
:= False;
189 In_Tree
.Projects
.Table
(Project
).Ada_Include_Path
:=
190 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
193 return In_Tree.Projects.Table (Project).Ada_Include_Path;
194 end Ada_Include_Path;
196 ----------------------
197 -- Ada_Include_Path --
198 ----------------------
200 function Ada_Include_Path
201 (Project : Project_Id;
202 In_Tree : Project_Tree_Ref;
203 Recursive : Boolean) return String
207 return Ada_Include_Path (Project, In_Tree).all;
209 Ada_Path_Length := 0;
211 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
212 return Ada_Path_Buffer (1 .. Ada_Path_Length);
214 end Ada_Include_Path;
216 ----------------------
217 -- Ada_Objects_Path --
218 ----------------------
220 function Ada_Objects_Path
221 (Project : Project_Id;
222 In_Tree : Project_Tree_Ref;
223 Including_Libraries : Boolean := True) return String_Access
225 procedure Add (Project : Project_Id);
226 -- Add all the object directories of a project to the path only if
227 -- this project has not been visited. Calls itself recursively for
228 -- projects being extended, and imported projects. Adds the project
229 -- to the list Seen if this is the first call to Add for this project.
235 procedure Add (Project : Project_Id) is
237 -- If this project has not been seen yet
239 if not In_Tree.Projects.Table (Project).Seen then
240 In_Tree.Projects.Table (Project).Seen := True;
243 Data : constant Project_Data :=
244 In_Tree.Projects.Table (Project);
245 List : Project_List := Data.Imported_Projects;
248 -- Add to path the object directory of this project
249 -- except if we don't include library project and
250 -- this is a library project.
252 if (Data.Library and then Including_Libraries)
254 (Data.Object_Directory /= No_Path
256 (not Including_Libraries or else not Data.Library))
258 -- For a library project, add the library directory,
259 -- if there is no object directory or if it contains ALI
260 -- files; otherwise add the object directory.
263 if Data.Object_Directory = No_Path
265 Contains_ALI_Files (Data.Library_ALI_Dir)
267 Add_To_Path (Get_Name_String (Data.Library_ALI_Dir));
269 Add_To_Path (Get_Name_String (Data.Object_Directory));
273 -- For a non library project, add the object directory
275 Add_To_Path (Get_Name_String (Data.Object_Directory));
279 -- Call Add to the project being extended, if any
281 if Data.Extends /= No_Project then
285 -- Call Add for each imported project, if any
287 while List /= Empty_Project_List loop
289 (In_Tree.Project_Lists.Table (List).Project);
290 List := In_Tree.Project_Lists.Table (List).Next;
297 -- Start of processing for Ada_Objects_Path
300 -- If it is the first time we call this function for
301 -- this project, compute the objects path
304 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
306 Ada_Path_Length := 0;
308 for Index in Project_Table.First ..
309 Project_Table.Last (In_Tree.Projects)
311 In_Tree.Projects.Table (Index).Seen := False;
315 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
316 new String'(Ada_Path_Buffer
(1 .. Ada_Path_Length
));
319 return In_Tree
.Projects
.Table
(Project
).Ada_Objects_Path
;
320 end Ada_Objects_Path
;
322 ------------------------
323 -- Add_To_Object_Path --
324 ------------------------
326 procedure Add_To_Object_Path
327 (Object_Dir
: Path_Name_Type
; In_Tree
: Project_Tree_Ref
)
330 -- Check if the directory is already in the table
332 for Index
in Object_Path_Table
.First
..
333 Object_Path_Table
.Last
(In_Tree
.Private_Part
.Object_Paths
)
336 -- If it is, remove it, and add it as the last one
338 if In_Tree
.Private_Part
.Object_Paths
.Table
(Index
) = Object_Dir
then
339 for Index2
in Index
+ 1 ..
340 Object_Path_Table
.Last
341 (In_Tree
.Private_Part
.Object_Paths
)
343 In_Tree
.Private_Part
.Object_Paths
.Table
(Index2
- 1) :=
344 In_Tree
.Private_Part
.Object_Paths
.Table
(Index2
);
347 In_Tree
.Private_Part
.Object_Paths
.Table
348 (Object_Path_Table
.Last
(In_Tree
.Private_Part
.Object_Paths
)) :=
354 -- The directory is not already in the table, add it
356 Object_Path_Table
.Increment_Last
(In_Tree
.Private_Part
.Object_Paths
);
357 In_Tree
.Private_Part
.Object_Paths
.Table
358 (Object_Path_Table
.Last
(In_Tree
.Private_Part
.Object_Paths
)) :=
360 end Add_To_Object_Path
;
366 procedure Add_To_Path
367 (Source_Dirs
: String_List_Id
;
368 In_Tree
: Project_Tree_Ref
)
370 Current
: String_List_Id
:= Source_Dirs
;
371 Source_Dir
: String_Element
;
373 while Current
/= Nil_String
loop
374 Source_Dir
:= In_Tree
.String_Elements
.Table
(Current
);
375 Add_To_Path
(Get_Name_String
(Source_Dir
.Display_Value
));
376 Current
:= Source_Dir
.Next
;
380 procedure Add_To_Path
(Dir
: String) is
382 New_Buffer
: String_Access
;
385 function Is_Present
(Path
: String; Dir
: String) return Boolean;
386 -- Return True if Dir is part of Path
392 function Is_Present
(Path
: String; Dir
: String) return Boolean is
393 Last
: constant Integer := Path
'Last - Dir
'Length + 1;
396 for J
in Path
'First .. Last
loop
398 -- Note: the order of the conditions below is important, since
399 -- it ensures a minimal number of string comparisons.
402 or else Path
(J
- 1) = Path_Separator
)
404 (J
+ Dir
'Length > Path
'Last
405 or else Path
(J
+ Dir
'Length) = Path_Separator
)
406 and then Dir
= Path
(J
.. J
+ Dir
'Length - 1)
415 -- Start of processing for Add_To_Path
418 if Is_Present
(Ada_Path_Buffer
(1 .. Ada_Path_Length
), Dir
) then
420 -- Dir is already in the path, nothing to do
425 Min_Len
:= Ada_Path_Length
+ Dir
'Length;
427 if Ada_Path_Length
> 0 then
429 -- Add 1 for the Path_Separator character
431 Min_Len
:= Min_Len
+ 1;
434 -- If Ada_Path_Buffer is too small, increase it
436 Len
:= Ada_Path_Buffer
'Last;
438 if Len
< Min_Len
then
441 exit when Len
>= Min_Len
;
444 New_Buffer
:= new String (1 .. Len
);
445 New_Buffer
(1 .. Ada_Path_Length
) :=
446 Ada_Path_Buffer
(1 .. Ada_Path_Length
);
447 Free
(Ada_Path_Buffer
);
448 Ada_Path_Buffer
:= New_Buffer
;
451 if Ada_Path_Length
> 0 then
452 Ada_Path_Length
:= Ada_Path_Length
+ 1;
453 Ada_Path_Buffer
(Ada_Path_Length
) := Path_Separator
;
457 (Ada_Path_Length
+ 1 .. Ada_Path_Length
+ Dir
'Length) := Dir
;
458 Ada_Path_Length
:= Ada_Path_Length
+ Dir
'Length;
461 ------------------------
462 -- Add_To_Source_Path --
463 ------------------------
465 procedure Add_To_Source_Path
466 (Source_Dirs
: String_List_Id
; In_Tree
: Project_Tree_Ref
)
468 Current
: String_List_Id
:= Source_Dirs
;
469 Source_Dir
: String_Element
;
473 -- Add each source directory
475 while Current
/= Nil_String
loop
476 Source_Dir
:= In_Tree
.String_Elements
.Table
(Current
);
479 -- Check if the source directory is already in the table
481 for Index
in Source_Path_Table
.First
..
482 Source_Path_Table
.Last
483 (In_Tree
.Private_Part
.Source_Paths
)
485 -- If it is already, no need to add it
487 if In_Tree
.Private_Part
.Source_Paths
.Table
(Index
) =
496 Source_Path_Table
.Increment_Last
497 (In_Tree
.Private_Part
.Source_Paths
);
498 In_Tree
.Private_Part
.Source_Paths
.Table
499 (Source_Path_Table
.Last
(In_Tree
.Private_Part
.Source_Paths
)) :=
503 -- Next source directory
505 Current
:= Source_Dir
.Next
;
507 end Add_To_Source_Path
;
509 -----------------------
510 -- Body_Path_Name_Of --
511 -----------------------
513 function Body_Path_Name_Of
515 In_Tree
: Project_Tree_Ref
) return String
517 Data
: Unit_Data
:= In_Tree
.Units
.Table
(Unit
);
520 -- If we don't know the path name of the body of this unit,
521 -- we compute it, and we store it.
523 if Data
.File_Names
(Body_Part
).Path
= No_Path
then
525 Current_Source
: String_List_Id
:=
526 In_Tree
.Projects
.Table
527 (Data
.File_Names
(Body_Part
).Project
).Ada_Sources
;
528 Path
: GNAT
.OS_Lib
.String_Access
;
531 -- By default, put the file name
533 Data
.File_Names
(Body_Part
).Path
:=
534 Path_Name_Type
(Data
.File_Names
(Body_Part
).Name
);
536 -- For each source directory
538 while Current_Source
/= Nil_String
loop
541 (Namet
.Get_Name_String
542 (Data
.File_Names
(Body_Part
).Name
),
543 Namet
.Get_Name_String
544 (In_Tree
.String_Elements
.Table
545 (Current_Source
).Value
));
547 -- If the file is in this directory, then we store the path,
551 Name_Len
:= Path
'Length;
552 Name_Buffer
(1 .. Name_Len
) := Path
.all;
553 Data
.File_Names
(Body_Part
).Path
:= Name_Enter
;
558 In_Tree
.String_Elements
.Table
559 (Current_Source
).Next
;
563 In_Tree
.Units
.Table
(Unit
) := Data
;
567 -- Returned the stored value
569 return Namet
.Get_Name_String
(Data
.File_Names
(Body_Part
).Path
);
570 end Body_Path_Name_Of
;
572 ------------------------
573 -- Contains_ALI_Files --
574 ------------------------
576 function Contains_ALI_Files
(Dir
: Path_Name_Type
) return Boolean is
577 Dir_Name
: constant String := Get_Name_String
(Dir
);
579 Name
: String (1 .. 1_000
);
581 Result
: Boolean := False;
584 Open
(Direct
, Dir_Name
);
586 -- For each file in the directory, check if it is an ALI file
589 Read
(Direct
, Name
, Last
);
591 Canonical_Case_File_Name
(Name
(1 .. Last
));
592 Result
:= Last
>= 5 and then Name
(Last
- 3 .. Last
) = ".ali";
600 -- If there is any problem, close the directory if open and return
601 -- True; the library directory will be added to the path.
604 if Is_Open
(Direct
) then
609 end Contains_ALI_Files
;
611 --------------------------------
612 -- Create_Config_Pragmas_File --
613 --------------------------------
615 procedure Create_Config_Pragmas_File
616 (For_Project
: Project_Id
;
617 Main_Project
: Project_Id
;
618 In_Tree
: Project_Tree_Ref
;
619 Include_Config_Files
: Boolean := True)
621 pragma Unreferenced
(Main_Project
);
622 pragma Unreferenced
(Include_Config_Files
);
624 File_Name
: Path_Name_Type
:= No_Path
;
625 File
: File_Descriptor
:= Invalid_FD
;
627 Current_Unit
: Unit_Index
:= Unit_Table
.First
;
629 First_Project
: Project_List
:= Empty_Project_List
;
631 Current_Project
: Project_List
;
632 Current_Naming
: Naming_Id
;
637 procedure Check
(Project
: Project_Id
);
638 -- Recursive procedure that put in the config pragmas file any non
639 -- standard naming schemes, if it is not already in the file, then call
640 -- itself for any imported project.
642 procedure Check_Temp_File
;
643 -- Check that a temporary file has been opened.
644 -- If not, create one, and put its name in the project data,
645 -- with the indication that it is a temporary file.
648 (Unit_Name
: Name_Id
;
649 File_Name
: File_Name_Type
;
650 Unit_Kind
: Spec_Or_Body
;
652 -- Put an SFN pragma in the temporary file
654 procedure Put
(File
: File_Descriptor
; S
: String);
655 procedure Put_Line
(File
: File_Descriptor
; S
: String);
656 -- Output procedures, analogous to normal Text_IO procs of same name
662 procedure Check
(Project
: Project_Id
) is
663 Data
: constant Project_Data
:=
664 In_Tree
.Projects
.Table
(Project
);
667 if Current_Verbosity
= High
then
668 Write_Str
("Checking project file """);
669 Write_Str
(Namet
.Get_Name_String
(Data
.Name
));
674 -- Is this project in the list of the visited project?
676 Current_Project
:= First_Project
;
677 while Current_Project
/= Empty_Project_List
678 and then In_Tree
.Project_Lists
.Table
679 (Current_Project
).Project
/= Project
682 In_Tree
.Project_Lists
.Table
(Current_Project
).Next
;
685 -- If it is not, put it in the list, and visit it
687 if Current_Project
= Empty_Project_List
then
688 Project_List_Table
.Increment_Last
689 (In_Tree
.Project_Lists
);
690 In_Tree
.Project_Lists
.Table
691 (Project_List_Table
.Last
(In_Tree
.Project_Lists
)) :=
692 (Project
=> Project
, Next
=> First_Project
);
694 Project_List_Table
.Last
(In_Tree
.Project_Lists
);
696 -- Is the naming scheme of this project one that we know?
698 Current_Naming
:= Default_Naming
;
699 while Current_Naming
<=
700 Naming_Table
.Last
(In_Tree
.Private_Part
.Namings
)
701 and then not Same_Naming_Scheme
702 (Left
=> In_Tree
.Private_Part
.Namings
.Table
(Current_Naming
),
703 Right
=> Data
.Naming
) loop
704 Current_Naming
:= Current_Naming
+ 1;
707 -- If we don't know it, add it
710 Naming_Table
.Last
(In_Tree
.Private_Part
.Namings
)
712 Naming_Table
.Increment_Last
(In_Tree
.Private_Part
.Namings
);
713 In_Tree
.Private_Part
.Namings
.Table
714 (Naming_Table
.Last
(In_Tree
.Private_Part
.Namings
)) :=
717 -- We need a temporary file to be created
721 -- Put the SFN pragmas for the naming scheme
726 (File
, "pragma Source_File_Name_Project");
728 (File
, " (Spec_File_Name => ""*" &
729 Spec_Suffix_Of
(In_Tree
, "ada", Data
.Naming
) &
732 (File
, " Casing => " &
733 Image
(Data
.Naming
.Casing
) & ",");
735 (File
, " Dot_Replacement => """ &
736 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
742 (File
, "pragma Source_File_Name_Project");
744 (File
, " (Body_File_Name => ""*" &
745 Body_Suffix_Of
(In_Tree
, "ada", Data
.Naming
) &
748 (File
, " Casing => " &
749 Image
(Data
.Naming
.Casing
) & ",");
751 (File
, " Dot_Replacement => """ &
752 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
755 -- and maybe separate
757 if Body_Suffix_Of
(In_Tree
, "ada", Data
.Naming
) /=
758 Get_Name_String
(Data
.Naming
.Separate_Suffix
)
761 (File
, "pragma Source_File_Name_Project");
763 (File
, " (Subunit_File_Name => ""*" &
764 Namet
.Get_Name_String
(Data
.Naming
.Separate_Suffix
) &
767 (File
, " Casing => " &
768 Image
(Data
.Naming
.Casing
) &
771 (File
, " Dot_Replacement => """ &
772 Namet
.Get_Name_String
(Data
.Naming
.Dot_Replacement
) &
777 if Data
.Extends
/= No_Project
then
778 Check
(Data
.Extends
);
782 Current
: Project_List
:= Data
.Imported_Projects
;
785 while Current
/= Empty_Project_List
loop
787 (In_Tree
.Project_Lists
.Table
789 Current
:= In_Tree
.Project_Lists
.Table
796 ---------------------
797 -- Check_Temp_File --
798 ---------------------
800 procedure Check_Temp_File
is
802 if File
= Invalid_FD
then
803 Tempdir
.Create_Temp_File
(File
, Name
=> File_Name
);
805 if File
= Invalid_FD
then
807 ("unable to create temporary configuration pragmas file");
810 Record_Temp_File
(File_Name
);
812 if Opt
.Verbose_Mode
then
813 Write_Str
("Creating temp file """);
814 Write_Str
(Get_Name_String
(File_Name
));
826 (Unit_Name
: Name_Id
;
827 File_Name
: File_Name_Type
;
828 Unit_Kind
: Spec_Or_Body
;
832 -- A temporary file needs to be open
836 -- Put the pragma SFN for the unit kind (spec or body)
838 Put
(File
, "pragma Source_File_Name_Project (");
839 Put
(File
, Namet
.Get_Name_String
(Unit_Name
));
841 if Unit_Kind
= Specification
then
842 Put
(File
, ", Spec_File_Name => """);
844 Put
(File
, ", Body_File_Name => """);
847 Put
(File
, Namet
.Get_Name_String
(File_Name
));
851 Put
(File
, ", Index =>");
852 Put
(File
, Index
'Img);
855 Put_Line
(File
, ");");
858 procedure Put
(File
: File_Descriptor
; S
: String) is
862 Last
:= Write
(File
, S
(S
'First)'Address, S
'Length);
864 if Last
/= S
'Length then
865 Prj
.Com
.Fail
("Disk full");
868 if Current_Verbosity
= High
then
877 procedure Put_Line
(File
: File_Descriptor
; S
: String) is
878 S0
: String (1 .. S
'Length + 1);
882 -- Add an ASCII.LF to the string. As this config file is supposed to
883 -- be used only by the compiler, we don't care about the characters
884 -- for the end of line. In fact we could have put a space, but
885 -- it is more convenient to be able to read gnat.adc during
886 -- development, for which the ASCII.LF is fine.
888 S0
(1 .. S
'Length) := S
;
889 S0
(S0
'Last) := ASCII
.LF
;
890 Last
:= Write
(File
, S0
'Address, S0
'Length);
892 if Last
/= S
'Length + 1 then
893 Prj
.Com
.Fail
("Disk full");
896 if Current_Verbosity
= High
then
901 -- Start of processing for Create_Config_Pragmas_File
905 In_Tree
.Projects
.Table
(For_Project
).Config_Checked
908 -- Remove any memory of processed naming schemes, if any
910 Naming_Table
.Set_Last
(In_Tree
.Private_Part
.Namings
, Default_Naming
);
912 -- Check the naming schemes
916 -- Visit all the units and process those that need an SFN pragma
919 Current_Unit
<= Unit_Table
.Last
(In_Tree
.Units
)
922 Unit
: constant Unit_Data
:=
923 In_Tree
.Units
.Table
(Current_Unit
);
926 if Unit
.File_Names
(Specification
).Needs_Pragma
then
928 Unit
.File_Names
(Specification
).Name
,
930 Unit
.File_Names
(Specification
).Index
);
933 if Unit
.File_Names
(Body_Part
).Needs_Pragma
then
935 Unit
.File_Names
(Body_Part
).Name
,
937 Unit
.File_Names
(Body_Part
).Index
);
940 Current_Unit
:= Current_Unit
+ 1;
944 -- If there are no non standard naming scheme, issue the GNAT
945 -- standard naming scheme. This will tell the compiler that
946 -- a project file is used and will forbid any pragma SFN.
948 if File
= Invalid_FD
then
951 Put_Line
(File
, "pragma Source_File_Name_Project");
952 Put_Line
(File
, " (Spec_File_Name => ""*.ads"",");
953 Put_Line
(File
, " Dot_Replacement => ""-"",");
954 Put_Line
(File
, " Casing => lowercase);");
956 Put_Line
(File
, "pragma Source_File_Name_Project");
957 Put_Line
(File
, " (Body_File_Name => ""*.adb"",");
958 Put_Line
(File
, " Dot_Replacement => ""-"",");
959 Put_Line
(File
, " Casing => lowercase);");
962 -- Close the temporary file
964 GNAT
.OS_Lib
.Close
(File
, Status
);
967 Prj
.Com
.Fail
("disk full");
970 if Opt
.Verbose_Mode
then
971 Write_Str
("Closing configuration file """);
972 Write_Str
(Get_Name_String
(File_Name
));
976 In_Tree
.Projects
.Table
(For_Project
).Config_File_Name
:=
978 In_Tree
.Projects
.Table
(For_Project
).Config_File_Temp
:=
981 In_Tree
.Projects
.Table
(For_Project
).Config_Checked
:=
984 end Create_Config_Pragmas_File
;
990 procedure Create_Mapping
(In_Tree
: Project_Tree_Ref
) is
991 The_Unit_Data
: Unit_Data
;
992 Data
: File_Name_Data
;
997 for Unit
in 1 .. Unit_Table
.Last
(In_Tree
.Units
) loop
998 The_Unit_Data
:= In_Tree
.Units
.Table
(Unit
);
1000 -- Process only if the unit has a valid name
1002 if The_Unit_Data
.Name
/= No_Name
then
1003 Data
:= The_Unit_Data
.File_Names
(Specification
);
1005 -- If there is a spec, put it in the mapping
1007 if Data
.Name
/= No_File
then
1008 if Data
.Path
= Slash
then
1009 Fmap
.Add_Forbidden_File_Name
(Data
.Name
);
1011 Fmap
.Add_To_File_Map
1012 (Unit_Name
=> Unit_Name_Type
(The_Unit_Data
.Name
),
1013 File_Name
=> Data
.Name
,
1014 Path_Name
=> File_Name_Type
(Data
.Path
));
1018 Data
:= The_Unit_Data
.File_Names
(Body_Part
);
1020 -- If there is a body (or subunit) put it in the mapping
1022 if Data
.Name
/= No_File
then
1023 if Data
.Path
= Slash
then
1024 Fmap
.Add_Forbidden_File_Name
(Data
.Name
);
1026 Fmap
.Add_To_File_Map
1027 (Unit_Name
=> Unit_Name_Type
(The_Unit_Data
.Name
),
1028 File_Name
=> Data
.Name
,
1029 Path_Name
=> File_Name_Type
(Data
.Path
));
1036 -------------------------
1037 -- Create_Mapping_File --
1038 -------------------------
1040 procedure Create_Mapping_File
1041 (Project
: Project_Id
;
1042 In_Tree
: Project_Tree_Ref
;
1043 Name
: out Path_Name_Type
)
1045 File
: File_Descriptor
:= Invalid_FD
;
1046 The_Unit_Data
: Unit_Data
;
1047 Data
: File_Name_Data
;
1050 -- For call to Close
1052 Present
: Project_Flags
1053 (No_Project
.. Project_Table
.Last
(In_Tree
.Projects
)) :=
1055 -- For each project in the closure of Project, the corresponding flag
1056 -- will be set to True;
1058 procedure Put_Name_Buffer
;
1059 -- Put the line contained in the Name_Buffer in the mapping file
1061 procedure Put_Data
(Spec
: Boolean);
1062 -- Put the mapping of the spec or body contained in Data in the file
1065 procedure Recursive_Flag
(Prj
: Project_Id
);
1066 -- Set the flags corresponding to Prj, the projects it imports
1067 -- (directly or indirectly) or extends to True. Call itself recursively.
1073 procedure Put_Name_Buffer
is
1077 Name_Len
:= Name_Len
+ 1;
1078 Name_Buffer
(Name_Len
) := ASCII
.LF
;
1079 Last
:= Write
(File
, Name_Buffer
(1)'Address, Name_Len
);
1081 if Last
/= Name_Len
then
1082 Prj
.Com
.Fail
("Disk full");
1084 end Put_Name_Buffer
;
1090 procedure Put_Data
(Spec
: Boolean) is
1092 -- Line with the unit name
1094 Get_Name_String
(The_Unit_Data
.Name
);
1095 Name_Len
:= Name_Len
+ 1;
1096 Name_Buffer
(Name_Len
) := '%';
1097 Name_Len
:= Name_Len
+ 1;
1100 Name_Buffer
(Name_Len
) := 's';
1102 Name_Buffer
(Name_Len
) := 'b';
1107 -- Line with the file name
1109 Get_Name_String
(Data
.Name
);
1112 -- Line with the path name
1114 Get_Name_String
(Data
.Path
);
1119 --------------------
1120 -- Recursive_Flag --
1121 --------------------
1123 procedure Recursive_Flag
(Prj
: Project_Id
) is
1124 Imported
: Project_List
;
1128 -- Nothing to do for non existent project or project that has
1129 -- already been flagged.
1131 if Prj
= No_Project
or else Present
(Prj
) then
1135 -- Flag the current project
1137 Present
(Prj
) := True;
1139 In_Tree
.Projects
.Table
(Prj
).Imported_Projects
;
1141 -- Call itself for each project directly imported
1143 while Imported
/= Empty_Project_List
loop
1145 In_Tree
.Project_Lists
.Table
(Imported
).Project
;
1147 In_Tree
.Project_Lists
.Table
(Imported
).Next
;
1148 Recursive_Flag
(Proj
);
1151 -- Call itself for an eventual project being extended
1153 Recursive_Flag
(In_Tree
.Projects
.Table
(Prj
).Extends
);
1156 -- Start of processing for Create_Mapping_File
1159 -- Flag the necessary projects
1161 Recursive_Flag
(Project
);
1163 -- Create the temporary file
1165 Tempdir
.Create_Temp_File
(File
, Name
=> Name
);
1167 if File
= Invalid_FD
then
1168 Prj
.Com
.Fail
("unable to create temporary mapping file");
1171 Record_Temp_File
(Name
);
1173 if Opt
.Verbose_Mode
then
1174 Write_Str
("Creating temp mapping file """);
1175 Write_Str
(Get_Name_String
(Name
));
1180 if Fill_Mapping_File
then
1182 -- For all units in table Units
1184 for Unit
in 1 .. Unit_Table
.Last
(In_Tree
.Units
) loop
1185 The_Unit_Data
:= In_Tree
.Units
.Table
(Unit
);
1187 -- If the unit has a valid name
1189 if The_Unit_Data
.Name
/= No_Name
then
1190 Data
:= The_Unit_Data
.File_Names
(Specification
);
1192 -- If there is a spec, put it mapping in the file if it is
1193 -- from a project in the closure of Project.
1195 if Data
.Name
/= No_File
and then Present
(Data
.Project
) then
1196 Put_Data
(Spec
=> True);
1199 Data
:= The_Unit_Data
.File_Names
(Body_Part
);
1201 -- If there is a body (or subunit) put its mapping in the file
1202 -- if it is from a project in the closure of Project.
1204 if Data
.Name
/= No_File
and then Present
(Data
.Project
) then
1205 Put_Data
(Spec
=> False);
1212 GNAT
.OS_Lib
.Close
(File
, Status
);
1215 Prj
.Com
.Fail
("disk full");
1217 end Create_Mapping_File
;
1219 procedure Create_Mapping_File
1220 (Project
: Project_Id
;
1222 In_Tree
: Project_Tree_Ref
;
1223 Name
: out Path_Name_Type
)
1225 File
: File_Descriptor
:= Invalid_FD
;
1228 -- For call to Close
1230 Present
: Project_Flags
1231 (No_Project
.. Project_Table
.Last
(In_Tree
.Projects
)) :=
1233 -- For each project in the closure of Project, the corresponding flag
1234 -- will be set to True.
1237 Src_Data
: Source_Data
;
1238 Suffix
: File_Name_Type
;
1240 procedure Put_Name_Buffer
;
1241 -- Put the line contained in the Name_Buffer in the mapping file
1243 procedure Recursive_Flag
(Prj
: Project_Id
);
1244 -- Set the flags corresponding to Prj, the projects it imports
1245 -- (directly or indirectly) or extends to True. Call itself recursively.
1251 procedure Put_Name_Buffer
is
1255 Name_Len
:= Name_Len
+ 1;
1256 Name_Buffer
(Name_Len
) := ASCII
.LF
;
1257 Last
:= Write
(File
, Name_Buffer
(1)'Address, Name_Len
);
1259 if Last
/= Name_Len
then
1260 Prj
.Com
.Fail
("Disk full");
1262 end Put_Name_Buffer
;
1264 --------------------
1265 -- Recursive_Flag --
1266 --------------------
1268 procedure Recursive_Flag
(Prj
: Project_Id
) is
1269 Imported
: Project_List
;
1273 -- Nothing to do for non existent project or project that has already
1276 if Prj
= No_Project
or else Present
(Prj
) then
1280 -- Flag the current project
1282 Present
(Prj
) := True;
1284 In_Tree
.Projects
.Table
(Prj
).Imported_Projects
;
1286 -- Call itself for each project directly imported
1288 while Imported
/= Empty_Project_List
loop
1290 In_Tree
.Project_Lists
.Table
(Imported
).Project
;
1292 In_Tree
.Project_Lists
.Table
(Imported
).Next
;
1293 Recursive_Flag
(Proj
);
1296 -- Call itself for an eventual project being extended
1298 Recursive_Flag
(In_Tree
.Projects
.Table
(Prj
).Extends
);
1301 -- Start of processing for Create_Mapping_File
1304 -- Flag the necessary projects
1306 Recursive_Flag
(Project
);
1308 -- Create the temporary file
1310 Tempdir
.Create_Temp_File
(File
, Name
=> Name
);
1312 if File
= Invalid_FD
then
1313 Prj
.Com
.Fail
("unable to create temporary mapping file");
1316 Record_Temp_File
(Name
);
1318 if Opt
.Verbose_Mode
then
1319 Write_Str
("Creating temp mapping file """);
1320 Write_Str
(Get_Name_String
(Name
));
1325 -- For all source of the Language of all projects in the closure
1327 for Proj
in Present
'Range loop
1328 if Present
(Proj
) then
1329 Source
:= In_Tree
.Projects
.Table
(Proj
).First_Source
;
1331 while Source
/= No_Source
loop
1332 Src_Data
:= In_Tree
.Sources
.Table
(Source
);
1334 if Src_Data
.Language_Name
= Language
and then
1335 (not Src_Data
.Locally_Removed
) and then
1336 Src_Data
.Replaced_By
= No_Source
1338 if Src_Data
.Unit
/= No_Name
then
1339 Get_Name_String
(Src_Data
.Unit
);
1341 if Src_Data
.Kind
= Spec
then
1342 Suffix
:= In_Tree
.Languages_Data
.Table
1343 (Src_Data
.Language
).Config
.Mapping_Spec_Suffix
;
1346 Suffix
:= In_Tree
.Languages_Data
.Table
1347 (Src_Data
.Language
).Config
.Mapping_Body_Suffix
;
1350 if Suffix
/= No_File
then
1351 Add_Str_To_Name_Buffer
(Get_Name_String
(Suffix
));
1357 Get_Name_String
(Src_Data
.File
);
1360 Get_Name_String
(Src_Data
.Path
);
1364 Source
:= Src_Data
.Next_In_Project
;
1369 GNAT
.OS_Lib
.Close
(File
, Status
);
1372 Prj
.Com
.Fail
("disk full");
1374 end Create_Mapping_File
;
1376 --------------------------
1377 -- Create_New_Path_File --
1378 --------------------------
1380 procedure Create_New_Path_File
1381 (In_Tree
: Project_Tree_Ref
;
1382 Path_FD
: out File_Descriptor
;
1383 Path_Name
: out Path_Name_Type
)
1386 Tempdir
.Create_Temp_File
(Path_FD
, Path_Name
);
1388 if Path_Name
/= No_Path
then
1389 Record_Temp_File
(Path_Name
);
1391 -- Record the name, so that the temp path file will be deleted at the
1392 -- end of the program.
1394 Path_File_Table
.Increment_Last
(In_Tree
.Private_Part
.Path_Files
);
1395 In_Tree
.Private_Part
.Path_Files
.Table
1396 (Path_File_Table
.Last
(In_Tree
.Private_Part
.Path_Files
)) :=
1399 end Create_New_Path_File
;
1401 ---------------------------
1402 -- Delete_All_Path_Files --
1403 ---------------------------
1405 procedure Delete_All_Path_Files
(In_Tree
: Project_Tree_Ref
) is
1406 Disregard
: Boolean := True;
1409 for Index
in Path_File_Table
.First
..
1410 Path_File_Table
.Last
(In_Tree
.Private_Part
.Path_Files
)
1412 if In_Tree
.Private_Part
.Path_Files
.Table
(Index
) /= No_Path
then
1415 (In_Tree
.Private_Part
.Path_Files
.Table
(Index
)),
1420 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1421 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1422 -- the empty string. On VMS, this has the effect of deassigning
1423 -- the logical names.
1425 if Ada_Prj_Include_File_Set
then
1426 Setenv
(Project_Include_Path_File
, "");
1427 Ada_Prj_Include_File_Set
:= False;
1430 if Ada_Prj_Objects_File_Set
then
1431 Setenv
(Project_Objects_Path_File
, "");
1432 Ada_Prj_Objects_File_Set
:= False;
1434 end Delete_All_Path_Files
;
1436 ------------------------------------
1437 -- File_Name_Of_Library_Unit_Body --
1438 ------------------------------------
1440 function File_Name_Of_Library_Unit_Body
1442 Project
: Project_Id
;
1443 In_Tree
: Project_Tree_Ref
;
1444 Main_Project_Only
: Boolean := True;
1445 Full_Path
: Boolean := False) return String
1447 The_Project
: Project_Id
:= Project
;
1448 Data
: Project_Data
:=
1449 In_Tree
.Projects
.Table
(Project
);
1450 Original_Name
: String := Name
;
1452 Extended_Spec_Name
: String :=
1454 Spec_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
1455 Extended_Body_Name
: String :=
1457 Body_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
1461 The_Original_Name
: Name_Id
;
1462 The_Spec_Name
: Name_Id
;
1463 The_Body_Name
: Name_Id
;
1466 Canonical_Case_File_Name
(Original_Name
);
1467 Name_Len
:= Original_Name
'Length;
1468 Name_Buffer
(1 .. Name_Len
) := Original_Name
;
1469 The_Original_Name
:= Name_Find
;
1471 Canonical_Case_File_Name
(Extended_Spec_Name
);
1472 Name_Len
:= Extended_Spec_Name
'Length;
1473 Name_Buffer
(1 .. Name_Len
) := Extended_Spec_Name
;
1474 The_Spec_Name
:= Name_Find
;
1476 Canonical_Case_File_Name
(Extended_Body_Name
);
1477 Name_Len
:= Extended_Body_Name
'Length;
1478 Name_Buffer
(1 .. Name_Len
) := Extended_Body_Name
;
1479 The_Body_Name
:= Name_Find
;
1481 if Current_Verbosity
= High
then
1482 Write_Str
("Looking for file name of """);
1486 Write_Str
(" Extended Spec Name = """);
1487 Write_Str
(Extended_Spec_Name
);
1490 Write_Str
(" Extended Body Name = """);
1491 Write_Str
(Extended_Body_Name
);
1496 -- For extending project, search in the extended project if the source
1497 -- is not found. For non extending projects, this loop will be run only
1501 -- Loop through units
1502 -- Should have comment explaining reverse ???
1504 for Current
in reverse Unit_Table
.First
..
1505 Unit_Table
.Last
(In_Tree
.Units
)
1507 Unit
:= In_Tree
.Units
.Table
(Current
);
1511 if not Main_Project_Only
1512 or else Unit
.File_Names
(Body_Part
).Project
= The_Project
1515 Current_Name
: constant File_Name_Type
:=
1516 Unit
.File_Names
(Body_Part
).Name
;
1519 -- Case of a body present
1521 if Current_Name
/= No_File
then
1522 if Current_Verbosity
= High
then
1523 Write_Str
(" Comparing with """);
1524 Write_Str
(Get_Name_String
(Current_Name
));
1529 -- If it has the name of the original name, return the
1532 if Unit
.Name
= The_Original_Name
1534 Current_Name
= File_Name_Type
(The_Original_Name
)
1536 if Current_Verbosity
= High
then
1541 return Get_Name_String
1542 (Unit
.File_Names
(Body_Part
).Path
);
1545 return Get_Name_String
(Current_Name
);
1548 -- If it has the name of the extended body name,
1549 -- return the extended body name
1551 elsif Current_Name
= File_Name_Type
(The_Body_Name
) then
1552 if Current_Verbosity
= High
then
1557 return Get_Name_String
1558 (Unit
.File_Names
(Body_Part
).Path
);
1561 return Extended_Body_Name
;
1565 if Current_Verbosity
= High
then
1566 Write_Line
(" not good");
1575 if not Main_Project_Only
1576 or else Unit
.File_Names
(Specification
).Project
= The_Project
1579 Current_Name
: constant File_Name_Type
:=
1580 Unit
.File_Names
(Specification
).Name
;
1583 -- Case of spec present
1585 if Current_Name
/= No_File
then
1586 if Current_Verbosity
= High
then
1587 Write_Str
(" Comparing with """);
1588 Write_Str
(Get_Name_String
(Current_Name
));
1593 -- If name same as original name, return original name
1595 if Unit
.Name
= The_Original_Name
1597 Current_Name
= File_Name_Type
(The_Original_Name
)
1599 if Current_Verbosity
= High
then
1604 return Get_Name_String
1605 (Unit
.File_Names
(Specification
).Path
);
1607 return Get_Name_String
(Current_Name
);
1610 -- If it has the same name as the extended spec name,
1611 -- return the extended spec name.
1613 elsif Current_Name
= File_Name_Type
(The_Spec_Name
) then
1614 if Current_Verbosity
= High
then
1619 return Get_Name_String
1620 (Unit
.File_Names
(Specification
).Path
);
1622 return Extended_Spec_Name
;
1626 if Current_Verbosity
= High
then
1627 Write_Line
(" not good");
1635 -- If we are not in an extending project, give up
1637 exit when (not Main_Project_Only
) or else Data
.Extends
= No_Project
;
1639 -- Otherwise, look in the project we are extending
1641 The_Project
:= Data
.Extends
;
1642 Data
:= In_Tree
.Projects
.Table
(The_Project
);
1645 -- We don't know this file name, return an empty string
1648 end File_Name_Of_Library_Unit_Body
;
1650 -------------------------
1651 -- For_All_Object_Dirs --
1652 -------------------------
1654 procedure For_All_Object_Dirs
1655 (Project
: Project_Id
;
1656 In_Tree
: Project_Tree_Ref
)
1658 Seen
: Project_List
:= Empty_Project_List
;
1660 procedure Add
(Project
: Project_Id
);
1661 -- Process a project. Remember the processes visited to avoid processing
1662 -- a project twice. Recursively process an eventual extended project,
1663 -- and all imported projects.
1669 procedure Add
(Project
: Project_Id
) is
1670 Data
: constant Project_Data
:=
1671 In_Tree
.Projects
.Table
(Project
);
1672 List
: Project_List
:= Data
.Imported_Projects
;
1675 -- If the list of visited project is empty, then
1676 -- for sure we never visited this project.
1678 if Seen
= Empty_Project_List
then
1679 Project_List_Table
.Increment_Last
(In_Tree
.Project_Lists
);
1680 Seen
:= Project_List_Table
.Last
(In_Tree
.Project_Lists
);
1681 In_Tree
.Project_Lists
.Table
(Seen
) :=
1682 (Project
=> Project
, Next
=> Empty_Project_List
);
1685 -- Check if the project is in the list
1688 Current
: Project_List
:= Seen
;
1692 -- If it is, then there is nothing else to do
1694 if In_Tree
.Project_Lists
.Table
1695 (Current
).Project
= Project
1701 In_Tree
.Project_Lists
.Table
(Current
).Next
=
1704 In_Tree
.Project_Lists
.Table
(Current
).Next
;
1707 -- This project has never been visited, add it
1710 Project_List_Table
.Increment_Last
1711 (In_Tree
.Project_Lists
);
1712 In_Tree
.Project_Lists
.Table
(Current
).Next
:=
1713 Project_List_Table
.Last
(In_Tree
.Project_Lists
);
1714 In_Tree
.Project_Lists
.Table
1715 (Project_List_Table
.Last
1716 (In_Tree
.Project_Lists
)) :=
1717 (Project
=> Project
, Next
=> Empty_Project_List
);
1721 -- If there is an object directory, call Action with its name
1723 if Data
.Object_Directory
/= No_Path
then
1724 Get_Name_String
(Data
.Display_Object_Dir
);
1725 Action
(Name_Buffer
(1 .. Name_Len
));
1728 -- If we are extending a project, visit it
1730 if Data
.Extends
/= No_Project
then
1734 -- And visit all imported projects
1736 while List
/= Empty_Project_List
loop
1737 Add
(In_Tree
.Project_Lists
.Table
(List
).Project
);
1738 List
:= In_Tree
.Project_Lists
.Table
(List
).Next
;
1742 -- Start of processing for For_All_Object_Dirs
1745 -- Visit this project, and its imported projects, recursively
1748 end For_All_Object_Dirs
;
1750 -------------------------
1751 -- For_All_Source_Dirs --
1752 -------------------------
1754 procedure For_All_Source_Dirs
1755 (Project
: Project_Id
;
1756 In_Tree
: Project_Tree_Ref
)
1758 Seen
: Project_List
:= Empty_Project_List
;
1760 procedure Add
(Project
: Project_Id
);
1761 -- Process a project. Remember the processes visited to avoid processing
1762 -- a project twice. Recursively process an eventual extended project,
1763 -- and all imported projects.
1769 procedure Add
(Project
: Project_Id
) is
1770 Data
: constant Project_Data
:=
1771 In_Tree
.Projects
.Table
(Project
);
1772 List
: Project_List
:= Data
.Imported_Projects
;
1775 -- If the list of visited project is empty, then for sure we never
1776 -- visited this project.
1778 if Seen
= Empty_Project_List
then
1779 Project_List_Table
.Increment_Last
1780 (In_Tree
.Project_Lists
);
1781 Seen
:= Project_List_Table
.Last
1782 (In_Tree
.Project_Lists
);
1783 In_Tree
.Project_Lists
.Table
(Seen
) :=
1784 (Project
=> Project
, Next
=> Empty_Project_List
);
1787 -- Check if the project is in the list
1790 Current
: Project_List
:= Seen
;
1794 -- If it is, then there is nothing else to do
1796 if In_Tree
.Project_Lists
.Table
1797 (Current
).Project
= Project
1803 In_Tree
.Project_Lists
.Table
(Current
).Next
=
1806 In_Tree
.Project_Lists
.Table
(Current
).Next
;
1809 -- This project has never been visited, add it to the list
1811 Project_List_Table
.Increment_Last
1812 (In_Tree
.Project_Lists
);
1813 In_Tree
.Project_Lists
.Table
(Current
).Next
:=
1814 Project_List_Table
.Last
(In_Tree
.Project_Lists
);
1815 In_Tree
.Project_Lists
.Table
1816 (Project_List_Table
.Last
1817 (In_Tree
.Project_Lists
)) :=
1818 (Project
=> Project
, Next
=> Empty_Project_List
);
1823 Current
: String_List_Id
:= Data
.Source_Dirs
;
1824 The_String
: String_Element
;
1827 -- If there are Ada sources, call action with the name of every
1828 -- source directory.
1831 In_Tree
.Projects
.Table
(Project
).Ada_Sources
/= Nil_String
1833 while Current
/= Nil_String
loop
1835 In_Tree
.String_Elements
.Table
(Current
);
1836 Action
(Get_Name_String
(The_String
.Display_Value
));
1837 Current
:= The_String
.Next
;
1842 -- If we are extending a project, visit it
1844 if Data
.Extends
/= No_Project
then
1848 -- And visit all imported projects
1850 while List
/= Empty_Project_List
loop
1851 Add
(In_Tree
.Project_Lists
.Table
(List
).Project
);
1852 List
:= In_Tree
.Project_Lists
.Table
(List
).Next
;
1856 -- Start of processing for For_All_Source_Dirs
1859 -- Visit this project, and its imported projects recursively
1862 end For_All_Source_Dirs
;
1868 procedure Get_Reference
1869 (Source_File_Name
: String;
1870 In_Tree
: Project_Tree_Ref
;
1871 Project
: out Project_Id
;
1872 Path
: out Path_Name_Type
)
1875 -- Body below could use some comments ???
1877 if Current_Verbosity
> Default
then
1878 Write_Str
("Getting Reference_Of (""");
1879 Write_Str
(Source_File_Name
);
1880 Write_Str
(""") ... ");
1884 Original_Name
: String := Source_File_Name
;
1888 Canonical_Case_File_Name
(Original_Name
);
1890 for Id
in Unit_Table
.First
..
1891 Unit_Table
.Last
(In_Tree
.Units
)
1893 Unit
:= In_Tree
.Units
.Table
(Id
);
1895 if (Unit
.File_Names
(Specification
).Name
/= No_File
1897 Namet
.Get_Name_String
1898 (Unit
.File_Names
(Specification
).Name
) = Original_Name
)
1899 or else (Unit
.File_Names
(Specification
).Path
/= No_Path
1901 Namet
.Get_Name_String
1902 (Unit
.File_Names
(Specification
).Path
) =
1905 Project
:= Ultimate_Extension_Of
1906 (Project
=> Unit
.File_Names
(Specification
).Project
,
1907 In_Tree
=> In_Tree
);
1908 Path
:= Unit
.File_Names
(Specification
).Display_Path
;
1910 if Current_Verbosity
> Default
then
1911 Write_Str
("Done: Specification.");
1917 elsif (Unit
.File_Names
(Body_Part
).Name
/= No_File
1919 Namet
.Get_Name_String
1920 (Unit
.File_Names
(Body_Part
).Name
) = Original_Name
)
1921 or else (Unit
.File_Names
(Body_Part
).Path
/= No_Path
1922 and then Namet
.Get_Name_String
1923 (Unit
.File_Names
(Body_Part
).Path
) =
1926 Project
:= Ultimate_Extension_Of
1927 (Project
=> Unit
.File_Names
(Body_Part
).Project
,
1928 In_Tree
=> In_Tree
);
1929 Path
:= Unit
.File_Names
(Body_Part
).Display_Path
;
1931 if Current_Verbosity
> Default
then
1932 Write_Str
("Done: Body.");
1941 Project
:= No_Project
;
1944 if Current_Verbosity
> Default
then
1945 Write_Str
("Cannot be found.");
1954 procedure Initialize
is
1956 Fill_Mapping_File
:= True;
1959 ------------------------------------
1960 -- Path_Name_Of_Library_Unit_Body --
1961 ------------------------------------
1963 -- Could use some comments in the body here ???
1965 function Path_Name_Of_Library_Unit_Body
1967 Project
: Project_Id
;
1968 In_Tree
: Project_Tree_Ref
) return String
1970 Data
: constant Project_Data
:=
1971 In_Tree
.Projects
.Table
(Project
);
1972 Original_Name
: String := Name
;
1974 Extended_Spec_Name
: String :=
1976 Spec_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
1977 Extended_Body_Name
: String :=
1979 Body_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
1981 First
: Unit_Index
:= Unit_Table
.First
;
1982 Current
: Unit_Index
;
1986 Canonical_Case_File_Name
(Original_Name
);
1987 Canonical_Case_File_Name
(Extended_Spec_Name
);
1988 Canonical_Case_File_Name
(Extended_Body_Name
);
1990 if Current_Verbosity
= High
then
1991 Write_Str
("Looking for path name of """);
1995 Write_Str
(" Extended Spec Name = """);
1996 Write_Str
(Extended_Spec_Name
);
1999 Write_Str
(" Extended Body Name = """);
2000 Write_Str
(Extended_Body_Name
);
2005 while First
<= Unit_Table
.Last
(In_Tree
.Units
)
2006 and then In_Tree
.Units
.Table
2007 (First
).File_Names
(Body_Part
).Project
/= Project
2013 while Current
<= Unit_Table
.Last
(In_Tree
.Units
) loop
2014 Unit
:= In_Tree
.Units
.Table
(Current
);
2016 if Unit
.File_Names
(Body_Part
).Project
= Project
2017 and then Unit
.File_Names
(Body_Part
).Name
/= No_File
2020 Current_Name
: constant String :=
2021 Namet
.Get_Name_String
(Unit
.File_Names
(Body_Part
).Name
);
2023 if Current_Verbosity
= High
then
2024 Write_Str
(" Comparing with """);
2025 Write_Str
(Current_Name
);
2030 if Current_Name
= Original_Name
then
2031 if Current_Verbosity
= High
then
2035 return Body_Path_Name_Of
(Current
, In_Tree
);
2037 elsif Current_Name
= Extended_Body_Name
then
2038 if Current_Verbosity
= High
then
2042 return Body_Path_Name_Of
(Current
, In_Tree
);
2045 if Current_Verbosity
= High
then
2046 Write_Line
(" not good");
2051 elsif Unit
.File_Names
(Specification
).Name
/= No_File
then
2053 Current_Name
: constant String :=
2054 Namet
.Get_Name_String
2055 (Unit
.File_Names
(Specification
).Name
);
2058 if Current_Verbosity
= High
then
2059 Write_Str
(" Comparing with """);
2060 Write_Str
(Current_Name
);
2065 if Current_Name
= Original_Name
then
2066 if Current_Verbosity
= High
then
2070 return Spec_Path_Name_Of
(Current
, In_Tree
);
2072 elsif Current_Name
= Extended_Spec_Name
then
2073 if Current_Verbosity
= High
then
2077 return Spec_Path_Name_Of
(Current
, In_Tree
);
2080 if Current_Verbosity
= High
then
2081 Write_Line
(" not good");
2086 Current
:= Current
+ 1;
2090 end Path_Name_Of_Library_Unit_Body
;
2096 -- Could use some comments in this body ???
2098 procedure Print_Sources
(In_Tree
: Project_Tree_Ref
) is
2102 Write_Line
("List of Sources:");
2104 for Id
in Unit_Table
.First
..
2105 Unit_Table
.Last
(In_Tree
.Units
)
2107 Unit
:= In_Tree
.Units
.Table
(Id
);
2109 Write_Line
(Namet
.Get_Name_String
(Unit
.Name
));
2111 if Unit
.File_Names
(Specification
).Name
/= No_File
then
2112 if Unit
.File_Names
(Specification
).Project
= No_Project
then
2113 Write_Line
(" No project");
2116 Write_Str
(" Project: ");
2118 (In_Tree
.Projects
.Table
2119 (Unit
.File_Names
(Specification
).Project
).Path_Name
);
2120 Write_Line
(Name_Buffer
(1 .. Name_Len
));
2123 Write_Str
(" spec: ");
2125 (Namet
.Get_Name_String
2126 (Unit
.File_Names
(Specification
).Name
));
2129 if Unit
.File_Names
(Body_Part
).Name
/= No_File
then
2130 if Unit
.File_Names
(Body_Part
).Project
= No_Project
then
2131 Write_Line
(" No project");
2134 Write_Str
(" Project: ");
2136 (In_Tree
.Projects
.Table
2137 (Unit
.File_Names
(Body_Part
).Project
).Path_Name
);
2138 Write_Line
(Name_Buffer
(1 .. Name_Len
));
2141 Write_Str
(" body: ");
2143 (Namet
.Get_Name_String
2144 (Unit
.File_Names
(Body_Part
).Name
));
2148 Write_Line
("end of List of Sources.");
2157 Main_Project
: Project_Id
;
2158 In_Tree
: Project_Tree_Ref
) return Project_Id
2160 Result
: Project_Id
:= No_Project
;
2162 Original_Name
: String := Name
;
2164 Data
: constant Project_Data
:=
2165 In_Tree
.Projects
.Table
(Main_Project
);
2167 Extended_Spec_Name
: String :=
2169 Spec_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
2170 Extended_Body_Name
: String :=
2172 Body_Suffix_Of
(In_Tree
, "ada", Data
.Naming
);
2176 Current_Name
: File_Name_Type
;
2177 The_Original_Name
: File_Name_Type
;
2178 The_Spec_Name
: File_Name_Type
;
2179 The_Body_Name
: File_Name_Type
;
2182 Canonical_Case_File_Name
(Original_Name
);
2183 Name_Len
:= Original_Name
'Length;
2184 Name_Buffer
(1 .. Name_Len
) := Original_Name
;
2185 The_Original_Name
:= Name_Find
;
2187 Canonical_Case_File_Name
(Extended_Spec_Name
);
2188 Name_Len
:= Extended_Spec_Name
'Length;
2189 Name_Buffer
(1 .. Name_Len
) := Extended_Spec_Name
;
2190 The_Spec_Name
:= Name_Find
;
2192 Canonical_Case_File_Name
(Extended_Body_Name
);
2193 Name_Len
:= Extended_Body_Name
'Length;
2194 Name_Buffer
(1 .. Name_Len
) := Extended_Body_Name
;
2195 The_Body_Name
:= Name_Find
;
2197 for Current
in reverse Unit_Table
.First
..
2198 Unit_Table
.Last
(In_Tree
.Units
)
2200 Unit
:= In_Tree
.Units
.Table
(Current
);
2204 Current_Name
:= Unit
.File_Names
(Body_Part
).Name
;
2206 -- Case of a body present
2208 if Current_Name
/= No_File
then
2210 -- If it has the name of the original name or the body name,
2211 -- we have found the project.
2213 if Unit
.Name
= Name_Id
(The_Original_Name
)
2214 or else Current_Name
= The_Original_Name
2215 or else Current_Name
= The_Body_Name
2217 Result
:= Unit
.File_Names
(Body_Part
).Project
;
2224 Current_Name
:= Unit
.File_Names
(Specification
).Name
;
2226 if Current_Name
/= No_File
then
2228 -- If name same as the original name, or the spec name, we have
2229 -- found the project.
2231 if Unit
.Name
= Name_Id
(The_Original_Name
)
2232 or else Current_Name
= The_Original_Name
2233 or else Current_Name
= The_Spec_Name
2235 Result
:= Unit
.File_Names
(Specification
).Project
;
2241 -- Get the ultimate extending project
2243 if Result
/= No_Project
then
2244 while In_Tree
.Projects
.Table
(Result
).Extended_By
/=
2247 Result
:= In_Tree
.Projects
.Table
(Result
).Extended_By
;
2258 procedure Set_Ada_Paths
2259 (Project
: Project_Id
;
2260 In_Tree
: Project_Tree_Ref
;
2261 Including_Libraries
: Boolean)
2263 Source_FD
: File_Descriptor
:= Invalid_FD
;
2264 Object_FD
: File_Descriptor
:= Invalid_FD
;
2266 Process_Source_Dirs
: Boolean := False;
2267 Process_Object_Dirs
: Boolean := False;
2270 -- For calls to Close
2274 procedure Add
(Proj
: Project_Id
);
2275 -- Add all the source/object directories of a project to the path only
2276 -- if this project has not been visited. Calls an internal procedure
2277 -- recursively for projects being extended, and imported projects.
2283 procedure Add
(Proj
: Project_Id
) is
2285 procedure Recursive_Add
(Project
: Project_Id
);
2286 -- Recursive procedure to add the source/object paths of extended/
2287 -- imported projects.
2293 procedure Recursive_Add
(Project
: Project_Id
) is
2295 -- If Seen is False, then the project has not yet been visited
2297 if not In_Tree
.Projects
.Table
(Project
).Seen
then
2298 In_Tree
.Projects
.Table
(Project
).Seen
:= True;
2301 Data
: constant Project_Data
:=
2302 In_Tree
.Projects
.Table
(Project
);
2303 List
: Project_List
:= Data
.Imported_Projects
;
2306 if Process_Source_Dirs
then
2308 -- Add to path all source directories of this project if
2309 -- there are Ada sources.
2311 if In_Tree
.Projects
.Table
(Project
).Ada_Sources
/=
2314 Add_To_Source_Path
(Data
.Source_Dirs
, In_Tree
);
2318 if Process_Object_Dirs
then
2320 -- Add to path the object directory of this project
2321 -- except if we don't include library project and this
2322 -- is a library project.
2324 if (Data
.Library
and then Including_Libraries
)
2326 (Data
.Object_Directory
/= No_Path
2328 (not Including_Libraries
or else not Data
.Library
))
2330 -- For a library project, add the library ALI
2331 -- directory if there is no object directory or
2332 -- if the library ALI directory contains ALI files;
2333 -- otherwise add the object directory.
2335 if Data
.Library
then
2336 if Data
.Object_Directory
= No_Path
2337 or else Contains_ALI_Files
(Data
.Library_ALI_Dir
)
2340 (Data
.Library_ALI_Dir
, In_Tree
);
2343 (Data
.Object_Directory
, In_Tree
);
2346 -- For a non-library project, add the object
2347 -- directory, if it is not a virtual project, and if
2348 -- there are Ada sources or if the project is an
2349 -- extending project. if There Are No Ada sources,
2350 -- adding the object directory could disrupt the order
2351 -- of the object dirs in the path.
2353 elsif not Data
.Virtual
2354 and then There_Are_Ada_Sources
(In_Tree
, Project
)
2357 (Data
.Object_Directory
, In_Tree
);
2362 -- Call Add to the project being extended, if any
2364 if Data
.Extends
/= No_Project
then
2365 Recursive_Add
(Data
.Extends
);
2368 -- Call Add for each imported project, if any
2370 while List
/= Empty_Project_List
loop
2372 (In_Tree
.Project_Lists
.Table
2375 In_Tree
.Project_Lists
.Table
(List
).Next
;
2382 Source_Path_Table
.Set_Last
(In_Tree
.Private_Part
.Source_Paths
, 0);
2383 Object_Path_Table
.Set_Last
(In_Tree
.Private_Part
.Object_Paths
, 0);
2385 for Index
in Project_Table
.First
..
2386 Project_Table
.Last
(In_Tree
.Projects
)
2388 In_Tree
.Projects
.Table
(Index
).Seen
:= False;
2391 Recursive_Add
(Proj
);
2394 -- Start of processing for Set_Ada_Paths
2397 -- If it is the first time we call this procedure for
2398 -- this project, compute the source path and/or the object path.
2400 if In_Tree
.Projects
.Table
(Project
).Include_Path_File
= No_Path
then
2401 Process_Source_Dirs
:= True;
2402 Create_New_Path_File
2403 (In_Tree
, Source_FD
,
2404 In_Tree
.Projects
.Table
(Project
).Include_Path_File
);
2407 -- For the object path, we make a distinction depending on
2408 -- Including_Libraries.
2410 if Including_Libraries
then
2411 if In_Tree
.Projects
.Table
2412 (Project
).Objects_Path_File_With_Libs
= No_Path
2414 Process_Object_Dirs
:= True;
2415 Create_New_Path_File
2416 (In_Tree
, Object_FD
, In_Tree
.Projects
.Table
(Project
).
2417 Objects_Path_File_With_Libs
);
2421 if In_Tree
.Projects
.Table
2422 (Project
).Objects_Path_File_Without_Libs
= No_Path
2424 Process_Object_Dirs
:= True;
2425 Create_New_Path_File
2426 (In_Tree
, Object_FD
, In_Tree
.Projects
.Table
(Project
).
2427 Objects_Path_File_Without_Libs
);
2431 -- If there is something to do, set Seen to False for all projects,
2432 -- then call the recursive procedure Add for Project.
2434 if Process_Source_Dirs
or Process_Object_Dirs
then
2438 -- Write and close any file that has been created
2440 if Source_FD
/= Invalid_FD
then
2441 for Index
in Source_Path_Table
.First
..
2442 Source_Path_Table
.Last
2443 (In_Tree
.Private_Part
.Source_Paths
)
2445 Get_Name_String
(In_Tree
.Private_Part
.Source_Paths
.Table
(Index
));
2446 Name_Len
:= Name_Len
+ 1;
2447 Name_Buffer
(Name_Len
) := ASCII
.LF
;
2448 Len
:= Write
(Source_FD
, Name_Buffer
(1)'Address, Name_Len
);
2450 if Len
/= Name_Len
then
2451 Prj
.Com
.Fail
("disk full");
2455 Close
(Source_FD
, Status
);
2458 Prj
.Com
.Fail
("disk full");
2462 if Object_FD
/= Invalid_FD
then
2463 for Index
in Object_Path_Table
.First
..
2464 Object_Path_Table
.Last
2465 (In_Tree
.Private_Part
.Object_Paths
)
2467 Get_Name_String
(In_Tree
.Private_Part
.Object_Paths
.Table
(Index
));
2468 Name_Len
:= Name_Len
+ 1;
2469 Name_Buffer
(Name_Len
) := ASCII
.LF
;
2470 Len
:= Write
(Object_FD
, Name_Buffer
(1)'Address, Name_Len
);
2472 if Len
/= Name_Len
then
2473 Prj
.Com
.Fail
("disk full");
2477 Close
(Object_FD
, Status
);
2480 Prj
.Com
.Fail
("disk full");
2484 -- Set the env vars, if they need to be changed, and set the
2485 -- corresponding flags.
2487 if Current_Source_Path_File
/=
2488 In_Tree
.Projects
.Table
(Project
).Include_Path_File
2490 Current_Source_Path_File
:=
2491 In_Tree
.Projects
.Table
(Project
).Include_Path_File
;
2493 (Project_Include_Path_File
,
2494 Get_Name_String
(Current_Source_Path_File
));
2495 Ada_Prj_Include_File_Set
:= True;
2498 if Including_Libraries
then
2499 if Current_Object_Path_File
2500 /= In_Tree
.Projects
.Table
2501 (Project
).Objects_Path_File_With_Libs
2503 Current_Object_Path_File
:=
2504 In_Tree
.Projects
.Table
2505 (Project
).Objects_Path_File_With_Libs
;
2507 (Project_Objects_Path_File
,
2508 Get_Name_String
(Current_Object_Path_File
));
2509 Ada_Prj_Objects_File_Set
:= True;
2513 if Current_Object_Path_File
/=
2514 In_Tree
.Projects
.Table
2515 (Project
).Objects_Path_File_Without_Libs
2517 Current_Object_Path_File
:=
2518 In_Tree
.Projects
.Table
2519 (Project
).Objects_Path_File_Without_Libs
;
2521 (Project_Objects_Path_File
,
2522 Get_Name_String
(Current_Object_Path_File
));
2523 Ada_Prj_Objects_File_Set
:= True;
2528 ---------------------------------------------
2529 -- Set_Mapping_File_Initial_State_To_Empty --
2530 ---------------------------------------------
2532 procedure Set_Mapping_File_Initial_State_To_Empty
is
2534 Fill_Mapping_File
:= False;
2535 end Set_Mapping_File_Initial_State_To_Empty
;
2537 -----------------------
2538 -- Set_Path_File_Var --
2539 -----------------------
2541 procedure Set_Path_File_Var
(Name
: String; Value
: String) is
2542 Host_Spec
: String_Access
:= To_Host_File_Spec
(Value
);
2545 if Host_Spec
= null then
2547 ("could not convert file name """, Value
, """ to host spec");
2549 Setenv
(Name
, Host_Spec
.all);
2552 end Set_Path_File_Var
;
2554 -----------------------
2555 -- Spec_Path_Name_Of --
2556 -----------------------
2558 function Spec_Path_Name_Of
2559 (Unit
: Unit_Index
; In_Tree
: Project_Tree_Ref
) return String
2561 Data
: Unit_Data
:= In_Tree
.Units
.Table
(Unit
);
2564 if Data
.File_Names
(Specification
).Path
= No_Path
then
2566 Current_Source
: String_List_Id
:=
2567 In_Tree
.Projects
.Table
2568 (Data
.File_Names
(Specification
).Project
).Ada_Sources
;
2569 Path
: GNAT
.OS_Lib
.String_Access
;
2572 Data
.File_Names
(Specification
).Path
:=
2573 Path_Name_Type
(Data
.File_Names
(Specification
).Name
);
2575 while Current_Source
/= Nil_String
loop
2576 Path
:= Locate_Regular_File
2577 (Namet
.Get_Name_String
2578 (Data
.File_Names
(Specification
).Name
),
2579 Namet
.Get_Name_String
2580 (In_Tree
.String_Elements
.Table
2581 (Current_Source
).Value
));
2583 if Path
/= null then
2584 Name_Len
:= Path
'Length;
2585 Name_Buffer
(1 .. Name_Len
) := Path
.all;
2586 Data
.File_Names
(Specification
).Path
:= Name_Enter
;
2590 In_Tree
.String_Elements
.Table
2591 (Current_Source
).Next
;
2595 In_Tree
.Units
.Table
(Unit
) := Data
;
2599 return Namet
.Get_Name_String
(Data
.File_Names
(Specification
).Path
);
2600 end Spec_Path_Name_Of
;
2602 ---------------------------
2603 -- Ultimate_Extension_Of --
2604 ---------------------------
2606 function Ultimate_Extension_Of
2607 (Project
: Project_Id
;
2608 In_Tree
: Project_Tree_Ref
) return Project_Id
2610 Result
: Project_Id
:= Project
;
2613 while In_Tree
.Projects
.Table
(Result
).Extended_By
/=
2616 Result
:= In_Tree
.Projects
.Table
(Result
).Extended_By
;
2620 end Ultimate_Extension_Of
;