]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/ada/g-os_lib.adb
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / ada / g-os_lib.adb
diff --git a/gcc/ada/g-os_lib.adb b/gcc/ada/g-os_lib.adb
deleted file mode 100644 (file)
index f3b4782..0000000
+++ /dev/null
@@ -1,1398 +0,0 @@
-------------------------------------------------------------------------------
---                                                                          --
---                         GNAT COMPILER COMPONENTS                         --
---                                                                          --
---                          G N A T . O S _ L I B                           --
---                                                                          --
---                                 B o d y                                  --
---                                                                          --
---                            $Revision: 1.3 $
---                                                                          --
---           Copyright (C) 1995-2001 Ada Core Technologies, 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- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
--- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
--- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
---                                                                          --
--- As a special exception,  if other files  instantiate  generics from this --
--- unit, or you link  this unit with other files  to produce an executable, --
--- this  unit  does not  by itself cause  the resulting  executable  to  be --
--- covered  by the  GNU  General  Public  License.  This exception does not --
--- however invalidate  any other reasons why  the executable file  might be --
--- covered by the  GNU Public License.                                      --
---                                                                          --
--- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com).   --
---                                                                          --
-------------------------------------------------------------------------------
-
-with System.Soft_Links;
-with Unchecked_Conversion;
-with System; use System;
-
-package body GNAT.OS_Lib is
-
-   package SSL renames System.Soft_Links;
-
-   -----------------------
-   -- 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 to Spawn (blocking and 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.
-
-   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
-
-   -----------------
-   -- 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 : Integer := Arg_String'Length;
-      New_Argv : Argument_List (1 .. Max_Args);
-      New_Argc : Natural := 0;
-      Idx      : Integer;
-
-   begin
-      Idx := Arg_String'First;
-
-      loop
-         declare
-            Quoted   : Boolean := False;
-            Backqd   : Boolean := False;
-            Old_Idx  : Integer;
-
-         begin
-            Old_Idx := Idx;
-
-            loop
-               --  A vanilla space is the end of an argument
-
-               if not Backqd and then not Quoted
-                 and then Arg_String (Idx) = ' '
-               then
-                  exit;
-
-               --  Start of a quoted string
-
-               elsif not Backqd and then not Quoted
-                 and then Arg_String (Idx) = '"'
-               then
-                  Quoted := True;
-
-               --  End of a quoted string and end of an argument
-
-               elsif not Backqd and then Quoted
-                 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;
-
-         exit when Idx > Arg_String'Last;
-      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;
-
-   -----------------
-   -- 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_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;
-
-   -----------------
-   -- 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;
-
-   ------------
-   -- 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_get_env_value_ptr");
-
-      procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
-      pragma Import (C, Strncpy, "strncpy");
-
-      Env_Value_Ptr    : Address;
-      Env_Value_Length : Integer;
-      F_Name           : 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) return Integer;
-      pragma Import (C, Is_Absolute_Path, "__gnat_is_absolute_path");
-
-      F_Name : String (1 .. Name'Length + 1);
-
-   begin
-      F_Name (1 .. Name'Length) := Name;
-      F_Name (F_Name'Last)      := ASCII.NUL;
-
-      return Is_Absolute_Path (F_Name'Address) /= 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_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_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);
-         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);
-
-   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;
-
-      return Locate_Regular_File (C_File_Name'Address, C_Path'Address);
-   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;
-
-   ------------------------
-   -- Normalize_Pathname --
-   ------------------------
-
-   function Normalize_Pathname
-     (Name      : String;
-      Directory : String := "")
-      return      String
-   is
-      Max_Path : Integer;
-      pragma Import (C, Max_Path, "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 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 Get_Directory return String;
-      --  If Directory is not empty, return it, adding a directory separator
-      --  if not already present, otherwise return current working directory
-      --  with terminating directory separator.
-
-      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".
-
-      -------------------
-      -- Get_Directory --
-      -------------------
-
-      function Get_Directory return String is
-      begin
-         --  Directory given, add directory separator if needed
-
-         if Directory'Length > 0 then
-            if Directory (Directory'Length) = Directory_Separator then
-               return Directory;
-            else
-               declare
-                  Result : String (1 .. Directory'Length + 1);
-
-               begin
-                  Result (1 .. Directory'Length) := Directory;
-                  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;
-
-               return Buffer (1 .. Path_Len);
-            end;
-         end if;
-      end Get_Directory;
-
-      Reference_Dir : constant String := Get_Directory;
-      --  Current directory name specified
-
-      function Final_Value (S : String) return String is
-      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;
-               return Result;
-            end;
-
-         else
-            return S;
-         end if;
-
-      end Final_Value;
-
-   --  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 : 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;
-
-      --  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;
-
-         --  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
-                  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
-
-         else
-            declare
-               Saved : 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;
-         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;
-
-   -----------------
-   -- 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;
-
-   ------------
-   -- 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_set_env_value");
-
-   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;
-
-   --------------------
-   -- Spawn_Internal --
-   --------------------
-
-   procedure Spawn_Internal
-     (Program_Name : String;
-      Args         : Argument_List;
-      Result       : out Integer;
-      Pid          : out Process_Id;
-      Blocking     : Boolean)
-   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.
-
-         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_Internal
-
-   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_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 : 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;
-
-end GNAT.OS_Lib;