-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT 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 the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

-------------------------------------------------------------------------------
--                                                                           --
-- SPARK.Ada.Text_IO                                                         --
--                                                                           --
-- Description                                                               --
--   This is a binding to package Ada.Text_IO                                --
--                                                                           --
-- Language                                                                  --
--   Specification : SPARK                                                   --
--   Private Part  : Ada                                                     --
--   Body          : Ada                                                     --
--                                                                           --
-- Runtime Requirements and Dependencies                                     --
--   Full Ada Runtime                                                        --
--                                                                           --
-- Verification                                                              --
--   N/A                                                                     --
--                                                                           --
-- Exceptions                                                                --
--   Functions and Look_Ahead_* procedures may raise exceptions at present.  --
--   The intention is to add preconditions in future to guard against these. --
--   For details of the exceptions that can be raised please refer to        --
--   Ada.Text_IO.                                                            --
--                                                                           --
--   Exceptions raised in procedures are caught and returned via the File    --
--   parameter, which must be tested for exception status by calling the     --
--   appropriate Get_Last_Exception_* function. The exception can be         --
--   reraised by calling the appropriate Raise_Last_Exception_* procedure.   --
--                                                                           --
--   IMPORTANT NOTE. When adding a new procedure to this package the         --
--   procedure body must re-raise the exception if Get_Exception_T returns   --
--   No_Exception, otherwise unexpected exceptions will be silently ignored. --
--   The existing procedure bodies provide examples of this.                 --
--                                                                           --
-------------------------------------------------------------------------------

with Ada.Text_IO;

