home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / a-ststio.adb < prev    next >
Text File  |  1996-09-28  |  12KB  |  436 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                A D A . S T R E A M S . S T R E A M _ I O                 --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.13 $                             --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved        --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. with Interfaces.C_Streams;      use Interfaces.C_Streams;
  27. with System;                    use System;
  28. with System.File_IO;
  29. with System.Tasking_Soft_Links;
  30. with Unchecked_Conversion;
  31. with Unchecked_Deallocation;
  32.  
  33. package body Ada.Streams.Stream_IO is
  34.  
  35.    package FIO renames System.File_IO;
  36.  
  37.    subtype AP is FCB.AFCB_Ptr;
  38.  
  39.    function To_FCB is new Unchecked_Conversion (File_Mode, FCB.File_Mode);
  40.    function To_SIO is new Unchecked_Conversion (FCB.File_Mode, File_Mode);
  41.  
  42.    -----------------------
  43.    -- Local Subprograms --
  44.    -----------------------
  45.  
  46.    procedure Set_Position (File : in File_Type);
  47.    --  Sets file position pointer according to value of current index
  48.  
  49.    -------------------
  50.    -- AFCB_Allocate --
  51.    -------------------
  52.  
  53.    function AFCB_Allocate (Control_Block : Stream_AFCB) return FCB.AFCB_Ptr is
  54.    begin
  55.       return new Stream_AFCB;
  56.    end AFCB_Allocate;
  57.  
  58.    ----------------
  59.    -- AFCB_Close --
  60.    ----------------
  61.  
  62.    --  No special processing required for closing Stream_IO file
  63.  
  64.    procedure AFCB_Close (File : access Stream_AFCB) is
  65.    begin
  66.       null;
  67.    end AFCB_Close;
  68.  
  69.    ---------------
  70.    -- AFCB_Free --
  71.    ---------------
  72.  
  73.    procedure AFCB_Free (File : access Stream_AFCB) is
  74.       type FCB_Ptr is access all Stream_AFCB;
  75.       FT : FCB_Ptr := File;
  76.  
  77.       procedure Free is new Unchecked_Deallocation (Stream_AFCB, FCB_Ptr);
  78.  
  79.    begin
  80.       Free (FT);
  81.    end AFCB_Free;
  82.  
  83.    -----------
  84.    -- Close --
  85.    -----------
  86.  
  87.    procedure Close (File : in out File_Type) is
  88.    begin
  89.       FIO.Close (AP (File));
  90.    end Close;
  91.  
  92.    ------------
  93.    -- Create --
  94.    ------------
  95.  
  96.    procedure Create
  97.      (File : in out File_Type;
  98.       Mode : in File_Mode := Out_File;
  99.       Name : in String := "";
  100.       Form : in String := "")
  101.    is
  102.       File_Control_Block : Stream_AFCB;
  103.  
  104.    begin
  105.       FIO.Open (File_Ptr  => AP (File),
  106.                 Dummy_FCB => File_Control_Block,
  107.                 Mode      => To_FCB (Mode),
  108.                 Name      => Name,
  109.                 Form      => Form,
  110.                 Amethod   => 'S',
  111.                 Creat     => True,
  112.                 Text      => False);
  113.       File.Last_Op := Op_Write;
  114.    end Create;
  115.  
  116.    ------------
  117.    -- Delete --
  118.    ------------
  119.  
  120.    procedure Delete (File : in out File_Type) is
  121.    begin
  122.       FIO.Delete (AP (File));
  123.    end Delete;
  124.  
  125.    -----------------
  126.    -- End_Of_File --
  127.    -----------------
  128.  
  129.    function End_Of_File (File : in File_Type) return Boolean is
  130.    begin
  131.       FIO.Check_Read_Status (AP (File));
  132.       return Count (File.Index) > Size (File);
  133.    end End_Of_File;
  134.  
  135.    -----------
  136.    -- Flush --
  137.    -----------
  138.  
  139.    procedure Flush (File : in out File_Type) is
  140.    begin
  141.       FIO.Flush (AP (File));
  142.    end Flush;
  143.  
  144.    ----------
  145.    -- Form --
  146.    ----------
  147.  
  148.    function Form (File : in File_Type) return String is
  149.    begin
  150.       return FIO.Form (AP (File));
  151.    end Form;
  152.  
  153.    -----------
  154.    -- Index --
  155.    -----------
  156.  
  157.    function Index (File : in File_Type) return Positive_Count is
  158.    begin
  159.       FIO.Check_File_Open (AP (File));
  160.       return Count (File.Index);
  161.    end Index;
  162.  
  163.    -------------
  164.    -- Is_Open --
  165.    -------------
  166.  
  167.    function Is_Open (File : in File_Type) return Boolean is
  168.    begin
  169.       return FIO.Is_Open (AP (File));
  170.    end Is_Open;
  171.  
  172.    ----------
  173.    -- Mode --
  174.    ----------
  175.  
  176.    function Mode (File : in File_Type) return File_Mode is
  177.    begin
  178.       return To_SIO (FIO.Mode (AP (File)));
  179.    end Mode;
  180.  
  181.    ----------
  182.    -- Name --
  183.    ----------
  184.  
  185.    function Name (File : in File_Type) return String is
  186.    begin
  187.       return FIO.Name (AP (File));
  188.    end Name;
  189.  
  190.    ----------
  191.    -- Open --
  192.    ----------
  193.  
  194.    procedure Open
  195.      (File : in out File_Type;
  196.       Mode : in File_Mode;
  197.       Name : in String;
  198.       Form : in String := "")
  199.    is
  200.       File_Control_Block : Stream_AFCB;
  201.  
  202.    begin
  203.       FIO.Open (File_Ptr  => AP (File),
  204.                 Dummy_FCB => File_Control_Block,
  205.                 Mode      => To_FCB (Mode),
  206.                 Name      => Name,
  207.                 Form      => Form,
  208.                 Amethod   => 'S',
  209.                 Creat     => False,
  210.                 Text      => False);
  211.       File.Last_Op := Op_Read;
  212.    end Open;
  213.  
  214.    ----------
  215.    -- Read --
  216.    ----------
  217.  
  218.    procedure Read
  219.      (File : in File_Type;
  220.       Item : out Stream_Element_Array;
  221.       Last : out Stream_Element_Offset;
  222.       From : in Positive_Count)
  223.    is
  224.    begin
  225.       Set_Index (File, From);
  226.       Read (File, Item, Last);
  227.    end Read;
  228.  
  229.    procedure Read
  230.      (File : in File_Type;
  231.       Item : out Stream_Element_Array;
  232.       Last : out Stream_Element_Offset)
  233.    is
  234.       Nread : size_t;
  235.  
  236.    begin
  237.       FIO.Check_Read_Status (AP (File));
  238.  
  239.       --  If last operation was not a read, or if in file sharing mode,
  240.       --  then reset the physical pointer of the file to match the index
  241.       --  We lock out task access over the two operations in this case.
  242.  
  243.       if File.Last_Op /= Op_Read
  244.         or else File.Shared_Status = FCB.Yes
  245.       then
  246.          if End_Of_File (File) then
  247.             raise End_Error;
  248.          end if;
  249.  
  250.          System.Tasking_Soft_Links.Lock_Task;
  251.          Set_Position (File);
  252.          FIO.Read_Buf (AP (File), Item'Address, Item'Length, Nread);
  253.          System.Tasking_Soft_Links.Unlock_Task;
  254.  
  255.       else
  256.          FIO.Read_Buf (AP (File), Item'Address, Item'Length, Nread);
  257.       end if;
  258.  
  259.       File.Index := File.Index + Count (Nread);
  260.       Last := Item'First + Stream_Element_Offset (Nread) - 1;
  261.       File.Last_Op := Op_Read;
  262.    end Read;
  263.  
  264.    --  This version of Read is the primitive operation on the underlying
  265.    --  Stream type, used when a Stream_IO file is treated as a Stream
  266.  
  267.    procedure Read
  268.      (File : in out Stream_AFCB;
  269.       Item : out Ada.Streams.Stream_Element_Array;
  270.       Last : out Ada.Streams.Stream_Element_Offset)
  271.    is
  272.    begin
  273.       if File.Mode > FCB.Inout_File then
  274.          raise Mode_Error;
  275.       end if;
  276.  
  277.       Last :=
  278.         Item'First +
  279.         Stream_Element_Offset
  280.           (fread (Item'Address, 1, Item'Length, File.Stream)) - 1;
  281.  
  282.       if Last < Item'Last then
  283.          if ferror (File.Stream) /= 0 then
  284.             raise Device_Error;
  285.          end if;
  286.       end if;
  287.    end Read;
  288.  
  289.    -----------
  290.    -- Reset --
  291.    -----------
  292.  
  293.    procedure Reset (File : in out File_Type; Mode : in File_Mode) is
  294.    begin
  295.       FIO.Reset (AP (File), To_FCB (Mode));
  296.       File.Index := 1;
  297.       File.Last_Op := Op_Read;
  298.    end Reset;
  299.  
  300.    procedure Reset (File : in out File_Type) is
  301.    begin
  302.       FIO.Reset (AP (File));
  303.       File.Index := 1;
  304.       File.Last_Op := Op_Read;
  305.    end Reset;
  306.  
  307.    ---------------
  308.    -- Set_Index --
  309.    ---------------
  310.  
  311.    procedure Set_Index (File : in File_Type; To : in Positive_Count) is
  312.    begin
  313.       FIO.Check_File_Open (AP (File));
  314.       File.Index := Count (To);
  315.       File.Last_Op := Op_Other;
  316.    end Set_Index;
  317.  
  318.    --------------
  319.    -- Set_Mode --
  320.    --------------
  321.  
  322.    procedure Set_Mode (File : in out File_Type; Mode : in File_Mode) is
  323.    begin
  324.       --  If we are switching from read to write, or vice versa, and
  325.       --  we are not already open in update mode, then reopen in update
  326.       --  mode now. Note that we can use Inout_File as the mode for the
  327.       --  call since File_IO handles all modes for all file types.
  328.  
  329.       if ((File.Mode = FCB.In_File) /= (Mode = In_File))
  330.         and then File.Update_Mode
  331.       then
  332.          FIO.Reset (AP (File), FCB.Inout_File);
  333.       end if;
  334.  
  335.       --  Set required mode and position to end of file if append mode
  336.  
  337.       File.Mode := To_FCB (Mode);
  338.       FIO.Append_Set (AP (File));
  339.       File.Index := Count (ftell (File.Stream)) + 1;
  340.       File.Last_Op := Op_Other;
  341.    end Set_Mode;
  342.  
  343.    ------------------
  344.    -- Set_Position --
  345.    ------------------
  346.  
  347.    procedure Set_Position (File : in File_Type) is
  348.    begin
  349.       if fseek (File.Stream, long (File.Index) - 1, SEEK_SET) /= 0 then
  350.          raise Use_Error;
  351.       end if;
  352.    end Set_Position;
  353.  
  354.    ----------
  355.    -- Size --
  356.    ----------
  357.  
  358.    function Size (File : in File_Type) return Count is
  359.    begin
  360.       FIO.Check_File_Open (AP (File));
  361.       File.Last_Op := Op_Other;
  362.  
  363.       if fseek (File.Stream, 0, SEEK_END) /= 0 then
  364.          raise Device_Error;
  365.       end if;
  366.  
  367.       return Positive_Count (ftell (File.Stream));
  368.    end Size;
  369.  
  370.    ------------
  371.    -- Stream --
  372.    ------------
  373.  
  374.    function Stream (File : in File_Type) return Stream_Access is
  375.    begin
  376.       return Stream_Access (File);
  377.    end Stream;
  378.  
  379.    -----------
  380.    -- Write --
  381.    -----------
  382.  
  383.    procedure Write
  384.      (File : in File_Type;
  385.       Item : in Stream_Element_Array;
  386.       To   : in Positive_Count)
  387.    is
  388.    begin
  389.       Set_Index (File, To);
  390.       Write (File, Item);
  391.    end Write;
  392.  
  393.    procedure Write (File : in File_Type; Item : in Stream_Element_Array) is
  394.    begin
  395.       FIO.Check_Write_Status (AP (File));
  396.  
  397.       --  If last operation was not a write, or if in file sharing mode,
  398.       --  then reset the physical pointer of the file to match the index
  399.       --  We lock out task access over the two operations in this case.
  400.  
  401.       if File.Last_Op /= Op_Write
  402.         or else File.Shared_Status = FCB.Yes
  403.       then
  404.          System.Tasking_Soft_Links.Lock_Task;
  405.          Set_Position (File);
  406.          FIO.Write_Buf (AP (File), Item'Address, Item'Length);
  407.          System.Tasking_Soft_Links.Unlock_Task;
  408.       else
  409.          FIO.Write_Buf (AP (File), Item'Address, Item'Length);
  410.       end if;
  411.  
  412.       File.Index := File.Index + Item'Length;
  413.       File.Last_Op := Op_Write;
  414.    end Write;
  415.  
  416.    --  This version of Write is the primitive operation on the underlying
  417.    --  Stream type, used when a Stream_IO file is treated as a Stream
  418.  
  419.    procedure Write
  420.      (File : in out Stream_AFCB;
  421.       Item : in Ada.Streams.Stream_Element_Array)
  422.    is
  423.       Siz : constant size_t := Item'Length;
  424.  
  425.    begin
  426.       if File.Mode = FCB.In_File then
  427.          raise Mode_Error;
  428.       end if;
  429.  
  430.       if fwrite (Item'Address, 1, Siz, File.Stream) /= Siz then
  431.          raise Device_Error;
  432.       end if;
  433.    end Write;
  434.  
  435. end Ada.Streams.Stream_IO;
  436.