DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦9a6809ed0⟧ TextFile

    Length: 25478 (0x6386)
    Types: TextFile
    Names: »B«

Derivation

└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
    └─ ⟦77aa8350c⟧ »DATA« 
        └─⟦f794ecd1d⟧ 
            └─⟦4c85d69e2⟧ 
                └─⟦this⟧ 

TextFile

--    The use of this system is subject to the software license terms and
--    conditions agreed upon between Rational and the Customer.
--
--                Copyright 1988 by Rational.
--
--                          RESTRICTED RIGHTS LEGEND
--
--    Use, duplication, or disclosure by the Government is subject to
--    restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
--    Technical Data and Computer Software clause at 52.227-7013.
--
--
--                Rational
--                3320 Scott Boulevard
--                Santa Clara, California 95054-3197
--
--   PROPRIETARY AND CONFIDENTIAL INFORMATION OF RATIONAL;
--   USE OR COPYING WITHOUT EXPRESS WRITTEN AUTHORIZATION
--   IS STRICTLY PROHIBITED.  THIS MATERIAL IS PROTECTED AS
--   AN UNPUBLISHED WORK UNDER THE U.S. COPYRIGHT ACT OF
--   1976.  CREATED 1988.  ALL RIGHTS RESERVED.
--
--

with Buffering;
with Os_Dependent_Io;
with Semaphore;
with Unchecked_Conversion;
with Unchecked_Deallocation;

-- with Primitive_Io;  -- For debugging only (e.g., List_All_Open_Files)

