OSDN Git Service

2007-04-20 Vincent Celier <celier@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2007 10:30:30 +0000 (10:30 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2007 10:30:30 +0000 (10:30 +0000)
* g-os_lib.ads, g-os_lib.adb (Normalize_Pathname.Get_Directory):
Correct obvious bug (return Dir; instead of return Directory;).
(Normalize_Pathname): Use Reference_Dir'Length, not Reference_Dir'Last

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125421 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/g-os_lib.adb
gcc/ada/g-os_lib.ads

index e6d08dd..6ed3605 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                     Copyright (C) 1995-2006, AdaCore                     --
+--                     Copyright (C) 1995-2007, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
 --                                                                          --
 ------------------------------------------------------------------------------
 
-with System.Case_Util;
-with System.CRTL;
-with System.Soft_Links;
-with Unchecked_Conversion;
-with Unchecked_Deallocation;
-with System; use System;
+--  This package does not require a body, since it is a package renaming. We
+--  provide a dummy file containing a No_Body pragma so that previous versions
+--  of the body (which did exist) will not intefere.
 
-package body GNAT.OS_Lib is
-
-   --  Imported procedures Dup and Dup2 are used in procedures Spawn and
-   --  Non_Blocking_Spawn.
-
-   function Dup (Fd : File_Descriptor) return File_Descriptor;
-   pragma Import (C, Dup, "__gnat_dup");
-
-   procedure Dup2 (Old_Fd, New_Fd : File_Descriptor);
-   pragma Import (C, Dup2, "__gnat_dup2");
-
-   On_Windows : constant Boolean := Directory_Separator = '\';
-   --  An indication that we are on Windows. Used in Normalize_Pathname, to
-   --  deal with drive letters in the beginning of absolute paths.
-
-   package SSL renames System.Soft_Links;
-
-   --  The following are used by Create_Temp_File
-
-   First_Temp_File_Name : constant String := "GNAT-TEMP-000000.TMP";
-   --  Used to initialize Current_Temp_File_Name and Temp_File_Name_Last_Digit
-
-   Current_Temp_File_Name : String := First_Temp_File_Name;
-   --  Name of the temp file last created
-
-   Temp_File_Name_Last_Digit : constant Positive :=
-                                 First_Temp_File_Name'Last - 4;
-   --  Position of the last digit in Current_Temp_File_Name
-
-   Max_Attempts : constant := 100;
-   --  The maximum number of attempts to create a new temp file
-
-   -----------------------
-   -- Local Subprograms --
-   -----------------------
-
-   function Args_Length (Args : Argument_List) return Natural;
-   --  Returns total number of characters needed to create a string
-   --  of all Args terminated by ASCII.NUL characters
-
-   function C_String_Length (S : Address) return Integer;
-   --  Returns the length of a C string. Does check for null address
-   --  (returns 0).
-
-   procedure Spawn_Internal
-     (Program_Name : String;
-      Args         : Argument_List;
-      Result       : out Integer;
-      Pid          : out Process_Id;
-      Blocking     : Boolean);
-   --  Internal routine to implement the two Spawn (blocking/non blocking)
-   --  routines. If Blocking is set to True then the spawn is blocking
-   --  otherwise it is non blocking. In this latter case the Pid contains the
-   --  process id number. The first three parameters are as in Spawn. Note that
-   --  Spawn_Internal normalizes the argument list before calling the low level
-   --  system spawn routines (see Normalize_Arguments).
-   --
-   --  Note: Normalize_Arguments is designed to do nothing if it is called more
-   --  than once, so calling Normalize_Arguments before calling one of the
-   --  spawn routines is fine.
-
-   function To_Path_String_Access
-     (Path_Addr : Address;
-      Path_Len  : Integer) return String_Access;
-   --  Converts a C String to an Ada String. We could do this making use of
-   --  Interfaces.C.Strings but we prefer not to import that entire package
-
-   ---------
-   -- "<" --
-   ---------
-
-   function "<"  (X, Y : OS_Time) return Boolean is
-   begin
-      return Long_Integer (X) < Long_Integer (Y);
-   end "<";
-
-   ----------
-   -- "<=" --
-   ----------
-
-   function "<="  (X, Y : OS_Time) return Boolean is
-   begin
-      return Long_Integer (X) <= Long_Integer (Y);
-   end "<=";
-
-   ---------
-   -- ">" --
-   ---------
-
-   function ">"  (X, Y : OS_Time) return Boolean is
-   begin
-      return Long_Integer (X) > Long_Integer (Y);
-   end ">";
-
-   ----------
-   -- ">=" --
-   ----------
-
-   function ">="  (X, Y : OS_Time) return Boolean is
-   begin
-      return Long_Integer (X) >= Long_Integer (Y);
-   end ">=";
-
-   -----------------
-   -- Args_Length --
-   -----------------
-
-   function Args_Length (Args : Argument_List) return Natural is
-      Len : Natural := 0;
-
-   begin
-      for J in Args'Range loop
-         Len := Len + Args (J)'Length + 1; --  One extra for ASCII.NUL
-      end loop;
-
-      return Len;
-   end Args_Length;
-
-   -----------------------------
-   -- Argument_String_To_List --
-   -----------------------------
-
-   function Argument_String_To_List
-     (Arg_String : String) return Argument_List_Access
-   is
-      Max_Args : constant Integer := Arg_String'Length;
-      New_Argv : Argument_List (1 .. Max_Args);
-      New_Argc : Natural := 0;
-      Idx      : Integer;
-
-   begin
-      Idx := Arg_String'First;
-
-      loop
-         exit when Idx > Arg_String'Last;
-
-         declare
-            Quoted  : Boolean := False;
-            Backqd  : Boolean := False;
-            Old_Idx : Integer;
-
-         begin
-            Old_Idx := Idx;
-
-            loop
-               --  An unquoted space is the end of an argument
-
-               if not (Backqd or Quoted)
-                 and then Arg_String (Idx) = ' '
-               then
-                  exit;
-
-               --  Start of a quoted string
-
-               elsif not (Backqd or Quoted)
-                 and then Arg_String (Idx) = '"'
-               then
-                  Quoted := True;
-
-               --  End of a quoted string and end of an argument
-
-               elsif (Quoted and not Backqd)
-                 and then Arg_String (Idx) = '"'
-               then
-                  Idx := Idx + 1;
-                  exit;
-
-               --  Following character is backquoted
-
-               elsif Arg_String (Idx) = '\' then
-                  Backqd := True;
-
-               --  Turn off backquoting after advancing one character
-
-               elsif Backqd then
-                  Backqd := False;
-
-               end if;
-
-               Idx := Idx + 1;
-               exit when Idx > Arg_String'Last;
-            end loop;
-
-            --  Found an argument
-
-            New_Argc := New_Argc + 1;
-            New_Argv (New_Argc) :=
-              new String'(Arg_String (Old_Idx .. Idx - 1));
-
-            --  Skip extraneous spaces
-
-            while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
-               Idx := Idx + 1;
-            end loop;
-         end;
-      end loop;
-
-      return new Argument_List'(New_Argv (1 .. New_Argc));
-   end Argument_String_To_List;
-
-   ---------------------
-   -- C_String_Length --
-   ---------------------
-
-   function C_String_Length (S : Address) return Integer is
-      function Strlen (S : Address) return Integer;
-      pragma Import (C, Strlen, "strlen");
-   begin
-      if S = Null_Address then
-         return 0;
-      else
-         return Strlen (S);
-      end if;
-   end C_String_Length;
-
-   -----------
-   -- Close --
-   -----------
-
-   procedure Close (FD : File_Descriptor) is
-      procedure C_Close (FD : File_Descriptor);
-      pragma Import (C, C_Close, "close");
-   begin
-      C_Close (FD);
-   end Close;
-
-   procedure Close (FD : File_Descriptor; Status : out Boolean) is
-      function C_Close (FD : File_Descriptor) return Integer;
-      pragma Import (C, C_Close, "close");
-   begin
-      Status := (C_Close (FD) = 0);
-   end Close;
-
-   ---------------
-   -- Copy_File --
-   ---------------
-
-   procedure Copy_File
-     (Name     : String;
-      Pathname : String;
-      Success  : out Boolean;
-      Mode     : Copy_Mode := Copy;
-      Preserve : Attribute := Time_Stamps)
-   is
-      From : File_Descriptor;
-      To   : File_Descriptor;
-
-      Copy_Error : exception;
-      --  Internal exception raised to signal error in copy
-
-      function Build_Path (Dir : String; File : String) return String;
-      --  Returns pathname Dir catenated with File adding the directory
-      --  separator only if needed.
-
-      procedure Copy (From, To : File_Descriptor);
-      --  Read data from From and place them into To. In both cases the
-      --  operations uses the current file position. Raises Constraint_Error
-      --  if a problem occurs during the copy.
-
-      procedure Copy_To (To_Name : String);
-      --  Does a straight copy from source to designated destination file
-
-      ----------------
-      -- Build_Path --
-      ----------------
-
-      function Build_Path (Dir : String; File : String) return String is
-         Res : String (1 .. Dir'Length + File'Length + 1);
-
-         Base_File_Ptr : Integer;
-         --  The base file name is File (Base_File_Ptr + 1 .. File'Last)
-
-         function Is_Dirsep (C : Character) return Boolean;
-         pragma Inline (Is_Dirsep);
-         --  Returns True if C is a directory separator. On Windows we
-         --  handle both styles of directory separator.
-
-         ---------------
-         -- Is_Dirsep --
-         ---------------
-
-         function Is_Dirsep (C : Character) return Boolean is
-         begin
-            return C = Directory_Separator or else C = '/';
-         end Is_Dirsep;
-
-      --  Start of processing for Build_Path
-
-      begin
-         --  Find base file name
-
-         Base_File_Ptr := File'Last;
-         while Base_File_Ptr >= File'First loop
-            exit when Is_Dirsep (File (Base_File_Ptr));
-            Base_File_Ptr := Base_File_Ptr - 1;
-         end loop;
-
-         declare
-            Base_File : String renames
-                          File (Base_File_Ptr + 1 .. File'Last);
-
-         begin
-            Res (1 .. Dir'Length) := Dir;
-
-            if Is_Dirsep (Dir (Dir'Last)) then
-               Res (Dir'Length + 1 .. Dir'Length + Base_File'Length) :=
-                 Base_File;
-               return Res (1 .. Dir'Length + Base_File'Length);
-
-            else
-               Res (Dir'Length + 1) := Directory_Separator;
-               Res (Dir'Length + 2 .. Dir'Length + 1 + Base_File'Length) :=
-                 Base_File;
-               return Res (1 .. Dir'Length + 1 + Base_File'Length);
-            end if;
-         end;
-      end Build_Path;
-
-      ----------
-      -- Copy --
-      ----------
-
-      procedure Copy (From, To : File_Descriptor) is
-         Buf_Size : constant := 200_000;
-         type Buf is array (1 .. Buf_Size) of Character;
-         type Buf_Ptr is access Buf;
-
-         Buffer : Buf_Ptr;
-         R      : Integer;
-         W      : Integer;
-
-         Status_From : Boolean;
-         Status_To   : Boolean;
-         --  Statuses for the calls to Close
-
-         procedure Free is new Unchecked_Deallocation (Buf, Buf_Ptr);
-
-      begin
-         --  Check for invalid descriptors, making sure that we do not
-         --  accidentally leave an open file descriptor around.
-
-         if From = Invalid_FD then
-            if To /= Invalid_FD then
-               Close (To, Status_To);
-            end if;
-
-            raise Copy_Error;
-
-         elsif To = Invalid_FD then
-            Close (From, Status_From);
-            raise Copy_Error;
-         end if;
-
-         --  Allocate the buffer on the heap
-
-         Buffer := new Buf;
-
-         loop
-            R := Read (From, Buffer (1)'Address, Buf_Size);
-
-            --  For VMS, the buffer may not be full. So, we need to try again
-            --  until there is nothing to read.
-
-            exit when R = 0;
-
-            W := Write (To, Buffer (1)'Address, R);
-
-            if W < R then
-
-               --  Problem writing data, could be a disk full. Close files
-               --  without worrying about status, since we are raising a
-               --  Copy_Error exception in any case.
-
-               Close (From, Status_From);
-               Close (To, Status_To);
-
-               Free (Buffer);
-
-               raise Copy_Error;
-            end if;
-         end loop;
-
-         Close (From, Status_From);
-         Close (To, Status_To);
-
-         Free (Buffer);
-
-         if not (Status_From and Status_To) then
-            raise Copy_Error;
-         end if;
-      end Copy;
-
-      -------------
-      -- Copy_To --
-      -------------
-
-      procedure Copy_To (To_Name : String) is
-
-         function Copy_Attributes
-           (From, To : System.Address;
-            Mode     : Integer) return Integer;
-         pragma Import (C, Copy_Attributes, "__gnat_copy_attribs");
-         --  Mode = 0 - copy only time stamps.
-         --  Mode = 1 - copy time stamps and read/write/execute attributes
-
-         C_From : String (1 .. Name'Length + 1);
-         C_To   : String (1 .. To_Name'Length + 1);
-
-      begin
-         From := Open_Read (Name, Binary);
-         To   := Create_File (To_Name, Binary);
-         Copy (From, To);
-
-         --  Copy attributes
-
-         C_From (1 .. Name'Length) := Name;
-         C_From (C_From'Last) := ASCII.Nul;
-
-         C_To (1 .. To_Name'Length) := To_Name;
-         C_To (C_To'Last) := ASCII.Nul;
-
-         case Preserve is
-
-            when Time_Stamps =>
-               if Copy_Attributes (C_From'Address, C_To'Address, 0) = -1 then
-                  raise Copy_Error;
-               end if;
-
-            when Full =>
-               if Copy_Attributes (C_From'Address, C_To'Address, 1) = -1 then
-                  raise Copy_Error;
-               end if;
-
-            when None =>
-               null;
-         end case;
-
-      end Copy_To;
-
-   --  Start of processing for Copy_File
-
-   begin
-      Success := True;
-
-      --  The source file must exist
-
-      if not Is_Regular_File (Name) then
-         raise Copy_Error;
-      end if;
-
-      --  The source file exists
-
-      case Mode is
-
-         --  Copy case, target file must not exist
-
-         when Copy =>
-
-            --  If the target file exists, we have an error
-
-            if Is_Regular_File (Pathname) then
-               raise Copy_Error;
-
-            --  Case of target is a directory
-
-            elsif Is_Directory (Pathname) then
-               declare
-                  Dest : constant String := Build_Path (Pathname, Name);
-
-               begin
-                  --  If target file exists, we have an error, else do copy
-
-                  if Is_Regular_File (Dest) then
-                     raise Copy_Error;
-                  else
-                     Copy_To (Dest);
-                  end if;
-               end;
-
-            --  Case of normal copy to file (destination does not exist)
-
-            else
-               Copy_To (Pathname);
-            end if;
-
-         --  Overwrite case (destination file may or may not exist)
-
-         when Overwrite =>
-            if Is_Directory (Pathname) then
-               Copy_To (Build_Path (Pathname, Name));
-            else
-               Copy_To (Pathname);
-            end if;
-
-         --  Append case (destination file may or may not exist)
-
-         when Append =>
-
-            --  Appending to existing file
-
-            if Is_Regular_File (Pathname) then
-
-               --  Append mode and destination file exists, append data at the
-               --  end of Pathname.
-
-               From := Open_Read (Name, Binary);
-               To   := Open_Read_Write (Pathname, Binary);
-               Lseek (To, 0, Seek_End);
-
-               Copy (From, To);
-
-            --  Appending to directory, not allowed
-
-            elsif Is_Directory (Pathname) then
-               raise Copy_Error;
-
-            --  Appending when target file does not exist
-
-            else
-               Copy_To (Pathname);
-            end if;
-      end case;
-
-   --  All error cases are caught here
-
-   exception
-      when Copy_Error =>
-         Success := False;
-   end Copy_File;
-
-   procedure Copy_File
-     (Name     : C_File_Name;
-      Pathname : C_File_Name;
-      Success  : out Boolean;
-      Mode     : Copy_Mode := Copy;
-      Preserve : Attribute := Time_Stamps)
-   is
-      Ada_Name : String_Access :=
-                   To_Path_String_Access
-                     (Name, C_String_Length (Name));
-
-      Ada_Pathname : String_Access :=
-                       To_Path_String_Access
-                         (Pathname, C_String_Length (Pathname));
-
-   begin
-      Copy_File (Ada_Name.all, Ada_Pathname.all, Success, Mode, Preserve);
-      Free (Ada_Name);
-      Free (Ada_Pathname);
-   end Copy_File;
-
-   ----------------------
-   -- Copy_Time_Stamps --
-   ----------------------
-
-   procedure Copy_Time_Stamps (Source, Dest : String; Success : out Boolean) is
-
-      function Copy_Attributes
-        (From, To : System.Address;
-         Mode     : Integer) return Integer;
-      pragma Import (C, Copy_Attributes, "__gnat_copy_attribs");
-      --  Mode = 0 - copy only time stamps.
-      --  Mode = 1 - copy time stamps and read/write/execute attributes
-
-   begin
-      if Is_Regular_File (Source) and then Is_Writable_File (Dest) then
-         declare
-            C_Source : String (1 .. Source'Length + 1);
-            C_Dest   : String (1 .. Dest'Length + 1);
-         begin
-            C_Source (1 .. Source'Length) := Source;
-            C_Source (C_Source'Last)      := ASCII.NUL;
-
-            C_Dest (1 .. Dest'Length) := Dest;
-            C_Dest (C_Dest'Last)      := ASCII.NUL;
-
-            if Copy_Attributes (C_Source'Address, C_Dest'Address, 0) = -1 then
-               Success := False;
-            else
-               Success := True;
-            end if;
-         end;
-
-      else
-         Success := False;
-      end if;
-   end Copy_Time_Stamps;
-
-   procedure Copy_Time_Stamps
-     (Source, Dest : C_File_Name;
-      Success      : out Boolean)
-   is
-      Ada_Source : String_Access :=
-                     To_Path_String_Access
-                       (Source, C_String_Length (Source));
-
-      Ada_Dest : String_Access :=
-                   To_Path_String_Access
-                     (Dest, C_String_Length (Dest));
-   begin
-      Copy_Time_Stamps (Ada_Source.all, Ada_Dest.all, Success);
-      Free (Ada_Source);
-      Free (Ada_Dest);
-   end Copy_Time_Stamps;
-
-   -----------------
-   -- Create_File --
-   -----------------
-
-   function Create_File
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor
-   is
-      function C_Create_File
-        (Name  : C_File_Name;
-         Fmode : Mode) return File_Descriptor;
-      pragma Import (C, C_Create_File, "__gnat_open_create");
-
-   begin
-      return C_Create_File (Name, Fmode);
-   end Create_File;
-
-   function Create_File
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor
-   is
-      C_Name : String (1 .. Name'Length + 1);
-
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-      return Create_File (C_Name (C_Name'First)'Address, Fmode);
-   end Create_File;
-
-   ---------------------
-   -- Create_New_File --
-   ---------------------
-
-   function Create_New_File
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor
-   is
-      function C_Create_New_File
-        (Name  : C_File_Name;
-         Fmode : Mode) return File_Descriptor;
-      pragma Import (C, C_Create_New_File, "__gnat_open_new");
-
-   begin
-      return C_Create_New_File (Name, Fmode);
-   end Create_New_File;
-
-   function Create_New_File
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor
-   is
-      C_Name : String (1 .. Name'Length + 1);
-
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-      return Create_New_File (C_Name (C_Name'First)'Address, Fmode);
-   end Create_New_File;
-
-   -----------------------------
-   -- Create_Output_Text_File --
-   -----------------------------
-
-   function Create_Output_Text_File (Name : String) return File_Descriptor is
-      function C_Create_File
-        (Name : C_File_Name) return File_Descriptor;
-      pragma Import (C, C_Create_File, "__gnat_create_output_file");
-
-      C_Name : String (1 .. Name'Length + 1);
-
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-      return C_Create_File (C_Name (C_Name'First)'Address);
-   end Create_Output_Text_File;
-
-   ----------------------
-   -- Create_Temp_File --
-   ----------------------
-
-   procedure Create_Temp_File
-     (FD   : out File_Descriptor;
-      Name : out Temp_File_Name)
-   is
-      function Open_New_Temp
-        (Name  : System.Address;
-         Fmode : Mode) return File_Descriptor;
-      pragma Import (C, Open_New_Temp, "__gnat_open_new_temp");
-
-   begin
-      FD := Open_New_Temp (Name'Address, Binary);
-   end Create_Temp_File;
-
-   procedure Create_Temp_File
-     (FD   : out File_Descriptor;
-      Name : out String_Access)
-   is
-      Pos      : Positive;
-      Attempts : Natural := 0;
-      Current  : String (Current_Temp_File_Name'Range);
-
-   begin
-      --  Loop until a new temp file can be created
-
-      File_Loop : loop
-         Locked : begin
-            --  We need to protect global variable Current_Temp_File_Name
-            --  against concurrent access by different tasks.
-
-            SSL.Lock_Task.all;
-
-            --  Start at the last digit
-
-            Pos := Temp_File_Name_Last_Digit;
-
-            Digit_Loop :
-            loop
-               --  Increment the digit by one
-
-               case Current_Temp_File_Name (Pos) is
-                  when '0' .. '8' =>
-                     Current_Temp_File_Name (Pos) :=
-                       Character'Succ (Current_Temp_File_Name (Pos));
-                     exit Digit_Loop;
-
-                  when '9' =>
-
-                     --  For 9, set the digit to 0 and go to the previous digit
-
-                     Current_Temp_File_Name (Pos) := '0';
-                     Pos := Pos - 1;
-
-                  when others =>
-
-                     --  If it is not a digit, then there are no available
-                     --  temp file names. Return Invalid_FD. There is almost
-                     --  no that this code will be ever be executed, since
-                     --  it would mean that there are one million temp files
-                     --  in the same directory!
-
-                     SSL.Unlock_Task.all;
-                     FD := Invalid_FD;
-                     Name := null;
-                     exit File_Loop;
-               end case;
-            end loop Digit_Loop;
-
-            Current := Current_Temp_File_Name;
-
-            --  We can now release the lock, because we are no longer
-            --  accessing Current_Temp_File_Name.
-
-            SSL.Unlock_Task.all;
-
-         exception
-            when others =>
-               SSL.Unlock_Task.all;
-               raise;
-         end Locked;
-
-         --  Attempt to create the file
-
-         FD := Create_New_File (Current, Binary);
-
-         if FD /= Invalid_FD then
-            Name := new String'(Current);
-            exit File_Loop;
-         end if;
-
-         if not Is_Regular_File (Current) then
-
-            --  If the file does not already exist and we are unable to create
-            --  it, we give up after Max_Attempts. Otherwise, we try again with
-            --  the next available file name.
-
-            Attempts := Attempts + 1;
-
-            if Attempts >= Max_Attempts then
-               FD := Invalid_FD;
-               Name := null;
-               exit File_Loop;
-            end if;
-         end if;
-      end loop File_Loop;
-   end Create_Temp_File;
-
-   -----------------
-   -- Delete_File --
-   -----------------
-
-   procedure Delete_File (Name : Address; Success : out Boolean) is
-      R : Integer;
-
-      function unlink (A : Address) return Integer;
-      pragma Import (C, unlink, "unlink");
-
-   begin
-      R := unlink (Name);
-      Success := (R = 0);
-   end Delete_File;
-
-   procedure Delete_File (Name : String; Success : out Boolean) is
-      C_Name : String (1 .. Name'Length + 1);
-
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-
-      Delete_File (C_Name'Address, Success);
-   end Delete_File;
-
-   ---------------------
-   -- File_Time_Stamp --
-   ---------------------
-
-   function File_Time_Stamp (FD : File_Descriptor) return OS_Time is
-      function File_Time (FD    : File_Descriptor) return OS_Time;
-      pragma Import (C, File_Time, "__gnat_file_time_fd");
-   begin
-      return File_Time (FD);
-   end File_Time_Stamp;
-
-   function File_Time_Stamp (Name : C_File_Name) return OS_Time is
-      function File_Time (Name : Address) return OS_Time;
-      pragma Import (C, File_Time, "__gnat_file_time_name");
-   begin
-      return File_Time (Name);
-   end File_Time_Stamp;
-
-   function File_Time_Stamp (Name : String) return OS_Time is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return File_Time_Stamp (F_Name'Address);
-   end File_Time_Stamp;
-
-   ---------------------------
-   -- Get_Debuggable_Suffix --
-   ---------------------------
-
-   function Get_Debuggable_Suffix return String_Access is
-      procedure Get_Suffix_Ptr (Length, Ptr : Address);
-      pragma Import (C, Get_Suffix_Ptr, "__gnat_get_debuggable_suffix_ptr");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      Suffix_Ptr    : Address;
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Debuggable_Suffix;
-
-   ---------------------------
-   -- Get_Executable_Suffix --
-   ---------------------------
-
-   function Get_Executable_Suffix return String_Access is
-      procedure Get_Suffix_Ptr (Length, Ptr : Address);
-      pragma Import (C, Get_Suffix_Ptr, "__gnat_get_executable_suffix_ptr");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      Suffix_Ptr    : Address;
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Executable_Suffix;
-
-   -----------------------
-   -- Get_Object_Suffix --
-   -----------------------
-
-   function Get_Object_Suffix return String_Access is
-      procedure Get_Suffix_Ptr (Length, Ptr : Address);
-      pragma Import (C, Get_Suffix_Ptr, "__gnat_get_object_suffix_ptr");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      Suffix_Ptr    : Address;
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Object_Suffix;
-
-   ----------------------------------
-   -- Get_Target_Debuggable_Suffix --
-   ----------------------------------
-
-   function Get_Target_Debuggable_Suffix return String_Access is
-      Target_Exec_Ext_Ptr : Address;
-      pragma Import
-        (C, Target_Exec_Ext_Ptr, "__gnat_target_debuggable_extension");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      function Strlen (Cstring : Address) return Integer;
-      pragma Import (C, Strlen, "strlen");
-
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Suffix_Length := Strlen (Target_Exec_Ext_Ptr);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Target_Exec_Ext_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Target_Debuggable_Suffix;
-
-   ----------------------------------
-   -- Get_Target_Executable_Suffix --
-   ----------------------------------
-
-   function Get_Target_Executable_Suffix return String_Access is
-      Target_Exec_Ext_Ptr : Address;
-      pragma Import
-        (C, Target_Exec_Ext_Ptr, "__gnat_target_executable_extension");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      function Strlen (Cstring : Address) return Integer;
-      pragma Import (C, Strlen, "strlen");
-
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Suffix_Length := Strlen (Target_Exec_Ext_Ptr);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Target_Exec_Ext_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Target_Executable_Suffix;
-
-   ------------------------------
-   -- Get_Target_Object_Suffix --
-   ------------------------------
-
-   function Get_Target_Object_Suffix return String_Access is
-      Target_Object_Ext_Ptr : Address;
-      pragma Import
-        (C, Target_Object_Ext_Ptr, "__gnat_target_object_extension");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      function Strlen (Cstring : Address) return Integer;
-      pragma Import (C, Strlen, "strlen");
-
-      Suffix_Length : Integer;
-      Result        : String_Access;
-
-   begin
-      Suffix_Length := Strlen (Target_Object_Ext_Ptr);
-
-      Result := new String (1 .. Suffix_Length);
-
-      if Suffix_Length > 0 then
-         Strncpy (Result.all'Address, Target_Object_Ext_Ptr, Suffix_Length);
-      end if;
-
-      return Result;
-   end Get_Target_Object_Suffix;
-
-   ------------
-   -- Getenv --
-   ------------
-
-   function Getenv (Name : String) return String_Access is
-      procedure Get_Env_Value_Ptr (Name, Length, Ptr : Address);
-      pragma Import (C, Get_Env_Value_Ptr, "__gnat_getenv");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      Env_Value_Ptr    : aliased Address;
-      Env_Value_Length : aliased Integer;
-      F_Name           : aliased String (1 .. Name'Length + 1);
-      Result           : String_Access;
-
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-
-      Get_Env_Value_Ptr
-        (F_Name'Address, Env_Value_Length'Address, Env_Value_Ptr'Address);
-
-      Result := new String (1 .. Env_Value_Length);
-
-      if Env_Value_Length > 0 then
-         Strncpy (Result.all'Address, Env_Value_Ptr, Env_Value_Length);
-      end if;
-
-      return Result;
-   end Getenv;
-
-   ------------
-   -- GM_Day --
-   ------------
-
-   function GM_Day (Date : OS_Time) return Day_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return D;
-   end GM_Day;
-
-   -------------
-   -- GM_Hour --
-   -------------
-
-   function GM_Hour (Date : OS_Time) return Hour_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return H;
-   end GM_Hour;
-
-   ---------------
-   -- GM_Minute --
-   ---------------
-
-   function GM_Minute (Date : OS_Time) return Minute_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return Mn;
-   end GM_Minute;
-
-   --------------
-   -- GM_Month --
-   --------------
-
-   function GM_Month (Date : OS_Time) return Month_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return Mo;
-   end GM_Month;
-
-   ---------------
-   -- GM_Second --
-   ---------------
-
-   function GM_Second (Date : OS_Time) return Second_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return S;
-   end GM_Second;
-
-   --------------
-   -- GM_Split --
-   --------------
-
-   procedure GM_Split
-     (Date   : OS_Time;
-      Year   : out Year_Type;
-      Month  : out Month_Type;
-      Day    : out Day_Type;
-      Hour   : out Hour_Type;
-      Minute : out Minute_Type;
-      Second : out Second_Type)
-   is
-      procedure To_GM_Time
-        (P_Time_T, P_Year, P_Month, P_Day, P_Hours, P_Mins, P_Secs : Address);
-      pragma Import (C, To_GM_Time, "__gnat_to_gm_time");
-
-      T  : OS_Time := Date;
-      Y  : Integer;
-      Mo : Integer;
-      D  : Integer;
-      H  : Integer;
-      Mn : Integer;
-      S  : Integer;
-
-   begin
-      --  Use the global lock because To_GM_Time is not thread safe
-
-      Locked_Processing : begin
-         SSL.Lock_Task.all;
-         To_GM_Time
-           (T'Address, Y'Address, Mo'Address, D'Address,
-            H'Address, Mn'Address, S'Address);
-         SSL.Unlock_Task.all;
-
-      exception
-         when others =>
-            SSL.Unlock_Task.all;
-            raise;
-      end Locked_Processing;
-
-      Year   := Y + 1900;
-      Month  := Mo + 1;
-      Day    := D;
-      Hour   := H;
-      Minute := Mn;
-      Second := S;
-   end GM_Split;
-
-   -------------
-   -- GM_Year --
-   -------------
-
-   function GM_Year (Date : OS_Time) return Year_Type is
-      Y  : Year_Type;
-      Mo : Month_Type;
-      D  : Day_Type;
-      H  : Hour_Type;
-      Mn : Minute_Type;
-      S  : Second_Type;
-
-   begin
-      GM_Split (Date, Y, Mo, D, H, Mn, S);
-      return Y;
-   end GM_Year;
-
-   ----------------------
-   -- Is_Absolute_Path --
-   ----------------------
-
-   function Is_Absolute_Path (Name : String) return Boolean is
-      function Is_Absolute_Path
-        (Name   : Address;
-         Length : Integer) return Integer;
-      pragma Import (C, Is_Absolute_Path, "__gnat_is_absolute_path");
-   begin
-      return Is_Absolute_Path (Name'Address, Name'Length) /= 0;
-   end Is_Absolute_Path;
-
-   ------------------
-   -- Is_Directory --
-   ------------------
-
-   function Is_Directory (Name : C_File_Name) return Boolean is
-      function Is_Directory (Name : Address) return Integer;
-      pragma Import (C, Is_Directory, "__gnat_is_directory");
-   begin
-      return Is_Directory (Name) /= 0;
-   end Is_Directory;
-
-   function Is_Directory (Name : String) return Boolean is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return Is_Directory (F_Name'Address);
-   end Is_Directory;
-
-   ----------------------
-   -- Is_Readable_File --
-   ----------------------
-
-   function Is_Readable_File (Name : C_File_Name) return Boolean is
-      function Is_Readable_File (Name : Address) return Integer;
-      pragma Import (C, Is_Readable_File, "__gnat_is_readable_file");
-   begin
-      return Is_Readable_File (Name) /= 0;
-   end Is_Readable_File;
-
-   function Is_Readable_File (Name : String) return Boolean is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return Is_Readable_File (F_Name'Address);
-   end Is_Readable_File;
-
-   ---------------------
-   -- Is_Regular_File --
-   ---------------------
-
-   function Is_Regular_File (Name : C_File_Name) return Boolean is
-      function Is_Regular_File (Name : Address) return Integer;
-      pragma Import (C, Is_Regular_File, "__gnat_is_regular_file");
-   begin
-      return Is_Regular_File (Name) /= 0;
-   end Is_Regular_File;
-
-   function Is_Regular_File (Name : String) return Boolean is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return Is_Regular_File (F_Name'Address);
-   end Is_Regular_File;
-
-   ----------------------
-   -- Is_Symbolic_Link --
-   ----------------------
-
-   function Is_Symbolic_Link (Name : C_File_Name) return Boolean is
-      function Is_Symbolic_Link (Name : Address) return Integer;
-      pragma Import (C, Is_Symbolic_Link, "__gnat_is_symbolic_link");
-   begin
-      return Is_Symbolic_Link (Name) /= 0;
-   end Is_Symbolic_Link;
-
-   function Is_Symbolic_Link (Name : String) return Boolean is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return Is_Symbolic_Link (F_Name'Address);
-   end Is_Symbolic_Link;
-
-   ----------------------
-   -- Is_Writable_File --
-   ----------------------
-
-   function Is_Writable_File (Name : C_File_Name) return Boolean is
-      function Is_Writable_File (Name : Address) return Integer;
-      pragma Import (C, Is_Writable_File, "__gnat_is_writable_file");
-   begin
-      return Is_Writable_File (Name) /= 0;
-   end Is_Writable_File;
-
-   function Is_Writable_File (Name : String) return Boolean is
-      F_Name : String (1 .. Name'Length + 1);
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-      return Is_Writable_File (F_Name'Address);
-   end Is_Writable_File;
-
-   -------------------------
-   -- Locate_Exec_On_Path --
-   -------------------------
-
-   function Locate_Exec_On_Path
-     (Exec_Name : String) return String_Access
-   is
-      function Locate_Exec_On_Path (C_Exec_Name : Address) return Address;
-      pragma Import (C, Locate_Exec_On_Path, "__gnat_locate_exec_on_path");
-
-      procedure Free (Ptr : System.Address);
-      pragma Import (C, Free, "free");
-
-      C_Exec_Name  : String (1 .. Exec_Name'Length + 1);
-      Path_Addr    : Address;
-      Path_Len     : Integer;
-      Result       : String_Access;
-
-   begin
-      C_Exec_Name (1 .. Exec_Name'Length)   := Exec_Name;
-      C_Exec_Name (C_Exec_Name'Last)        := ASCII.NUL;
-
-      Path_Addr := Locate_Exec_On_Path (C_Exec_Name'Address);
-      Path_Len  := C_String_Length (Path_Addr);
-
-      if Path_Len = 0 then
-         return null;
-
-      else
-         Result := To_Path_String_Access (Path_Addr, Path_Len);
-         Free (Path_Addr);
-
-         --  Always return an absolute path name
-
-         if not Is_Absolute_Path (Result.all) then
-            declare
-               Absolute_Path : constant String :=
-                                 Normalize_Pathname (Result.all);
-            begin
-               Free (Result);
-               Result := new String'(Absolute_Path);
-            end;
-         end if;
-
-         return Result;
-      end if;
-   end Locate_Exec_On_Path;
-
-   -------------------------
-   -- Locate_Regular_File --
-   -------------------------
-
-   function Locate_Regular_File
-     (File_Name : C_File_Name;
-      Path      : C_File_Name) return String_Access
-   is
-      function Locate_Regular_File
-        (C_File_Name, Path_Val : Address) return Address;
-      pragma Import (C, Locate_Regular_File, "__gnat_locate_regular_file");
-
-      procedure Free (Ptr : System.Address);
-      pragma Import (C, Free, "free");
-
-      Path_Addr    : Address;
-      Path_Len     : Integer;
-      Result       : String_Access;
-
-   begin
-      Path_Addr := Locate_Regular_File (File_Name, Path);
-      Path_Len  := C_String_Length (Path_Addr);
-
-      if Path_Len = 0 then
-         return null;
-      else
-         Result := To_Path_String_Access (Path_Addr, Path_Len);
-         Free (Path_Addr);
-         return Result;
-      end if;
-   end Locate_Regular_File;
-
-   function Locate_Regular_File
-     (File_Name : String;
-      Path      : String) return String_Access
-   is
-      C_File_Name : String (1 .. File_Name'Length + 1);
-      C_Path      : String (1 .. Path'Length + 1);
-      Result      : String_Access;
-
-   begin
-      C_File_Name (1 .. File_Name'Length)   := File_Name;
-      C_File_Name (C_File_Name'Last)        := ASCII.NUL;
-
-      C_Path    (1 .. Path'Length)          := Path;
-      C_Path    (C_Path'Last)               := ASCII.NUL;
-
-      Result := Locate_Regular_File (C_File_Name'Address, C_Path'Address);
-
-      --  Always return an absolute path name
-
-      if Result /= null and then not Is_Absolute_Path (Result.all) then
-         declare
-            Absolute_Path : constant String := Normalize_Pathname (Result.all);
-         begin
-            Free (Result);
-            Result := new String'(Absolute_Path);
-         end;
-      end if;
-
-      return Result;
-   end Locate_Regular_File;
-
-   ------------------------
-   -- Non_Blocking_Spawn --
-   ------------------------
-
-   function Non_Blocking_Spawn
-     (Program_Name : String;
-      Args         : Argument_List) return Process_Id
-   is
-      Junk : Integer;
-      Pid  : Process_Id;
-
-   begin
-      Spawn_Internal (Program_Name, Args, Junk, Pid, Blocking => False);
-      return Pid;
-   end Non_Blocking_Spawn;
-
-   function Non_Blocking_Spawn
-     (Program_Name           : String;
-      Args                   : Argument_List;
-      Output_File_Descriptor : File_Descriptor;
-      Err_To_Out             : Boolean := True) return Process_Id
-   is
-      Saved_Output : File_Descriptor;
-      Saved_Error  : File_Descriptor := Invalid_FD; -- prevent warning
-      Pid          : Process_Id;
-
-   begin
-      if Output_File_Descriptor = Invalid_FD then
-         return Invalid_Pid;
-      end if;
-
-      --  Set standard output and, if specified, error to the temporary file
-
-      Saved_Output := Dup (Standout);
-      Dup2 (Output_File_Descriptor, Standout);
-
-      if Err_To_Out then
-         Saved_Error  := Dup (Standerr);
-         Dup2 (Output_File_Descriptor, Standerr);
-      end if;
-
-      --  Spawn the program
-
-      Pid := Non_Blocking_Spawn (Program_Name, Args);
-
-      --  Restore the standard output and error
-
-      Dup2 (Saved_Output, Standout);
-
-      if Err_To_Out then
-         Dup2 (Saved_Error, Standerr);
-      end if;
-
-      --  And close the saved standard output and error file descriptors
-
-      Close (Saved_Output);
-
-      if Err_To_Out then
-         Close (Saved_Error);
-      end if;
-
-      return Pid;
-   end Non_Blocking_Spawn;
-
-   function Non_Blocking_Spawn
-     (Program_Name : String;
-      Args         : Argument_List;
-      Output_File  : String;
-      Err_To_Out   : Boolean := True) return Process_Id
-   is
-      Output_File_Descriptor : constant File_Descriptor :=
-                                 Create_Output_Text_File (Output_File);
-      Result : Process_Id;
-
-   begin
-      --  Do not attempt to spawn if the output file could not be created
-
-      if Output_File_Descriptor = Invalid_FD then
-         return Invalid_Pid;
-
-      else
-         Result := Non_Blocking_Spawn
-                     (Program_Name, Args, Output_File_Descriptor, Err_To_Out);
-
-         --  Close the file just created for the output, as the file descriptor
-         --  cannot be used anywhere, being a local value. It is safe to do
-         --  that, as the file descriptor has been duplicated to form
-         --  standard output and error of the spawned process.
-
-         Close (Output_File_Descriptor);
-
-         return Result;
-      end if;
-   end Non_Blocking_Spawn;
-
-   -------------------------
-   -- Normalize_Arguments --
-   -------------------------
-
-   procedure Normalize_Arguments (Args : in out Argument_List) is
-
-      procedure Quote_Argument (Arg : in out String_Access);
-      --  Add quote around argument if it contains spaces
-
-      C_Argument_Needs_Quote : Integer;
-      pragma Import (C, C_Argument_Needs_Quote, "__gnat_argument_needs_quote");
-      Argument_Needs_Quote : constant Boolean := C_Argument_Needs_Quote /= 0;
-
-      --------------------
-      -- Quote_Argument --
-      --------------------
-
-      procedure Quote_Argument (Arg : in out String_Access) is
-         Res          : String (1 .. Arg'Length * 2);
-         J            : Positive := 1;
-         Quote_Needed : Boolean  := False;
-
-      begin
-         if Arg (Arg'First) /= '"' or else Arg (Arg'Last) /= '"' then
-
-            --  Starting quote
-
-            Res (J) := '"';
-
-            for K in Arg'Range loop
-
-               J := J + 1;
-
-               if Arg (K) = '"' then
-                  Res (J) := '\';
-                  J := J + 1;
-                  Res (J) := '"';
-                  Quote_Needed := True;
-
-               elsif Arg (K) = ' ' then
-                  Res (J) := Arg (K);
-                  Quote_Needed := True;
-
-               else
-                  Res (J) := Arg (K);
-               end if;
-
-            end loop;
-
-            if Quote_Needed then
-
-               --  If null terminated string, put the quote before
-
-               if Res (J) = ASCII.Nul then
-                  Res (J) := '"';
-                  J := J + 1;
-                  Res (J) := ASCII.Nul;
-
-               --  If argument is terminated by '\', then double it. Otherwise
-               --  the ending quote will be taken as-is. This is quite strange
-               --  spawn behavior from Windows, but this is what we see!
-
-               else
-                  if Res (J) = '\' then
-                     J := J + 1;
-                     Res (J) := '\';
-                  end if;
-
-                  --  Ending quote
-
-                  J := J + 1;
-                  Res (J) := '"';
-               end if;
-
-               declare
-                  Old : String_Access := Arg;
-
-               begin
-                  Arg := new String'(Res (1 .. J));
-                  Free (Old);
-               end;
-            end if;
-
-         end if;
-      end Quote_Argument;
-
-   --  Start of processing for Normalize_Arguments
-
-   begin
-      if Argument_Needs_Quote then
-         for K in Args'Range loop
-            if Args (K) /= null and then Args (K)'Length /= 0 then
-               Quote_Argument (Args (K));
-            end if;
-         end loop;
-      end if;
-   end Normalize_Arguments;
-
-   ------------------------
-   -- Normalize_Pathname --
-   ------------------------
-
-   function Normalize_Pathname
-     (Name           : String;
-      Directory      : String  := "";
-      Resolve_Links  : Boolean := True;
-      Case_Sensitive : Boolean := True) return String
-   is
-      Max_Path : Integer;
-      pragma Import (C, Max_Path, "__gnat_max_path_len");
-      --  Maximum length of a path name
-
-      procedure Get_Current_Dir
-        (Dir    : System.Address;
-         Length : System.Address);
-      pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
-
-      Path_Buffer : String (1 .. Max_Path + Max_Path + 2);
-      End_Path    : Natural := 0;
-      Link_Buffer : String (1 .. Max_Path + 2);
-      Status      : Integer;
-      Last        : Positive;
-      Start       : Natural;
-      Finish      : Positive;
-
-      Max_Iterations : constant := 500;
-
-      function Get_File_Names_Case_Sensitive return Integer;
-      pragma Import
-        (C, Get_File_Names_Case_Sensitive,
-         "__gnat_get_file_names_case_sensitive");
-
-      Fold_To_Lower_Case : constant Boolean :=
-                             not Case_Sensitive
-                               and then Get_File_Names_Case_Sensitive = 0;
-
-      function Readlink
-        (Path   : System.Address;
-         Buf    : System.Address;
-         Bufsiz : Integer) return Integer;
-      pragma Import (C, Readlink, "__gnat_readlink");
-
-      function To_Canonical_File_Spec
-        (Host_File : System.Address) return System.Address;
-      pragma Import
-        (C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
-
-      The_Name : String (1 .. Name'Length + 1);
-      Canonical_File_Addr : System.Address;
-      Canonical_File_Len  : Integer;
-
-      Need_To_Check_Drive_Letter : Boolean := False;
-      --  Set to true if Name is an absolute path that starts with "//"
-
-      function Strlen (S : System.Address) return Integer;
-      pragma Import (C, Strlen, "strlen");
-
-      function Final_Value (S : String) return String;
-      --  Make final adjustment to the returned string.
-      --  To compensate for non standard path name in Interix,
-      --  if S is "/x" or starts with "/x", where x is a capital
-      --  letter 'A' to 'Z', add an additional '/' at the beginning
-      --  so that the returned value starts with "//x".
-
-      function Get_Directory  (Dir : String) return String;
-      --  If Dir is not empty, return it, adding a directory separator
-      --  if not already present, otherwise return current working directory
-      --  with terminating directory separator.
-
-      -----------------
-      -- Final_Value --
-      -----------------
-
-      function Final_Value (S : String) return String is
-         S1 : String := S;
-         --  We may need to fold S to lower case, so we need a variable
-
-         Last : Natural;
-
-      begin
-         --  Interix has the non standard notion of disk drive
-         --  indicated by two '/' followed by a capital letter
-         --  'A' .. 'Z'. One of the two '/' may have been removed
-         --  by Normalize_Pathname. It has to be added again.
-         --  For other OSes, this should not make no difference.
-
-         if Need_To_Check_Drive_Letter
-           and then S'Length >= 2
-           and then S (S'First) = '/'
-           and then S (S'First + 1) in 'A' .. 'Z'
-           and then (S'Length = 2 or else S (S'First + 2) = '/')
-         then
-            declare
-               Result : String (1 .. S'Length + 1);
-
-            begin
-               Result (1) := '/';
-               Result (2 .. Result'Last) := S;
-               Last := Result'Last;
-
-               if Fold_To_Lower_Case then
-                  System.Case_Util.To_Lower (Result);
-               end if;
-
-               --  Remove trailing directory separator, if any
-
-               if Last > 1 and then
-                 (Result (Last) = '/' or else
-                  Result (Last) = Directory_Separator)
-               then
-                  Last := Last - 1;
-               end if;
-
-               return Result (1 .. Last);
-            end;
-
-         else
-            if Fold_To_Lower_Case then
-               System.Case_Util.To_Lower (S1);
-            end if;
-
-            --  Remove trailing directory separator, if any
-
-            Last := S1'Last;
-
-            if Last > 1
-              and then (S1 (Last) = '/'
-                          or else
-                        S1 (Last) = Directory_Separator)
-            then
-               --  Special case for Windows: C:\
-
-               if Last = 3
-                 and then S1 (1) /= Directory_Separator
-                 and then S1 (2) = ':'
-               then
-                  null;
-
-               else
-                  Last := Last - 1;
-               end if;
-            end if;
-
-            return S1 (1 .. Last);
-         end if;
-      end Final_Value;
-
-      -------------------
-      -- Get_Directory --
-      -------------------
-
-      function Get_Directory (Dir : String) return String is
-      begin
-         --  Directory given, add directory separator if needed
-
-         if Dir'Length > 0 then
-            if Dir (Dir'Last) = Directory_Separator then
-               return Directory;
-            else
-               declare
-                  Result : String (1 .. Dir'Length + 1);
-               begin
-                  Result (1 .. Dir'Length) := Dir;
-                  Result (Result'Length) := Directory_Separator;
-                  return Result;
-               end;
-            end if;
-
-         --  Directory name not given, get current directory
-
-         else
-            declare
-               Buffer   : String (1 .. Max_Path + 2);
-               Path_Len : Natural := Max_Path;
-
-            begin
-               Get_Current_Dir (Buffer'Address, Path_Len'Address);
-
-               if Buffer (Path_Len) /= Directory_Separator then
-                  Path_Len := Path_Len + 1;
-                  Buffer (Path_Len) := Directory_Separator;
-               end if;
-
-               --  By default, the drive letter on Windows is in upper case
-
-               if On_Windows and then Path_Len >= 2 and then
-                 Buffer (2) = ':'
-               then
-                  System.Case_Util.To_Upper (Buffer (1 .. 1));
-               end if;
-
-               return Buffer (1 .. Path_Len);
-            end;
-         end if;
-      end Get_Directory;
-
-      Reference_Dir : constant String := Get_Directory (Directory);
-      --  Current directory name specified
-
-   --  Start of processing for Normalize_Pathname
-
-   begin
-      --  Special case, if name is null, then return null
-
-      if Name'Length = 0 then
-         return "";
-      end if;
-
-      --  First, convert VMS file spec to Unix file spec.
-      --  If Name is not in VMS syntax, then this is equivalent
-      --  to put Name at the begining of Path_Buffer.
-
-      VMS_Conversion : begin
-         The_Name (1 .. Name'Length) := Name;
-         The_Name (The_Name'Last) := ASCII.NUL;
-
-         Canonical_File_Addr := To_Canonical_File_Spec (The_Name'Address);
-         Canonical_File_Len  := Strlen (Canonical_File_Addr);
-
-         --  If VMS syntax conversion has failed, return an empty string
-         --  to indicate the failure.
-
-         if Canonical_File_Len = 0 then
-            return "";
-         end if;
-
-         declare
-            subtype Path_String is String (1 .. Canonical_File_Len);
-            type    Path_String_Access is access Path_String;
-
-            function Address_To_Access is new
-               Unchecked_Conversion (Source => Address,
-                                     Target => Path_String_Access);
-
-            Path_Access : constant Path_String_Access :=
-                            Address_To_Access (Canonical_File_Addr);
-
-         begin
-            Path_Buffer (1 .. Canonical_File_Len) := Path_Access.all;
-            End_Path := Canonical_File_Len;
-            Last := 1;
-         end;
-      end VMS_Conversion;
-
-      --  Replace all '/' by Directory Separators (this is for Windows)
-
-      if Directory_Separator /= '/' then
-         for Index in 1 .. End_Path loop
-            if Path_Buffer (Index) = '/' then
-               Path_Buffer (Index) := Directory_Separator;
-            end if;
-         end loop;
-      end if;
-
-      --  Resolve directory names for Windows (formerly also VMS)
-
-      --  On VMS, if we have a Unix path such as /temp/..., and TEMP is a
-      --  logical name, we must not try to resolve this logical name, because
-      --  it may have multiple equivalences and if resolved we will only
-      --  get the first one.
-
-      --  On Windows, if we have an absolute path starting with a directory
-      --  separator, we need to have the drive letter appended in front.
-
-      --  On Windows, Get_Current_Dir will return a suitable directory
-      --  name (path starting with a drive letter on Windows). So we take this
-      --  drive letter and prepend it to the current path.
-
-      if On_Windows
-        and then Path_Buffer (1) = Directory_Separator
-        and then Path_Buffer (2) /= Directory_Separator
-      then
-         declare
-            Cur_Dir : String := Get_Directory ("");
-            --  Get the current directory to get the drive letter
-
-         begin
-            if Cur_Dir'Length > 2
-              and then Cur_Dir (Cur_Dir'First + 1) = ':'
-            then
-               Path_Buffer (3 .. End_Path + 2) := Path_Buffer (1 .. End_Path);
-               Path_Buffer (1 .. 2) :=
-                 Cur_Dir (Cur_Dir'First .. Cur_Dir'First + 1);
-               End_Path := End_Path + 2;
-            end if;
-         end;
-      end if;
-
-      --  Start the conversions
-
-      --  If this is not finished after Max_Iterations, give up and return an
-      --  empty string.
-
-      for J in 1 .. Max_Iterations loop
-
-         --  If we don't have an absolute pathname, prepend the directory
-         --  Reference_Dir.
-
-         if Last = 1
-           and then not Is_Absolute_Path (Path_Buffer (1 .. End_Path))
-         then
-            Path_Buffer
-              (Reference_Dir'Last + 1 .. Reference_Dir'Length + End_Path) :=
-                 Path_Buffer (1 .. End_Path);
-            End_Path := Reference_Dir'Length + End_Path;
-            Path_Buffer (1 .. Reference_Dir'Length) := Reference_Dir;
-            Last := Reference_Dir'Length;
-         end if;
-
-         --  If name starts with "//", we may have a drive letter on Interix
-
-         if Last = 1 and then End_Path >= 3 then
-            Need_To_Check_Drive_Letter := (Path_Buffer (1 .. 2)) = "//";
-         end if;
-
-         Start  := Last + 1;
-         Finish := Last;
-
-         --  Ensure that Windows network drives are kept, e.g: \\server\drive-c
-
-         if Start = 2
-           and then Directory_Separator = '\'
-           and then Path_Buffer (1 .. 2) = "\\"
-         then
-            Start := 3;
-         end if;
-
-         --  If we have traversed the full pathname, return it
-
-         if Start > End_Path then
-            return Final_Value (Path_Buffer (1 .. End_Path));
-         end if;
-
-         --  Remove duplicate directory separators
-
-         while Path_Buffer (Start) = Directory_Separator loop
-            if Start = End_Path then
-               return Final_Value (Path_Buffer (1 .. End_Path - 1));
-
-            else
-               Path_Buffer (Start .. End_Path - 1) :=
-                 Path_Buffer (Start + 1 .. End_Path);
-               End_Path := End_Path - 1;
-            end if;
-         end loop;
-
-         --  Find the end of the current field: last character or the one
-         --  preceding the next directory separator.
-
-         while Finish < End_Path
-           and then Path_Buffer (Finish + 1) /= Directory_Separator
-         loop
-            Finish := Finish + 1;
-         end loop;
-
-         --  Remove "." field
-
-         if Start = Finish and then Path_Buffer (Start) = '.' then
-            if Start = End_Path then
-               if Last = 1 then
-                  return (1 => Directory_Separator);
-               else
-
-                  if Fold_To_Lower_Case then
-                     System.Case_Util.To_Lower (Path_Buffer (1 .. Last - 1));
-                  end if;
-
-                  return Path_Buffer (1 .. Last - 1);
-
-               end if;
-
-            else
-               Path_Buffer (Last + 1 .. End_Path - 2) :=
-                 Path_Buffer (Last + 3 .. End_Path);
-               End_Path := End_Path - 2;
-            end if;
-
-         --  Remove ".." fields
-
-         elsif Finish = Start + 1
-           and then Path_Buffer (Start .. Finish) = ".."
-         then
-            Start := Last;
-            loop
-               Start := Start - 1;
-               exit when Start < 1 or else
-                 Path_Buffer (Start) = Directory_Separator;
-            end loop;
-
-            if Start <= 1 then
-               if Finish = End_Path then
-                  return (1 => Directory_Separator);
-
-               else
-                  Path_Buffer (1 .. End_Path - Finish) :=
-                    Path_Buffer (Finish + 1 .. End_Path);
-                  End_Path := End_Path - Finish;
-                  Last := 1;
-               end if;
-
-            else
-               if Finish = End_Path then
-                  return Final_Value (Path_Buffer (1 .. Start - 1));
-
-               else
-                  Path_Buffer (Start + 1 .. Start + End_Path - Finish - 1) :=
-                    Path_Buffer (Finish + 2 .. End_Path);
-                  End_Path := Start + End_Path - Finish - 1;
-                  Last := Start;
-               end if;
-            end if;
-
-         --  Check if current field is a symbolic link
-
-         elsif Resolve_Links then
-            declare
-               Saved : constant Character := Path_Buffer (Finish + 1);
-
-            begin
-               Path_Buffer (Finish + 1) := ASCII.NUL;
-               Status := Readlink (Path_Buffer'Address,
-                                   Link_Buffer'Address,
-                                   Link_Buffer'Length);
-               Path_Buffer (Finish + 1) := Saved;
-            end;
-
-            --  Not a symbolic link, move to the next field, if any
-
-            if Status <= 0 then
-               Last := Finish + 1;
-
-            --  Replace symbolic link with its value
-
-            else
-               if Is_Absolute_Path (Link_Buffer (1 .. Status)) then
-                  Path_Buffer (Status + 1 .. End_Path - (Finish - Status)) :=
-                  Path_Buffer (Finish + 1 .. End_Path);
-                  End_Path := End_Path - (Finish - Status);
-                  Path_Buffer (1 .. Status) := Link_Buffer (1 .. Status);
-                  Last := 1;
-
-               else
-                  Path_Buffer
-                    (Last + Status + 1 .. End_Path - Finish + Last + Status) :=
-                    Path_Buffer (Finish + 1 .. End_Path);
-                  End_Path := End_Path - Finish + Last + Status;
-                  Path_Buffer (Last + 1 .. Last + Status) :=
-                    Link_Buffer (1 .. Status);
-               end if;
-            end if;
-
-         else
-            Last := Finish + 1;
-         end if;
-      end loop;
-
-      --  Too many iterations: give up
-
-      --  This can happen when there is a circularity in the symbolic links: A
-      --  is a symbolic link for B, which itself is a symbolic link, and the
-      --  target of B or of another symbolic link target of B is A. In this
-      --  case, we return an empty string to indicate failure to resolve.
-
-      return "";
-   end Normalize_Pathname;
-
-   ---------------
-   -- Open_Read --
-   ---------------
-
-   function Open_Read
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor
-   is
-      function C_Open_Read
-        (Name  : C_File_Name;
-         Fmode : Mode) return File_Descriptor;
-      pragma Import (C, C_Open_Read, "__gnat_open_read");
-   begin
-      return C_Open_Read (Name, Fmode);
-   end Open_Read;
-
-   function Open_Read
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor
-   is
-      C_Name : String (1 .. Name'Length + 1);
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-      return Open_Read (C_Name (C_Name'First)'Address, Fmode);
-   end Open_Read;
-
-   ---------------------
-   -- Open_Read_Write --
-   ---------------------
-
-   function Open_Read_Write
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor
-   is
-      function C_Open_Read_Write
-        (Name  : C_File_Name;
-         Fmode : Mode) return File_Descriptor;
-      pragma Import (C, C_Open_Read_Write, "__gnat_open_rw");
-   begin
-      return C_Open_Read_Write (Name, Fmode);
-   end Open_Read_Write;
-
-   function Open_Read_Write
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor
-   is
-      C_Name : String (1 .. Name'Length + 1);
-   begin
-      C_Name (1 .. Name'Length) := Name;
-      C_Name (C_Name'Last)      := ASCII.NUL;
-      return Open_Read_Write (C_Name (C_Name'First)'Address, Fmode);
-   end Open_Read_Write;
-
-   --------------------
-   -- Pid_To_Integer --
-   --------------------
-
-   function Pid_To_Integer (Pid : Process_Id) return Integer is
-   begin
-      return Integer (Pid);
-   end Pid_To_Integer;
-
-   ----------
-   -- Read --
-   ----------
-
-   function Read
-     (FD : File_Descriptor;
-      A  : System.Address;
-      N  : Integer) return Integer
-   is
-   begin
-      return Integer (System.CRTL.read
-        (System.CRTL.int (FD), System.CRTL.chars (A), System.CRTL.int (N)));
-   end Read;
-
-   -----------------
-   -- Rename_File --
-   -----------------
-
-   procedure Rename_File
-     (Old_Name : C_File_Name;
-      New_Name : C_File_Name;
-      Success  : out Boolean)
-   is
-      function rename (From, To : Address) return Integer;
-      pragma Import (C, rename, "rename");
-      R : Integer;
-   begin
-      R := rename (Old_Name, New_Name);
-      Success := (R = 0);
-   end Rename_File;
-
-   procedure Rename_File
-     (Old_Name : String;
-      New_Name : String;
-      Success  : out Boolean)
-   is
-      C_Old_Name : String (1 .. Old_Name'Length + 1);
-      C_New_Name : String (1 .. New_Name'Length + 1);
-   begin
-      C_Old_Name (1 .. Old_Name'Length) := Old_Name;
-      C_Old_Name (C_Old_Name'Last)      := ASCII.NUL;
-      C_New_Name (1 .. New_Name'Length) := New_Name;
-      C_New_Name (C_New_Name'Last)      := ASCII.NUL;
-      Rename_File (C_Old_Name'Address, C_New_Name'Address, Success);
-   end Rename_File;
-
-   -----------------------
-   -- Set_Close_On_Exec --
-   -----------------------
-
-   procedure Set_Close_On_Exec
-     (FD            : File_Descriptor;
-      Close_On_Exec : Boolean;
-      Status        : out Boolean)
-   is
-      function C_Set_Close_On_Exec
-        (FD : File_Descriptor; Close_On_Exec : System.CRTL.int)
-         return System.CRTL.int;
-      pragma Import (C, C_Set_Close_On_Exec, "__gnat_set_close_on_exec");
-   begin
-      Status := C_Set_Close_On_Exec (FD, Boolean'Pos (Close_On_Exec)) = 0;
-   end Set_Close_On_Exec;
-
-   --------------------
-   -- Set_Executable --
-   --------------------
-
-   procedure Set_Executable (Name : String) is
-      procedure C_Set_Executable (Name : C_File_Name);
-      pragma Import (C, C_Set_Executable, "__gnat_set_executable");
-      C_Name : aliased String (Name'First .. Name'Last + 1);
-   begin
-      C_Name (Name'Range)  := Name;
-      C_Name (C_Name'Last) := ASCII.NUL;
-      C_Set_Executable (C_Name (C_Name'First)'Address);
-   end Set_Executable;
-
-   --------------------
-   -- Set_Read_Only --
-   --------------------
-
-   procedure Set_Read_Only (Name : String) is
-      procedure C_Set_Read_Only (Name : C_File_Name);
-      pragma Import (C, C_Set_Read_Only, "__gnat_set_readonly");
-      C_Name : aliased String (Name'First .. Name'Last + 1);
-   begin
-      C_Name (Name'Range)  := Name;
-      C_Name (C_Name'Last) := ASCII.NUL;
-      C_Set_Read_Only (C_Name (C_Name'First)'Address);
-   end Set_Read_Only;
-
-   --------------------
-   -- Set_Writable --
-   --------------------
-
-   procedure Set_Writable (Name : String) is
-      procedure C_Set_Writable (Name : C_File_Name);
-      pragma Import (C, C_Set_Writable, "__gnat_set_writable");
-      C_Name : aliased String (Name'First .. Name'Last + 1);
-   begin
-      C_Name (Name'Range)  := Name;
-      C_Name (C_Name'Last) := ASCII.NUL;
-      C_Set_Writable (C_Name (C_Name'First)'Address);
-   end Set_Writable;
-
-   ------------
-   -- Setenv --
-   ------------
-
-   procedure Setenv (Name : String; Value : String) is
-      F_Name  : String (1 .. Name'Length + 1);
-      F_Value : String (1 .. Value'Length + 1);
-
-      procedure Set_Env_Value (Name, Value : System.Address);
-      pragma Import (C, Set_Env_Value, "__gnat_setenv");
-
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-
-      F_Value (1 .. Value'Length) := Value;
-      F_Value (F_Value'Last)      := ASCII.NUL;
-
-      Set_Env_Value (F_Name'Address, F_Value'Address);
-   end Setenv;
-
-   -----------
-   -- Spawn --
-   -----------
-
-   function Spawn
-     (Program_Name : String;
-      Args         : Argument_List) return Integer
-   is
-      Junk   : Process_Id;
-      Result : Integer;
-   begin
-      Spawn_Internal (Program_Name, Args, Result, Junk, Blocking => True);
-      return Result;
-   end Spawn;
-
-   procedure Spawn
-     (Program_Name : String;
-      Args         : Argument_List;
-      Success      : out Boolean)
-   is
-   begin
-      Success := (Spawn (Program_Name, Args) = 0);
-   end Spawn;
-
-   procedure Spawn
-     (Program_Name           : String;
-      Args                   : Argument_List;
-      Output_File_Descriptor : File_Descriptor;
-      Return_Code            : out Integer;
-      Err_To_Out             : Boolean := True)
-   is
-      Saved_Output : File_Descriptor;
-      Saved_Error  : File_Descriptor := Invalid_FD; -- prevent compiler warning
-
-   begin
-      --  Set standard output and error to the temporary file
-
-      Saved_Output := Dup (Standout);
-      Dup2 (Output_File_Descriptor, Standout);
-
-      if Err_To_Out then
-         Saved_Error  := Dup (Standerr);
-         Dup2 (Output_File_Descriptor, Standerr);
-      end if;
-
-      --  Spawn the program
-
-      Return_Code := Spawn (Program_Name, Args);
-
-      --  Restore the standard output and error
-
-      Dup2 (Saved_Output, Standout);
-
-      if Err_To_Out then
-         Dup2 (Saved_Error, Standerr);
-      end if;
-
-      --  And close the saved standard output and error file descriptors
-
-      Close (Saved_Output);
-
-      if Err_To_Out then
-         Close (Saved_Error);
-      end if;
-   end Spawn;
-
-   procedure Spawn
-     (Program_Name  : String;
-      Args          : Argument_List;
-      Output_File   : String;
-      Success       : out Boolean;
-      Return_Code   : out Integer;
-      Err_To_Out    : Boolean := True)
-   is
-      FD : File_Descriptor;
-
-   begin
-      Success := True;
-      Return_Code := 0;
-
-      FD := Create_Output_Text_File (Output_File);
-
-      if FD = Invalid_FD then
-         Success := False;
-         return;
-      end if;
-
-      Spawn (Program_Name, Args, FD, Return_Code, Err_To_Out);
-
-      Close (FD, Success);
-   end Spawn;
-
-   --------------------
-   -- Spawn_Internal --
-   --------------------
-
-   procedure Spawn_Internal
-     (Program_Name : String;
-      Args         : Argument_List;
-      Result       : out Integer;
-      Pid          : out Process_Id;
-      Blocking     : Boolean)
-   is
-
-      procedure Spawn (Args : Argument_List);
-      --  Call Spawn with given argument list
-
-      N_Args : Argument_List (Args'Range);
-      --  Normalized arguments
-
-      -----------
-      -- Spawn --
-      -----------
-
-      procedure Spawn (Args : Argument_List) is
-         type Chars is array (Positive range <>) of aliased Character;
-         type Char_Ptr is access constant Character;
-
-         Command_Len : constant Positive := Program_Name'Length + 1
-                                              + Args_Length (Args);
-         Command_Last : Natural := 0;
-         Command : aliased Chars (1 .. Command_Len);
-         --  Command contains all characters of the Program_Name and Args, all
-         --  terminated by ASCII.NUL characters
-
-         Arg_List_Len : constant Positive := Args'Length + 2;
-         Arg_List_Last : Natural := 0;
-         Arg_List : aliased array (1 .. Arg_List_Len) of Char_Ptr;
-         --  List with pointers to NUL-terminated strings of the Program_Name
-         --  and the Args and terminated with a null pointer. We rely on the
-         --  default initialization for the last null pointer.
-
-         procedure Add_To_Command (S : String);
-         --  Add S and a NUL character to Command, updating Last
-
-         function Portable_Spawn (Args : Address) return Integer;
-         pragma Import (C, Portable_Spawn, "__gnat_portable_spawn");
-
-         function Portable_No_Block_Spawn (Args : Address) return Process_Id;
-         pragma Import
-           (C, Portable_No_Block_Spawn, "__gnat_portable_no_block_spawn");
-
-         --------------------
-         -- Add_To_Command --
-         --------------------
-
-         procedure Add_To_Command (S : String) is
-            First : constant Natural := Command_Last + 1;
-
-         begin
-            Command_Last := Command_Last + S'Length;
-
-            --  Move characters one at a time, because Command has aliased
-            --  components.
-
-            --  But not volatile, so why is this necessary ???
-
-            for J in S'Range loop
-               Command (First + J - S'First) := S (J);
-            end loop;
-
-            Command_Last := Command_Last + 1;
-            Command (Command_Last) := ASCII.NUL;
-
-            Arg_List_Last := Arg_List_Last + 1;
-            Arg_List (Arg_List_Last) := Command (First)'Access;
-         end Add_To_Command;
-
-      --  Start of processing for Spawn
-
-      begin
-         Add_To_Command (Program_Name);
-
-         for J in Args'Range loop
-            Add_To_Command (Args (J).all);
-         end loop;
-
-         if Blocking then
-            Pid     := Invalid_Pid;
-            Result  := Portable_Spawn (Arg_List'Address);
-         else
-            Pid     := Portable_No_Block_Spawn (Arg_List'Address);
-            Result  := Boolean'Pos (Pid /= Invalid_Pid);
-         end if;
-      end Spawn;
-
-   --  Start of processing for Spawn_Internal
-
-   begin
-      --  Copy arguments into a local structure
-
-      for K in N_Args'Range loop
-         N_Args (K) := new String'(Args (K).all);
-      end loop;
-
-      --  Normalize those arguments
-
-      Normalize_Arguments (N_Args);
-
-      --  Call spawn using the normalized arguments
-
-      Spawn (N_Args);
-
-      --  Free arguments list
-
-      for K in N_Args'Range loop
-         Free (N_Args (K));
-      end loop;
-   end Spawn_Internal;
-
-   ---------------------------
-   -- To_Path_String_Access --
-   ---------------------------
-
-   function To_Path_String_Access
-     (Path_Addr : Address;
-      Path_Len  : Integer) return String_Access
-   is
-      subtype Path_String is String (1 .. Path_Len);
-      type    Path_String_Access is access Path_String;
-
-      function Address_To_Access is new
-        Unchecked_Conversion (Source => Address,
-                              Target => Path_String_Access);
-
-      Path_Access : constant Path_String_Access :=
-                      Address_To_Access (Path_Addr);
-
-      Return_Val  : String_Access;
-
-   begin
-      Return_Val := new String (1 .. Path_Len);
-
-      for J in 1 .. Path_Len loop
-         Return_Val (J) := Path_Access (J);
-      end loop;
-
-      return Return_Val;
-   end To_Path_String_Access;
-
-   ------------------
-   -- Wait_Process --
-   ------------------
-
-   procedure Wait_Process (Pid : out Process_Id; Success : out Boolean) is
-      Status : Integer;
-
-      function Portable_Wait (S : Address) return Process_Id;
-      pragma Import (C, Portable_Wait, "__gnat_portable_wait");
-
-   begin
-      Pid := Portable_Wait (Status'Address);
-      Success := (Status = 0);
-   end Wait_Process;
-
-   -----------
-   -- Write --
-   -----------
-
-   function Write
-     (FD : File_Descriptor;
-      A  : System.Address;
-      N  : Integer) return Integer
-   is
-   begin
-      return Integer (System.CRTL.write
-        (System.CRTL.int (FD), System.CRTL.chars (A), System.CRTL.int (N)));
-   end Write;
-
-end GNAT.OS_Lib;
+pragma No_Body;
index f80dde9..aebffec 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1995-2006, Free Software Foundation, Inc.         --
+--          Copyright (C) 1995-2007, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
 --  Except where specifically noted, these routines are portable across all
 --  GNAT implementations on all supported operating systems.
 
-with System;
-with GNAT.Strings;
+--  See file s-os_lib.ads for full documentation of the interface
 
-package GNAT.OS_Lib is
-   pragma Elaborate_Body (OS_Lib);
+with System.OS_Lib;
 
-   -----------------------
-   -- String Operations --
-   -----------------------
-
-   --  These are reexported from package Strings (which was introduced to
-   --  avoid different packages declarting different types unnecessarily).
-   --  See package GNAT.Strings for details.
-
-   subtype String_Access is Strings.String_Access;
-
-   function "=" (Left, Right : String_Access) return Boolean
-     renames Strings."=";
-
-   procedure Free (X : in out String_Access) renames Strings.Free;
-
-   subtype String_List is Strings.String_List;
-
-   function "=" (Left, Right : String_List) return Boolean
-     renames Strings."=";
-
-   function "&" (Left : String_Access; Right : String_Access)
-     return String_List renames Strings."&";
-   function "&" (Left : String_Access; Right : String_List)
-     return String_List renames Strings."&";
-   function "&" (Left : String_List; Right : String_Access)
-     return String_List renames Strings."&";
-   function "&" (Left : String_List; Right : String_List)
-     return String_List renames Strings."&";
-
-   subtype String_List_Access is Strings.String_List_Access;
-
-   function "=" (Left, Right : String_List_Access) return Boolean
-     renames Strings."=";
-
-   procedure Free (Arg : in out String_List_Access)
-     renames Strings.Free;
-
-   ---------------------
-   -- Time/Date Stuff --
-   ---------------------
-
-   type OS_Time is private;
-   --  The OS's notion of time is represented by the private type OS_Time.
-   --  This is the type returned by the File_Time_Stamp functions to obtain
-   --  the time stamp of a specified file. Functions and a procedure (modeled
-   --  after the similar subprograms in package Calendar) are provided for
-   --  extracting information from a value of this type. Although these are
-   --  called GM, the intention is not that they provide GMT times in all
-   --  cases but rather the actual (time-zone independent) time stamp of the
-   --  file (of course in Unix systems, this *is* in GMT form).
-
-   Invalid_Time : constant OS_Time;
-   --  A special unique value used to flag an invalid time stamp value
-
-   subtype Year_Type   is Integer range 1900 .. 2099;
-   subtype Month_Type  is Integer range    1 ..   12;
-   subtype Day_Type    is Integer range    1 ..   31;
-   subtype Hour_Type   is Integer range    0 ..   23;
-   subtype Minute_Type is Integer range    0 ..   59;
-   subtype Second_Type is Integer range    0 ..   59;
-   --  Declarations similar to those in Calendar, breaking down the time
-
-   function Current_Time return OS_Time;
-   --  Return the system clock value as OS_Time
-
-   function GM_Year    (Date : OS_Time) return Year_Type;
-   function GM_Month   (Date : OS_Time) return Month_Type;
-   function GM_Day     (Date : OS_Time) return Day_Type;
-   function GM_Hour    (Date : OS_Time) return Hour_Type;
-   function GM_Minute  (Date : OS_Time) return Minute_Type;
-   function GM_Second  (Date : OS_Time) return Second_Type;
-   --  Functions to extract information from OS_Time value
-
-   function "<"  (X, Y : OS_Time) return Boolean;
-   function ">"  (X, Y : OS_Time) return Boolean;
-   function ">=" (X, Y : OS_Time) return Boolean;
-   function "<=" (X, Y : OS_Time) return Boolean;
-   --  Basic comparison operators on OS_Time with obvious meanings. Note that
-   --  these have Intrinsic convention, so for example it is not permissible
-   --  to create accesses to any of these functions.
-
-   procedure GM_Split
-     (Date   : OS_Time;
-      Year   : out Year_Type;
-      Month  : out Month_Type;
-      Day    : out Day_Type;
-      Hour   : out Hour_Type;
-      Minute : out Minute_Type;
-      Second : out Second_Type);
-   --  Analogous to the Split routine in Ada.Calendar, takes an OS_Time
-   --  and provides a representation of it as a set of component parts,
-   --  to be interpreted as a date point in UTC.
-
-   ----------------
-   -- File Stuff --
-   ----------------
-
-   --  These routines give access to the open/creat/close/read/write level of
-   --  I/O routines in the typical C library (these functions are not part of
-   --  the ANSI C standard, but are typically available in all systems). See
-   --  also package Interfaces.C_Streams for access to the stream level
-   --  routines.
-
-   --  Note on file names. If a file name is passed as type String in any of
-   --  the following specifications, then the name is a normal Ada string and
-   --  need not be NUL-terminated. However, a trailing NUL character is
-   --  permitted, and will be ignored (more accurately, the NUL and any
-   --  characters that follow it will be ignored).
-
-   type File_Descriptor is new Integer;
-   --  Corresponds to the int file handle values used in the C routines
-
-   Standin  : constant File_Descriptor := 0;
-   Standout : constant File_Descriptor := 1;
-   Standerr : constant File_Descriptor := 2;
-   --  File descriptors for standard input output files
-
-   Invalid_FD : constant File_Descriptor := -1;
-   --  File descriptor returned when error in opening/creating file;
-
-   type Mode is (Binary, Text);
-   for Mode'Size use Integer'Size;
-   for Mode use (Binary => 0, Text => 1);
-   --  Used in all the Open and Create calls to specify if the file is to be
-   --  opened in binary mode or text mode. In systems like Unix, this has no
-   --  effect, but in systems capable of text mode translation, the use of
-   --  Text as the mode parameter causes the system to do CR/LF translation
-   --  and also to recognize the DOS end of file character on input. The use
-   --  of Text where appropriate allows programs to take a portable Unix view
-   --  of DOS-format files and process them appropriately.
-
-   function Open_Read
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor;
-   --  Open file Name for reading, returning file descriptor File descriptor
-   --  returned is Invalid_FD if file cannot be opened.
-
-   function Open_Read_Write
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor;
-   --  Open file Name for both reading and writing, returning file descriptor.
-   --  File descriptor returned is Invalid_FD if file cannot be opened.
-
-   function Create_File
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor;
-   --  Creates new file with given name for writing, returning file descriptor
-   --  for subsequent use in Write calls. File descriptor returned is
-   --  Invalid_FD if file cannot be successfully created.
-
-   function Create_Output_Text_File (Name : String) return File_Descriptor;
-   --  Creates new text file with given name suitable to redirect standard
-   --  output, returning file descriptor. File descriptor returned is
-   --  Invalid_FD if file cannot be successfully created.
-
-   function Create_New_File
-     (Name  : String;
-      Fmode : Mode) return File_Descriptor;
-   --  Create new file with given name for writing, returning file descriptor
-   --  for subsequent use in Write calls. This differs from Create_File in
-   --  that it fails if the file already exists. File descriptor returned is
-   --  Invalid_FD if the file exists or cannot be created.
-
-   Temp_File_Len : constant Integer := 12;
-   --  Length of name returned by Create_Temp_File call (GNAT-XXXXXX & NUL)
-
-   subtype Temp_File_Name is String (1 .. Temp_File_Len);
-   --  String subtype set by Create_Temp_File
-
-   procedure Create_Temp_File
-     (FD   : out File_Descriptor;
-      Name : out Temp_File_Name);
-   --  Create and open for writing a temporary file in the current working
-   --  directory. The name of the file and the File Descriptor are returned.
-   --  The File Descriptor returned is Invalid_FD in the case of failure. No
-   --  mode parameter is provided. Since this is a temporary file, there is no
-   --  point in doing text translation on it.
-   --
-   --  On some OSes, the maximum number of temp files that can be created with
-   --  this procedure may be limited. When the maximum is reached, this
-   --  procedure returns Invalid_FD. On some OSes, there may be a race
-   --  condition between processes trying to create temp files at the same
-   --  time in the same directory using this procedure.
-
-   procedure Create_Temp_File
-     (FD   : out File_Descriptor;
-      Name : out String_Access);
-   --  Create and open for writing a temporary file in the current working
-   --  directory. The name of the file and the File Descriptor are returned.
-   --  No mode parameter is provided. Since this is a temporary file, there is
-   --  no point in doing text translation on it. It is the responsibility of
-   --  the caller to deallocate the access value returned in Name.
-   --
-   --  This procedure will always succeed if the current working directory is
-   --  writable. If the current working directory is not writable, then
-   --  Invalid_FD is returned for the file descriptor and null for the Name.
-   --  There is no race condition problem between processes trying to create
-   --  temp files at the same time in the same directory.
-
-   procedure Close (FD : File_Descriptor; Status : out Boolean);
-   --  Close file referenced by FD. Status is False if the underlying service
-   --  failed. Reasons for failure include: disk full, disk quotas exceeded
-   --  and invalid file descriptor (the file may have been closed twice).
-
-   procedure Close (FD : File_Descriptor);
-   --  Close file referenced by FD. This form is used when the caller wants to
-   --  ignore any possible error (see above for error cases).
-
-   procedure Set_Close_On_Exec
-     (FD            : File_Descriptor;
-      Close_On_Exec : Boolean;
-      Status        : out Boolean);
-   --  When Close_On_Exec is True, mark FD to be closed automatically when new
-   --  program is executed by the calling process (i.e. prevent FD from being
-   --  inherited by child processes). When Close_On_Exec is False, mark FD to
-   --  not be closed on exec (i.e. allow it to be inherited). Status is False
-   --  if the operation could not be performed.
-
-   procedure Delete_File (Name : String; Success : out Boolean);
-   --  Deletes file. Success is set True or False indicating if the delete is
-   --  successful.
-
-   procedure Rename_File
-     (Old_Name : String;
-      New_Name : String;
-      Success  : out Boolean);
-   --  Rename a file. Success is set True or False indicating if the rename is
-   --  successful or not.
-
-   --  The following defines the mode for the Copy_File procedure below. Note
-   --  that "time stamps and other file attributes" in the descriptions below
-   --  refers to the creation and last modification times, and also the file
-   --  access (read/write/execute) status flags.
-
-   type Copy_Mode is
-     (Copy,
-      --  Copy the file. It is an error if the target file already exists. The
-      --  time stamps and other file attributes are preserved in the copy.
-
-      Overwrite,
-      --  If the target file exists, the file is replaced otherwise the file
-      --  is just copied. The time stamps and other file attributes are
-      --  preserved in the copy.
-
-      Append);
-      --  If the target file exists, the contents of the source file is
-      --  appended at the end. Otherwise the source file is just copied. The
-      --  time stamps and other file attributes are are preserved if the
-      --  destination file does not exist.
-
-   type Attribute is
-     (Time_Stamps,
-      --  Copy time stamps from source file to target file. All other
-      --  attributes are set to normal default values for file creation.
-
-      Full,
-      --  All attributes are copied from the source file to the target file.
-      --  This includes the timestamps, and for example also includes
-      --  read/write/execute attributes in Unix systems.
-
-      None);
-      --  No attributes are copied. All attributes including the time stamp
-      --  values are set to normal default values for file creation.
-
-   --  Note: The default is Time_Stamps, which corresponds to the normal
-   --  default on Windows style systems. Full corresponds to the typical
-   --  effect of "cp -p" on Unix systems, and None corresponds to the typical
-   --  effect of "cp" on Unix systems.
-
-   --  Note: Time_Stamps and Full are not supported on VMS and VxWorks
-
-   procedure Copy_File
-     (Name     : String;
-      Pathname : String;
-      Success  : out Boolean;
-      Mode     : Copy_Mode := Copy;
-      Preserve : Attribute := Time_Stamps);
-   --  Copy a file. Name must designate a single file (no wild cards allowed).
-   --  Pathname can be a filename or directory name. In the latter case Name
-   --  is copied into the directory preserving the same file name. Mode
-   --  defines the kind of copy, see above with the default being a normal
-   --  copy in which the target file must not already exist. Success is set to
-   --  True or False indicating if the copy is successful (depending on the
-   --  specified Mode).
-   --
-   --  Note: this procedure is only supported to a very limited extent on VMS.
-   --  The only supported mode is Overwrite, and the only supported value for
-   --  Preserve is None, resulting in the default action which for Overwrite
-   --  is to leave attributes unchanged. Furthermore, the copy only works for
-   --  simple text files.
-
-   procedure Copy_Time_Stamps (Source, Dest : String; Success : out Boolean);
-   --  Copy Source file time stamps (last modification and last access time
-   --  stamps) to Dest file. Source and Dest must be valid filenames,
-   --  furthermore Dest must be writable. Success will be set to True if the
-   --  operation was successful and False otherwise.
-   --
-   --  Note: this procedure is not supported on VMS and VxWorks. On these
-   --  platforms, Success is always set to False.
-
-   function Read
-     (FD : File_Descriptor;
-      A  : System.Address;
-      N  : Integer) return Integer;
-   --  Read N bytes to address A from file referenced by FD. Returned value is
-   --  count of bytes actually read, which can be less than N at EOF.
-
-   function Write
-     (FD : File_Descriptor;
-      A  : System.Address;
-      N  : Integer) return Integer;
-   --  Write N bytes from address A to file referenced by FD. The returned
-   --  value is the number of bytes written, which can be less than N if a
-   --  disk full condition was detected.
-
-   Seek_Cur : constant := 1;
-   Seek_End : constant := 2;
-   Seek_Set : constant := 0;
-   --  Used to indicate origin for Lseek call
-
-   procedure Lseek
-     (FD     : File_Descriptor;
-      offset : Long_Integer;
-      origin : Integer);
-   pragma Import (C, Lseek, "__gnat_lseek");
-   --  Sets the current file pointer to the indicated offset value, relative
-   --  to the current position (origin = SEEK_CUR), end of file (origin =
-   --  SEEK_END), or start of file (origin = SEEK_SET).
-
-   function File_Length (FD : File_Descriptor) return Long_Integer;
-   pragma Import (C, File_Length, "__gnat_file_length");
-   --  Get length of file from file descriptor FD
-
-   function File_Time_Stamp (Name : String) return OS_Time;
-   --  Given the name of a file or directory, Name, obtains and returns the
-   --  time stamp. This function can be used for an unopened file. Returns
-   --  Invalid_Time is Name doesn't correspond to an existing file.
-
-   function File_Time_Stamp (FD : File_Descriptor) return OS_Time;
-   --  Get time stamp of file from file descriptor FD Returns Invalid_Time is
-   --  FD doesn't correspond to an existing file.
-
-   function Normalize_Pathname
-     (Name           : String;
-      Directory      : String  := "";
-      Resolve_Links  : Boolean := True;
-      Case_Sensitive : Boolean := True) return String;
-   --  Returns a file name as an absolute path name, resolving all relative
-   --  directories, and symbolic links. The parameter Directory is a fully
-   --  resolved path name for a directory, or the empty string (the default).
-   --  Name is the name of a file, which is either relative to the given
-   --  directory name, if Directory is non-null, or to the current working
-   --  directory if Directory is null. The result returned is the normalized
-   --  name of the file. For most cases, if two file names designate the same
-   --  file through different paths, Normalize_Pathname will return the same
-   --  canonical name in both cases. However, there are cases when this is not
-   --  true; for example, this is not true in Unix for two hard links
-   --  designating the same file.
-   --
-   --  On Windows, the returned path will start with a drive letter except
-   --  when Directory is not empty and does not include a drive letter. If
-   --  Directory is empty (the default) and Name is a relative path or an
-   --  absolute path without drive letter, the letter of the current drive
-   --  will start the returned path. If Case_Sensitive is True (the default),
-   --  then this drive letter will be forced to upper case ("C:\...").
-   --
-   --  If Resolve_Links is set to True, then the symbolic links, on systems
-   --  that support them, will be fully converted to the name of the file or
-   --  directory pointed to. This is slightly less efficient, since it
-   --  requires system calls.
-   --
-   --  If Name cannot be resolved or is null on entry (for example if there is
-   --  symbolic link circularity, e.g. A is a symbolic link for B, and B is a
-   --  symbolic link for A), then Normalize_Pathname returns an empty  string.
-   --
-   --  In VMS, if Name follows the VMS syntax file specification, it is first
-   --  converted into Unix syntax. If the conversion fails, Normalize_Pathname
-   --  returns an empty string.
-   --
-   --  For case-sensitive file systems, the value of Case_Sensitive parameter
-   --  is ignored. For file systems that are not case-sensitive, such as
-   --  Windows and OpenVMS, if this parameter is set to False, then the file
-   --  and directory names are folded to lower case. This allows checking
-   --  whether two files are the same by applying this function to their names
-   --  and comparing the results. If Case_Sensitive is set to True, this
-   --  function does not change the casing of file and directory names.
-
-   function Is_Absolute_Path (Name : String) return Boolean;
-   --  Returns True if Name is an absolute path name, i.e. it designates a
-   --  file or directory absolutely rather than relative to another directory.
-
-   function Is_Regular_File (Name : String) return Boolean;
-   --  Determines if the given string, Name, is the name of an existing
-   --  regular file. Returns True if so, False otherwise. Name may be an
-   --  absolute path name or a relative path name, including a simple file
-   --  name. If it is a relative path name, it is relative to the current
-   --  working directory.
-
-   function Is_Directory (Name : String) return Boolean;
-   --  Determines if the given string, Name, is the name of a directory.
-   --  Returns True if so, False otherwise. Name may be an absolute path
-   --  name or a relative path name, including a simple file name. If it is
-   --  a relative path name, it is relative to the current working directory.
-
-   function Is_Readable_File (Name : String) return Boolean;
-   --  Determines if the given string, Name, is the name of an existing file
-   --  that is readable. Returns True if so, False otherwise. Note that this
-   --  function simply interrogates the file attributes (e.g. using the C
-   --  function stat), so it does not indicate a situation in which a file may
-   --  not actually be readable due to some other process having exclusive
-   --  access.
-
-   function Is_Writable_File (Name : String) return Boolean;
-   --  Determines if the given string, Name, is the name of an existing file
-   --  that is writable. Returns True if so, False otherwise. Note that this
-   --  function simply interrogates the file attributes (e.g. using the C
-   --  function stat), so it does not indicate a situation in which a file may
-   --  not actually be writeable due to some other process having exclusive
-   --  access.
-
-   function Is_Symbolic_Link (Name : String) return Boolean;
-   --  Determines if the given string, Name, is the path of a symbolic link on
-   --  systems that support it. Returns True if so, False if the path is not a
-   --  symbolic link or if the system does not support symbolic links.
-   --
-   --  A symbolic link is an indirect pointer to a file; its directory entry
-   --  contains the name of the file to which it is linked. Symbolic links may
-   --  span file systems and may refer to directories.
-
-   procedure Set_Writable (Name : String);
-   --  Change the permissions on the named file to make it writable
-   --  for its owner.
-
-   procedure Set_Read_Only (Name : String);
-   --  Change the permissions on the named file to make it non-writable
-   --  for its owner.
-
-   procedure Set_Executable (Name : String);
-   --  Change the permissions on the named file to make it executable
-   --  for its owner.
-
-   function Locate_Exec_On_Path
-     (Exec_Name : String) return String_Access;
-   --  Try to locate an executable whose name is given by Exec_Name in the
-   --  directories listed in the environment Path. If the Exec_Name doesn't
-   --  have the executable suffix, it will be appended before the search.
-   --  Otherwise works like Locate_Regular_File below.
-   --
-   --  Note that this function allocates some memory for the returned value.
-   --  This memory needs to be deallocated after use.
-
-   function Locate_Regular_File
-     (File_Name : String;
-      Path      : String) return String_Access;
-   --  Try to locate a regular file whose name is given by File_Name in the
-   --  directories listed in Path. If a file is found, its full pathname is
-   --  returned; otherwise, a null pointer is returned. If the File_Name given
-   --  is an absolute pathname, then Locate_Regular_File just checks that the
-   --  file exists and is a regular file. Otherwise, if the File_Name given
-   --  includes directory information, Locate_Regular_File first checks if the
-   --  file exists relative to the current directory. If it does not, or if
-   --  the File_Name given is a simple file name, the Path argument is parsed
-   --  according to OS conventions, and for each directory in the Path a check
-   --  is made if File_Name is a relative pathname of a regular file from that
-   --  directory.
-   --
-   --  Note that this function allocates some memory for the returned value.
-   --  This memory needs to be deallocated after use.
-
-   function Get_Debuggable_Suffix return String_Access;
-   --  Return the debuggable suffix convention. Usually this is the same as
-   --  the convention for Get_Executable_Suffix. The result is allocated on
-   --  the heap and should be freed after use to avoid storage leaks.
-
-   function Get_Target_Debuggable_Suffix return String_Access;
-   --  Return the target debuggable suffix convention. Usually this is the
-   --  same as the convention for Get_Executable_Suffix. The result is
-   --  allocated on the heap and should be freed after use to avoid storage
-   --  leaks.
-
-   function Get_Executable_Suffix return String_Access;
-   --  Return the executable suffix convention. The result is allocated on the
-   --  heap and should be freed after use to avoid storage leaks.
-
-   function Get_Object_Suffix return String_Access;
-   --  Return the object suffix convention. The result is allocated on the heap
-   --  and should be freed after use to avoid storage leaks.
-
-   function Get_Target_Executable_Suffix return String_Access;
-   --  Return the target executable suffix convention. The result is allocated
-   --  on the heap and should be freed after use to avoid storage leaks.
-
-   function Get_Target_Object_Suffix return String_Access;
-   --  Return the target object suffix convention. The result is allocated on
-   --  the heap and should be freed after use to avoid storage leaks.
-
-   --  The following section contains low-level routines using addresses to
-   --  pass file name and executable name. In each routine the name must be
-   --  Nul-Terminated. For complete documentation refer to the equivalent
-   --  routine (using String in place of C_File_Name) defined above.
-
-   subtype C_File_Name is System.Address;
-   --  This subtype is used to document that a parameter is the address of a
-   --  null-terminated string containing the name of a file.
-
-   --  All the following functions need comments ???
-
-   function Open_Read
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor;
-
-   function Open_Read_Write
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor;
-
-   function Create_File
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor;
-
-   function Create_New_File
-     (Name  : C_File_Name;
-      Fmode : Mode) return File_Descriptor;
-
-   procedure Delete_File (Name : C_File_Name; Success : out Boolean);
-
-   procedure Rename_File
-     (Old_Name : C_File_Name;
-      New_Name : C_File_Name;
-      Success  : out Boolean);
-
-   procedure Copy_File
-     (Name     : C_File_Name;
-      Pathname : C_File_Name;
-      Success  : out Boolean;
-      Mode     : Copy_Mode := Copy;
-      Preserve : Attribute := Time_Stamps);
-
-   procedure Copy_Time_Stamps
-     (Source, Dest : C_File_Name;
-      Success      : out Boolean);
-
-   function File_Time_Stamp (Name : C_File_Name) return OS_Time;
-   --  Returns Invalid_Time is Name doesn't correspond to an existing file
-
-   function Is_Regular_File (Name : C_File_Name) return Boolean;
-   function Is_Directory (Name : C_File_Name) return Boolean;
-   function Is_Readable_File (Name : C_File_Name) return Boolean;
-   function Is_Writable_File (Name : C_File_Name) return Boolean;
-   function Is_Symbolic_Link (Name : C_File_Name) return Boolean;
-
-   function Locate_Regular_File
-     (File_Name : C_File_Name;
-      Path      : C_File_Name) return String_Access;
-
-   ------------------
-   -- Subprocesses --
-   ------------------
-
-   subtype Argument_List is String_List;
-   --  Type used for argument list in call to Spawn. The lower bound of the
-   --  array should be 1, and the length of the array indicates the number of
-   --  arguments.
-
-   subtype Argument_List_Access is String_List_Access;
-   --  Type used to return Argument_List without dragging in secondary stack.
-   --  Note that there is a Free procedure declared for this subtype which
-   --  frees the array and all referenced strings.
-
-   procedure Normalize_Arguments (Args : in out Argument_List);
-   --  Normalize all arguments in the list. This ensure that the argument list
-   --  is compatible with the running OS and will works fine with Spawn and
-   --  Non_Blocking_Spawn for example. If Normalize_Arguments is called twice
-   --  on the same list it will do nothing the second time. Note that Spawn
-   --  and Non_Blocking_Spawn call Normalize_Arguments automatically, but
-   --  since there is a guarantee that a second call does nothing, this
-   --  internal call will have no effect if Normalize_Arguments is called
-   --  before calling Spawn. The call to Normalize_Arguments assumes that the
-   --  individual referenced arguments in Argument_List are on the heap, and
-   --  may free them and reallocate if they are modified.
-
-   procedure Spawn
-     (Program_Name : String;
-      Args         : Argument_List;
-      Success      : out Boolean);
-   --  This procedure spawns a program with a given list of arguments. The
-   --  first parameter of is the name of the executable. The second parameter
-   --  contains the arguments to be passed to this program. Success is False
-   --  if the named program could not be spawned or its execution completed
-   --  unsuccessfully. Note that the caller will be blocked until the
-   --  execution of the spawned program is complete. For maximum portability,
-   --  use a full path name for the Program_Name argument. On some systems
-   --  (notably Unix systems) a simple file name may also work (if the
-   --  executable can be located in the path).
-   --
-   --  "Spawn" should not be used in tasking applications. Why not??? More
-   --  documentation would be helpful here ??? Is it really tasking programs,
-   --  or tasking activity that cause trouble ???
-   --
-   --  Note: Arguments in Args that contain spaces and/or quotes such as
-   --  "--GCC=gcc -v" or "--GCC=""gcc -v""" are not portable across all
-   --  operating systems, and would not have the desired effect if they were
-   --  passed directly to the operating system. To avoid this problem, Spawn
-   --  makes an internal call to Normalize_Arguments, which ensures that such
-   --  arguments are modified in a manner that ensures that the desired effect
-   --  is obtained on all operating systems. The caller may call
-   --  Normalize_Arguments explicitly before the call (e.g. to print out the
-   --  exact form of arguments passed to the operating system). In this case
-   --  the guarantee a second call to Normalize_Arguments has no effect
-   --  ensures that the internal call will not affect the result. Note that
-   --  the implicit call to Normalize_Arguments may free and reallocate some
-   --  of the individual arguments.
-   --
-   --  This function will always set Success to False under VxWorks and other
-   --  similar operating systems which have no notion of the concept of
-   --  dynamically executable file.
-
-   function Spawn
-     (Program_Name : String;
-      Args         : Argument_List) return Integer;
-   --  Similar to the above procedure, but returns the actual status returned
-   --  by the operating system, or -1 under VxWorks and any other similar
-   --  operating systems which have no notion of separately spawnable programs.
-   --
-   --  "Spawn" should not be used in tasking applications.
-
-   procedure Spawn
-     (Program_Name           : String;
-      Args                   : Argument_List;
-      Output_File_Descriptor : File_Descriptor;
-      Return_Code            : out Integer;
-      Err_To_Out             : Boolean := True);
-   --  Similar to the procedure above, but redirects the output to the file
-   --  designated by Output_File_Descriptor. If Err_To_Out is True, then the
-   --  Standard Error output is also redirected.
-   --  Return_Code is set to the status code returned by the operating system
-   --
-   --  "Spawn" should not be used in tasking applications.
-
-   procedure Spawn
-     (Program_Name  : String;
-      Args          : Argument_List;
-      Output_File   : String;
-      Success       : out Boolean;
-      Return_Code   : out Integer;
-      Err_To_Out    : Boolean := True);
-   --  Similar to the procedure above, but saves the output of the command to
-   --  a file with the name Output_File.
-   --
-   --  Success is set to True if the command is executed and its output
-   --  successfully written to the file. If Success is True, then Return_Code
-   --  will be set to the status code returned by the operating system.
-   --  Otherwise, Return_Code is undefined.
-   --
-   --  "Spawn" should not be used in tasking applications.
-
-   type Process_Id is private;
-   --  A private type used to identify a process activated by the following
-   --  non-blocking calls. The only meaningful operation on this type is a
-   --  comparison for equality.
-
-   Invalid_Pid : constant Process_Id;
-   --  A special value used to indicate errors, as described below
-
-   function Pid_To_Integer (Pid : Process_Id) return Integer;
-   --  Convert a process id to an Integer. Useful for writing hash functions
-   --  for type Process_Id or to compare two Process_Id (e.g. for sorting).
-
-   function Non_Blocking_Spawn
-     (Program_Name : String;
-      Args         : Argument_List) return Process_Id;
-   --  This is a non blocking call. The Process_Id of the spawned process is
-   --  returned. Parameters are to be used as in Spawn. If Invalid_Pid is
-   --  returned the program could not be spawned.
-   --
-   --  "Non_Blocking_Spawn" should not be used in tasking applications.
-   --
-   --  This function will always return Invalid_Pid under VxWorks, since there
-   --  is no notion of executables under this OS.
-
-   function Non_Blocking_Spawn
-     (Program_Name           : String;
-      Args                   : Argument_List;
-      Output_File_Descriptor : File_Descriptor;
-      Err_To_Out             : Boolean := True) return Process_Id;
-   --  Similar to the procedure above, but redirects the output to the file
-   --  designated by Output_File_Descriptor. If Err_To_Out is True, then the
-   --  Standard Error output is also redirected. Invalid_Pid is returned
-   --  if the program could not be spawned successfully.
-   --
-   --  "Non_Blocking_Spawn" should not be used in tasking applications.
-   --
-   --  This function will always return Invalid_Pid under VxWorks, since there
-   --  is no notion of executables under this OS.
-
-   function Non_Blocking_Spawn
-     (Program_Name : String;
-      Args         : Argument_List;
-      Output_File  : String;
-      Err_To_Out   : Boolean := True) return Process_Id;
-   --  Similar to the procedure above, but saves the output of the command to
-   --  a file with the name Output_File.
-   --
-   --  Success is set to True if the command is executed and its output
-   --  successfully written to the file. Invalid_Pid is returned if the output
-   --  file could not be created or if the program could not be spawned
-   --  successfully.
-   --
-   --  "Non_Blocking_Spawn" should not be used in tasking applications.
-   --
-   --  This function will always return Invalid_Pid under VxWorks, since there
-   --  is no notion of executables under this OS.
-
-   procedure Wait_Process (Pid : out Process_Id; Success : out Boolean);
-   --  Wait for the completion of any of the processes created by previous
-   --  calls to Non_Blocking_Spawn. The caller will be suspended until one of
-   --  these processes terminates (normally or abnormally). If any of these
-   --  subprocesses terminates prior to the call to Wait_Process (and has not
-   --  been returned by a previous call to Wait_Process), then the call to
-   --  Wait_Process is immediate. Pid identifies the process that has
-   --  terminated (matching the value returned from Non_Blocking_Spawn).
-   --  Success is set to True if this sub-process terminated successfully. If
-   --  Pid = Invalid_Pid, there were no subprocesses left to wait on.
-   --
-   --  This function will always set success to False under VxWorks, since
-   --  there is no notion of executables under this OS.
-
-   function Argument_String_To_List
-     (Arg_String : String) return Argument_List_Access;
-   --  Take a string that is a program and its arguments and parse it into an
-   --  Argument_List. Note that the result is allocated on the heap, and must
-   --  be freed by the programmer (when it is no longer needed) to avoid
-   --  memory leaks.
-
-   -------------------
-   -- Miscellaneous --
-   -------------------
-
-   function Getenv (Name : String) return String_Access;
-   --  Get the value of the environment variable. Returns an access to the
-   --  empty string if the environment variable does not exist or has an
-   --  explicit null value (in some operating systems these are distinct
-   --  cases, in others they are not; this interface abstracts away that
-   --  difference. The argument is allocated on the heap (even in the null
-   --  case), and needs to be freed explicitly when no longer needed to avoid
-   --  memory leaks.
-
-   procedure Setenv (Name : String; Value : String);
-   --  Set the value of the environment variable Name to Value. This call
-   --  modifies the current environment, but does not modify the parent
-   --  process environment. After a call to Setenv, Getenv (Name) will always
-   --  return a String_Access referencing the same String as Value. This is
-   --  true also for the null string case (the actual effect may be to either
-   --  set an explicit null as the value, or to remove the entry, this is
-   --  operating system dependent). Note that any following calls to Spawn
-   --  will pass an environment to the spawned process that includes the
-   --  changes made by Setenv calls. This procedure is not available on VMS.
-
-   procedure OS_Exit (Status : Integer);
-   pragma Import (C, OS_Exit, "__gnat_os_exit");
-   pragma No_Return (OS_Exit);
-   --  Exit to OS with given status code (program is terminated). Note that
-   --  this is abrupt termination. All tasks are immediately terminated. There
-   --  is no finalization or other cleanup actions performed.
-
-   procedure OS_Abort;
-   pragma Import (C, OS_Abort, "abort");
-   pragma No_Return (OS_Abort);
-   --  Exit to OS signalling an abort (traceback or other appropriate
-   --  diagnostic information should be given if possible, or entry made to
-   --  the debugger if that is possible).
-
-   function Errno return Integer;
-   pragma Import (C, Errno, "__get_errno");
-   --  Return the task-safe last error number
-
-   procedure Set_Errno (Errno : Integer);
-   pragma Import (C, Set_Errno, "__set_errno");
-   --  Set the task-safe error number
-
-   Directory_Separator : constant Character;
-   --  The character that is used to separate parts of a pathname
-
-   Path_Separator : constant Character;
-   --  The character to separate paths in an environment variable value
-
-private
-   pragma Import (C, Path_Separator, "__gnat_path_separator");
-   pragma Import (C, Directory_Separator, "__gnat_dir_separator");
-   pragma Import (C, Current_Time, "__gnat_current_time");
-
-   type OS_Time is new Long_Integer;
-   --  Type used for timestamps in the compiler. This type is used to hold
-   --  time stamps, but may have a different representation than C's time_t.
-   --  This type needs to match the declaration of OS_Time in adaint.h.
-
-   --  Add pragma Inline statements for comparison operations on OS_Time. It
-   --  would actually be nice to use pragma Import (Intrinsic) here, but this
-   --  was not properly supported till GNAT 3.15a, so that would cause
-   --  bootstrap path problems. To be changed later ???
-
-   Invalid_Time : constant OS_Time := -1;
-   --  This value should match the return valud by __gnat_file_time_*
-
-   pragma Inline ("<");
-   pragma Inline (">");
-   pragma Inline ("<=");
-   pragma Inline (">=");
-
-   type Process_Id is new Integer;
-   Invalid_Pid : constant Process_Id := -1;
-
-end GNAT.OS_Lib;
+package GNAT.OS_Lib renames System.OS_Lib;