1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1998-2002 Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
27 with Unchecked_Deallocation
;
29 with Ada
.IO_Exceptions
;
30 with Ada
.Strings
.Fixed
;
33 with Ada
.Strings
.Unbounded
; use Ada
.Strings
.Unbounded
;
36 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
37 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
39 package body Xr_Tabls
is
41 function Base_File_Name
(File
: String) return String;
42 -- Return the base file name for File (ie not including the directory)
44 function Dir_Name
(File
: String; Base
: String := "") return String;
45 -- Return the directory name of File, or "" if there is no directory part
47 -- This includes the last separator at the end, and always return an
48 -- absolute path name (directories are relative to Base, or the current
49 -- directory if Base is "")
51 Dir_Sep
: Character renames GNAT
.OS_Lib
.Directory_Separator
;
54 Entities
: Entity_Table
;
55 Directories
: Project_File_Ptr
;
56 Default_Match
: Boolean := False;
62 function Add_Declaration
63 (File_Ref
: File_Reference
;
67 Decl_Type
: Character)
68 return Declaration_Reference
70 The_Entities
: Declaration_Reference
:= Entities
.Table
;
71 New_Decl
: Declaration_Reference
;
72 Result
: Compare_Result
;
73 Prev
: Declaration_Reference
:= null;
76 -- Check if the identifier already exists in the table
78 while The_Entities
/= null loop
79 Result
:= Compare
(The_Entities
, File_Ref
, Line
, Column
, Symbol
);
80 exit when Result
= GreaterThan
;
82 if Result
= Equal
then
87 The_Entities
:= The_Entities
.Next
;
90 -- Insert the Declaration in the table
93 new Declaration_Record
'
94 (Symbol_Length => Symbol'Length,
96 Decl => (File => File_Ref,
99 Source_Line => Null_Unbounded_String,
101 Decl_Type => Decl_Type,
105 Match => Default_Match
106 or else Match (File_Ref, Line, Column),
111 New_Decl.Next := Entities.Table;
112 Entities.Table := New_Decl;
114 New_Decl.Next := Prev.Next;
115 Prev.Next := New_Decl;
118 if New_Decl.Match then
119 Files.Longest_Name := Natural'Max (File_Ref.File'Length,
126 ----------------------
127 -- Add_To_Xref_File --
128 ----------------------
130 procedure Add_To_Xref_File
132 File_Existed : out Boolean;
133 Ref : out File_Reference;
134 Visited : Boolean := True;
135 Emit_Warning : Boolean := False;
136 Gnatchop_File : String := "";
137 Gnatchop_Offset : Integer := 0)
139 The_Files : File_Reference := Files.Table;
140 Base : constant String := Base_File_Name (File_Name);
141 Dir : constant String := Xr_Tabls.Dir_Name (File_Name);
142 Dir_Acc : String_Access := null;
145 -- Do we have a directory name as well?
148 Dir_Acc := new String' (Dir
);
151 -- Check if the file already exists in the table
153 while The_Files
/= null loop
155 if The_Files
.File
= File_Name
then
156 File_Existed
:= True;
161 The_Files
:= The_Files
.Next
;
164 Ref
:= new File_Record
'
165 (File_Length => Base'Length,
170 Emit_Warning => Emit_Warning,
171 Gnatchop_File => new String' (Gnatchop_File
),
172 Gnatchop_Offset
=> Gnatchop_Offset
,
173 Next
=> Files
.Table
);
175 File_Existed
:= False;
176 end Add_To_Xref_File
;
183 (File
: File_Reference
;
188 File
.Lines
:= new Ref_In_File
'(Line => Line,
198 (Declaration : in out Declaration_Reference;
202 File_Ref : File_Reference)
205 Declaration.Par_Symbol := new Declaration_Record'
206 (Symbol_Length
=> Symbol
'Length,
208 Decl
=> (File
=> File_Ref
,
211 Source_Line
=> Null_Unbounded_String
,
226 procedure Add_Reference
227 (Declaration
: Declaration_Reference
;
228 File_Ref
: File_Reference
;
231 Ref_Type
: Character)
233 procedure Free
is new Unchecked_Deallocation
234 (Reference_Record
, Reference
);
237 Prev
: Reference
:= null;
238 Result
: Compare_Result
;
239 New_Ref
: Reference
:= new Reference_Record
'
243 Source_Line => Null_Unbounded_String,
249 Ref := Declaration.Body_Ref;
251 when 'r
' | 'i
' | 'l
' | ' ' | 'x
' =>
252 Ref := Declaration.Ref_Ref;
255 Ref := Declaration.Modif_Ref;
257 when 'e
' | 't
' | 'p
' =>
261 Ada.Text_IO.Put_Line ("Unknown reference type: " & Ref_Type);
265 -- Check if the reference already exists
267 while Ref /= null loop
268 Result := Compare (New_Ref, Ref);
269 exit when Result = LessThan;
271 if Result = Equal then
280 -- Insert it in the list
283 New_Ref.Next := Prev.Next;
284 Prev.Next := New_Ref;
289 New_Ref.Next := Declaration.Body_Ref;
290 Declaration.Body_Ref := New_Ref;
292 when 'r
' | 'i
' | 'l
' | ' ' | 'x
' =>
293 New_Ref.Next := Declaration.Ref_Ref;
294 Declaration.Ref_Ref := New_Ref;
297 New_Ref.Next := Declaration.Modif_Ref;
298 Declaration.Modif_Ref := New_Ref;
305 if not Declaration.Match then
306 Declaration.Match := Match (File_Ref, Line, Column);
309 if Declaration.Match then
310 Files.Longest_Name := Natural'Max (File_Ref.File'Length,
319 function ALI_File_Name (Ada_File_Name : String) return String is
320 Index : Natural := Ada.Strings.Fixed.Index
321 (Ada_File_Name, ".", Going => Ada.Strings.Backward);
325 return Ada_File_Name (Ada_File_Name'First .. Index)
328 return Ada_File_Name & ".ali";
336 function Base_File_Name (File : String) return String is
338 for J in reverse File'Range loop
339 if File (J) = '/' or else File (J) = Dir_Sep then
340 return File (J + 1 .. File'Last);
354 return Compare_Result
359 elsif Ref2 = null then
363 if Ref1.File.File < Ref2.File.File then
366 elsif Ref1.File.File = Ref2.File.File then
367 if Ref1.Line < Ref2.Line then
370 elsif Ref1.Line = Ref2.Line then
371 if Ref1.Column < Ref2.Column then
373 elsif Ref1.Column = Ref2.Column then
393 (Decl1 : Declaration_Reference;
394 File2 : File_Reference;
398 return Compare_Result
405 if Decl1.Symbol < Symb2 then
407 elsif Decl1.Symbol > Symb2 then
411 if Decl1.Decl.File.File < Get_File (File2) then
414 elsif Decl1.Decl.File.File = Get_File (File2) then
415 if Decl1.Decl.Line < Line2 then
418 elsif Decl1.Decl.Line = Line2 then
419 if Decl1.Decl.Column < Col2 then
422 elsif Decl1.Decl.Column = Col2 then
438 -------------------------
439 -- Create_Project_File --
440 -------------------------
442 procedure Create_Project_File
445 use Ada.Strings.Unbounded;
447 Obj_Dir : Unbounded_String := Null_Unbounded_String;
448 Src_Dir : Unbounded_String := Null_Unbounded_String;
449 Build_Dir : Unbounded_String;
451 Gnatls_Src_Cache : Unbounded_String;
452 Gnatls_Obj_Cache : Unbounded_String;
456 File_Name : aliased String := Name & ASCII.NUL;
460 -- Read the size of the file
461 F := Open_Read (File_Name'Address, Text);
463 -- Project file not found
464 if F /= Invalid_FD then
465 Len := Positive (File_Length (F));
468 Buffer : String (1 .. Len);
469 Index : Positive := Buffer'First;
472 Len := Read (F, Buffer'Address, Len);
475 -- First, look for Build_Dir, since all the source and object
476 -- path are relative to it.
478 while Index <= Buffer'Last loop
480 -- find the end of line
483 while Last <= Buffer'Last
484 and then Buffer (Last) /= ASCII.LF
485 and then Buffer (Last) /= ASCII.CR
490 if Index <= Buffer'Last - 9
491 and then Buffer (Index .. Index + 9) = "build_dir="
495 and then (Buffer (Index) = ' '
496 or else Buffer (Index) = ASCII.HT)
502 To_Unbounded_String (Buffer (Index .. Last - 1));
503 if Buffer (Last - 1) /= Dir_Sep then
504 Append (Build_Dir, Dir_Sep);
510 -- In case we had a ASCII.CR/ASCII.LF end of line, skip the
513 if Index <= Buffer'Last
514 and then Buffer (Index) = ASCII.LF
520 -- Now parse the source and object paths
522 Index := Buffer'First;
523 while Index <= Buffer'Last loop
525 -- find the end of line
528 while Last <= Buffer'Last
529 and then Buffer (Last) /= ASCII.LF
530 and then Buffer (Last) /= ASCII.CR
535 if Index <= Buffer'Last - 7
536 and then Buffer (Index .. Index + 7) = "src_dir="
539 S : String := Ada.Strings.Fixed.Trim
540 (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both);
542 -- A relative directory ?
543 if S (S'First) /= Dir_Sep then
544 Append (Src_Dir, Build_Dir);
547 if S (S'Last) = Dir_Sep then
548 Append (Src_Dir, S & " ");
550 Append (Src_Dir, S & Dir_Sep & " ");
554 elsif Index <= Buffer'Last - 7
555 and then Buffer (Index .. Index + 7) = "obj_dir="
558 S : String := Ada.Strings.Fixed.Trim
559 (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both);
561 -- A relative directory ?
562 if S (S'First) /= Dir_Sep then
563 Append (Obj_Dir, Build_Dir);
566 if S (S'Last) = Dir_Sep then
567 Append (Obj_Dir, S & " ");
569 Append (Obj_Dir, S & Dir_Sep & " ");
574 -- In case we had a ASCII.CR/ASCII.LF end of line, skip the
578 if Index <= Buffer'Last
579 and then Buffer (Index) = ASCII.LF
587 Parse_Gnatls (Gnatls_Src_Cache, Gnatls_Obj_Cache);
589 Directories := new Project_File'
590 (Src_Dir_Length
=> Length
(Src_Dir
) + Length
(Gnatls_Src_Cache
),
591 Obj_Dir_Length
=> Length
(Obj_Dir
) + Length
(Gnatls_Obj_Cache
),
592 Src_Dir
=> To_String
(Src_Dir
& Gnatls_Src_Cache
),
593 Obj_Dir
=> To_String
(Obj_Dir
& Gnatls_Obj_Cache
),
596 Last_Obj_Dir_Start
=> 0);
597 end Create_Project_File
;
599 ---------------------
600 -- Current_Obj_Dir --
601 ---------------------
603 function Current_Obj_Dir
return String is
605 return Directories
.Obj_Dir
(Directories
.Last_Obj_Dir_Start
606 .. Directories
.Obj_Dir_Index
- 2);
613 function Dir_Name
(File
: String; Base
: String := "") return String is
615 for J
in reverse File
'Range loop
616 if File
(J
) = '/' or else File
(J
) = Dir_Sep
then
618 -- Is this an absolute directory ?
619 if File
(File
'First) = '/'
620 or else File
(File
'First) = Dir_Sep
622 return File
(File
'First .. J
);
624 -- Else do we know the base directory ?
625 elsif Base
/= "" then
626 return Base
& File
(File
'First .. J
);
631 pragma Import
(C
, Max_Path
, "__gnat_max_path_len");
633 Base2
: Dir_Name_Str
(1 .. Max_Path
);
636 Get_Current_Dir
(Base2
, Last
);
637 return Base2
(Base2
'First .. Last
) & File
(File
'First .. J
);
649 function Find_ALI_File
(Short_Name
: String) return String is
650 use type Ada
.Strings
.Unbounded
.String_Access
;
651 Old_Obj_Dir
: constant Integer := Directories
.Obj_Dir_Index
;
658 Obj_Dir
: String := Next_Obj_Dir
;
660 exit when Obj_Dir
'Length = 0;
661 if GNAT
.IO_Aux
.File_Exists
(Obj_Dir
& Short_Name
) then
662 Directories
.Obj_Dir_Index
:= Old_Obj_Dir
;
668 -- Finally look in the standard directories
670 Directories
.Obj_Dir_Index
:= Old_Obj_Dir
;
674 ----------------------
675 -- Find_Source_File --
676 ----------------------
678 function Find_Source_File
(Short_Name
: String) return String is
679 use type Ada
.Strings
.Unbounded
.String_Access
;
685 Src_Dir
: String := Next_Src_Dir
;
687 exit when Src_Dir
'Length = 0;
689 if GNAT
.IO_Aux
.File_Exists
(Src_Dir
& Short_Name
) then
695 -- Finally look in the standard directories
698 end Find_Source_File
;
704 function First_Body
(Decl
: Declaration_Reference
) return Reference
is
706 return Decl
.Body_Ref
;
709 -----------------------
710 -- First_Declaration --
711 -----------------------
713 function First_Declaration
return Declaration_Reference
is
715 return Entities
.Table
;
716 end First_Declaration
;
722 function First_Modif
(Decl
: Declaration_Reference
) return Reference
is
724 return Decl
.Modif_Ref
;
727 ---------------------
728 -- First_Reference --
729 ---------------------
731 function First_Reference
(Decl
: Declaration_Reference
) return Reference
is
740 function Get_Column
(Decl
: Declaration_Reference
) return String is
742 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Decl
.Decl
.Column
),
746 function Get_Column
(Ref
: Reference
) return String is
748 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Ref
.Column
),
752 ---------------------
753 -- Get_Declaration --
754 ---------------------
756 function Get_Declaration
757 (File_Ref
: File_Reference
;
760 return Declaration_Reference
762 The_Entities
: Declaration_Reference
:= Entities
.Table
;
764 while The_Entities
/= null loop
765 if The_Entities
.Decl
.Line
= Line
766 and then The_Entities
.Decl
.Column
= Column
767 and then The_Entities
.Decl
.File
= File_Ref
771 The_Entities
:= The_Entities
.Next
;
775 return Empty_Declaration
;
778 ----------------------
779 -- Get_Emit_Warning --
780 ----------------------
782 function Get_Emit_Warning
(File
: File_Reference
) return Boolean is
784 return File
.Emit_Warning
;
785 end Get_Emit_Warning
;
792 (Decl
: Declaration_Reference
;
793 With_Dir
: Boolean := False)
797 return Get_File
(Decl
.Decl
.File
, With_Dir
);
802 With_Dir
: Boolean := False)
806 return Get_File
(Ref
.File
, With_Dir
);
810 (File
: File_Reference
;
811 With_Dir
: in Boolean := False;
812 Strip
: Natural := 0)
815 function Internal_Strip
(Full_Name
: String) return String;
816 -- Internal function to process the Strip parameter
822 function Internal_Strip
(Full_Name
: String) return String is
823 Unit_End
, Extension_Start
: Natural;
824 S
: Natural := Strip
;
830 -- Isolate the file extension
832 Extension_Start
:= Full_Name
'Last;
833 while Extension_Start
>= Full_Name
'First
834 and then Full_Name
(Extension_Start
) /= '.'
836 Extension_Start
:= Extension_Start
- 1;
839 -- Strip the right number of subunit_names
841 Unit_End
:= Extension_Start
- 1;
842 while Unit_End
>= Full_Name
'First
845 if Full_Name
(Unit_End
) = '-' then
848 Unit_End
:= Unit_End
- 1;
851 if Unit_End
< Full_Name
'First then
854 return Full_Name
(Full_Name
'First .. Unit_End
)
855 & Full_Name
(Extension_Start
.. Full_Name
'Last);
860 -- If we do not want the full path name
863 return Internal_Strip
(File
.File
);
866 if File
.Dir
= null then
868 if Ada
.Strings
.Fixed
.Tail
(File
.File
, 3) = "ali" then
869 File
.Dir
:= new String'(Find_ALI_File (File.File));
871 File.Dir := new String'(Find_Source_File
(File
.File
));
875 return Internal_Strip
(File
.Dir
.all & File
.File
);
882 function Get_File_Ref
(Ref
: Reference
) return File_Reference
is
887 -----------------------
888 -- Get_Gnatchop_File --
889 -----------------------
891 function Get_Gnatchop_File
892 (File
: File_Reference
; With_Dir
: Boolean := False) return String is
894 if File
.Gnatchop_File
.all = "" then
895 return Get_File
(File
, With_Dir
);
897 return File
.Gnatchop_File
.all;
899 end Get_Gnatchop_File
;
901 -----------------------
902 -- Get_Gnatchop_File --
903 -----------------------
905 function Get_Gnatchop_File
906 (Ref
: Reference
; With_Dir
: Boolean := False) return String is
908 return Get_Gnatchop_File
(Ref
.File
, With_Dir
);
909 end Get_Gnatchop_File
;
911 -----------------------
912 -- Get_Gnatchop_File --
913 -----------------------
915 function Get_Gnatchop_File
916 (Decl
: Declaration_Reference
; With_Dir
: Boolean := False) return String
919 return Get_Gnatchop_File
(Decl
.Decl
.File
, With_Dir
);
920 end Get_Gnatchop_File
;
926 function Get_Line
(Decl
: Declaration_Reference
) return String is
928 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Decl
.Decl
.Line
),
932 function Get_Line
(Ref
: Reference
) return String is
934 return Ada
.Strings
.Fixed
.Trim
(Natural'Image (Ref
.Line
),
943 (Decl
: Declaration_Reference
)
944 return Declaration_Reference
is
946 return Decl
.Par_Symbol
;
949 ---------------------
950 -- Get_Source_Line --
951 ---------------------
953 function Get_Source_Line
(Ref
: Reference
) return String is
955 return To_String
(Ref
.Source_Line
);
958 function Get_Source_Line
(Decl
: Declaration_Reference
) return String is
960 return To_String
(Decl
.Decl
.Source_Line
);
967 function Get_Symbol
(Decl
: Declaration_Reference
) return String is
976 function Get_Type
(Decl
: Declaration_Reference
) return Character is
978 return Decl
.Decl_Type
;
981 -----------------------
982 -- Grep_Source_Files --
983 -----------------------
985 procedure Grep_Source_Files
is
986 Decl
: Declaration_Reference
:= First_Declaration
;
989 type Simple_Ref_Access
is access Simple_Ref
;
990 type Simple_Ref
is record
992 Next
: Simple_Ref_Access
;
994 List
: Simple_Ref_Access
:= null;
995 -- This structure is used to speed up the parsing of Ada sources:
996 -- Every reference found by parsing the .ali files is inserted in this
997 -- list, sorted by filename and line numbers. This allows avoiding
998 -- parsing a same ada file multiple times
1000 procedure Free
is new Unchecked_Deallocation
1001 (Simple_Ref
, Simple_Ref_Access
);
1002 -- Clear an element of the list
1004 procedure Grep_List
;
1005 -- For each reference in the list, parse the file and find the
1008 procedure Insert_In_Order
(Ref
: Reference
);
1009 -- Insert a new reference in the list, ordered by line numbers
1011 procedure Insert_List_Ref
(First_Ref
: Reference
);
1012 -- Process a list of references
1018 procedure Grep_List
is
1019 Line
: String (1 .. 1024);
1021 File
: Ada
.Text_IO
.File_Type
;
1022 Line_Number
: Natural;
1024 Save_List
: Simple_Ref_Access
:= List
;
1025 Current_File
: File_Reference
;
1028 while List
/= null loop
1030 -- Makes sure we can find and read the file
1032 Current_File
:= List
.Ref
.File
;
1036 Ada
.Text_IO
.Open
(File
,
1037 Ada
.Text_IO
.In_File
,
1038 Get_File
(List
.Ref
, True));
1040 -- Read the file and find every relevant lines
1043 and then List
.Ref
.File
= Current_File
1044 and then not Ada
.Text_IO
.End_Of_File
(File
)
1046 Ada
.Text_IO
.Get_Line
(File
, Line
, Last
);
1047 Line_Number
:= Line_Number
+ 1;
1050 and then Line_Number
= List
.Ref
.Line
1053 -- Skip the leading blanks on the line
1056 while Line
(Pos
) = ' '
1057 or else Line
(Pos
) = ASCII
.HT
1062 List
.Ref
.Source_Line
:=
1063 To_Unbounded_String
(Line
(Pos
.. Last
));
1065 -- Find the next element in the list
1072 Ada
.Text_IO
.Close
(File
);
1074 -- If the Current_File was not found, just skip it
1077 when Ada
.IO_Exceptions
.Name_Error
=>
1081 -- If the line or the file were not found
1084 and then List
.Ref
.File
= Current_File
1093 while Save_List
/= null loop
1095 Save_List
:= Save_List
.Next
;
1100 ---------------------
1101 -- Insert_In_Order --
1102 ---------------------
1104 procedure Insert_In_Order
(Ref
: Reference
) is
1105 Iter
: Simple_Ref_Access
:= List
;
1106 Prev
: Simple_Ref_Access
:= null;
1109 while Iter
/= null loop
1111 -- If we have found the file, sort by lines
1113 if Iter
.Ref
.File
= Ref
.File
then
1116 and then Iter
.Ref
.File
= Ref
.File
1118 if Iter
.Ref
.Line
> Ref
.Line
then
1121 List
:= new Simple_Ref
'(Ref, List);
1123 Prev.Next := new Simple_Ref'(Ref
, Iter
);
1133 List
:= new Simple_Ref
'(Ref, List);
1135 Prev.Next := new Simple_Ref'(Ref
, Iter
);
1145 -- The file was not already in the list, insert it
1147 List
:= new Simple_Ref
'(Ref, List);
1148 end Insert_In_Order;
1150 ---------------------
1151 -- Insert_List_Ref --
1152 ---------------------
1154 procedure Insert_List_Ref (First_Ref : Reference) is
1155 Ref : Reference := First_Ref;
1158 while Ref /= Empty_Reference loop
1159 Insert_In_Order (Ref);
1162 end Insert_List_Ref;
1164 -- Start of processing for Grep_Source_Files
1167 while Decl /= Empty_Declaration loop
1168 Insert_In_Order (Decl.Decl'Access);
1169 Insert_List_Ref (First_Body (Decl));
1170 Insert_List_Ref (First_Reference (Decl));
1171 Insert_List_Ref (First_Modif (Decl));
1172 Decl := Next (Decl);
1176 end Grep_Source_Files;
1178 -----------------------
1179 -- Longest_File_Name --
1180 -----------------------
1182 function Longest_File_Name return Natural is
1184 return Files.Longest_Name;
1185 end Longest_File_Name;
1192 (File : File_Reference;
1197 Ref : Ref_In_File_Ptr := File.Lines;
1200 while Ref /= null loop
1201 if (Ref.Line = 0 or else Ref.Line = Line)
1202 and then (Ref.Column = 0 or else Ref.Column = Column)
1217 function Match (Decl : Declaration_Reference) return Boolean is
1226 function Next (Decl : Declaration_Reference) return Declaration_Reference is
1235 function Next (Ref : Reference) return Reference is
1244 function Next_Obj_Dir return String is
1245 First : Integer := Directories.Obj_Dir_Index;
1246 Last : Integer := Directories.Obj_Dir_Index;
1249 if Last > Directories.Obj_Dir_Length then
1250 return String'(1 .. 0 => ' ');
1253 while Directories
.Obj_Dir
(Last
) /= ' ' loop
1257 Directories
.Obj_Dir_Index
:= Last
+ 1;
1258 Directories
.Last_Obj_Dir_Start
:= First
;
1259 return Directories
.Obj_Dir
(First
.. Last
- 1);
1266 function Next_Src_Dir
return String is
1267 First
: Integer := Directories
.Src_Dir_Index
;
1268 Last
: Integer := Directories
.Src_Dir_Index
;
1271 if Last
> Directories
.Src_Dir_Length
then
1272 return String'(1 .. 0 => ' ');
1275 while Directories.Src_Dir (Last) /= ' ' loop
1279 Directories.Src_Dir_Index := Last + 1;
1280 return Directories.Src_Dir (First .. Last - 1);
1283 -------------------------
1284 -- Next_Unvisited_File --
1285 -------------------------
1287 function Next_Unvisited_File return File_Reference is
1288 The_Files : File_Reference := Files.Table;
1291 while The_Files /= null loop
1292 if not The_Files.Visited then
1293 The_Files.Visited := True;
1297 The_Files := The_Files.Next;
1301 end Next_Unvisited_File;
1307 procedure Parse_Gnatls
1308 (Gnatls_Src_Cache : out Ada.Strings.Unbounded.Unbounded_String;
1309 Gnatls_Obj_Cache : out Ada.Strings.Unbounded.Unbounded_String)
1312 Osint.Add_Default_Search_Dirs;
1314 for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1315 if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1316 Ada.Strings.Unbounded.Append (Gnatls_Src_Cache, "./" & ' ');
1318 Ada.Strings.Unbounded.Append
1319 (Gnatls_Src_Cache, Osint.Dir_In_Src_Search_Path (J).all & ' ');
1323 for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1324 if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1325 Ada.Strings.Unbounded.Append (Gnatls_Obj_Cache, "./" & ' ');
1327 Ada.Strings.Unbounded.Append
1328 (Gnatls_Obj_Cache, Osint.Dir_In_Obj_Search_Path (J).all & ' ');
1337 procedure Reset_Obj_Dir is
1339 Directories.Obj_Dir_Index := 1;
1346 procedure Reset_Src_Dir is
1348 Directories.Src_Dir_Index := 1;
1351 -----------------------
1352 -- Set_Default_Match --
1353 -----------------------
1355 procedure Set_Default_Match (Value : Boolean) is
1357 Default_Match := Value;
1358 end Set_Default_Match;
1364 procedure Set_Directory
1365 (File : in File_Reference;
1369 File.Dir := new String'(Dir
);
1376 procedure Set_Unvisited
(File_Ref
: in File_Reference
) is
1377 The_Files
: File_Reference
:= Files
.Table
;
1380 while The_Files
/= null loop
1381 if The_Files
= File_Ref
then
1382 The_Files
.Visited
:= False;
1386 The_Files
:= The_Files
.Next
;