1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 1998-2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 ------------------------------------------------------------------------------
28 with Ada
.IO_Exceptions
;
29 with Ada
.Strings
.Fixed
;
34 with Unchecked_Deallocation
;
35 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
36 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
39 with Ada
.Strings
.Unbounded
; use Ada
.Strings
.Unbounded
;
41 package body Xr_Tabls
is
43 subtype Line_String
is String (1 .. Hostparm
.Max_Line_Length
);
44 subtype File_Name_String
is String (1 .. Hostparm
.Max_Name_Length
);
46 function Base_File_Name
(File
: String) return String;
47 -- Return the base file name for File (ie not including the directory)
49 function Dir_Name
(File
: String; Base
: String := "") return String;
50 -- Return the directory name of File, or "" if there is no directory part
52 -- This includes the last separator at the end, and always return an
53 -- absolute path name (directories are relative to Base, or the current
54 -- directory if Base is "")
56 Dir_Sep
: Character renames GNAT
.OS_Lib
.Directory_Separator
;
59 Entities
: Entity_Table
;
60 Directories
: Project_File_Ptr
;
61 Default_Match
: Boolean := False;
67 function Add_Declaration
68 (File_Ref
: File_Reference
;
72 Decl_Type
: Character)
73 return Declaration_Reference
75 The_Entities
: Declaration_Reference
:= Entities
.Table
;
76 New_Decl
: Declaration_Reference
;
77 Result
: Compare_Result
;
78 Prev
: Declaration_Reference
:= null;
81 -- Check if the identifier already exists in the table
83 while The_Entities
/= null loop
84 Result
:= Compare
(The_Entities
, File_Ref
, Line
, Column
, Symbol
);
85 exit when Result
= GreaterThan
;
87 if Result
= Equal
then
92 The_Entities
:= The_Entities
.Next
;
95 -- Insert the Declaration in the table
97 New_Decl
:= new Declaration_Record
'
98 (Symbol_Length => Symbol'Length,
100 Decl => (File => File_Ref,
103 Source_Line => Null_Unbounded_String,
105 Decl_Type => Decl_Type,
109 Match => Default_Match or else Match (File_Ref, Line, Column),
114 New_Decl.Next := Entities.Table;
115 Entities.Table := New_Decl;
117 New_Decl.Next := Prev.Next;
118 Prev.Next := New_Decl;
121 if New_Decl.Match then
122 Files.Longest_Name := Natural'Max (File_Ref.File'Length,
135 File_Existed : out Boolean;
136 Ref : out File_Reference;
137 Visited : Boolean := True;
138 Emit_Warning : Boolean := False;
139 Gnatchop_File : String := "";
140 Gnatchop_Offset : Integer := 0)
142 The_Files : File_Reference := Files.Table;
143 Base : constant String := Base_File_Name (File_Name);
144 Dir : constant String := Xr_Tabls.Dir_Name (File_Name);
145 Dir_Acc : String_Access := null;
148 -- Do we have a directory name as well ?
150 Dir_Acc := new String' (Dir
);
153 -- Check if the file already exists in the table
155 while The_Files
/= null loop
157 if The_Files
.File
= File_Name
then
158 File_Existed
:= True;
163 The_Files
:= The_Files
.Next
;
166 Ref
:= new File_Record
'
167 (File_Length => Base'Length,
172 Emit_Warning => Emit_Warning,
173 Gnatchop_File => new String' (Gnatchop_File
),
174 Gnatchop_Offset
=> Gnatchop_Offset
,
175 Next
=> Files
.Table
);
177 File_Existed
:= False;
185 (File
: File_Reference
;
190 File
.Lines
:= new Ref_In_File
'(Line => Line,
200 (Declaration : in out Declaration_Reference;
204 File_Ref : File_Reference)
207 Declaration.Par_Symbol := new Declaration_Record'
208 (Symbol_Length
=> Symbol
'Length,
210 Decl
=> (File
=> File_Ref
,
213 Source_Line
=> Null_Unbounded_String
,
228 procedure Add_Reference
229 (Declaration
: Declaration_Reference
;
230 File_Ref
: File_Reference
;
233 Ref_Type
: Character)
235 procedure Free
is new Unchecked_Deallocation
236 (Reference_Record
, Reference
);
239 Prev
: Reference
:= null;
240 Result
: Compare_Result
;
241 New_Ref
: Reference
:= new Reference_Record
'
245 Source_Line => Null_Unbounded_String,
250 when 'b
' | 'c
' => Ref := Declaration.Body_Ref;
251 when 'r
' | 'i
' => Ref := Declaration.Ref_Ref;
252 when 'm
' => Ref := Declaration.Modif_Ref;
253 when others => return;
256 -- Check if the reference already exists
258 while Ref /= null loop
259 Result := Compare (New_Ref, Ref);
260 exit when Result = LessThan;
262 if Result = Equal then
271 -- Insert it in the list
274 New_Ref.Next := Prev.Next;
275 Prev.Next := New_Ref;
280 New_Ref.Next := Declaration.Body_Ref;
281 Declaration.Body_Ref := New_Ref;
283 New_Ref.Next := Declaration.Ref_Ref;
284 Declaration.Ref_Ref := New_Ref;
286 New_Ref.Next := Declaration.Modif_Ref;
287 Declaration.Modif_Ref := New_Ref;
292 if not Declaration.Match then
293 Declaration.Match := Match (File_Ref, Line, Column);
296 if Declaration.Match then
297 Files.Longest_Name := Natural'Max (File_Ref.File'Length,
306 function ALI_File_Name (Ada_File_Name : String) return String is
307 Index : Natural := Ada.Strings.Fixed.Index
308 (Ada_File_Name, ".", Going => Ada.Strings.Backward);
312 return Ada_File_Name (Ada_File_Name'First .. Index)
315 return Ada_File_Name & ".ali";
323 function Base_File_Name (File : String) return String is
325 for J in reverse File'Range loop
326 if File (J) = '/' or else File (J) = Dir_Sep then
327 return File (J + 1 .. File'Last);
340 return Compare_Result
345 elsif Ref2 = null then
349 if Ref1.File.File < Ref2.File.File then
352 elsif Ref1.File.File = Ref2.File.File then
353 if Ref1.Line < Ref2.Line then
356 elsif Ref1.Line = Ref2.Line then
357 if Ref1.Column < Ref2.Column then
359 elsif Ref1.Column = Ref2.Column then
379 (Decl1 : Declaration_Reference;
380 File2 : File_Reference;
384 return Compare_Result
391 if Decl1.Symbol < Symb2 then
393 elsif Decl1.Symbol > Symb2 then
397 if Decl1.Decl.File.File < Get_File (File2) then
400 elsif Decl1.Decl.File.File = Get_File (File2) then
401 if Decl1.Decl.Line < Line2 then
404 elsif Decl1.Decl.Line = Line2 then
405 if Decl1.Decl.Column < Col2 then
408 elsif Decl1.Decl.Column = Col2 then
424 -------------------------
425 -- Create_Project_File --
426 -------------------------
428 procedure Create_Project_File
431 use Ada.Strings.Unbounded;
433 Obj_Dir : Unbounded_String := Null_Unbounded_String;
434 Src_Dir : Unbounded_String := Null_Unbounded_String;
435 Build_Dir : Unbounded_String;
437 Gnatls_Src_Cache : Unbounded_String;
438 Gnatls_Obj_Cache : Unbounded_String;
442 File_Name : aliased String := Name & ASCII.NUL;
446 -- Read the size of the file
447 F := Open_Read (File_Name'Address, Text);
449 -- Project file not found
450 if F /= Invalid_FD then
451 Len := Positive (File_Length (F));
454 Buffer : String (1 .. Len);
455 Index : Positive := Buffer'First;
458 Len := Read (F, Buffer'Address, Len);
461 -- First, look for Build_Dir, since all the source and object
462 -- path are relative to it.
464 while Index <= Buffer'Last loop
466 -- find the end of line
469 while Last <= Buffer'Last
470 and then Buffer (Last) /= ASCII.LF
471 and then Buffer (Last) /= ASCII.CR
476 if Index <= Buffer'Last - 9
477 and then Buffer (Index .. Index + 9) = "build_dir="
481 and then (Buffer (Index) = ' '
482 or else Buffer (Index) = ASCII.HT)
488 To_Unbounded_String (Buffer (Index .. Last - 1));
489 if Buffer (Last - 1) /= Dir_Sep then
490 Append (Build_Dir, Dir_Sep);
496 -- In case we had a ASCII.CR/ASCII.LF end of line, skip the
499 if Index <= Buffer'Last
500 and then Buffer (Index) = ASCII.LF
506 -- Now parse the source and object paths
508 Index := Buffer'First;
509 while Index <= Buffer'Last loop
511 -- find the end of line
514 while Last <= Buffer'Last
515 and then Buffer (Last) /= ASCII.LF
516 and then Buffer (Last) /= ASCII.CR
521 if Index <= Buffer'Last - 7
522 and then Buffer (Index .. Index + 7) = "src_dir="
525 S : String := Ada.Strings.Fixed.Trim
526 (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both);
528 -- A relative directory ?
529 if S (S'First) /= Dir_Sep then
530 Append (Src_Dir, Build_Dir);
533 if S (S'Last) = Dir_Sep then
534 Append (Src_Dir, S & " ");
536 Append (Src_Dir, S & Dir_Sep & " ");
540 elsif Index <= Buffer'Last - 7
541 and then Buffer (Index .. Index + 7) = "obj_dir="
544 S : String := Ada.Strings.Fixed.Trim
545 (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both);
547 -- A relative directory ?
548 if S (S'First) /= Dir_Sep then
549 Append (Obj_Dir, Build_Dir);
552 if S (S'Last) = Dir_Sep then
553 Append (Obj_Dir, S & " ");
555 Append (Obj_Dir, S & Dir_Sep & " ");
560 -- In case we had a ASCII.CR/ASCII.LF end of line, skip the
564 if Index <= Buffer'Last
565 and then Buffer (Index) = ASCII.LF
573 Parse_Gnatls (Gnatls_Src_Cache, Gnatls_Obj_Cache);
575 Directories := new Project_File'
576 (Src_Dir_Length
=> Length
(Src_Dir
) + Length
(Gnatls_Src_Cache
),
577 Obj_Dir_Length
=> Length
(Obj_Dir
) + Length
(Gnatls_Obj_Cache
),
578 Src_Dir
=> To_String
(Src_Dir
& Gnatls_Src_Cache
),
579 Obj_Dir
=> To_String
(Obj_Dir
& Gnatls_Obj_Cache
),
582 Last_Obj_Dir_Start
=> 0);
583 end Create_Project_File
;
585 ---------------------
586 -- Current_Obj_Dir --
587 ---------------------
589 function Current_Obj_Dir
return String is
591 return Directories
.Obj_Dir
(Directories
.Last_Obj_Dir_Start
592 .. Directories
.Obj_Dir_Index
- 2);
599 function Dir_Name
(File
: String; Base
: String := "") return String is
601 for J
in reverse File
'Range loop
602 if File
(J
) = '/' or else File
(J
) = Dir_Sep
then
604 -- Is this an absolute directory ?
605 if File
(File
'First) = '/'
606 or else File
(File
'First) = Dir_Sep
608 return File
(File
'First .. J
);
610 -- Else do we know the base directory ?
611 elsif Base
/= "" then
612 return Base
& File
(File
'First .. J
);
617 pragma Import
(C
, Max_Path
, "max_path_len");
619 Base2
: Dir_Name_Str
(1 .. Max_Path
);
622 Get_Current_Dir
(Base2
, Last
);
623 return Base2
(Base2
'First .. Last
) & File
(File
'First .. J
);
635 function Find_ALI_File
(Short_Name
: String) return String is
636 use type Ada
.Strings
.Unbounded
.String_Access
;
637 Old_Obj_Dir
: constant Integer := Directories
.Obj_Dir_Index
;
644 Obj_Dir
: String := Next_Obj_Dir
;
646 exit when Obj_Dir
'Length = 0;
647 if GNAT
.IO_Aux
.File_Exists
(Obj_Dir
& Short_Name
) then
648 Directories
.Obj_Dir_Index
:= Old_Obj_Dir
;
654 -- Finally look in the standard directories
656 Directories
.Obj_Dir_Index
:= Old_Obj_Dir
;
660 ----------------------
661 -- Find_Source_File --
662 ----------------------
664 function Find_Source_File
(Short_Name
: String) return String is
665 use type Ada
.Strings
.Unbounded
.String_Access
;
671 Src_Dir
: String := Next_Src_Dir
;
673 exit when Src_Dir
'Length = 0;
675 if GNAT
.IO_Aux
.File_Exists
(Src_Dir
& Short_Name
) then
681 -- Finally look in the standard directories
684 end Find_Source_File
;
690 function First_Body
(Decl
: Declaration_Reference
) return Reference
is
692 return Decl
.Body_Ref
;
695 -----------------------
696 -- First_Declaration --
697 -----------------------
699 function First_Declaration
return Declaration_Reference
is
701 return Entities
.Table
;
702 end First_Declaration
;
708 function First_Modif
(Decl
: Declaration_Reference
) return Reference
is
710 return Decl
.Modif_Ref
;
713 ---------------------
714 -- First_Reference --
715 ---------------------
717 function First_Reference
(Decl
: Declaration_Reference
) return Reference
is
726 function Get_Column
(Decl
: Declaration_Reference
) return String is
728 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Decl
.Decl
.Column
),
732 function Get_Column
(Ref
: Reference
) return String is
734 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Ref
.Column
),
738 ---------------------
739 -- Get_Declaration --
740 ---------------------
742 function Get_Declaration
743 (File_Ref
: File_Reference
;
746 return Declaration_Reference
748 The_Entities
: Declaration_Reference
:= Entities
.Table
;
750 while The_Entities
/= null loop
751 if The_Entities
.Decl
.Line
= Line
752 and then The_Entities
.Decl
.Column
= Column
753 and then The_Entities
.Decl
.File
= File_Ref
757 The_Entities
:= The_Entities
.Next
;
761 return Empty_Declaration
;
764 ----------------------
765 -- Get_Emit_Warning --
766 ----------------------
768 function Get_Emit_Warning
(File
: File_Reference
) return Boolean is
770 return File
.Emit_Warning
;
771 end Get_Emit_Warning
;
778 (Decl
: Declaration_Reference
;
779 With_Dir
: Boolean := False)
783 return Get_File
(Decl
.Decl
.File
, With_Dir
);
788 With_Dir
: Boolean := False)
792 return Get_File
(Ref
.File
, With_Dir
);
796 (File
: File_Reference
;
797 With_Dir
: in Boolean := False;
798 Strip
: Natural := 0)
801 function Internal_Strip
(Full_Name
: String) return String;
802 -- Internal function to process the Strip parameter
808 function Internal_Strip
(Full_Name
: String) return String is
809 Unit_End
, Extension_Start
: Natural;
810 S
: Natural := Strip
;
816 -- Isolate the file extension
818 Extension_Start
:= Full_Name
'Last;
819 while Extension_Start
>= Full_Name
'First
820 and then Full_Name
(Extension_Start
) /= '.'
822 Extension_Start
:= Extension_Start
- 1;
825 -- Strip the right number of subunit_names
827 Unit_End
:= Extension_Start
- 1;
828 while Unit_End
>= Full_Name
'First
831 if Full_Name
(Unit_End
) = '-' then
834 Unit_End
:= Unit_End
- 1;
837 if Unit_End
< Full_Name
'First then
840 return Full_Name
(Full_Name
'First .. Unit_End
)
841 & Full_Name
(Extension_Start
.. Full_Name
'Last);
846 -- If we do not want the full path name
849 return Internal_Strip
(File
.File
);
852 if File
.Dir
= null then
854 if Ada
.Strings
.Fixed
.Tail
(File
.File
, 3) = "ali" then
855 File
.Dir
:= new String'(Find_ALI_File (File.File));
857 File.Dir := new String'(Find_Source_File
(File
.File
));
861 return Internal_Strip
(File
.Dir
.all & File
.File
);
868 function Get_File_Ref
(Ref
: Reference
) return File_Reference
is
873 -----------------------
874 -- Get_Gnatchop_File --
875 -----------------------
877 function Get_Gnatchop_File
878 (File
: File_Reference
; With_Dir
: Boolean := False) return String is
880 if File
.Gnatchop_File
.all = "" then
881 return Get_File
(File
, With_Dir
);
883 return File
.Gnatchop_File
.all;
885 end Get_Gnatchop_File
;
887 -----------------------
888 -- Get_Gnatchop_File --
889 -----------------------
891 function Get_Gnatchop_File
892 (Ref
: Reference
; With_Dir
: Boolean := False) return String is
894 return Get_Gnatchop_File
(Ref
.File
, With_Dir
);
895 end Get_Gnatchop_File
;
897 -----------------------
898 -- Get_Gnatchop_File --
899 -----------------------
901 function Get_Gnatchop_File
902 (Decl
: Declaration_Reference
; With_Dir
: Boolean := False) return String
905 return Get_Gnatchop_File
(Decl
.Decl
.File
, With_Dir
);
906 end Get_Gnatchop_File
;
912 function Get_Line
(Decl
: Declaration_Reference
) return String is
914 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Decl
.Decl
.Line
),
918 function Get_Line
(Ref
: Reference
) return String is
920 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Ref
.Line
),
929 (Decl
: Declaration_Reference
)
930 return Declaration_Reference
is
932 return Decl
.Par_Symbol
;
935 ---------------------
936 -- Get_Source_Line --
937 ---------------------
939 function Get_Source_Line
(Ref
: Reference
) return String is
941 return To_String
(Ref
.Source_Line
);
944 function Get_Source_Line
(Decl
: Declaration_Reference
) return String is
946 return To_String
(Decl
.Decl
.Source_Line
);
953 function Get_Symbol
(Decl
: Declaration_Reference
) return String is
962 function Get_Type
(Decl
: Declaration_Reference
) return Character is
964 return Decl
.Decl_Type
;
967 -----------------------
968 -- Grep_Source_Files --
969 -----------------------
971 procedure Grep_Source_Files
is
972 Decl
: Declaration_Reference
:= First_Declaration
;
975 type Simple_Ref_Access
is access Simple_Ref
;
979 Next
: Simple_Ref_Access
;
981 List
: Simple_Ref_Access
:= null;
982 -- This structure is used to speed up the parsing of Ada sources:
983 -- Every reference found by parsing the .ali files is inserted in this
984 -- list, sorted by filename and line numbers.
985 -- This allows use not to parse a same ada file multiple times
987 procedure Free
is new Unchecked_Deallocation
988 (Simple_Ref
, Simple_Ref_Access
);
989 -- Clear an element of the list
992 -- For each reference in the list, parse the file and find the
995 procedure Insert_In_Order
(Ref
: Reference
);
996 -- Insert a new reference in the list, ordered by line numbers
998 procedure Insert_List_Ref
(First_Ref
: Reference
);
999 -- Process a list of references
1005 procedure Grep_List
is
1006 Line
: String (1 .. 1024);
1008 File
: Ada
.Text_IO
.File_Type
;
1009 Line_Number
: Natural;
1011 Save_List
: Simple_Ref_Access
:= List
;
1012 Current_File
: File_Reference
;
1015 while List
/= null loop
1017 -- Makes sure we can find and read the file
1019 Current_File
:= List
.Ref
.File
;
1023 Ada
.Text_IO
.Open
(File
,
1024 Ada
.Text_IO
.In_File
,
1025 Get_File
(List
.Ref
, True));
1027 -- Read the file and find every relevant lines
1030 and then List
.Ref
.File
= Current_File
1031 and then not Ada
.Text_IO
.End_Of_File
(File
)
1033 Ada
.Text_IO
.Get_Line
(File
, Line
, Last
);
1034 Line_Number
:= Line_Number
+ 1;
1037 and then Line_Number
= List
.Ref
.Line
1040 -- Skip the leading blanks on the line
1043 while Line
(Pos
) = ' '
1044 or else Line
(Pos
) = ASCII
.HT
1049 List
.Ref
.Source_Line
:=
1050 To_Unbounded_String
(Line
(Pos
.. Last
));
1052 -- Find the next element in the list
1059 Ada
.Text_IO
.Close
(File
);
1061 -- If the Current_File was not found, just skip it
1064 when Ada
.IO_Exceptions
.Name_Error
=>
1068 -- If the line or the file were not found
1071 and then List
.Ref
.File
= Current_File
1080 while Save_List
/= null loop
1082 Save_List
:= Save_List
.Next
;
1087 ---------------------
1088 -- Insert_In_Order --
1089 ---------------------
1091 procedure Insert_In_Order
(Ref
: Reference
) is
1092 Iter
: Simple_Ref_Access
:= List
;
1093 Prev
: Simple_Ref_Access
:= null;
1096 while Iter
/= null loop
1098 -- If we have found the file, sort by lines
1100 if Iter
.Ref
.File
= Ref
.File
then
1103 and then Iter
.Ref
.File
= Ref
.File
1105 if Iter
.Ref
.Line
> Ref
.Line
then
1108 List
:= new Simple_Ref
'(Ref, List);
1110 Prev.Next := new Simple_Ref'(Ref
, Iter
);
1120 List
:= new Simple_Ref
'(Ref, List);
1122 Prev.Next := new Simple_Ref'(Ref
, Iter
);
1131 -- The file was not already in the list, insert it
1133 List
:= new Simple_Ref
'(Ref, List);
1134 end Insert_In_Order;
1136 ---------------------
1137 -- Insert_List_Ref --
1138 ---------------------
1140 procedure Insert_List_Ref (First_Ref : Reference) is
1141 Ref : Reference := First_Ref;
1144 while Ref /= Empty_Reference loop
1145 Insert_In_Order (Ref);
1148 end Insert_List_Ref;
1150 -- Start of processing for Grep_Source_Files
1153 while Decl /= Empty_Declaration loop
1154 Insert_In_Order (Decl.Decl'Access);
1155 Insert_List_Ref (First_Body (Decl));
1156 Insert_List_Ref (First_Reference (Decl));
1157 Insert_List_Ref (First_Modif (Decl));
1158 Decl := Next (Decl);
1162 end Grep_Source_Files;
1164 -----------------------
1165 -- Longest_File_Name --
1166 -----------------------
1168 function Longest_File_Name return Natural is
1170 return Files.Longest_Name;
1171 end Longest_File_Name;
1178 (File : File_Reference;
1183 Ref : Ref_In_File_Ptr := File.Lines;
1186 while Ref /= null loop
1187 if (Ref.Line = 0 or else Ref.Line = Line)
1188 and then (Ref.Column = 0 or else Ref.Column = Column)
1203 function Match (Decl : Declaration_Reference) return Boolean is
1212 function Next (Decl : Declaration_Reference) return Declaration_Reference is
1221 function Next (Ref : Reference) return Reference is
1230 function Next_Obj_Dir return String is
1231 First : Integer := Directories.Obj_Dir_Index;
1232 Last : Integer := Directories.Obj_Dir_Index;
1235 if Last > Directories.Obj_Dir_Length then
1236 return String'(1 .. 0 => ' ');
1239 while Directories
.Obj_Dir
(Last
) /= ' ' loop
1243 Directories
.Obj_Dir_Index
:= Last
+ 1;
1244 Directories
.Last_Obj_Dir_Start
:= First
;
1245 return Directories
.Obj_Dir
(First
.. Last
- 1);
1252 function Next_Src_Dir
return String is
1253 First
: Integer := Directories
.Src_Dir_Index
;
1254 Last
: Integer := Directories
.Src_Dir_Index
;
1257 if Last
> Directories
.Src_Dir_Length
then
1258 return String'(1 .. 0 => ' ');
1261 while Directories.Src_Dir (Last) /= ' ' loop
1265 Directories.Src_Dir_Index := Last + 1;
1266 return Directories.Src_Dir (First .. Last - 1);
1269 -------------------------
1270 -- Next_Unvisited_File --
1271 -------------------------
1273 function Next_Unvisited_File return File_Reference is
1274 The_Files : File_Reference := Files.Table;
1277 while The_Files /= null loop
1278 if not The_Files.Visited then
1279 The_Files.Visited := True;
1283 The_Files := The_Files.Next;
1287 end Next_Unvisited_File;
1293 procedure Parse_Gnatls
1294 (Gnatls_Src_Cache : out Ada.Strings.Unbounded.Unbounded_String;
1295 Gnatls_Obj_Cache : out Ada.Strings.Unbounded.Unbounded_String)
1298 Osint.Add_Default_Search_Dirs;
1300 for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1301 if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1302 Ada.Strings.Unbounded.Append (Gnatls_Src_Cache, "./" & ' ');
1304 Ada.Strings.Unbounded.Append
1305 (Gnatls_Src_Cache, Osint.Dir_In_Src_Search_Path (J).all & ' ');
1309 for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1310 if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1311 Ada.Strings.Unbounded.Append (Gnatls_Obj_Cache, "./" & ' ');
1313 Ada.Strings.Unbounded.Append
1314 (Gnatls_Obj_Cache, Osint.Dir_In_Obj_Search_Path (J).all & ' ');
1323 procedure Reset_Obj_Dir is
1325 Directories.Obj_Dir_Index := 1;
1332 procedure Reset_Src_Dir is
1334 Directories.Src_Dir_Index := 1;
1337 -----------------------
1338 -- Set_Default_Match --
1339 -----------------------
1341 procedure Set_Default_Match (Value : Boolean) is
1343 Default_Match := Value;
1344 end Set_Default_Match;
1350 procedure Set_Directory
1351 (File : in File_Reference;
1355 File.Dir := new String'(Dir
);
1362 procedure Set_Unvisited
(File_Ref
: in File_Reference
) is
1363 The_Files
: File_Reference
:= Files
.Table
;
1366 while The_Files
/= null loop
1367 if The_Files
= File_Ref
then
1368 The_Files
.Visited
:= False;
1372 The_Files
:= The_Files
.Next
;