summaryrefslogtreecommitdiff
path: root/gcc/ada/s-fileio.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/s-fileio.adb')
-rw-r--r--gcc/ada/s-fileio.adb288
1 files changed, 261 insertions, 27 deletions
diff --git a/gcc/ada/s-fileio.adb b/gcc/ada/s-fileio.adb
index 88bad49f76e..64b89926753 100644
--- a/gcc/ada/s-fileio.adb
+++ b/gcc/ada/s-fileio.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, 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- --
@@ -29,15 +29,15 @@
-- --
------------------------------------------------------------------------------
-with Ada.Finalization; use Ada.Finalization;
-with Ada.IO_Exceptions; use Ada.IO_Exceptions;
+with Ada.Finalization; use Ada.Finalization;
+with Ada.IO_Exceptions; use Ada.IO_Exceptions;
with Interfaces.C;
-with Interfaces.C.Strings; use Interfaces.C.Strings;
-with Interfaces.C_Streams; use Interfaces.C_Streams;
+with Interfaces.C.Strings; use Interfaces.C.Strings;
+with Interfaces.C_Streams; use Interfaces.C_Streams;
with System.CRTL.Runtime;
-with System.Case_Util; use System.Case_Util;
+with System.Case_Util; use System.Case_Util;
with System.OS_Lib;
with System.Soft_Links;
@@ -52,6 +52,12 @@ package body System.File_IO is
use type Interfaces.C.int;
use type CRTL.size_t;
+ subtype String_Access is System.OS_Lib.String_Access;
+ procedure Free (X : in out String_Access) renames System.OS_Lib.Free;
+
+ function "=" (X, Y : String_Access) return Boolean
+ renames System.OS_Lib."=";
+
----------------------
-- Global Variables --
----------------------
@@ -98,6 +104,9 @@ package body System.File_IO is
(C, text_translation_required, "__gnat_text_translation_required");
-- If true, add appropriate suffix to control string for Open
+ VMS_Formstr : String_Access := null;
+ -- For special VMS RMS keywords and values
+
-----------------------
-- Local Subprograms --
-----------------------
@@ -132,11 +141,20 @@ package body System.File_IO is
-- with Name includes that file name in the message.
procedure Raise_Device_Error
- (File : AFCB_Ptr; Errno : Integer := OS_Lib.Errno);
+ (File : AFCB_Ptr;
+ Errno : Integer := OS_Lib.Errno);
pragma No_Return (Raise_Device_Error);
-- Clear error indication on File and raise Device_Error with an exception
-- message providing errno information.
+ procedure Form_VMS_RMS_Keys (Form : String; VMS_Form : out String_Access);
+ -- Parse the RMS Keys
+
+ function Form_RMS_Context_Key
+ (Form : String;
+ VMS_Form : String_Access) return Natural;
+ -- Parse the RMS Context Key
+
----------------
-- Append_Set --
----------------
@@ -514,7 +532,6 @@ package body System.File_IO is
Fopstr (1) := (if Creat then 'w' else 'r');
Fopstr (2) := '+';
Fptr := 3;
-
end case;
-- If text_translation_required is true then we need to append either a
@@ -558,13 +575,10 @@ package body System.File_IO is
if V1 = 0 then
return Default;
-
elsif Form (V1) = 'y' then
return True;
-
elsif Form (V1) = 'n' then
return False;
-
else
raise Use_Error with "invalid Form";
end if;
@@ -640,6 +654,197 @@ package body System.File_IO is
Stop := 0;
end Form_Parameter;
+ --------------------------
+ -- Form_RMS_Context_Key --
+ --------------------------
+
+ function Form_RMS_Context_Key
+ (Form : String;
+ VMS_Form : String_Access) return Natural
+ is
+ type Context_Parms is
+ (Binary_Data, Convert_Fortran_Carriage_Control, Force_Record_Mode,
+ Force_Stream_Mode, Explicit_Write);
+ -- Ada-fied list of all possible Context keyword values
+
+ Pos : Natural := 0;
+ Klen : Natural := 0;
+ Index : Natural;
+
+ begin
+ -- Find the end of the occupation
+
+ for J in VMS_Form'First .. VMS_Form'Last loop
+ if VMS_Form (J) = ASCII.NUL then
+ Pos := J;
+ exit;
+ end if;
+ end loop;
+
+ Index := Form'First;
+ while Index < Form'Last loop
+ if Form (Index) = '=' then
+ Index := Index + 1;
+
+ -- Loop through the context values and look for a match
+
+ for Parm in Context_Parms loop
+ declare
+ KImage : String := Context_Parms'Image (Parm);
+
+ begin
+ Klen := KImage'Length;
+ To_Lower (KImage);
+
+ if Index + Klen - 1 <= Form'Last
+ and then Form (Index .. Index + Klen - 1) = KImage
+ then
+ case Parm is
+ when Force_Record_Mode =>
+ VMS_Form (Pos) := '"';
+ Pos := Pos + 1;
+ VMS_Form (Pos .. Pos + 6) := "ctx=rec";
+ Pos := Pos + 7;
+ VMS_Form (Pos) := '"';
+ Pos := Pos + 1;
+ VMS_Form (Pos) := ',';
+ return Index + Klen;
+
+ when Force_Stream_Mode =>
+ VMS_Form (Pos) := '"';
+ Pos := Pos + 1;
+ VMS_Form (Pos .. Pos + 6) := "ctx=stm";
+ Pos := Pos + 7;
+ VMS_Form (Pos) := '"';
+ Pos := Pos + 1;
+ VMS_Form (Pos) := ',';
+ return Index + Klen;
+
+ when others =>
+ raise Use_Error
+ with "unimplemented RMS Context Value";
+ end case;
+ end if;
+ end;
+ end loop;
+
+ raise Use_Error with "unrecognized RMS Context Value";
+ end if;
+ end loop;
+
+ raise Use_Error with "malformed RMS Context Value";
+ end Form_RMS_Context_Key;
+
+ -----------------------
+ -- Form_VMS_RMS_Keys --
+ -----------------------
+
+ procedure Form_VMS_RMS_Keys (Form : String; VMS_Form : out String_Access)
+ is
+ VMS_RMS_Keys_Token : constant String := "vms_rms_keys";
+ Klen : Natural := VMS_RMS_Keys_Token'Length;
+ Index : Natural;
+
+ -- Ada-fied list of all RMS keywords, translated from the HP C Run-Time
+ -- Library Reference Manual, Table REF-3: RMS Valid Keywords and Values.
+
+ type RMS_Keys is
+ (Access_Callback, Allocation_Quantity, Block_Size, Context,
+ Default_Extension_Quantity, Default_File_Name_String, Error_Callback,
+ File_Processing_Options, Fixed_Header_Size, Global_Buffer_Count,
+ Multiblock_Count, Multibuffer_Count, Maximum_Record_Size,
+ Terminal_Input_Prompt, Record_Attributes, Record_Format,
+ Record_Processing_Options, Retrieval_Pointer_Count, Sharing_Options,
+ Timeout_IO_Value);
+
+ begin
+ Index := Form'First + Klen - 1;
+ while Index < Form'Last loop
+ Index := Index + 1;
+
+ -- Scan for the token signalling VMS RMS Keys ahead. Should
+ -- whitespace be eaten???
+
+ if Form (Index - Klen .. Index - 1) = VMS_RMS_Keys_Token then
+
+ -- Allocate the VMS form string that will contain the cryptic
+ -- CRTL RMS strings and initialize it to all nulls. Since the
+ -- CRTL strings are always shorter than the Ada-fied strings,
+ -- it follows that an allocation of the original size will be
+ -- more than adequate.
+ VMS_Form := new String'(Form (Form'First .. Form'Last));
+ VMS_Form.all := (others => ASCII.NUL);
+
+ if Form (Index) = '=' then
+ Index := Index + 1;
+ if Form (Index) = '(' then
+ while Index < Form'Last loop
+ Index := Index + 1;
+
+ -- Loop through the RMS Keys and dispatch.
+
+ for Key in RMS_Keys loop
+ declare
+ KImage : String := RMS_Keys'Image (Key);
+
+ begin
+ Klen := KImage'Length;
+ To_Lower (KImage);
+
+ if Form (Index .. Index + Klen - 1) = KImage then
+ case Key is
+ when Context =>
+ Index := Form_RMS_Context_Key
+ (Form (Index + Klen .. Form'Last),
+ VMS_Form);
+ exit;
+
+ when others =>
+ raise Use_Error
+ with "unimplemented VMS RMS Form Key";
+ end case;
+ end if;
+ end;
+ end loop;
+
+ if Form (Index) = ')' then
+
+ -- Done, erase the unneeded trailing comma and return
+
+ for J in reverse VMS_Form'First .. VMS_Form'Last loop
+ if VMS_Form (J) = ',' then
+ VMS_Form (J) := ASCII.NUL;
+ return;
+ end if;
+ end loop;
+
+ -- Shouldn't be possible to get here
+
+ raise Use_Error;
+
+ elsif Form (Index) = ',' then
+
+ -- Another key ahead, exit inner loop
+
+ null;
+
+ else
+
+ -- Keyword value not terminated correctly
+
+ raise Use_Error with "malformed VMS RMS Form";
+ end if;
+ end loop;
+ end if;
+ end if;
+
+ -- Found the keyword, but not followed by correct syntax
+
+ raise Use_Error with "malformed VMS RMS Form";
+ end if;
+ end loop;
+ end Form_VMS_RMS_Keys;
+
-------------
-- Is_Open --
-------------
@@ -822,13 +1027,10 @@ package body System.File_IO is
if V1 = 0 then
Shared := None;
-
elsif Formstr (V1 .. V2) = "yes" then
Shared := Yes;
-
elsif Formstr (V1 .. V2) = "no" then
Shared := No;
-
else
raise Use_Error with "invalid Form";
end if;
@@ -844,13 +1046,10 @@ package body System.File_IO is
if V1 = 0 then
Encoding := CRTL.Unspecified;
-
elsif Formstr (V1 .. V2) = "utf8" then
Encoding := CRTL.UTF8;
-
elsif Formstr (V1 .. V2) = "8bits" then
Encoding := CRTL.ASCII_8bits;
-
else
raise Use_Error with "invalid Form";
end if;
@@ -868,6 +1067,17 @@ package body System.File_IO is
Form_Boolean (Formstr, "text_translation", Default => True);
end if;
+ -- Acquire settings of target specific form parameters on VMS. Only
+ -- Context is currently implemented, for forcing a byte stream mode
+ -- read. On non-VMS systems, the settings are ultimately ignored in
+ -- the implementation of __gnat_fopen.
+
+ -- Should a warning be issued on non-VMS systems? That's not possible
+ -- without testing System.OpenVMS boolean which isn't present in most
+ -- non-VMS versions of package System.
+
+ Form_VMS_RMS_Keys (Formstr, VMS_Formstr);
+
-- If we were given a stream (call from xxx.C_Streams.Open), then set
-- the full name to the given one, and skip to end of processing.
@@ -1030,7 +1240,19 @@ package body System.File_IO is
-- since by the time of the delete, the current working directory
-- may have changed and we do not want to delete a different file!
- Stream := fopen (Namestr'Address, Fopstr'Address, Encoding);
+ if VMS_Formstr = null then
+ Stream := fopen (Namestr'Address, Fopstr'Address, Encoding,
+ Null_Address);
+ else
+ Stream := fopen (Namestr'Address, Fopstr'Address, Encoding,
+ VMS_Formstr.all'Address);
+ end if;
+
+ -- No need to keep this around
+
+ if VMS_Formstr /= null then
+ Free (VMS_Formstr);
+ end if;
if Stream = NULL_Stream then
@@ -1042,15 +1264,15 @@ package body System.File_IO is
declare
function Is_File_Not_Found_Error
(Errno_Value : Integer) return Integer;
- -- Non-zero when the given errno value indicates a non-
- -- existing file.
-
pragma Import
(C, Is_File_Not_Found_Error,
"__gnat_is_file_not_found_error");
+ -- Non-zero when the given errno value indicates a non-
+ -- existing file.
- Errno : constant Integer := OS_Lib.Errno;
+ Errno : constant Integer := OS_Lib.Errno;
Message : constant String := Errno_Message (Name, Errno);
+
begin
if Is_File_Not_Found_Error (Errno) /= 0 then
raise Name_Error with Message;
@@ -1089,7 +1311,8 @@ package body System.File_IO is
------------------------
procedure Raise_Device_Error
- (File : AFCB_Ptr; Errno : Integer := OS_Lib.Errno)
+ (File : AFCB_Ptr;
+ Errno : Integer := OS_Lib.Errno)
is
begin
-- Clear error status so that the same error is not reported twice
@@ -1123,7 +1346,6 @@ package body System.File_IO is
else -- 0 < Nread < Siz
raise Data_Error with "not enough data read";
end if;
-
end Read_Buf;
procedure Read_Buf
@@ -1196,13 +1418,25 @@ package body System.File_IO is
Fopen_Mode
(Mode, File.Is_Text_File, False, File.Access_Method, Fopstr);
- File.Stream := freopen
- (File.Name.all'Address, Fopstr'Address, File.Stream, File.Encoding);
+ Form_VMS_RMS_Keys (File.Form.all, VMS_Formstr);
+
+ if VMS_Formstr = null then
+ File.Stream := freopen
+ (File.Name.all'Address, Fopstr'Address, File.Stream,
+ File.Encoding, Null_Address);
+ else
+ File.Stream := freopen
+ (File.Name.all'Address, Fopstr'Address, File.Stream,
+ File.Encoding, VMS_Formstr.all'Address);
+ end if;
+
+ if VMS_Formstr /= null then
+ Free (VMS_Formstr);
+ end if;
if File.Stream = NULL_Stream then
Close (File_Ptr);
raise Use_Error;
-
else
File.Mode := Mode;
Append_Set (File);