1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2012, 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 ------------------------------------------------------------------------------
26 with Ada
.Containers
.Indefinite_Ordered_Sets
;
28 with Ada
.Unchecked_Deallocation
;
30 with GNAT
.Case_Util
; use GNAT
.Case_Util
;
31 with GNAT
.Regexp
; use GNAT
.Regexp
;
34 with Osint
; use Osint
;
35 with Output
; use Output
;
38 with Snames
; use Snames
;
40 with Targparm
; use Targparm
;
44 package body Prj
.Util
is
46 package Source_Info_Table
is new Table
.Table
47 (Table_Component_Type
=> Source_Info_Iterator
,
48 Table_Index_Type
=> Natural,
51 Table_Increment
=> 100,
52 Table_Name
=> "Makeutl.Source_Info_Table");
54 package Source_Info_Project_HTable
is new GNAT
.HTable
.Simple_HTable
55 (Header_Num
=> Prj
.Header_Num
,
62 procedure Free
is new Ada
.Unchecked_Deallocation
63 (Text_File_Data
, Text_File
);
69 procedure Close
(File
: in out Text_File
) is
75 Prj
.Com
.Fail
("Close attempted on an invalid Text_File");
79 if File
.Buffer_Len
> 0 then
80 Len
:= Write
(File
.FD
, File
.Buffer
'Address, File
.Buffer_Len
);
82 if Len
/= File
.Buffer_Len
then
83 Prj
.Com
.Fail
("Unable to write to an out Text_File");
87 Close
(File
.FD
, Status
);
90 Prj
.Com
.Fail
("Unable to close an out Text_File");
95 -- Close in file, no need to test status, since this is a file that
96 -- we read, and the file was read successfully before we closed it.
108 procedure Create
(File
: out Text_File
; Name
: String) is
109 FD
: File_Descriptor
;
110 File_Name
: String (1 .. Name
'Length + 1);
113 File_Name
(1 .. Name
'Length) := Name
;
114 File_Name
(File_Name
'Last) := ASCII
.NUL
;
115 FD
:= Create_File
(Name
=> File_Name
'Address,
116 Fmode
=> GNAT
.OS_Lib
.Text
);
118 if FD
= Invalid_FD
then
122 File
:= new Text_File_Data
;
124 File
.Out_File
:= True;
125 File
.End_Of_File_Reached
:= True;
134 (This
: in out Name_List_Index
;
135 Shared
: Shared_Project_Tree_Data_Access
)
137 Old_Current
: Name_List_Index
;
138 New_Current
: Name_List_Index
;
141 if This
/= No_Name_List
then
143 Name_List_Table
.Increment_Last
(Shared
.Name_Lists
);
144 New_Current
:= Name_List_Table
.Last
(Shared
.Name_Lists
);
146 Shared
.Name_Lists
.Table
(New_Current
) :=
147 (Shared
.Name_Lists
.Table
(Old_Current
).Name
, No_Name_List
);
150 Old_Current
:= Shared
.Name_Lists
.Table
(Old_Current
).Next
;
151 exit when Old_Current
= No_Name_List
;
152 Shared
.Name_Lists
.Table
(New_Current
).Next
:= New_Current
+ 1;
153 Name_List_Table
.Increment_Last
(Shared
.Name_Lists
);
154 New_Current
:= New_Current
+ 1;
155 Shared
.Name_Lists
.Table
(New_Current
) :=
156 (Shared
.Name_Lists
.Table
(Old_Current
).Name
, No_Name_List
);
165 function End_Of_File
(File
: Text_File
) return Boolean is
168 Prj
.Com
.Fail
("End_Of_File attempted on an invalid Text_File");
171 return File
.End_Of_File_Reached
;
178 function Executable_Of
179 (Project
: Project_Id
;
180 Shared
: Shared_Project_Tree_Data_Access
;
181 Main
: File_Name_Type
;
183 Ada_Main
: Boolean := True;
184 Language
: String := "";
185 Include_Suffix
: Boolean := True) return File_Name_Type
187 pragma Assert
(Project
/= No_Project
);
189 The_Packages
: constant Package_Id
:= Project
.Decl
.Packages
;
191 Builder_Package
: constant Prj
.Package_Id
:=
193 (Name
=> Name_Builder
,
194 In_Packages
=> The_Packages
,
197 Executable
: Variable_Value
:=
199 (Name
=> Name_Id
(Main
),
201 Attribute_Or_Array_Name
=> Name_Executable
,
202 In_Package
=> Builder_Package
,
207 Spec_Suffix
: Name_Id
:= No_Name
;
208 Body_Suffix
: Name_Id
:= No_Name
;
210 Spec_Suffix_Length
: Natural := 0;
211 Body_Suffix_Length
: Natural := 0;
213 procedure Get_Suffixes
214 (B_Suffix
: File_Name_Type
;
215 S_Suffix
: File_Name_Type
);
216 -- Get the non empty suffixes in variables Spec_Suffix and Body_Suffix
218 function Add_Suffix
(File
: File_Name_Type
) return File_Name_Type
;
219 -- Return the name of the executable, based on File, and adding the
220 -- executable suffix if needed
226 procedure Get_Suffixes
227 (B_Suffix
: File_Name_Type
;
228 S_Suffix
: File_Name_Type
)
231 if B_Suffix
/= No_File
then
232 Body_Suffix
:= Name_Id
(B_Suffix
);
233 Body_Suffix_Length
:= Natural (Length_Of_Name
(Body_Suffix
));
236 if S_Suffix
/= No_File
then
237 Spec_Suffix
:= Name_Id
(S_Suffix
);
238 Spec_Suffix_Length
:= Natural (Length_Of_Name
(Spec_Suffix
));
246 function Add_Suffix
(File
: File_Name_Type
) return File_Name_Type
is
247 Saved_EEOT
: constant Name_Id
:= Executable_Extension_On_Target
;
248 Result
: File_Name_Type
;
249 Suffix_From_Project
: Variable_Value
;
251 if Include_Suffix
then
252 if Project
.Config
.Executable_Suffix
/= No_Name
then
253 Executable_Extension_On_Target
:=
254 Project
.Config
.Executable_Suffix
;
257 Result
:= Executable_Name
(File
);
258 Executable_Extension_On_Target
:= Saved_EEOT
;
261 elsif Builder_Package
/= No_Package
then
263 -- If the suffix is specified in the project itself, as opposed to
264 -- the config file, it needs to be taken into account. However,
265 -- when the project was processed, in both cases the suffix was
266 -- stored in Project.Config, so get it from the project again.
268 Suffix_From_Project
:=
270 (Variable_Name
=> Name_Executable_Suffix
,
272 Shared
.Packages
.Table
(Builder_Package
).Decl
.Attributes
,
275 if Suffix_From_Project
/= Nil_Variable_Value
276 and then Suffix_From_Project
.Value
/= No_Name
278 Executable_Extension_On_Target
:= Suffix_From_Project
.Value
;
279 Result
:= Executable_Name
(File
);
280 Executable_Extension_On_Target
:= Saved_EEOT
;
288 -- Start of processing for Executable_Of
292 Lang
:= Get_Language_From_Name
(Project
, "ada");
293 elsif Language
/= "" then
294 Lang
:= Get_Language_From_Name
(Project
, Language
);
299 (B_Suffix
=> Lang
.Config
.Naming_Data
.Body_Suffix
,
300 S_Suffix
=> Lang
.Config
.Naming_Data
.Spec_Suffix
);
303 if Builder_Package
/= No_Package
then
304 if Executable
= Nil_Variable_Value
and then Ada_Main
then
305 Get_Name_String
(Main
);
307 -- Try as index the name minus the implementation suffix or minus
308 -- the specification suffix.
311 Name
: constant String (1 .. Name_Len
) :=
312 Name_Buffer
(1 .. Name_Len
);
313 Last
: Positive := Name_Len
;
315 Truncated
: Boolean := False;
318 if Body_Suffix
/= No_Name
319 and then Last
> Natural (Length_Of_Name
(Body_Suffix
))
320 and then Name
(Last
- Body_Suffix_Length
+ 1 .. Last
) =
321 Get_Name_String
(Body_Suffix
)
324 Last
:= Last
- Body_Suffix_Length
;
327 if Spec_Suffix
/= No_Name
328 and then not Truncated
329 and then Last
> Spec_Suffix_Length
330 and then Name
(Last
- Spec_Suffix_Length
+ 1 .. Last
) =
331 Get_Name_String
(Spec_Suffix
)
334 Last
:= Last
- Spec_Suffix_Length
;
339 Name_Buffer
(1 .. Name_Len
) := Name
(1 .. Last
);
344 Attribute_Or_Array_Name
=> Name_Executable
,
345 In_Package
=> Builder_Package
,
351 -- If we have found an Executable attribute, return its value,
352 -- possibly suffixed by the executable suffix.
354 if Executable
/= Nil_Variable_Value
355 and then Executable
.Value
/= No_Name
356 and then Length_Of_Name
(Executable
.Value
) /= 0
358 return Add_Suffix
(File_Name_Type
(Executable
.Value
));
362 Get_Name_String
(Main
);
364 -- If there is a body suffix or a spec suffix, remove this suffix,
365 -- otherwise remove any suffix ('.' followed by other characters), if
368 if Body_Suffix
/= No_Name
369 and then Name_Len
> Body_Suffix_Length
370 and then Name_Buffer
(Name_Len
- Body_Suffix_Length
+ 1 .. Name_Len
) =
371 Get_Name_String
(Body_Suffix
)
373 -- Found the body termination, remove it
375 Name_Len
:= Name_Len
- Body_Suffix_Length
;
377 elsif Spec_Suffix
/= No_Name
378 and then Name_Len
> Spec_Suffix_Length
380 Name_Buffer
(Name_Len
- Spec_Suffix_Length
+ 1 .. Name_Len
) =
381 Get_Name_String
(Spec_Suffix
)
383 -- Found the spec termination, remove it
385 Name_Len
:= Name_Len
- Spec_Suffix_Length
;
388 -- Remove any suffix, if there is one
390 Get_Name_String
(Strip_Suffix
(Main
));
393 return Add_Suffix
(Name_Find
);
396 ---------------------------
397 -- For_Interface_Sources --
398 ---------------------------
400 procedure For_Interface_Sources
401 (Tree
: Project_Tree_Ref
;
402 Project
: Project_Id
)
405 use type Ada
.Containers
.Count_Type
;
407 package Dep_Names
is new Containers
.Indefinite_Ordered_Sets
(String);
409 function Load_ALI
(Filename
: String) return ALI_Id
;
410 -- Load an ALI file and return its id
416 function Load_ALI
(Filename
: String) return ALI_Id
is
417 Result
: ALI_Id
:= No_ALI_Id
;
418 Text
: Text_Buffer_Ptr
;
419 Lib_File
: File_Name_Type
;
422 if Directories
.Exists
(Filename
) then
424 Add_Str_To_Name_Buffer
(Filename
);
425 Lib_File
:= Name_Find
;
426 Text
:= Osint
.Read_Library_Info
(Lib_File
);
440 -- Local declarations
442 Iter
: Source_Iterator
;
446 First_Unit
: Unit_Id
;
447 Second_Unit
: Unit_Id
;
448 Body_Needed
: Boolean;
449 Deps
: Dep_Names
.Set
;
451 -- Start of processing for For_Interface_Sources
454 if Project
.Qualifier
= Aggregate_Library
then
455 Iter
:= For_Each_Source
(Tree
);
457 Iter
:= For_Each_Source
(Tree
, Project
);
460 -- First look at each spec, check if the body is needed
463 Sid
:= Element
(Iter
);
464 exit when Sid
= No_Source
;
466 -- Skip sources that are removed/excluded and sources not part of
467 -- the interface for standalone libraries.
470 and then not Sid
.Locally_Removed
471 and then (Project
.Standalone_Library
= No
472 or else Sid
.Declared_In_Interfaces
)
476 -- Check ALI for dependencies on body and sep
480 (Get_Name_String
(Get_Object_Directory
(Sid
.Project
, True))
481 & Get_Name_String
(Sid
.Dep_Name
));
483 if ALI
/= No_ALI_Id
then
484 First_Unit
:= ALIs
.Table
(ALI
).First_Unit
;
485 Second_Unit
:= No_Unit_Id
;
488 -- If there is both a spec and a body, check if both needed
490 if Units
.Table
(First_Unit
).Utype
= Is_Body
then
491 Second_Unit
:= ALIs
.Table
(ALI
).Last_Unit
;
493 -- If the body is not needed, then reset First_Unit
495 if not Units
.Table
(Second_Unit
).Body_Needed_For_SAL
then
496 Body_Needed
:= False;
499 elsif Units
.Table
(First_Unit
).Utype
= Is_Spec_Only
then
500 Body_Needed
:= False;
503 -- Handle all the separates, if any
506 if Other_Part
(Sid
) /= null then
507 Deps
.Include
(Get_Name_String
(Other_Part
(Sid
).File
));
510 for Dep
in ALIs
.Table
(ALI
).First_Sdep
..
511 ALIs
.Table
(ALI
).Last_Sdep
513 if Sdep
.Table
(Dep
).Subunit_Name
/= No_Name
then
515 (Get_Name_String
(Sdep
.Table
(Dep
).Sfile
));
525 -- Now handle the bodies and separates if needed
527 if Deps
.Length
/= 0 then
528 Iter
:= For_Each_Source
(Tree
, Project
);
531 Sid
:= Element
(Iter
);
532 exit when Sid
= No_Source
;
535 and then Deps
.Contains
(Get_Name_String
(Sid
.File
))
543 end For_Interface_Sources
;
564 if File
.Cursor
= File
.Buffer_Len
then
568 A
=> File
.Buffer
'Address,
569 N
=> File
.Buffer
'Length);
571 if File
.Buffer_Len
= 0 then
572 File
.End_Of_File_Reached
:= True;
579 File
.Cursor
:= File
.Cursor
+ 1;
583 -- Start of processing for Get_Line
587 Prj
.Com
.Fail
("Get_Line attempted on an invalid Text_File");
589 elsif File
.Out_File
then
590 Prj
.Com
.Fail
("Get_Line attempted on an out file");
593 Last
:= Line
'First - 1;
595 if not File
.End_Of_File_Reached
then
597 C
:= File
.Buffer
(File
.Cursor
);
598 exit when C
= ASCII
.CR
or else C
= ASCII
.LF
;
603 if File
.End_Of_File_Reached
then
607 exit when Last
= Line
'Last;
610 if C
= ASCII
.CR
or else C
= ASCII
.LF
then
613 if File
.End_Of_File_Reached
then
619 and then File
.Buffer
(File
.Cursor
) = ASCII
.LF
631 (Iter
: out Source_Info_Iterator
;
632 For_Project
: Name_Id
)
634 Ind
: constant Natural := Source_Info_Project_HTable
.Get
(For_Project
);
637 Iter
:= (No_Source_Info
, 0);
639 Iter
:= Source_Info_Table
.Table
(Ind
);
647 function Is_Valid
(File
: Text_File
) return Boolean is
656 procedure Next
(Iter
: in out Source_Info_Iterator
) is
658 if Iter
.Next
= 0 then
659 Iter
.Info
:= No_Source_Info
;
662 Iter
:= Source_Info_Table
.Table
(Iter
.Next
);
670 procedure Open
(File
: out Text_File
; Name
: String) is
671 FD
: File_Descriptor
;
672 File_Name
: String (1 .. Name
'Length + 1);
675 File_Name
(1 .. Name
'Length) := Name
;
676 File_Name
(File_Name
'Last) := ASCII
.NUL
;
677 FD
:= Open_Read
(Name
=> File_Name
'Address,
678 Fmode
=> GNAT
.OS_Lib
.Text
);
680 if FD
= Invalid_FD
then
684 File
:= new Text_File_Data
;
688 A
=> File
.Buffer
'Address,
689 N
=> File
.Buffer
'Length);
691 if File
.Buffer_Len
= 0 then
692 File
.End_Of_File_Reached
:= True;
704 (Into_List
: in out Name_List_Index
;
705 From_List
: String_List_Id
;
706 In_Tree
: Project_Tree_Ref
;
707 Lower_Case
: Boolean := False)
709 Shared
: constant Shared_Project_Tree_Data_Access
:= In_Tree
.Shared
;
711 Current_Name
: Name_List_Index
;
712 List
: String_List_Id
;
713 Element
: String_Element
;
714 Last
: Name_List_Index
:=
715 Name_List_Table
.Last
(Shared
.Name_Lists
);
719 Current_Name
:= Into_List
;
720 while Current_Name
/= No_Name_List
721 and then Shared
.Name_Lists
.Table
(Current_Name
).Next
/= No_Name_List
723 Current_Name
:= Shared
.Name_Lists
.Table
(Current_Name
).Next
;
727 while List
/= Nil_String
loop
728 Element
:= Shared
.String_Elements
.Table
(List
);
729 Value
:= Element
.Value
;
732 Get_Name_String
(Value
);
733 To_Lower
(Name_Buffer
(1 .. Name_Len
));
737 Name_List_Table
.Append
738 (Shared
.Name_Lists
, (Name
=> Value
, Next
=> No_Name_List
));
742 if Current_Name
= No_Name_List
then
745 Shared
.Name_Lists
.Table
(Current_Name
).Next
:= Last
;
748 Current_Name
:= Last
;
750 List
:= Element
.Next
;
754 procedure Put
(File
: Text_File
; S
: String) is
758 Prj
.Com
.Fail
("Attempted to write on an invalid Text_File");
760 elsif not File
.Out_File
then
761 Prj
.Com
.Fail
("Attempted to write an in Text_File");
764 if File
.Buffer_Len
+ S
'Length > File
.Buffer
'Last then
766 Len
:= Write
(File
.FD
, File
.Buffer
'Address, File
.Buffer_Len
);
768 if Len
/= File
.Buffer_Len
then
769 Prj
.Com
.Fail
("Failed to write to an out Text_File");
772 File
.Buffer_Len
:= 0;
775 File
.Buffer
(File
.Buffer_Len
+ 1 .. File
.Buffer_Len
+ S
'Length) := S
;
776 File
.Buffer_Len
:= File
.Buffer_Len
+ S
'Length;
783 procedure Put_Line
(File
: Text_File
; Line
: String) is
784 L
: String (1 .. Line
'Length + 1);
786 L
(1 .. Line
'Length) := Line
;
787 L
(L
'Last) := ASCII
.LF
;
791 ---------------------------
792 -- Read_Source_Info_File --
793 ---------------------------
795 procedure Read_Source_Info_File
(Tree
: Project_Tree_Ref
) is
797 Info
: Source_Info_Iterator
;
800 procedure Report_Error
;
806 procedure Report_Error
is
808 Write_Line
("errors in source info file """ &
809 Tree
.Source_Info_File_Name
.all & '"');
810 Tree
.Source_Info_File_Exists
:= False;
814 Source_Info_Project_HTable
.Reset
;
815 Source_Info_Table
.Init
;
817 if Tree
.Source_Info_File_Name
= null then
818 Tree
.Source_Info_File_Exists
:= False;
822 Open
(File
, Tree
.Source_Info_File_Name
.all);
824 if not Is_Valid
(File
) then
825 if Opt
.Verbose_Mode
then
826 Write_Line
("source info file " & Tree
.Source_Info_File_Name
.all &
830 Tree
.Source_Info_File_Exists
:= False;
834 Tree
.Source_Info_File_Exists
:= True;
836 if Opt
.Verbose_Mode
then
837 Write_Line
("Reading source info file " &
838 Tree
.Source_Info_File_Name
.all);
842 while not End_Of_File
(File
) loop
843 Info
:= (new Source_Info_Data
, 0);
844 Source_Info_Table
.Increment_Last
;
847 Get_Line
(File
, Name_Buffer
, Name_Len
);
849 Info
.Info
.Project
:= Proj
;
850 Info
.Next
:= Source_Info_Project_HTable
.Get
(Proj
);
851 Source_Info_Project_HTable
.Set
(Proj
, Source_Info_Table
.Last
);
853 if End_Of_File
(File
) then
859 Get_Line
(File
, Name_Buffer
, Name_Len
);
860 Info
.Info
.Language
:= Name_Find
;
862 if End_Of_File
(File
) then
868 Get_Line
(File
, Name_Buffer
, Name_Len
);
869 Info
.Info
.Kind
:= Source_Kind
'Value (Name_Buffer
(1 .. Name_Len
));
871 if End_Of_File
(File
) then
877 Get_Line
(File
, Name_Buffer
, Name_Len
);
878 Info
.Info
.Display_Path_Name
:= Name_Find
;
879 Info
.Info
.Path_Name
:= Info
.Info
.Display_Path_Name
;
881 if End_Of_File
(File
) then
889 Get_Line
(File
, Name_Buffer
, Name_Len
);
890 exit Option_Loop
when Name_Len
= 0;
892 if Name_Len
<= 2 then
897 if Name_Buffer
(1 .. 2) = "P=" then
898 Name_Buffer
(1 .. Name_Len
- 2) :=
899 Name_Buffer
(3 .. Name_Len
);
900 Name_Len
:= Name_Len
- 2;
901 Info
.Info
.Path_Name
:= Name_Find
;
903 elsif Name_Buffer
(1 .. 2) = "U=" then
904 Name_Buffer
(1 .. Name_Len
- 2) :=
905 Name_Buffer
(3 .. Name_Len
);
906 Name_Len
:= Name_Len
- 2;
907 Info
.Info
.Unit_Name
:= Name_Find
;
909 elsif Name_Buffer
(1 .. 2) = "I=" then
910 Info
.Info
.Index
:= Int
'Value (Name_Buffer
(3 .. Name_Len
));
912 elsif Name_Buffer
(1 .. Name_Len
) = "N=Y" then
913 Info
.Info
.Naming_Exception
:= Yes
;
915 elsif Name_Buffer
(1 .. Name_Len
) = "N=I" then
916 Info
.Info
.Naming_Exception
:= Inherited
;
923 end loop Option_Loop
;
925 Source_Info_Table
.Table
(Source_Info_Table
.Last
) := Info
;
926 end loop Source_Loop
;
934 end Read_Source_Info_File
;
940 function Source_Info_Of
(Iter
: Source_Info_Iterator
) return Source_Info
is
950 (Variable
: Variable_Value
;
951 Default
: String) return String
954 if Variable
.Kind
/= Single
955 or else Variable
.Default
956 or else Variable
.Value
= No_Name
960 return Get_Name_String
(Variable
.Value
);
966 In_Array
: Array_Element_Id
;
967 Shared
: Shared_Project_Tree_Data_Access
) return Name_Id
970 Current
: Array_Element_Id
;
971 Element
: Array_Element
;
972 Real_Index
: Name_Id
:= Index
;
977 if Current
= No_Array_Element
then
981 Element
:= Shared
.Array_Elements
.Table
(Current
);
983 if not Element
.Index_Case_Sensitive
then
984 Get_Name_String
(Index
);
985 To_Lower
(Name_Buffer
(1 .. Name_Len
));
986 Real_Index
:= Name_Find
;
989 while Current
/= No_Array_Element
loop
990 Element
:= Shared
.Array_Elements
.Table
(Current
);
992 if Real_Index
= Element
.Index
then
993 exit when Element
.Value
.Kind
/= Single
;
994 exit when Element
.Value
.Value
= Empty_String
;
995 return Element
.Value
.Value
;
997 Current
:= Element
.Next
;
1006 Src_Index
: Int
:= 0;
1007 In_Array
: Array_Element_Id
;
1008 Shared
: Shared_Project_Tree_Data_Access
;
1009 Force_Lower_Case_Index
: Boolean := False;
1010 Allow_Wildcards
: Boolean := False) return Variable_Value
1012 Current
: Array_Element_Id
;
1013 Element
: Array_Element
;
1014 Real_Index_1
: Name_Id
;
1015 Real_Index_2
: Name_Id
;
1018 Current
:= In_Array
;
1020 if Current
= No_Array_Element
then
1021 return Nil_Variable_Value
;
1024 Element
:= Shared
.Array_Elements
.Table
(Current
);
1026 Real_Index_1
:= Index
;
1028 if not Element
.Index_Case_Sensitive
or else Force_Lower_Case_Index
then
1029 if Index
/= All_Other_Names
then
1030 Get_Name_String
(Index
);
1031 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1032 Real_Index_1
:= Name_Find
;
1036 while Current
/= No_Array_Element
loop
1037 Element
:= Shared
.Array_Elements
.Table
(Current
);
1038 Real_Index_2
:= Element
.Index
;
1040 if not Element
.Index_Case_Sensitive
1041 or else Force_Lower_Case_Index
1043 if Element
.Index
/= All_Other_Names
then
1044 Get_Name_String
(Element
.Index
);
1045 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1046 Real_Index_2
:= Name_Find
;
1050 if Src_Index
= Element
.Src_Index
and then
1051 (Real_Index_1
= Real_Index_2
or else
1052 (Real_Index_2
/= All_Other_Names
and then
1053 Allow_Wildcards
and then
1054 Match
(Get_Name_String
(Real_Index_1
),
1055 Compile
(Get_Name_String
(Real_Index_2
),
1058 return Element
.Value
;
1060 Current
:= Element
.Next
;
1064 return Nil_Variable_Value
;
1070 Attribute_Or_Array_Name
: Name_Id
;
1071 In_Package
: Package_Id
;
1072 Shared
: Shared_Project_Tree_Data_Access
;
1073 Force_Lower_Case_Index
: Boolean := False;
1074 Allow_Wildcards
: Boolean := False) return Variable_Value
1076 The_Array
: Array_Element_Id
;
1077 The_Attribute
: Variable_Value
:= Nil_Variable_Value
;
1080 if In_Package
/= No_Package
then
1082 -- First, look if there is an array element that fits
1086 (Name
=> Attribute_Or_Array_Name
,
1087 In_Arrays
=> Shared
.Packages
.Table
(In_Package
).Decl
.Arrays
,
1093 In_Array
=> The_Array
,
1095 Force_Lower_Case_Index
=> Force_Lower_Case_Index
,
1096 Allow_Wildcards
=> Allow_Wildcards
);
1098 -- If there is no array element, look for a variable
1100 if The_Attribute
= Nil_Variable_Value
then
1103 (Variable_Name
=> Attribute_Or_Array_Name
,
1104 In_Variables
=> Shared
.Packages
.Table
1105 (In_Package
).Decl
.Attributes
,
1110 return The_Attribute
;
1116 In_Arrays
: Array_Id
;
1117 Shared
: Shared_Project_Tree_Data_Access
) return Name_Id
1120 The_Array
: Array_Data
;
1123 Current
:= In_Arrays
;
1124 while Current
/= No_Array
loop
1125 The_Array
:= Shared
.Arrays
.Table
(Current
);
1126 if The_Array
.Name
= In_Array
then
1128 (Index
, In_Array
=> The_Array
.Value
, Shared
=> Shared
);
1130 Current
:= The_Array
.Next
;
1139 In_Arrays
: Array_Id
;
1140 Shared
: Shared_Project_Tree_Data_Access
) return Array_Element_Id
1143 The_Array
: Array_Data
;
1146 Current
:= In_Arrays
;
1147 while Current
/= No_Array
loop
1148 The_Array
:= Shared
.Arrays
.Table
(Current
);
1150 if The_Array
.Name
= Name
then
1151 return The_Array
.Value
;
1153 Current
:= The_Array
.Next
;
1157 return No_Array_Element
;
1162 In_Packages
: Package_Id
;
1163 Shared
: Shared_Project_Tree_Data_Access
) return Package_Id
1165 Current
: Package_Id
;
1166 The_Package
: Package_Element
;
1169 Current
:= In_Packages
;
1170 while Current
/= No_Package
loop
1171 The_Package
:= Shared
.Packages
.Table
(Current
);
1172 exit when The_Package
.Name
/= No_Name
1173 and then The_Package
.Name
= Name
;
1174 Current
:= The_Package
.Next
;
1181 (Variable_Name
: Name_Id
;
1182 In_Variables
: Variable_Id
;
1183 Shared
: Shared_Project_Tree_Data_Access
) return Variable_Value
1185 Current
: Variable_Id
;
1186 The_Variable
: Variable
;
1189 Current
:= In_Variables
;
1190 while Current
/= No_Variable
loop
1191 The_Variable
:= Shared
.Variable_Elements
.Table
(Current
);
1193 if Variable_Name
= The_Variable
.Name
then
1194 return The_Variable
.Value
;
1196 Current
:= The_Variable
.Next
;
1200 return Nil_Variable_Value
;
1203 ----------------------------
1204 -- Write_Source_Info_File --
1205 ----------------------------
1207 procedure Write_Source_Info_File
(Tree
: Project_Tree_Ref
) is
1208 Iter
: Source_Iterator
:= For_Each_Source
(Tree
);
1209 Source
: Prj
.Source_Id
;
1213 if Opt
.Verbose_Mode
then
1214 Write_Line
("Writing new source info file " &
1215 Tree
.Source_Info_File_Name
.all);
1218 Create
(File
, Tree
.Source_Info_File_Name
.all);
1220 if not Is_Valid
(File
) then
1221 Write_Line
("warning: unable to create source info file """ &
1222 Tree
.Source_Info_File_Name
.all & '"');
1227 Source
:= Element
(Iter
);
1228 exit when Source
= No_Source
;
1230 if not Source
.Locally_Removed
and then
1231 Source
.Replaced_By
= No_Source
1235 Put_Line
(File
, Get_Name_String
(Source
.Project
.Name
));
1239 Put_Line
(File
, Get_Name_String
(Source
.Language
.Name
));
1243 Put_Line
(File
, Source
.Kind
'Img);
1245 -- Display path name
1247 Put_Line
(File
, Get_Name_String
(Source
.Path
.Display_Name
));
1253 if Source
.Path
.Name
/= Source
.Path
.Display_Name
then
1255 Put_Line
(File
, Get_Name_String
(Source
.Path
.Name
));
1260 if Source
.Unit
/= No_Unit_Index
then
1262 Put_Line
(File
, Get_Name_String
(Source
.Unit
.Name
));
1265 -- Multi-source index (I=)
1267 if Source
.Index
/= 0 then
1269 Put_Line
(File
, Source
.Index
'Img);
1272 -- Naming exception ("N=T");
1274 if Source
.Naming_Exception
= Yes
then
1275 Put_Line
(File
, "N=Y");
1277 elsif Source
.Naming_Exception
= Inherited
then
1278 Put_Line
(File
, "N=I");
1281 -- Empty line to indicate end of info on this source
1283 Put_Line
(File
, "");
1290 end Write_Source_Info_File
;
1298 Max_Length
: Positive;
1299 Separator
: Character)
1301 First
: Positive := S
'First;
1302 Last
: Natural := S
'Last;
1305 -- Nothing to do for empty strings
1307 if S
'Length > 0 then
1309 -- Start on a new line if current line is already longer than
1312 if Positive (Column
) >= Max_Length
then
1316 -- If length of remainder is longer than Max_Length, we need to
1317 -- cut the remainder in several lines.
1319 while Positive (Column
) + S
'Last - First
> Max_Length
loop
1321 -- Try the maximum length possible
1323 Last
:= First
+ Max_Length
- Positive (Column
);
1325 -- Look for last Separator in the line
1327 while Last
>= First
and then S
(Last
) /= Separator
loop
1331 -- If we do not find a separator, we output the maximum length
1334 if Last
< First
then
1335 Last
:= First
+ Max_Length
- Positive (Column
);
1338 Write_Line
(S
(First
.. Last
));
1340 -- Set the beginning of the new remainder
1345 -- What is left goes to the buffer, without EOL
1347 Write_Str
(S
(First
.. S
'Last));