comparison gcc/ada/libgnat/a-direct.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
4 -- -- 4 -- --
5 -- A D A . D I R E C T O R I E S -- 5 -- A D A . D I R E C T O R I E S --
6 -- -- 6 -- --
7 -- B o d y -- 7 -- B o d y --
8 -- -- 8 -- --
9 -- Copyright (C) 2004-2018, Free Software Foundation, Inc. -- 9 -- Copyright (C) 2004-2019, Free Software Foundation, Inc. --
10 -- -- 10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under -- 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- -- 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- -- 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- -- 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
31 31
32 with Ada.Calendar; use Ada.Calendar; 32 with Ada.Calendar; use Ada.Calendar;
33 with Ada.Calendar.Formatting; use Ada.Calendar.Formatting; 33 with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
34 with Ada.Characters.Handling; use Ada.Characters.Handling; 34 with Ada.Characters.Handling; use Ada.Characters.Handling;
35 with Ada.Directories.Validity; use Ada.Directories.Validity; 35 with Ada.Directories.Validity; use Ada.Directories.Validity;
36 with Ada.Directories.Hierarchical_File_Names;
37 use Ada.Directories.Hierarchical_File_Names;
36 with Ada.Strings.Fixed; 38 with Ada.Strings.Fixed;
37 with Ada.Strings.Maps; use Ada.Strings.Maps; 39 with Ada.Strings.Maps; use Ada.Strings.Maps;
38 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; 40 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
39 with Ada.Unchecked_Deallocation; 41 with Ada.Unchecked_Deallocation;
40 42
222 declare 224 declare
223 Last_DS : constant Natural := 225 Last_DS : constant Natural :=
224 Strings.Fixed.Index (Name, Dir_Seps, Going => Strings.Backward); 226 Strings.Fixed.Index (Name, Dir_Seps, Going => Strings.Backward);
225 227
226 begin 228 begin
227 if Last_DS = 0 then
228
229 -- There is no directory separator, returns "." representing
230 -- the current working directory.
231
232 return ".";
233
234 -- If Name indicates a root directory, raise Use_Error, because 229 -- If Name indicates a root directory, raise Use_Error, because
235 -- it has no containing directory. 230 -- it has no containing directory.
236 231
237 elsif Name = "/" 232 if Is_Parent_Directory_Name (Name)
238 or else 233 or else Is_Current_Directory_Name (Name)
239 (Windows 234 or else Is_Root_Directory_Name (Name)
240 and then
241 (Name = "\"
242 or else
243 (Name'Length = 3
244 and then Name (Name'Last - 1 .. Name'Last) = ":\"
245 and then (Name (Name'First) in 'a' .. 'z'
246 or else
247 Name (Name'First) in 'A' .. 'Z'))))
248 then 235 then
249 raise Use_Error with 236 raise Use_Error with
250 "directory """ & Name & """ has no containing directory"; 237 "directory """ & Name & """ has no containing directory";
238
239 elsif Last_DS = 0 then
240 -- There is no directory separator, so return ".", representing
241 -- the current working directory.
242
243 return ".";
251 244
252 else 245 else
253 declare 246 declare
254 Last : Positive := Last_DS - Name'First + 1; 247 Last : Positive := Last_DS - Name'First + 1;
255 Result : String (1 .. Last); 248 Result : String (1 .. Last);
260 -- Remove any trailing directory separator, except as the 253 -- Remove any trailing directory separator, except as the
261 -- first character or the first character following a drive 254 -- first character or the first character following a drive
262 -- number on Windows. 255 -- number on Windows.
263 256
264 while Last > 1 loop 257 while Last > 1 loop
265 exit when 258 exit when Is_Root_Directory_Name (Result (1 .. Last))
266 Result (Last) /= '/' 259 or else (Result (Last) /= Directory_Separator
267 and then 260 and then Result (Last) /= '/');
268 Result (Last) /= Directory_Separator;
269
270 exit when Windows
271 and then Last = 3
272 and then Result (2) = ':'
273 and then
274 (Result (1) in 'A' .. 'Z'
275 or else
276 Result (1) in 'a' .. 'z');
277 261
278 Last := Last - 1; 262 Last := Last - 1;
279 end loop; 263 end loop;
280 264
281 -- Special case of "..": the current directory may be a root 265 return Result (1 .. Last);
282 -- directory.
283
284 if Last = 2 and then Result (1 .. 2) = ".." then
285 return Containing_Directory (Current_Directory);
286
287 else
288 return Result (1 .. Last);
289 end if;
290 end; 266 end;
291 end if; 267 end if;
292 end; 268 end;
293 end if; 269 end if;
294 end Containing_Directory; 270 end Containing_Directory;
804 raise Use_Error 780 raise Use_Error
805 with Full_Name & ": " & Errno_Message (Err => Error); 781 with Full_Name & ": " & Errno_Message (Err => Error);
806 end if; 782 end if;
807 783
808 if Exists = 1 then 784 if Exists = 1 then
785 -- Ignore special directories "." and ".."
786
787 if (Full_Name'Length > 1
788 and then
789 Full_Name
790 (Full_Name'Last - 1 .. Full_Name'Last) = "\.")
791 or else
792 (Full_Name'Length > 2
793 and then
794 Full_Name
795 (Full_Name'Last - 2 .. Full_Name'Last) = "\..")
796 then
797 Exists := 0;
798 end if;
809 799
810 -- Now check if the file kind matches the filter 800 -- Now check if the file kind matches the filter
811 801
812 if Is_Regular_File_Attr 802 if Is_Regular_File_Attr
813 (C_Full_Name'Address, Attr'Access) = 1 803 (C_Full_Name'Address, Attr'Access) = 1
1278 -------------------------- 1268 --------------------------
1279 1269
1280 function Simple_Name_Internal (Path : String) return String is 1270 function Simple_Name_Internal (Path : String) return String is
1281 Cut_Start : Natural := 1271 Cut_Start : Natural :=
1282 Strings.Fixed.Index (Path, Dir_Seps, Going => Strings.Backward); 1272 Strings.Fixed.Index (Path, Dir_Seps, Going => Strings.Backward);
1283 Cut_End : Natural; 1273
1274 -- Cut_End points to the last simple name character
1275
1276 Cut_End : Natural := Path'Last;
1284 1277
1285 begin 1278 begin
1286 -- Cut_Start pointS to the first simple name character 1279 -- Root directories are considered simple
1280
1281 if Is_Root_Directory_Name (Path) then
1282 return Path;
1283 end if;
1284
1285 -- Handle trailing directory separators
1286
1287 if Cut_Start = Path'Last then
1288 Cut_End := Path'Last - 1;
1289 Cut_Start := Strings.Fixed.Index
1290 (Path (Path'First .. Path'Last - 1),
1291 Dir_Seps, Going => Strings.Backward);
1292 end if;
1293
1294 -- Cut_Start points to the first simple name character
1287 1295
1288 Cut_Start := (if Cut_Start = 0 then Path'First else Cut_Start + 1); 1296 Cut_Start := (if Cut_Start = 0 then Path'First else Cut_Start + 1);
1289
1290 -- Cut_End point to the last simple name character
1291
1292 Cut_End := Path'Last;
1293 1297
1294 Check_For_Standard_Dirs : declare 1298 Check_For_Standard_Dirs : declare
1295 BN : constant String := Path (Cut_Start .. Cut_End); 1299 BN : constant String := Path (Cut_Start .. Cut_End);
1296 1300
1297 Has_Drive_Letter : constant Boolean := 1301 Has_Drive_Letter : constant Boolean :=
1299 -- If Path separator is not ':' then we are on a DOS based OS 1303 -- If Path separator is not ':' then we are on a DOS based OS
1300 -- where this character is used as a drive letter separator. 1304 -- where this character is used as a drive letter separator.
1301 1305
1302 begin 1306 begin
1303 if BN = "." or else BN = ".." then 1307 if BN = "." or else BN = ".." then
1304 return ""; 1308 return BN;
1305 1309
1306 elsif Has_Drive_Letter 1310 elsif Has_Drive_Letter
1307 and then BN'Length > 2 1311 and then BN'Length > 2
1308 and then Characters.Handling.Is_Letter (BN (BN'First)) 1312 and then Characters.Handling.Is_Letter (BN (BN'First))
1309 and then BN (BN'First + 1) = ':' 1313 and then BN (BN'First + 1) = ':'