package body Device_Independent_Io is


    type Double_Link is
        record
            Prev : File_Type := null;
            Next : File_Type := null;
        end record;


    type File_Descriptor is
        record
            The_Mode         : File_Mode := Closed;
            The_Kind         : File_Kind := Normal;
            Exclusive_Access : Semaphore.Lock_State :=
               Semaphore.Initial_Lock_State;
            Os_Block         : Os_Dependent_Io.Os_Control_Block;
            Protocol_Block   : System.Address := System_Types.Null_Address;
            Data_Buffer      : Buffering.Data_Buffer := Buffering.No_Buffer;
            Connections      : Double_Link;
        end record;


    -- All open files are threaded on this list:

    All_Open_Files : File_Type := null;

    -- These three objects are logically constants, but we want all fields
    -- to take the implicit default values and Ada requires that if an
    -- object is declared constant it must have an explicit initialization.

    A_Closed_Input_File  : File_Descriptor;
    A_Closed_Output_File : File_Descriptor;
    A_Closed_Error_File  : File_Descriptor;

    function To_File_Type is new Unchecked_Conversion
                                    (System.Address, File_Type);


    -- Dio_Absorb_Output : constant Boolean := Primitive_Io.Global_Absorb_Output;
    -- procedure Pput (S : in String;
    --                 Absorb_Output : Boolean := Dio_Absorb_Output)
    --     renames Primitive_Io.Put_Line;

    procedure Free is new Unchecked_Deallocation (File_Descriptor, File_Type);


    function Is_Open (File : File_Type) return Boolean is
    begin
        return File /= null and then File.The_Mode /= Closed;
    end Is_Open;


    procedure Check_Open (File : File_Type) is
    begin
        -- if not Is_Open (File) then
        --     raise Status_Error;
        -- end if;
        if File = null or else File.The_Mode = Closed then
            raise Status_Error;
        end if;
    end Check_Open;
    pragma Inline (Check_Open);


    procedure Acquire (File : File_Type) is
    begin
        if File /= null then
            Semaphore.Acquire (File.Exclusive_Access);
        end if;
        -- exception
        --    when Constraint_Error =>
        --        -- If file was already closed, for example
        --        null;
    end Acquire;

    procedure Release (File : File_Type) is
    begin
        if File /= null then
            Semaphore.Release (File.Exclusive_Access);
        end if;
        -- exception
        --     when Constraint_Error =>
        --         -- If file was already closed, for example
        --        null;
    end Release;


    procedure Acquire_If_Needed (File : File_Type; Already_Locked : Boolean) is
    begin
        if not Already_Locked then
            begin
                Semaphore.Acquire (File.Exclusive_Access);
            exception
                when Constraint_Error =>
                    -- If file was already closed, for example
                    null;
            end;
        end if;
    end Acquire_If_Needed;

    procedure Release_If_Grabbed (File : File_Type; Already_Locked : Boolean) is
    begin
        if not Already_Locked then
            begin
                Semaphore.Release (File.Exclusive_Access);
            exception
                when Constraint_Error =>
                    -- If file was already closed, for example
                    null;
            end;
        end if;
    end Release_If_Grabbed;

    pragma Inline (Acquire_If_Needed, Release_If_Grabbed);


    -- Used to implement program termination

    procedure Add_To_Open_Files (File : File_Type) is
    begin
        File.Connections.Next := All_Open_Files;
        if All_Open_Files /= null then
            All_Open_Files.Connections.Prev := File;
        end if;
        All_Open_Files := File;
    end Add_To_Open_Files;

    procedure Remove_From_Open_Files (File : File_Type) is
    begin
        if File.Connections.Prev /= null then
            File.Connections.Prev.Connections.Next := File.Connections.Next;
            if File.Connections.Next /= null then
                File.Connections.Next.Connections.Prev := File.Connections.Prev;
            end if;
        end if;
        if All_Open_Files = File then
            All_Open_Files := File.Connections.Next;
        end if;
    end Remove_From_Open_Files;


    -- File is known to be null or Closed.
    procedure Real_Open (File                    : in out File_Type;
                         Mode                    : in File_Mode;
                         Kind                    : in File_Kind;
                         Name                    : in String;
                         Form                    : in String;
                         Recommended_Buffer_Size : in Natural;
                         Actual_Buffer_Size      : out Natural;
                         Client                  : in Client_Kind := Unknown) is

    begin
        File := new File_Descriptor;
        begin
            Os_Dependent_Io.Open (File, File.Os_Block, Mode, Kind,
                                  Name, Form, Recommended_Buffer_Size,
                                  Actual_Buffer_Size, Client);
        exception
            when others =>
                Free (File);
                raise;
        end;
        File.The_Mode := Mode;
        File.The_Kind := Kind;
        Add_To_Open_Files (File);
    end Real_Open;


    procedure Open (File                    : in out File_Type;
                    Mode                    : in     File_Mode;
                    Kind                    : in     File_Kind;
                    Name                    : in     String      := "";
                    Form                    : in     String      := "";
                    Recommended_Buffer_Size : in     Natural;
                    Actual_Buffer_Size      : out    Natural;
                    Client                  : in     Client_Kind := Unknown) is
    begin
        if Is_Open (File) then
            raise Status_Error;
        end if;
        if Kind = Temporary then
            -- Can't Open a temporary file, must Create it
            raise Name_Error;
        end if;
        Real_Open (File, Mode, Kind, Name, Form,
                   Recommended_Buffer_Size, Actual_Buffer_Size, Client);
    end Open;


    procedure Append (File                    : in out File_Type;
                      Mode                    : in     File_Mode;
                      Kind                    : in     File_Kind;
                      Name                    : in     String := "";
                      Form                    : in     String := "";
                      Recommended_Buffer_Size : in     Natural;
                      Actual_Buffer_Size      : out    Natural) is
    begin
        if Is_Open (File) then
            raise Status_Error;
        end if;
        if Kind = Temporary then
            -- Can't Append to a temporary file, must Create it
            raise Name_Error;
        end if;
        Real_Open (File, Mode, Kind, Name, Form, Recommended_Buffer_Size,
                   Actual_Buffer_Size, Unknown);
        -- ??? Ok wiseguy, now position to the end
        -- ??? When is check made that OS permits append on files
        -- ???    of this Mode and Kind?

        raise Program_Error;

    end Append;


    procedure Create (File                    : in out File_Type;
                      Mode                    : in     File_Mode;
                      Kind                    : in     File_Kind;
                      Name                    : in     String := "";
                      Form                    : in     String := "";
                      Recommended_Buffer_Size : in     Natural;
                      Actual_Buffer_Size      : out    Natural) is

    begin
        if Is_Open (File) then
            raise Status_Error;
        end if;
        File := new File_Descriptor;
        begin
            Os_Dependent_Io.Create
               (File, File.Os_Block, Mode, Kind, Name, Form,
                Recommended_Buffer_Size, Actual_Buffer_Size);
        exception
            when others =>
                Free (File);
                raise;
        end;
        File.The_Mode := Mode;
        File.The_Kind := Kind;
        Add_To_Open_Files (File);
    end Create;


    procedure Close (File           : in out File_Type;
                     Already_Locked :        Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            begin
                Os_Dependent_Io.Close (File, File.Os_Block);
                Buffering.Free (File.Data_Buffer);
                File.The_Mode := Closed;
                Remove_From_Open_Files (File);
                -- When closing the file we release the lock unconditionally
                Release (File);
                Free (File); -- File := null;
            exception
                when others =>
                    -- When closing the file we release the lock unconditionally
                    Release (File);
                    raise;
            end;
        end if;
    end Close;


    procedure Save (File             : File_Type;
                    Immediate_Effect : Boolean := True;
                    Already_Locked   : Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            begin
                Os_Dependent_Io.Save (File, File.Os_Block, Immediate_Effect);
                Release_If_Grabbed (File, Already_Locked);
            exception
                when others =>
                    Release_If_Grabbed (File, Already_Locked);
                    raise;
            end;
        end if;
    end Save;


    procedure Delete (File           : in out File_Type;
                      Already_Locked :        Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            begin
                Os_Dependent_Io.Delete (File, File.Os_Block);
                Buffering.Free (File.Data_Buffer);
                File.The_Mode := Closed;
                Remove_From_Open_Files (File);
                -- When deleting the file, we release the lock unconditionally
                Release (File);
                Free (File); -- File := null;
            exception
                when others =>
                    -- ??? Should the file be closed ???
                    -- Since here the file is not deleted, and not
                    -- closed, we release the lock conditionally.
                    Release_If_Grabbed (File, Already_Locked);
                    raise;
            end;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Delete;


    procedure Reset (File           : in out File_Type;
                     Mode           :        File_Mode;
                     Already_Locked :        Boolean := True) is
    begin
        if Mode = Closed then
            raise Status_Error;
        end if;

        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            begin
                Os_Dependent_Io.Reset (File, File.Os_Block, Mode);
                File.The_Mode := Mode;
                Release_If_Grabbed (File, Already_Locked);
            exception
                when others =>
                    Release_If_Grabbed (File, Already_Locked);
                    raise;
            end;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Reset;


    procedure Reset (File           : in out File_Type;
                     Already_Locked :        Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            begin
                Os_Dependent_Io.Reset (File, File.Os_Block, File.The_Mode);
                Release_If_Grabbed (File, Already_Locked);
            exception
                when others =>
                    Release_If_Grabbed (File, Already_Locked);
                    raise;
            end;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Reset;


    function Mode (File : File_Type; Already_Locked : Boolean := True)
                  return File_Mode is
        Mode : File_Mode;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            Mode := File.The_Mode;
            Release_If_Grabbed (File, Already_Locked);
            return Mode;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Mode;


    function Kind (File : File_Type; Already_Locked : Boolean := True)
                  return File_Kind is
        Kind : File_Kind;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            Kind := File.The_Kind;
            Release_If_Grabbed (File, Already_Locked);
            return Kind;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Kind;


    function Name (File : File_Type; Already_Locked : Boolean := True)
                  return String is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            declare
                Name : constant String :=
                   Os_Dependent_Io.Name (File, File.Os_Block);
            begin
                Release_If_Grabbed (File, Already_Locked);
                return Name;
            end;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Name;


    function Form (File : File_Type; Already_Locked : Boolean := True)
                  return String is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            declare
                Form : constant String :=
                   Os_Dependent_Io.Form (File, File.Os_Block);
            begin
                Release_If_Grabbed (File, Already_Locked);
                return Form;
            end;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Form;


    procedure Set (File : File_Type; Buffer : Buffering.Data_Buffer) is
    begin
        File.Data_Buffer := Buffer;
    end Set;


    function Get (File : File_Type) return Buffering.Data_Buffer is
    begin
        return File.Data_Buffer;
    end Get;


    function Buffer_Size (File : File_Type; Already_Locked : Boolean := True)
                         return Natural is
        N : Natural := 0;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            if Buffering.Is_Allocated (File.Data_Buffer) then
                N := Buffering.Max_Length (File.Data_Buffer);
            else
                N := 0;
            end if;
            Release_If_Grabbed (File, Already_Locked);
            return N;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Buffer_Size;


    function End_Of_File (File : File_Type; Already_Locked : Boolean := True)
                         return Boolean is
        Eof : Boolean;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            Eof := Os_Dependent_Io.End_Of_File (File, File.Os_Block);
            Release_If_Grabbed (File, Already_Locked);
            return Eof;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end End_Of_File;


    function Is_Interactive (File : File_Type; Already_Locked : Boolean := True)
                            return Boolean is
        Ii : Boolean;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            Ii := Os_Dependent_Io.Is_Interactive (File, File.Os_Block);
            Release_If_Grabbed (File, Already_Locked);
            return Ii;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Is_Interactive;


    procedure Read (File                     : in     File_Type;
                    Item                     : in out Byte_String;
                    Count                    : out    Natural;
                    Line_Terminator_Detected : out    Boolean;
                    Line_Last_Data_Index     : out    Natural;
                    Line_Terminator_Present  : out    Boolean;
                    Already_Locked           :        Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            if File.The_Mode = In_File then
                -- Data is always read into the user's buffer directly.  In case
                -- of error his buffer could be trashed.  This seems reasonable.
                Os_Dependent_Io.Read (File,  
                                      File.Os_Block,  
                                      Item, Count, Line_Terminator_Detected,  
                                      Line_Last_Data_Index,  
                                      Line_Terminator_Present);  
                Release_If_Grabbed (File, Already_Locked);
            else
                raise Mode_Error;
            end if;
        else
            raise Status_Error;
        end if;
    exception
        when others =>
            Release_If_Grabbed (File, Already_Locked);
            raise;
    end Read;


    procedure Read (File           :        File_Type;
                    Item           : in out Byte_String;
                    Count          : out    Natural;
                    Already_Locked :        Boolean := True) is
        Db, Dc : Boolean;
        Dn     : Natural;
    begin
        Read (File, Item, Count, Db, Dn, Dc, Already_Locked);
    end Read;


    procedure Write (File                    : in File_Type;
                     Item                    : in Byte_String;
                     Line_Terminator_Present : in Boolean;
                     Already_Locked          :    Boolean := True) is
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            if File.The_Mode = Out_File then
                -- With this call, which writes a record at a time, we
                -- don't go through the file's buffer.  (In fact, maybe
                -- we shouldn't allocate the buffer?)  Because even with
                -- asynchronous I/O the task which has the data can't
                -- continue until the I/O is complete.
                begin
                    Os_Dependent_Io.Write (File, File.Os_Block, Item,
                                           Line_Terminator_Present);
                    Release_If_Grabbed (File, Already_Locked);
                end;
            else
                raise Mode_Error;
            end if;
        else
            raise Status_Error;
        end if;
    exception
        when others =>
            Release_If_Grabbed (File, Already_Locked);
            raise;
    end Write;


    function Is_Empty (File : File_Type; Already_Locked : Boolean := True)
                      return Boolean is
        Ie : Boolean;
    begin
        Acquire_If_Needed (File, Already_Locked);
        if Is_Open (File) then
            Ie := Os_Dependent_Io.Is_Empty (File, File.Os_Block);
            Release_If_Grabbed (File, Already_Locked);
            return Ie;
        else
            Release_If_Grabbed (File, Already_Locked);
            raise Status_Error;
        end if;
    end Is_Empty;

    function Closed_Input_File return File_Type is
    begin
        return To_File_Type (A_Closed_Input_File'Address);
    end Closed_Input_File;

    function Closed_Output_File return File_Type is
    begin
        return To_File_Type (A_Closed_Output_File'Address);
    end Closed_Output_File;

    function Closed_Error_File return File_Type is
    begin
        return To_File_Type (A_Closed_Error_File'Address);
    end Closed_Error_File;


    procedure Close_All_Open_Files is
    begin
        -- The big problem, of course, is how (in Ada) to call the
        -- protocol-level Close ?!??!

        -- One way:  The protocol routine will provide the 'Address
        -- of the routine to call to be put in the file control
        -- block to be called through a special assembly language
        -- routine.

        raise Program_Error;
    end Close_All_Open_Files;


    procedure Identical_Files (File        : in  File_Type;
                               Open_In     : out Natural;
                               Open_Out    : out Natural;
                               Open_In_Out : out Natural) is
        Files                 : File_Type;
        O_In, O_Out, O_In_Out : Natural := 0;
    begin
        Files := All_Open_Files;
        loop
            exit when Files = null;

            if Os_Dependent_Io.Identical_File
                  (File, File.Os_Block, Files, Files.Os_Block) then
                case Files.The_Mode is
                    when In_File =>
                        O_In := O_In + 1;
                    when Out_File =>
                        O_Out := O_Out + 1;
                    when Inout_File =>
                        O_In_Out := O_In_Out + 1;
                    when Closed =>
                        null;
                end case;
            end if;
            Files := Files.Connections.Next;
        end loop;

        Open_In     := O_In;
        Open_Out    := O_Out;
        Open_In_Out := O_In_Out;
    end Identical_Files;


    procedure List_All_Open_Files is
        -- Files : File_Type;
        -- Debugging : constant Boolean := not Dio_Absorb_Output;
    begin
        -- if not Debugging then
        return;
        -- end if;
        -- if All_Open_Files = null then
        --     Pput ("Device_Independent_Io:  No open files");
        -- else
        --     Pput ("Device_Independent_Io:  Currently open files:");
        --     Files := All_Open_Files;
        --     loop
        --         begin
        --             Pput ("   " & Name (Files));
        --         exception
        --             when others =>
        --                 Pput
        --                    ("   << File open but name can't be determined >>");
        --         end;
        --         Files := Files.Connections.Next;
        --         exit when Files = null;
        --     end loop;
        -- end if;
    end List_All_Open_Files;


    package body Client_Specific is

        procedure Set (File : File_Type; Control : Pointer) is
        begin
            raise Program_Error;
        end Set;

        function Get (File : File_Type) return Pointer is
        begin
            raise Program_Error;
            return null;
        end Get;

    end Client_Specific;


    procedure Set (File : File_Type; Control : System.Address) is
    begin
        File.Protocol_Block := Control;
    end Set;

    function Get (File : File_Type) return System.Address is
    begin
        return File.Protocol_Block;
    end Get;

    function Get_Os_Dependent_Control
                (File : File_Type) return System.Address is
    begin
        if File /= null then
            return Os_Dependent_Io.Address_For_Control (File.Os_Block);
        else
            return System.Address_Zero;
        end if;
    end Get_Os_Dependent_Control;

    package body File_Type_Conversions is

        function To_Derived   is new Unchecked_Conversion
                                        (File_Type, Derived_File_Type);
        function From_Derived is new Unchecked_Conversion
                                        (Derived_File_Type, File_Type);

        function From_Standard (File : File_Type) return Derived_File_Type is
        begin
            return To_Derived (File);
        end From_Standard;

        function To_Standard (File : Derived_File_Type) return File_Type is
        begin
            return From_Derived (File);
        end To_Standard;

    end File_Type_Conversions;

end Device_Independent_Io;