1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . D I R E C T O R I E S --
9 -- Copyright (C) 2004-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 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, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Ada
.Calendar
; use Ada
.Calendar
;
35 with Ada
.Calendar
.Formatting
; use Ada
.Calendar
.Formatting
;
36 with Ada
.Directories
.Validity
; use Ada
.Directories
.Validity
;
37 with Ada
.Strings
.Maps
;
38 with Ada
.Strings
.Fixed
;
39 with Ada
.Strings
.Unbounded
; use Ada
.Strings
.Unbounded
;
40 with Ada
.Unchecked_Conversion
;
41 with Ada
.Unchecked_Deallocation
;
42 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
44 with System
.CRTL
; use System
.CRTL
;
45 with System
.OS_Lib
; use System
.OS_Lib
;
46 with System
.Regexp
; use System
.Regexp
;
50 package body Ada
.Directories
is
52 Filename_Max
: constant Integer := 1024;
53 -- 1024 is the value of FILENAME_MAX in stdio.h
55 type Dir_Type_Value
is new System
.Address
;
56 -- This is the low-level address directory structure as returned by the C
59 No_Dir
: constant Dir_Type_Value
:= Dir_Type_Value
(System
.Null_Address
);
61 Dir_Separator
: constant Character;
62 pragma Import
(C
, Dir_Separator
, "__gnat_dir_separator");
63 -- Running system default directory separator
65 Dir_Seps
: constant Ada
.Strings
.Maps
.Character_Set
:=
66 Ada
.Strings
.Maps
.To_Set
("/\");
67 -- UNIX and DOS style directory separators
70 pragma Import (C, Max_Path, "__gnat_max_path_len
");
71 -- The maximum length of a path
73 type Search_Data is record
74 Is_Valid : Boolean := False;
75 Name : Ada.Strings.Unbounded.Unbounded_String;
78 Dir : Dir_Type_Value := No_Dir;
79 Entry_Fetched : Boolean := False;
80 Dir_Entry : Directory_Entry_Type;
82 -- The current state of a search
84 Empty_String : constant String := (1 .. 0 => ASCII.NUL);
85 -- Empty string, returned by function Extension when there is no extension
87 procedure Free is new Ada.Unchecked_Deallocation (Search_Data, Search_Ptr);
89 procedure Close (Dir : Dir_Type_Value);
91 function File_Exists (Name : String) return Boolean;
92 -- Returns True if the named file exists
94 procedure Fetch_Next_Entry (Search : Search_Type);
95 -- Get the next entry in a directory, setting Entry_Fetched if successful
96 -- or resetting Is_Valid if not.
98 procedure To_Lower_If_Case_Insensitive (S : in out String);
99 -- Put S in lower case if file and path names are case-insensitive
105 function Base_Name (Name : String) return String is
106 Simple : String := Simple_Name (Name);
107 -- Simple'First is guaranteed to be 1
110 To_Lower_If_Case_Insensitive (Simple);
112 -- Look for the last dot in the file name and return the part of the
113 -- file name preceding this last dot. If the first dot is the first
114 -- character of the file name, the base name is the empty string.
116 for Pos in reverse Simple'Range loop
117 if Simple (Pos) = '.' then
118 return Simple (1 .. Pos - 1);
122 -- If there is no dot, return the complete file name
131 procedure Close (Dir : Dir_Type_Value) is
133 pragma Warnings (Off, Discard);
135 function closedir (directory : DIRs) return Integer;
136 pragma Import (C, closedir, "__gnat_closedir
");
139 Discard := closedir (DIRs (Dir));
147 (Containing_Directory : String := "";
149 Extension : String := "") return String
151 Result : String (1 .. Containing_Directory'Length +
152 Name'Length + Extension'Length + 2);
156 -- First, deal with the invalid cases
158 if Containing_Directory /= ""
159 and then not Is_Valid_Path_Name (Containing_Directory)
164 Extension'Length = 0 and then (not Is_Valid_Simple_Name (Name))
168 elsif Extension'Length /= 0
169 and then not Is_Valid_Simple_Name (Name & '.' & Extension)
173 -- This is not an invalid case so build the path name
176 Last := Containing_Directory'Length;
177 Result (1 .. Last) := Containing_Directory;
179 -- Add a directory separator if needed
181 if Last /= 0 and then Result (Last) /= Dir_Separator then
183 Result (Last) := Dir_Separator;
188 Result (Last + 1 .. Last + Name'Length) := Name;
189 Last := Last + Name'Length;
191 -- If extension was specified, add dot followed by this extension
193 if Extension'Length /= 0 then
195 Result (Last) := '.';
196 Result (Last + 1 .. Last + Extension'Length) := Extension;
197 Last := Last + Extension'Length;
200 To_Lower_If_Case_Insensitive (Result (1 .. Last));
201 return Result (1 .. Last);
205 --------------------------
206 -- Containing_Directory --
207 --------------------------
209 function Containing_Directory (Name : String) return String is
211 -- First, the invalid case
213 if not Is_Valid_Path_Name (Name) then
218 Norm : constant String := Normalize_Pathname (Name);
219 Last_DS : constant Natural :=
221 (Name, Dir_Seps, Going => Strings.Backward);
226 -- There is no directory separator, returns current working
229 return Current_Directory;
231 -- If Name indicates a root directory, raise Use_Error, because
232 -- it has no containing directory.
241 and then Norm
(Norm
'Last - 1 .. Norm
'Last) = ":\"
242 and then (Norm (Norm'First) in 'a' .. 'z'
243 or else Norm (Norm'First) in 'A' .. 'Z'))))
249 Last : Positive := Last_DS - Name'First + 1;
250 Result : String (1 .. Last);
253 Result := Name (Name'First .. Last_DS);
255 -- Remove any trailing directory separator, except as the
256 -- first character or the first character following a drive
257 -- number on Windows.
263 Result (Last) /= Directory_Separator;
267 and then Result (2) = ':'
269 (Result (1) in 'A' .. 'Z'
271 Result (1) in 'a' .. 'z');
276 -- Special case of current directory, identified by "."
278 if Last = 1 and then Result (1) = '.' then
279 return Current_Directory;
281 -- Special case of "..": the current directory may be a root
284 elsif Last = 2 and then Result (1 .. 2) = ".." then
285 return Containing_Directory (Current_Directory);
288 To_Lower_If_Case_Insensitive (Result (1 .. Last));
289 return Result (1 .. Last);
295 end Containing_Directory;
302 (Source_Name : String;
303 Target_Name : String;
306 pragma Unreferenced (Form);
310 -- First, the invalid cases
312 if not Is_Valid_Path_Name (Source_Name)
313 or else not Is_Valid_Path_Name (Target_Name)
314 or else not Is_Regular_File (Source_Name)
318 elsif Is_Directory (Target_Name) then
322 -- The implementation uses System.OS_Lib.Copy_File, with parameters
323 -- suitable for all platforms.
325 Copy_File (Source_Name, Target_Name, Success, Overwrite, None);
333 ----------------------
334 -- Create_Directory --
335 ----------------------
337 procedure Create_Directory
338 (New_Directory : String;
341 pragma Unreferenced (Form);
343 C_Dir_Name : constant String := New_Directory & ASCII.NUL;
345 function mkdir (Dir_Name : String) return Integer;
346 pragma Import (C, mkdir, "__gnat_mkdir
");
349 -- First, the invalid case
351 if not Is_Valid_Path_Name (New_Directory) then
355 if mkdir (C_Dir_Name) /= 0 then
359 end Create_Directory;
365 procedure Create_Path
366 (New_Directory : String;
369 pragma Unreferenced (Form);
371 New_Dir : String (1 .. New_Directory'Length + 1);
372 Last : Positive := 1;
375 -- First, the invalid case
377 if not Is_Valid_Path_Name (New_Directory) then
381 -- Build New_Dir with a directory separator at the end, so that the
382 -- complete path will be found in the loop below.
384 New_Dir (1 .. New_Directory'Length) := New_Directory;
385 New_Dir (New_Dir'Last) := Directory_Separator;
387 -- Create, if necessary, each directory in the path
389 for J in 2 .. New_Dir'Last loop
391 -- Look for the end of an intermediate directory
393 if New_Dir (J) /= Dir_Separator and then
398 -- We have found a new intermediate directory each time we find
399 -- a first directory separator.
401 elsif New_Dir (J - 1) /= Dir_Separator and then
402 New_Dir (J - 1) /= '/'
405 -- No need to create the directory if it already exists
407 if Is_Directory (New_Dir (1 .. Last)) then
410 -- It is an error if a file with such a name already exists
412 elsif Is_Regular_File (New_Dir (1 .. Last)) then
416 Create_Directory (New_Directory => New_Dir (1 .. Last));
423 -----------------------
424 -- Current_Directory --
425 -----------------------
427 function Current_Directory return String is
428 Path_Len : Natural := Max_Path;
429 Buffer : String (1 .. 1 + Max_Path + 1);
431 procedure Local_Get_Current_Dir
432 (Dir : System.Address;
433 Length : System.Address);
434 pragma Import (C, Local_Get_Current_Dir, "__gnat_get_current_dir
");
437 Local_Get_Current_Dir (Buffer'Address, Path_Len'Address);
440 Cur : String := Normalize_Pathname (Buffer (1 .. Path_Len));
443 To_Lower_If_Case_Insensitive (Cur);
445 if Cur'Length > 1 and then Cur (Cur'Last) = Dir_Separator then
446 return Cur (1 .. Cur'Last - 1);
451 end Current_Directory;
453 ----------------------
454 -- Delete_Directory --
455 ----------------------
457 procedure Delete_Directory (Directory : String) is
459 -- First, the invalid cases
461 if not Is_Valid_Path_Name (Directory) then
464 elsif not Is_Directory (Directory) then
469 C_Dir_Name : constant String := Directory & ASCII.NUL;
473 if System.OS_Lib.Is_Directory (Directory) then
478 end Delete_Directory;
484 procedure Delete_File (Name : String) is
488 -- First, the invalid cases
490 if not Is_Valid_Path_Name (Name) then
493 elsif not Is_Regular_File (Name) then
497 -- The implementation uses System.OS_Lib.Delete_File
499 Delete_File (Name, Success);
511 procedure Delete_Tree (Directory : String) is
512 Current_Dir : constant String := Current_Directory;
513 Search : Search_Type;
514 Dir_Ent : Directory_Entry_Type;
516 -- First, the invalid cases
518 if not Is_Valid_Path_Name (Directory) then
521 elsif not Is_Directory (Directory) then
525 Set_Directory (Directory);
526 Start_Search (Search, Directory => ".", Pattern => "");
528 while More_Entries (Search) loop
529 Get_Next_Entry (Search, Dir_Ent);
532 File_Name : constant String := Simple_Name (Dir_Ent);
535 if System.OS_Lib.Is_Directory (File_Name) then
536 if File_Name /= "." and then File_Name /= ".." then
537 Delete_Tree (File_Name);
541 Delete_File (File_Name);
546 Set_Directory (Current_Dir);
550 C_Dir_Name : constant String := Directory & ASCII.NUL;
555 if System.OS_Lib.Is_Directory (Directory) then
566 function Exists (Name : String) return Boolean is
568 -- First, the invalid case
570 if not Is_Valid_Path_Name (Name) then
574 -- The implementation is in File_Exists
576 return File_Exists (Name);
584 function Extension (Name : String) return String is
586 -- First, the invalid case
588 if not Is_Valid_Path_Name (Name) then
592 -- Look for first dot that is not followed by a directory separator
594 for Pos in reverse Name'Range loop
596 -- If a directory separator is found before a dot, there is no
599 if Name (Pos) = Dir_Separator then
602 elsif Name (Pos) = '.' then
604 -- We found a dot, build the return value with lower bound 1
607 subtype Result_Type is String (1 .. Name'Last - Pos);
609 return Result_Type (Name (Pos + 1 .. Name'Last));
614 -- No dot were found, there is no extension
620 ----------------------
621 -- Fetch_Next_Entry --
622 ----------------------
624 procedure Fetch_Next_Entry (Search : Search_Type) is
625 Name : String (1 .. 255);
628 Kind : File_Kind := Ordinary_File;
629 -- Initialized to avoid a compilation warning
631 Filename_Addr : System.Address;
632 Filename_Len : aliased Integer;
634 Buffer : array (0 .. Filename_Max + 12) of Character;
635 -- 12 is the size of the dirent structure (see dirent.h), without the
636 -- field for the filename.
638 function readdir_gnat
639 (Directory : System.Address;
640 Buffer : System.Address;
641 Last : not null access Integer) return System.Address;
642 pragma Import (C, readdir_gnat, "__gnat_readdir
");
647 -- Search.Value.Is_Valid is always True when Fetch_Next_Entry is called
652 (System.Address (Search.Value.Dir),
654 Filename_Len'Access);
656 -- If no matching entry is found, set Is_Valid to False
658 if Filename_Addr = System.Null_Address then
659 Search.Value.Is_Valid := False;
664 subtype Path_String is String (1 .. Filename_Len);
665 type Path_String_Access is access Path_String;
667 function Address_To_Access is new
668 Ada.Unchecked_Conversion
670 Target => Path_String_Access);
672 Path_Access : constant Path_String_Access :=
673 Address_To_Access (Filename_Addr);
676 Last := Filename_Len;
677 Name (1 .. Last) := Path_Access.all;
680 -- Check if the entry matches the pattern
682 if Match (Name (1 .. Last), Search.Value.Pattern) then
684 Full_Name : constant String :=
687 (Search.Value.Name), Name (1 .. Last));
688 Found : Boolean := False;
691 if File_Exists (Full_Name) then
693 -- Now check if the file kind matches the filter
695 if Is_Regular_File (Full_Name) then
696 if Search.Value.Filter (Ordinary_File) then
697 Kind := Ordinary_File;
701 elsif Is_Directory (Full_Name) then
702 if Search.Value.Filter (Directory) then
707 elsif Search.Value.Filter (Special_File) then
708 Kind := Special_File;
712 -- If it does, update Search and return
715 Search.Value.Entry_Fetched := True;
716 Search.Value.Dir_Entry :=
718 Simple => To_Unbounded_String (Name (1 .. Last)),
719 Full => To_Unbounded_String (Full_Name),
727 end Fetch_Next_Entry;
733 function File_Exists (Name : String) return Boolean is
734 function C_File_Exists (A : System.Address) return Integer;
735 pragma Import (C, C_File_Exists, "__gnat_file_exists
");
737 C_Name : String (1 .. Name'Length + 1);
740 C_Name (1 .. Name'Length) := Name;
741 C_Name (C_Name'Last) := ASCII.NUL;
742 return C_File_Exists (C_Name (1)'Address) = 1;
749 procedure Finalize (Search : in out Search_Type) is
751 if Search.Value /= null then
753 -- Close the directory, if one is open
755 if Search.Value.Dir /= No_Dir then
756 Close (Search.Value.Dir);
767 function Full_Name (Name : String) return String is
769 -- First, the invalid case
771 if not Is_Valid_Path_Name (Name) then
775 -- Build the return value with lower bound 1
777 -- Use System.OS_Lib.Normalize_Pathname
780 Value : String := Normalize_Pathname (Name);
781 subtype Result is String (1 .. Value'Length);
783 To_Lower_If_Case_Insensitive (Value);
784 return Result (Value);
789 function Full_Name (Directory_Entry : Directory_Entry_Type) return String is
791 -- First, the invalid case
793 if not Directory_Entry.Is_Valid then
797 -- The value to return has already been computed
799 return To_String (Directory_Entry.Full);
807 procedure Get_Next_Entry
808 (Search : in out Search_Type;
809 Directory_Entry : out Directory_Entry_Type)
812 -- First, the invalid case
814 if Search.Value = null or else not Search.Value.Is_Valid then
818 -- Fetch the next entry, if needed
820 if not Search.Value.Entry_Fetched then
821 Fetch_Next_Entry (Search);
824 -- It is an error if no valid entry is found
826 if not Search.Value.Is_Valid then
830 -- Reset Entry_Fatched and return the entry
832 Search.Value.Entry_Fetched := False;
833 Directory_Entry := Search.Value.Dir_Entry;
841 function Kind (Name : String) return File_Kind is
843 -- First, the invalid case
845 if not File_Exists (Name) then
848 elsif Is_Regular_File (Name) then
849 return Ordinary_File;
851 elsif Is_Directory (Name) then
859 function Kind (Directory_Entry : Directory_Entry_Type) return File_Kind is
861 -- First, the invalid case
863 if not Directory_Entry.Is_Valid then
867 -- The value to return has already be computed
869 return Directory_Entry.Kind;
873 -----------------------
874 -- Modification_Time --
875 -----------------------
877 function Modification_Time (Name : String) return Time is
883 Minute : Minute_Type;
884 Second : Second_Type;
888 -- First, the invalid cases
890 if not (Is_Regular_File (Name) or else Is_Directory (Name)) then
894 Date := File_Time_Stamp (Name);
896 -- Break down the time stamp into its constituents relative to GMT.
897 -- This version of Split does not recognize leap seconds or buffer
898 -- space for time zone processing.
900 GM_Split (Date, Year, Month, Day, Hour, Minute, Second);
902 -- On OpenVMS, the resulting time value must be in the local time
903 -- zone. Ada.Calendar.Time_Of is exactly what we need. Note that
904 -- in both cases, the sub seconds are set to zero (0.0) because the
905 -- time stamp does not store them in its value.
910 (Year, Month, Day, Seconds_Of (Hour, Minute, Second, 0.0));
912 -- On Unix and Windows, the result must be in GMT. Ada.Calendar.
913 -- Formatting.Time_Of with default time zone of zero (0) is the
914 -- routine of choice.
917 Result := Time_Of (Year, Month, Day, Hour, Minute, Second, 0.0);
922 end Modification_Time;
924 function Modification_Time
925 (Directory_Entry : Directory_Entry_Type) return Ada.Calendar.Time
928 -- First, the invalid case
930 if not Directory_Entry.Is_Valid then
934 -- The value to return has already be computed
936 return Modification_Time (To_String (Directory_Entry.Full));
938 end Modification_Time;
944 function More_Entries (Search : Search_Type) return Boolean is
946 if Search.Value = null then
949 elsif Search.Value.Is_Valid then
951 -- Fetch the next entry, if needed
953 if not Search.Value.Entry_Fetched then
954 Fetch_Next_Entry (Search);
958 return Search.Value.Is_Valid;
965 procedure Rename (Old_Name, New_Name : String) is
969 -- First, the invalid cases
971 if not Is_Valid_Path_Name (Old_Name)
972 or else not Is_Valid_Path_Name (New_Name)
973 or else (not Is_Regular_File (Old_Name)
974 and then not Is_Directory (Old_Name))
978 elsif Is_Regular_File (New_Name) or Is_Directory (New_Name) then
982 -- The implementation uses System.OS_Lib.Rename_File
984 Rename_File (Old_Name, New_Name, Success);
999 Filter : Filter_Type := (others => True);
1000 Process : not null access procedure
1001 (Directory_Entry : Directory_Entry_Type))
1004 Directory_Entry : Directory_Entry_Type;
1007 Start_Search (Srch, Directory, Pattern, Filter);
1009 while More_Entries (Srch) loop
1010 Get_Next_Entry (Srch, Directory_Entry);
1011 Process (Directory_Entry);
1021 procedure Set_Directory (Directory : String) is
1022 C_Dir_Name : constant String := Directory & ASCII.NUL;
1024 function chdir (Dir_Name : String) return Integer;
1025 pragma Import (C, chdir, "chdir
");
1028 if chdir (C_Dir_Name) /= 0 then
1037 function Simple_Name (Name : String) return String is
1039 function Simple_Name_CI (Path : String) return String;
1040 -- This function does the job. The difference between Simple_Name_CI
1041 -- and Simple_Name (the parent function) is that the former is case
1042 -- sensitive, while the latter is not. Path and Suffix are adjusted
1043 -- appropriately before calling Simple_Name_CI under platforms where
1044 -- the file system is not case sensitive.
1046 --------------------
1047 -- Simple_Name_CI --
1048 --------------------
1050 function Simple_Name_CI (Path : String) return String is
1051 Cut_Start : Natural :=
1053 (Path, Dir_Seps, Going => Strings.Backward);
1057 -- Cut_Start point to the first simple name character
1059 if Cut_Start = 0 then
1060 Cut_Start := Path'First;
1063 Cut_Start := Cut_Start + 1;
1066 -- Cut_End point to the last simple name character
1068 Cut_End := Path'Last;
1070 Check_For_Standard_Dirs : declare
1071 Offset : constant Integer := Path'First - Name'First;
1072 BN : constant String :=
1073 Name (Cut_Start - Offset .. Cut_End - Offset);
1074 -- Here we use Simple_Name.Name to keep the original casing
1076 Has_Drive_Letter : constant Boolean :=
1077 System.OS_Lib.Path_Separator /= ':';
1078 -- If Path separator is not ':' then we are on a DOS based OS
1079 -- where this character is used as a drive letter separator.
1082 if BN = "." or else BN = ".." then
1085 elsif Has_Drive_Letter
1086 and then BN'Length > 2
1087 and then Characters.Handling.Is_Letter (BN (BN'First))
1088 and then BN (BN'First + 1) = ':'
1090 -- We have a DOS drive letter prefix, remove it
1092 return BN (BN'First + 2 .. BN'Last);
1097 end Check_For_Standard_Dirs;
1100 -- Start of processing for Simple_Name
1103 -- First, the invalid case
1105 if not Is_Valid_Path_Name (Name) then
1109 -- Build the value to return with lower bound 1
1111 if Is_Path_Name_Case_Sensitive then
1113 Value : constant String := Simple_Name_CI (Name);
1114 subtype Result is String (1 .. Value'Length);
1116 return Result (Value);
1121 Value : constant String :=
1122 Simple_Name_CI (Characters.Handling.To_Lower (Name));
1123 subtype Result is String (1 .. Value'Length);
1125 return Result (Value);
1131 function Simple_Name
1132 (Directory_Entry : Directory_Entry_Type) return String
1135 -- First, the invalid case
1137 if not Directory_Entry.Is_Valid then
1141 -- The value to return has already be computed
1143 return To_String (Directory_Entry.Simple);
1151 function Size (Name : String) return File_Size is
1152 C_Name : String (1 .. Name'Length + 1);
1154 function C_Size (Name : System.Address) return Long_Integer;
1155 pragma Import (C, C_Size, "__gnat_named_file_length
");
1158 -- First, the invalid case
1160 if not Is_Regular_File (Name) then
1164 C_Name (1 .. Name'Length) := Name;
1165 C_Name (C_Name'Last) := ASCII.NUL;
1166 return File_Size (C_Size (C_Name'Address));
1170 function Size (Directory_Entry : Directory_Entry_Type) return File_Size is
1172 -- First, the invalid case
1174 if not Directory_Entry.Is_Valid then
1178 -- The value to return has already be computed
1180 return Size (To_String (Directory_Entry.Full));
1188 procedure Start_Search
1189 (Search : in out Search_Type;
1192 Filter : Filter_Type := (others => True))
1194 function opendir (file_name : String) return DIRs;
1195 pragma Import (C, opendir, "__gnat_opendir
");
1197 C_File_Name : constant String := Directory & ASCII.NUL;
1200 -- First, the invalid case
1202 if not Is_Directory (Directory) then
1206 -- If needed, finalize Search
1210 -- Allocate the default data
1212 Search.Value := new Search_Data;
1215 -- Check the pattern
1217 Search.Value.Pattern := Compile (Pattern, Glob => True);
1220 when Error_In_Regexp =>
1221 Free (Search.Value);
1225 -- Initialize some Search components
1227 Search.Value.Filter := Filter;
1228 Search.Value.Name := To_Unbounded_String (Full_Name (Directory));
1229 Search.Value.Dir := Dir_Type_Value (opendir (C_File_Name));
1230 Search.Value.Is_Valid := True;
1233 ----------------------------------
1234 -- To_Lower_If_Case_Insensitive --
1235 ----------------------------------
1237 procedure To_Lower_If_Case_Insensitive (S : in out String) is
1239 if not Is_Path_Name_Case_Sensitive then
1240 for J in S'Range loop
1241 S (J) := To_Lower (S (J));
1244 end To_Lower_If_Case_Insensitive;
1246 end Ada.Directories;