package SPARK.Ada.Text_IO
--# own The_Standard_Input  : Input_Type;
--#     The_Standard_Output : Output_Type;
--#     The_Standard_Error  : Error_Type;
--# initializes The_Standard_Input,
--#             The_Standard_Output,
--#             The_Standard_Error;
is

   --# type Input_Type is abstract;
   --# type Output_Type is abstract;
   --# type Error_Type is abstract;

   type File_Type is limited private;
   type File_Mode is (In_File, Out_File, Append_File);

   type Count is range 0 .. Natural'Last;
   --  The value of Count'Last must be large enough so that the
   --  assumption that the Line, Column and Page counts can never
   --  exceed this value is a valid assumption.

   subtype Positive_Count is Count range 1 .. Count'Last;

   Unbounded : constant Count := 0;
   --  Line and page length

   subtype Field is Integer range 0 .. 255;
   --  Note: if for any reason, there is a need to increase this value,
   --  then it will be necessary to change the corresponding value in
   --  System.Img_Real in file s-imgrea.adb.

   subtype Number_Base is Integer range 2 .. 16;

   type Type_Set is (Lower_Case, Upper_Case);

   type Exception_T is (No_Exception,
                        Status_Error,
                        Mode_Error,
                        Name_Error,
                        Use_Error,
                        Device_Error,
                        End_Error,
                        Data_Error,
                        Layout_Error);

   ---------------------
   -- File Management --
   ---------------------

   --  procedure Create
   --    (File : in out File_Type;
   --     Mode : in     File_Mode := Out_File;
   --     Name : in     String    := "";
   --     Form : in     String    := "");
   procedure Create
     (File :    out File_Type;
      Mode : in     File_Mode;
      Name : in     String;
      Form : in     String);
   --# derives File from Form,
   --#                   Mode,
   --#                   Name;
   --# declare delay;

   --  procedure Open
   --    (File : in out File_Type;
   --     Mode : in     File_Mode;
   --     Name : in     String;
   --     Form : in     String := "");
   procedure Open
     (File :    out File_Type;
      Mode : in     File_Mode;
      Name : in     String;
      Form : in     String);
   --# derives File from Form,
   --#                   Mode,
   --#                   Name;
   --# declare delay;

   procedure Close (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   procedure Delete (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   procedure Reset_Mode (File : in out File_Type;
                         Mode : in     File_Mode);
   --# derives File from *,
   --#                   Mode;
   --# declare delay;

   procedure Reset (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   function Mode (File : File_Type) return File_Mode;

   function Is_Open (File : File_Type) return Boolean;

   --------------------
   -- Buffer control --
   --------------------

   --  Note: The parameter file is IN OUT in the RM, but this is clearly
   --  an oversight, and was intended to be IN, see AI95-00057.

   --  procedure Flush (File : in File_Type);
   procedure Flush_File (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   --  procedure Flush (File : in File_Type := Standard_Output);
   procedure Flush_Output;
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *;
   --# declare delay;

   --  procedure Flush (File : in File_Type := Standard_Error);
   procedure Flush_Error;
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *;
   --# declare delay;

   --------------------------------------------
   -- Specification of line and page lengths --
   --------------------------------------------

   --  procedure Set_Line_Length (File : in File_Type;
   --                             To   : in Count);
   procedure Set_Line_Length_File (File : in out File_Type;
                                   To   : in     Count);
   --# derives File from *,
   --#                   To;
   --# declare delay;

   --  procedure Set_Line_Length (File : in File_Type := Standard_Output;
   --                             To   : in Count);
   procedure Set_Line_Length_Output (To : in Count);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  To;
   --# declare delay;

   --  procedure Set_Line_Length (File : in File_Type := Standard_Error;
   --                             To   : in Count);
   procedure Set_Line_Length_Error (To : in Count);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 To;
   --# declare delay;

   --  procedure Set_Page_Length (File : in File_Type;
   --                             To   : in Count);
   procedure Set_Page_Length_File (File : in out File_Type;
                                   To   : in     Count);
   --# derives File from *,
   --#                   To;
   --# declare delay;

   --  procedure Set_Page_Length (File : in File_Type := Standard_Output;
   --                             To   : in Count);
   procedure Set_Page_Length_Output (To : in Count);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  To;
   --# declare delay;

   --  procedure Set_Page_Length (File : in File_Type := Standard_Error;
   --                             To   : in Count);
   procedure Set_Page_Length_Error (To : in Count);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 To;
   --# declare delay;

   --  function Line_Length (File : File_Type) return Count;
   function Line_Length_File (File : File_Type) return Count;

   --  function Line_Length (File : File_Type := Standard_Output) return Count;
   function Line_Length_Output return Count;
   --# global in The_Standard_Output;

   --  function Line_Length (File : File_Type := Standard_Error) return Count;
   function Line_Length_Error return Count;
   --# global in The_Standard_Error;

   --  function Page_Length (File : File_Type) return Count;
   function Page_Length_File (File : File_Type) return Count;

   --  function Page_Length (File : File_Type := Standard_Output) return Count;
   function Page_Length_Output return Count;
   --# global in The_Standard_Output;

   --  function Page_Length (File : File_Type := Standard_Error) return Count;
   function Page_Length_Error return Count;
   --# global in The_Standard_Error;

   ------------------------------------
   -- Column, Line, and Page Control --
   ------------------------------------

   --  procedure New_Line (File    : in File_Type;
   --                      Spacing : in Positive_Count := 1);
   procedure New_Line_File (File    : in out File_Type;
                            Spacing : in     Positive_Count);
   --# derives File from *,
   --#                   Spacing;
   --# declare delay;

   --  procedure New_Line (File    : in File_Type      := Standard_Output;
   --                      Spacing : in Positive_Count := 1);
   procedure New_Line_Output (Spacing : in Positive_Count);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  Spacing;
   --# declare delay;

   --  procedure New_Line (File    : in File_Type      := Standard_Error;
   --                      Spacing : in Positive_Count := 1);
   procedure New_Line_Error (Spacing : in Positive_Count);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 Spacing;
   --# declare delay;

   --  procedure Skip_Line (File    : in File_Type;
   --                       Spacing : in Positive_Count := 1);
   procedure Skip_Line_File (File    : in out File_Type;
                             Spacing : in     Positive_Count);
   --# derives File from *,
   --#                   Spacing;
   --# declare delay;

   --  procedure Skip_Line (File    : in File_Type      := Standard_Input;
   --                       Spacing : in Positive_Count := 1);
   procedure Skip_Line_Input (Spacing : in Positive_Count);
   --# global in out The_Standard_Input;
   --# derives The_Standard_Input from *,
   --#                                 Spacing;
   --# declare delay;

   --  function End_Of_Line
   --    (File : File_Type) return Boolean;
   function End_Of_Line_File (File : File_Type) return Boolean;

   --  function End_Of_Line
   --    (File : File_Type := Standard_Input) return Boolean;
   function End_Of_Line_Input return Boolean;
   --# global in The_Standard_Input;

   --  procedure New_Page (File : in File_Type);
   procedure New_Page_File (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   --  procedure New_Page (File : in File_Type := Standard_Output);
   procedure New_Page_Output;
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *;
   --# declare delay;

   --  procedure New_Page (File : in File_Type := Standard_Error);
   procedure New_Page_Error;
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *;
   --# declare delay;

   --  procedure Skip_Page (File : File_Type);
   procedure Skip_Page_File (File : in out File_Type);
   --# derives File from *;
   --# declare delay;

   --  procedure Skip_Page (File : File_Type := Standard_Input);
   procedure Skip_Page_Input;
   --# global in out The_Standard_Input;
   --# derives The_Standard_Input from *;
   --# declare delay;

   --  function End_Of_Page
   --    (File : File_Type) return Boolean;
   function End_Of_Page_File (File : File_Type) return Boolean;

   --  function End_Of_Page
   --    (File : File_Type := Standard_Input) return Boolean;
   function End_Of_Page_Input return Boolean;
   --# global in The_Standard_Input;

   --  function End_Of_File
   --    (File : File_Type) return Boolean;
   function End_Of_File_File (File : File_Type) return Boolean;

   --  function End_Of_File
   --    (File : File_Type := Standard_Input) return Boolean;
   function End_Of_File_Input return Boolean;
   --# global in The_Standard_Input;

   --  procedure Set_Col (File : in File_Type;
   --                     To   : in Positive_Count);
   procedure Set_Col_File (File : in out File_Type;
                           To   : in     Positive_Count);
   --# derives File from *,
   --#                   To;
   --# declare delay;

   --  procedure Set_Col (File : in File_Type := Standard_Input;
   --                     To   : in Positive_Count);
   procedure Set_Col_Input (To : in Positive_Count);
   --# global in out The_Standard_Input;
   --# derives The_Standard_Input from *,
   --#                                 To;
   --# declare delay;

   --  procedure Set_Col (File : in File_Type := Standard_Output;
   --                     To   : in Positive_Count);
   procedure Set_Col_Output (To : in Positive_Count);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  To;
   --# declare delay;

   --  procedure Set_Col (File : in File_Type := Standard_Error;
   --                     To   : in Positive_Count);
   procedure Set_Col_Error (To : in Positive_Count);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 To;
   --# declare delay;

   --  procedure Set_Line (File : in File_Type;
   --                      To   : in Positive_Count);
   procedure Set_Line_File (File : in out File_Type;
                            To   : in     Positive_Count);
   --# derives File from *,
   --#                   To;
   --# declare delay;

   --  procedure Set_Line (File : in File_Type := Standard_Input;
   --                      To   : in Positive_Count);
   procedure Set_Line_Input (To : in Positive_Count);
   --# global in out The_Standard_Input;
   --# derives The_Standard_Input from *,
   --#                                 To;
   --# declare delay;

   --  procedure Set_Line (File : in File_Type := Standard_Output;
   --                      To   : in Positive_Count);
   procedure Set_Line_Output (To : in Positive_Count);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  To;
   --# declare delay;

   --  procedure Set_Line (File : in File_Type := Standard_Error;
   --                      To   : in Positive_Count);
   procedure Set_Line_Error (To : in Positive_Count);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 To;
   --# declare delay;

   --  function Col
   --    (File : File_Type) return Positive_Count;
   function Col_File (File : File_Type) return Positive_Count;

   --  function Col
   --    (File : File_Type := Standard_Input) return Positive_Count;
   function Col_Input return Positive_Count;
   --# global in The_Standard_Input;

   --  function Col
   --    (File : File_Type := Standard_Output) return Positive_Count;
   function Col_Output return Positive_Count;
   --# global in The_Standard_Output;

   --  function Col
   --    (File : File_Type := Standard_Error) return Positive_Count;
   function Col_Error return Positive_Count;
   --# global in The_Standard_Error;

   --  function Line (File : File_Type) return Positive_Count;
   function Line_File (File : File_Type) return Positive_Count;

   --  function Line
   --    (File : File_Type := Standard_Input) return Positive_Count;
   function Line_Input return Positive_Count;
   --# global in The_Standard_Input;

   --  function Line
   --    (File : File_Type := Standard_Output) return Positive_Count;
   function Line_Output return Positive_Count;
   --# global in The_Standard_Output;

   --  function Line
   --    (File : File_Type := Standard_Error) return Positive_Count;
   function Line_Error return Positive_Count;
   --# global in The_Standard_Error;

   --  function Page (File : File_Type) return Positive_Count;
   function Page_File (File : File_Type) return Positive_Count;

   --  function Page
   --    (File : File_Type := Standard_Input) return Positive_Count;
   function Page_Input return Positive_Count;
   --# global in The_Standard_Input;

   --  function Page
   --    (File : File_Type := Standard_Output) return Positive_Count;
   function Page_Output return Positive_Count;
   --# global in The_Standard_Output;

   --  function Page
   --    (File : File_Type := Standard_Error) return Positive_Count;
   function Page_Error return Positive_Count;
   --# global in The_Standard_Error;

   ----------------------------
   -- Character Input-Output --
   ----------------------------

   --  procedure Get (File : in     File_Type;
   --                 Item :    out Character);
   procedure Get_Character_File (File : in out File_Type;
                                 Item :    out Character);
   --# derives File,
   --#         Item from File;
   --# declare delay;

   --  procedure Get (File : in     File_Type := Standard_Input;
   --                 Item :    out Character);
   procedure Get_Character_Input (Item : out Character);
   --# global in out The_Standard_Input;
   --# derives Item,
   --#         The_Standard_Input from The_Standard_Input;
   --# declare delay;

   --  procedure Put (File : in File_Type;
   --                 Item : in Character);
   procedure Put_Character_File (File : in out File_Type;
                                 Item : in     Character);
   --# derives File from *,
   --#                   Item;
   --# declare delay;

   --  procedure Put (File : in File_Type := Standard_Output;
   --                 Item : in Character);
   procedure Put_Character_Output (Item : in Character);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  Item;
   --# declare delay;

   --  procedure Put (File : in File_Type := Standard_Error;
   --                 Item : in Character);
   procedure Put_Character_Error (Item : in Character);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 Item;
   --# declare delay;

   --  procedure Look_Ahead
   --    (File        : in     File_Type;
   --     Item        :    out Character;
   --     End_Of_Line :    out Boolean);
   procedure Look_Ahead_File
     (File        : in     File_Type;
      Item        :    out Character;
      End_Of_Line :    out Boolean);
   --# derives End_Of_Line,
   --#         Item        from File;
   --# declare delay;

   --  procedure Look_Ahead
   --    (File        : in     File_Type := Standard_Input;
   --     Item        :    out Character;
   --     End_Of_Line :    out Boolean);
   procedure Look_Ahead_Input
     (Item        : out Character;
      End_Of_Line : out Boolean);
   --# global in The_Standard_Input;
   --# derives End_Of_Line,
   --#         Item        from The_Standard_Input;
   --# declare delay;

   --  procedure Get_Immediate
   --    (File : in     File_Type;
   --     Item :    out Character);
   procedure Get_Immediate_File
     (File : in out File_Type;
      Item :    out Character);
   --# derives File,
   --#         Item from File;
   --# declare delay;

   --  procedure Get_Immediate
   --    (File : in     File_Type := Standard_Input;
   --     Item :    out Character);
   procedure Get_Immediate_Input
     (Item : out Character);
   --# global in out The_Standard_Input;
   --# derives Item,
   --#         The_Standard_Input from The_Standard_Input;
   --# declare delay;

   --  procedure Get_Immediate
   --    (File      : in     File_Type;
   --     Item      :    out Character;
   --     Available :    out Boolean);
   procedure Get_Immediate_Available_File
     (File      : in out File_Type;
      Item      :    out Character;
      Available :    out Boolean);
   --# derives Available,
   --#         File,
   --#         Item      from File;
   --# declare delay;

   --  procedure Get_Immediate
   --    (File      : in     File_Type := Standard_Input;
   --     Item      :    out Character;
   --     Available :    out Boolean);
   procedure Get_Immediate_Available_Input
     (Item      : out Character;
      Available : out Boolean);
   --# global in out The_Standard_Input;
   --# derives Available,
   --#         Item,
   --#         The_Standard_Input from The_Standard_Input;
   --# declare delay;

   -------------------------
   -- String Input-Output --
   -------------------------

   --  procedure Get (File : in     File_Type;
   --                 Item :    out String);
   procedure Get_File (File : in out File_Type;
                       Item :    out String);
   --# derives File,
   --#         Item from File;
   --# declare delay;

   --  procedure Get (File : in     File_Type := Standard_Input;
   --                 Item :    out String);
   procedure Get_Input (Item : out String);
   --# global in out The_Standard_Input;
   --# derives Item,
   --#         The_Standard_Input from The_Standard_Input;
   --# declare delay;

   --  procedure Put (File : in File_Type;
   --                 Item : in String);
   procedure Put_File (File : in out File_Type;
                       Item : in     String);
   --# derives File from *,
   --#                   Item;
   --# declare delay;

   --  procedure Put (File : in File_Type := Standard_Output;
   --                 Item : in String);
   procedure Put_Output (Item : in String);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  Item;
   --# declare delay;

   --  procedure Put (File : in File_Type := Standard_Error;
   --                 Item : in String);
   procedure Put_Error (Item : in String);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 Item;
   --# declare delay;

   --  procedure Get_Line
   --    (File : in     File_Type;
   --     Item :    out String;
   --     Last :    out Natural);
   procedure Procedure_Get_Line_File
     (File     : in out File_Type;
      Item     :    out String;
      Arg_Last :    out Natural);
   --# derives Arg_Last,
   --#         File,
   --#         Item     from File;
   --# declare delay;

   --  procedure Get_Line
   --    (File : in     File_Type := Standard_Input;
   --     Item :    out String;
   --     Last :    out Natural);
   procedure Procedure_Get_Line_Input
     (Item     : out String;
      Arg_Last : out Natural);
   --# global in out The_Standard_Input;
   --# derives Arg_Last,
   --#         Item,
   --#         The_Standard_Input from The_Standard_Input;
   --# declare delay;

   --  procedure Put_Line
   --    (File : in File_Type;
   --     Item : in String);
   procedure Put_Line_File
     (File : in out File_Type;
      Item : in     String);
   --# derives File from *,
   --#                   Item;
   --# declare delay;

   --  procedure Put_Line
   --    (File : in File_Type := Standard_Output;
   --     Item : in String);
   procedure Put_Line_Output
     (Item : in String);
   --# global in out The_Standard_Output;
   --# derives The_Standard_Output from *,
   --#                                  Item;
   --# declare delay;

   --  procedure Put_Line
   --    (File : in File_Type := Standard_Error;
   --     Item : in String);
   procedure Put_Line_Error
     (Item : in String);
   --# global in out The_Standard_Error;
   --# derives The_Standard_Error from *,
   --#                                 Item;
   --# declare delay;

   function Get_Last_Exception_File (File : File_Type) return Exception_T;

   function Get_Last_Exception_Input return Exception_T;
   --# global The_Standard_Input;

   function Get_Last_Exception_Output return Exception_T;
   --# global The_Standard_Output;

   function Get_Last_Exception_Error return Exception_T;
   --# global The_Standard_Error;

   procedure Raise_Last_Exception_File (File : in File_Type);
   --# derives null from File;

   procedure Raise_Last_Exception_Input;
   --# global in The_Standard_Input;
   --# derives null from The_Standard_Input;

   procedure Raise_Last_Exception_Output;
   --# global in The_Standard_Output;
   --# derives null from The_Standard_Output;

   procedure Raise_Last_Exception_Error;
   --# global in The_Standard_Error;
   --# derives null from The_Standard_Error;

private
   --# hide SPARK.Ada.Text_IO;

   type File_Type is record
      The_File_Type : Standard.Ada.Text_IO.File_Type;
      The_Exception : Exception_T;
   end record;

   The_Standard_Input_Exception  : Exception_T;
   The_Standard_Output_Exception : Exception_T;
   The_Standard_Error_Exception  : Exception_T;

   function Get_Exception_T (The_Exception_Name : String) return Exception_T;

end SPARK.Ada.Text_IO;
