annotate gcc/ada/libgnat/g-diopit.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT COMPILER COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- G N A T . D I R E C T O R Y _ O P E R A T I O N S . I T E R A T I O N --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 -- Copyright (C) 2001-2018, AdaCore --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with Ada.Characters.Handling;
kono
parents:
diff changeset
33 with Ada.Strings.Fixed;
kono
parents:
diff changeset
34 with Ada.Strings.Maps;
kono
parents:
diff changeset
35 with GNAT.OS_Lib;
kono
parents:
diff changeset
36 with GNAT.Regexp;
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 package body GNAT.Directory_Operations.Iteration is
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 use Ada;
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 ----------
kono
parents:
diff changeset
43 -- Find --
kono
parents:
diff changeset
44 ----------
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 procedure Find
kono
parents:
diff changeset
47 (Root_Directory : Dir_Name_Str;
kono
parents:
diff changeset
48 File_Pattern : String)
kono
parents:
diff changeset
49 is
kono
parents:
diff changeset
50 File_Regexp : constant Regexp.Regexp := Regexp.Compile (File_Pattern);
kono
parents:
diff changeset
51 Index : Natural := 0;
kono
parents:
diff changeset
52 Quit : Boolean;
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 procedure Read_Directory (Directory : Dir_Name_Str);
kono
parents:
diff changeset
55 -- Open Directory and read all entries. This routine is called
kono
parents:
diff changeset
56 -- recursively for each sub-directories.
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 function Make_Pathname (Dir, File : String) return String;
kono
parents:
diff changeset
59 -- Returns the pathname for File by adding Dir as prefix
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 -------------------
kono
parents:
diff changeset
62 -- Make_Pathname --
kono
parents:
diff changeset
63 -------------------
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 function Make_Pathname (Dir, File : String) return String is
kono
parents:
diff changeset
66 begin
kono
parents:
diff changeset
67 if Dir (Dir'Last) = '/' or else Dir (Dir'Last) = '\' then
kono
parents:
diff changeset
68 return Dir & File;
kono
parents:
diff changeset
69 else
kono
parents:
diff changeset
70 return Dir & Dir_Separator & File;
kono
parents:
diff changeset
71 end if;
kono
parents:
diff changeset
72 end Make_Pathname;
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 --------------------
kono
parents:
diff changeset
75 -- Read_Directory --
kono
parents:
diff changeset
76 --------------------
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 procedure Read_Directory (Directory : Dir_Name_Str) is
kono
parents:
diff changeset
79 Buffer : String (1 .. 2_048);
kono
parents:
diff changeset
80 Last : Natural;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 Dir : Dir_Type;
kono
parents:
diff changeset
83 pragma Warnings (Off, Dir);
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 begin
kono
parents:
diff changeset
86 Open (Dir, Directory);
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 loop
kono
parents:
diff changeset
89 Read (Dir, Buffer, Last);
kono
parents:
diff changeset
90 exit when Last = 0;
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 declare
kono
parents:
diff changeset
93 Dir_Entry : constant String := Buffer (1 .. Last);
kono
parents:
diff changeset
94 Pathname : constant String :=
kono
parents:
diff changeset
95 Make_Pathname (Directory, Dir_Entry);
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 begin
kono
parents:
diff changeset
98 if Regexp.Match (Dir_Entry, File_Regexp) then
kono
parents:
diff changeset
99 Index := Index + 1;
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 begin
kono
parents:
diff changeset
102 Action (Pathname, Index, Quit);
kono
parents:
diff changeset
103 exception
kono
parents:
diff changeset
104 when others =>
kono
parents:
diff changeset
105 Close (Dir);
kono
parents:
diff changeset
106 raise;
kono
parents:
diff changeset
107 end;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 exit when Quit;
kono
parents:
diff changeset
110 end if;
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 -- Recursively call for sub-directories, except for . and ..
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 if not (Dir_Entry = "." or else Dir_Entry = "..")
kono
parents:
diff changeset
115 and then OS_Lib.Is_Directory (Pathname)
kono
parents:
diff changeset
116 then
kono
parents:
diff changeset
117 Read_Directory (Pathname);
kono
parents:
diff changeset
118 exit when Quit;
kono
parents:
diff changeset
119 end if;
kono
parents:
diff changeset
120 end;
kono
parents:
diff changeset
121 end loop;
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 Close (Dir);
kono
parents:
diff changeset
124 end Read_Directory;
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 begin
kono
parents:
diff changeset
127 Quit := False;
kono
parents:
diff changeset
128 Read_Directory (Root_Directory);
kono
parents:
diff changeset
129 end Find;
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 -----------------------
kono
parents:
diff changeset
132 -- Wildcard_Iterator --
kono
parents:
diff changeset
133 -----------------------
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 procedure Wildcard_Iterator (Path : Path_Name) is
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 Index : Natural := 0;
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 procedure Read
kono
parents:
diff changeset
140 (Directory : String;
kono
parents:
diff changeset
141 File_Pattern : String;
kono
parents:
diff changeset
142 Suffix_Pattern : String);
kono
parents:
diff changeset
143 -- Read entries in Directory and call user's callback if the entry match
kono
parents:
diff changeset
144 -- File_Pattern and Suffix_Pattern is empty; otherwise go down one more
kono
parents:
diff changeset
145 -- directory level by calling Next_Level routine below.
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 procedure Next_Level
kono
parents:
diff changeset
148 (Current_Path : String;
kono
parents:
diff changeset
149 Suffix_Path : String);
kono
parents:
diff changeset
150 -- Extract next File_Pattern from Suffix_Path and call Read routine
kono
parents:
diff changeset
151 -- above.
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 ----------------
kono
parents:
diff changeset
154 -- Next_Level --
kono
parents:
diff changeset
155 ----------------
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 procedure Next_Level
kono
parents:
diff changeset
158 (Current_Path : String;
kono
parents:
diff changeset
159 Suffix_Path : String)
kono
parents:
diff changeset
160 is
kono
parents:
diff changeset
161 DS : Natural;
kono
parents:
diff changeset
162 SP : String renames Suffix_Path;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 begin
kono
parents:
diff changeset
165 if SP'Length > 2
kono
parents:
diff changeset
166 and then SP (SP'First) = '.'
kono
parents:
diff changeset
167 and then Strings.Maps.Is_In (SP (SP'First + 1), Dir_Seps)
kono
parents:
diff changeset
168 then
kono
parents:
diff changeset
169 -- Starting with "./"
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 DS := Strings.Fixed.Index
kono
parents:
diff changeset
172 (SP (SP'First + 2 .. SP'Last),
kono
parents:
diff changeset
173 Dir_Seps);
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 if DS = 0 then
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 -- We have "./"
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 Read (Current_Path & ".", "*", "");
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 else
kono
parents:
diff changeset
182 -- We have "./dir"
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 Read (Current_Path & ".",
kono
parents:
diff changeset
185 SP (SP'First + 2 .. DS - 1),
kono
parents:
diff changeset
186 SP (DS .. SP'Last));
kono
parents:
diff changeset
187 end if;
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 elsif SP'Length > 3
kono
parents:
diff changeset
190 and then SP (SP'First .. SP'First + 1) = ".."
kono
parents:
diff changeset
191 and then Strings.Maps.Is_In (SP (SP'First + 2), Dir_Seps)
kono
parents:
diff changeset
192 then
kono
parents:
diff changeset
193 -- Starting with "../"
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 DS := Strings.Fixed.Index
kono
parents:
diff changeset
196 (SP (SP'First + 3 .. SP'Last), Dir_Seps);
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 if DS = 0 then
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 -- We have "../"
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 Read (Current_Path & "..", "*", "");
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 else
kono
parents:
diff changeset
205 -- We have "../dir"
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 Read (Current_Path & "..",
kono
parents:
diff changeset
208 SP (SP'First + 3 .. DS - 1),
kono
parents:
diff changeset
209 SP (DS .. SP'Last));
kono
parents:
diff changeset
210 end if;
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 elsif Current_Path = ""
kono
parents:
diff changeset
213 and then SP'Length > 1
kono
parents:
diff changeset
214 and then Characters.Handling.Is_Letter (SP (SP'First))
kono
parents:
diff changeset
215 and then SP (SP'First + 1) = ':'
kono
parents:
diff changeset
216 then
kono
parents:
diff changeset
217 -- Starting with "<drive>:"
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 if SP'Length > 2
kono
parents:
diff changeset
220 and then Strings.Maps.Is_In (SP (SP'First + 2), Dir_Seps)
kono
parents:
diff changeset
221 then
kono
parents:
diff changeset
222 -- Starting with "<drive>:\"
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 DS := Strings.Fixed.Index
kono
parents:
diff changeset
225 (SP (SP'First + 3 .. SP'Last), Dir_Seps);
kono
parents:
diff changeset
226
kono
parents:
diff changeset
227 if DS = 0 then
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 -- We have "<drive>:\dir"
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 Read (SP (SP'First .. SP'First + 2),
kono
parents:
diff changeset
232 SP (SP'First + 3 .. SP'Last),
kono
parents:
diff changeset
233 "");
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 else
kono
parents:
diff changeset
236 -- We have "<drive>:\dir\kkk"
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 Read (SP (SP'First .. SP'First + 2),
kono
parents:
diff changeset
239 SP (SP'First + 3 .. DS - 1),
kono
parents:
diff changeset
240 SP (DS .. SP'Last));
kono
parents:
diff changeset
241 end if;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 else
kono
parents:
diff changeset
244 -- Starting with "<drive>:" and the drive letter not followed
kono
parents:
diff changeset
245 -- by a directory separator. The proper semantic on Windows is
kono
parents:
diff changeset
246 -- to read the content of the current selected directory on
kono
parents:
diff changeset
247 -- this drive. For example, if drive C current selected
kono
parents:
diff changeset
248 -- directory is c:\temp the suffix pattern "c:m*" is
kono
parents:
diff changeset
249 -- equivalent to c:\temp\m*.
kono
parents:
diff changeset
250
kono
parents:
diff changeset
251 DS := Strings.Fixed.Index
kono
parents:
diff changeset
252 (SP (SP'First + 2 .. SP'Last), Dir_Seps);
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 if DS = 0 then
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 -- We have "<drive>:dir"
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 Read (SP, "", "");
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 else
kono
parents:
diff changeset
261 -- We have "<drive>:dir/kkk"
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 Read (SP (SP'First .. DS - 1), "", SP (DS .. SP'Last));
kono
parents:
diff changeset
264 end if;
kono
parents:
diff changeset
265 end if;
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 elsif Strings.Maps.Is_In (SP (SP'First), Dir_Seps) then
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 -- Starting with a /
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 DS := Strings.Fixed.Index
kono
parents:
diff changeset
272 (SP (SP'First + 1 .. SP'Last), Dir_Seps);
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 if DS = 0 then
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 -- We have "/dir"
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 Read (Current_Path, SP (SP'First + 1 .. SP'Last), "");
kono
parents:
diff changeset
279 else
kono
parents:
diff changeset
280 -- We have "/dir/kkk"
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 Read (Current_Path,
kono
parents:
diff changeset
283 SP (SP'First + 1 .. DS - 1),
kono
parents:
diff changeset
284 SP (DS .. SP'Last));
kono
parents:
diff changeset
285 end if;
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 else
kono
parents:
diff changeset
288 -- Starting with a name
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 DS := Strings.Fixed.Index (SP, Dir_Seps);
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 if DS = 0 then
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 -- We have "dir"
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 Read (Current_Path & '.', SP, "");
kono
parents:
diff changeset
297 else
kono
parents:
diff changeset
298 -- We have "dir/kkk"
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 Read (Current_Path & '.',
kono
parents:
diff changeset
301 SP (SP'First .. DS - 1),
kono
parents:
diff changeset
302 SP (DS .. SP'Last));
kono
parents:
diff changeset
303 end if;
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 end if;
kono
parents:
diff changeset
306 end Next_Level;
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 ----------
kono
parents:
diff changeset
309 -- Read --
kono
parents:
diff changeset
310 ----------
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 Quit : Boolean := False;
kono
parents:
diff changeset
313 -- Global state to be able to exit all recursive calls
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 procedure Read
kono
parents:
diff changeset
316 (Directory : String;
kono
parents:
diff changeset
317 File_Pattern : String;
kono
parents:
diff changeset
318 Suffix_Pattern : String)
kono
parents:
diff changeset
319 is
kono
parents:
diff changeset
320 File_Regexp : constant Regexp.Regexp :=
kono
parents:
diff changeset
321 Regexp.Compile (File_Pattern, Glob => True);
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 Dir : Dir_Type;
kono
parents:
diff changeset
324 pragma Warnings (Off, Dir);
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 Buffer : String (1 .. 2_048);
kono
parents:
diff changeset
327 Last : Natural;
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 begin
kono
parents:
diff changeset
330 if OS_Lib.Is_Directory (Directory & Dir_Separator) then
kono
parents:
diff changeset
331 Open (Dir, Directory & Dir_Separator);
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 Dir_Iterator : loop
kono
parents:
diff changeset
334 Read (Dir, Buffer, Last);
kono
parents:
diff changeset
335 exit Dir_Iterator when Last = 0;
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 declare
kono
parents:
diff changeset
338 Dir_Entry : constant String := Buffer (1 .. Last);
kono
parents:
diff changeset
339 Pathname : constant String :=
kono
parents:
diff changeset
340 Directory & Dir_Separator & Dir_Entry;
kono
parents:
diff changeset
341 begin
kono
parents:
diff changeset
342 -- Handle "." and ".." only if explicit use in the
kono
parents:
diff changeset
343 -- File_Pattern.
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345 if not
kono
parents:
diff changeset
346 ((Dir_Entry = "." and then File_Pattern /= ".")
kono
parents:
diff changeset
347 or else
kono
parents:
diff changeset
348 (Dir_Entry = ".." and then File_Pattern /= ".."))
kono
parents:
diff changeset
349 then
kono
parents:
diff changeset
350 if Regexp.Match (Dir_Entry, File_Regexp) then
kono
parents:
diff changeset
351 if Suffix_Pattern = "" then
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 -- No more matching needed, call user's callback
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 Index := Index + 1;
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 begin
kono
parents:
diff changeset
358 Action (Pathname, Index, Quit);
kono
parents:
diff changeset
359 exception
kono
parents:
diff changeset
360 when others =>
kono
parents:
diff changeset
361 Close (Dir);
kono
parents:
diff changeset
362 raise;
kono
parents:
diff changeset
363 end;
kono
parents:
diff changeset
364
kono
parents:
diff changeset
365 else
kono
parents:
diff changeset
366 -- Down one level
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 Next_Level
kono
parents:
diff changeset
369 (Directory & Dir_Separator & Dir_Entry,
kono
parents:
diff changeset
370 Suffix_Pattern);
kono
parents:
diff changeset
371 end if;
kono
parents:
diff changeset
372 end if;
kono
parents:
diff changeset
373 end if;
kono
parents:
diff changeset
374 end;
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 -- Exit if Quit set by call to Action, either at this level
kono
parents:
diff changeset
377 -- or at some lower recursive call to Next_Level.
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 exit Dir_Iterator when Quit;
kono
parents:
diff changeset
380 end loop Dir_Iterator;
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 Close (Dir);
kono
parents:
diff changeset
383 end if;
kono
parents:
diff changeset
384 end Read;
kono
parents:
diff changeset
385
kono
parents:
diff changeset
386 -- Start of processing for Wildcard_Iterator
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 begin
kono
parents:
diff changeset
389 if Path = "" then
kono
parents:
diff changeset
390 return;
kono
parents:
diff changeset
391 end if;
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 Next_Level ("", Path);
kono
parents:
diff changeset
394 end Wildcard_Iterator;
kono
parents:
diff changeset
395
kono
parents:
diff changeset
396 end GNAT.Directory_Operations.Iteration;