OSDN Git Service

2005-03-29 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-sequio.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT RUNTIME COMPONENTS                          --
4 --                                                                          --
5 --                    A D A . S E Q U E N T I A L _ I O                     --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2003, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- As a special exception,  if other files  instantiate  generics from this --
23 -- unit, or you link  this unit with other files  to produce an executable, --
24 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
25 -- covered  by the  GNU  General  Public  License.  This exception does not --
26 -- however invalidate  any other reasons why  the executable file  might be --
27 -- covered by the  GNU Public License.                                      --
28 --                                                                          --
29 -- GNAT was originally developed  by the GNAT team at  New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 --  This is the generic template for Sequential_IO, i.e. the code that gets
35 --  duplicated. We absolutely minimize this code by either calling routines
36 --  in System.File_IO (for common file functions), or in System.Sequential_IO
37 --  (for specialized Sequential_IO functions)
38
39 with Interfaces.C_Streams; use Interfaces.C_Streams;
40 with System;
41 with System.CRTL;
42 with System.File_Control_Block;
43 with System.File_IO;
44 with System.Storage_Elements;
45 with Unchecked_Conversion;
46
47 package body Ada.Sequential_IO is
48
49    package FIO renames System.File_IO;
50    package FCB renames System.File_Control_Block;
51    package SIO renames System.Sequential_IO;
52    package SSE renames System.Storage_Elements;
53
54    SU : constant := System.Storage_Unit;
55
56    subtype AP is FCB.AFCB_Ptr;
57    subtype FP is SIO.File_Type;
58
59    function To_FCB is new Unchecked_Conversion (File_Mode, FCB.File_Mode);
60    function To_SIO is new Unchecked_Conversion (FCB.File_Mode, File_Mode);
61
62    use type System.CRTL.size_t;
63
64    -----------
65    -- Close --
66    -----------
67
68    procedure Close (File : in out File_Type) is
69    begin
70       FIO.Close (AP (File));
71    end Close;
72
73    ------------
74    -- Create --
75    ------------
76
77    procedure Create
78      (File : in out File_Type;
79       Mode : in File_Mode := Out_File;
80       Name : in String := "";
81       Form : in String := "")
82    is
83    begin
84       SIO.Create (FP (File), To_FCB (Mode), Name, Form);
85    end Create;
86
87    ------------
88    -- Delete --
89    ------------
90
91    procedure Delete (File : in out File_Type) is
92    begin
93       FIO.Delete (AP (File));
94    end Delete;
95
96    -----------------
97    -- End_Of_File --
98    -----------------
99
100    function End_Of_File (File : in File_Type) return Boolean is
101    begin
102       return FIO.End_Of_File (AP (File));
103    end End_Of_File;
104
105    ----------
106    -- Form --
107    ----------
108
109    function Form (File : in File_Type) return String is
110    begin
111       return FIO.Form (AP (File));
112    end Form;
113
114    -------------
115    -- Is_Open --
116    -------------
117
118    function Is_Open (File : in File_Type) return Boolean is
119    begin
120       return FIO.Is_Open (AP (File));
121    end Is_Open;
122
123    ----------
124    -- Mode --
125    ----------
126
127    function Mode (File : in File_Type) return File_Mode is
128    begin
129       return To_SIO (FIO.Mode (AP (File)));
130    end Mode;
131
132    ----------
133    -- Name --
134    ----------
135
136    function Name (File : in File_Type) return String is
137    begin
138       return FIO.Name (AP (File));
139    end Name;
140
141    ----------
142    -- Open --
143    ----------
144
145    procedure Open
146      (File : in out File_Type;
147       Mode : in File_Mode;
148       Name : in String;
149       Form : in String := "")
150    is
151    begin
152       SIO.Open (FP (File), To_FCB (Mode), Name, Form);
153    end Open;
154
155    ----------
156    -- Read --
157    ----------
158
159    procedure Read (File : in File_Type; Item : out Element_Type) is
160       Siz  : constant size_t := (Item'Size + SU - 1) / SU;
161       Rsiz : size_t;
162
163    begin
164       FIO.Check_Read_Status (AP (File));
165
166       --  For non-definite type or type with discriminants, read size and
167       --  raise Program_Error if it is larger than the size of the item.
168
169       if not Element_Type'Definite
170         or else Element_Type'Has_Discriminants
171       then
172          FIO.Read_Buf
173            (AP (File), Rsiz'Address, size_t'Size / System.Storage_Unit);
174
175          --  For a type with discriminants, we have to read into a temporary
176          --  buffer if Item is constrained, to check that the discriminants
177          --  are correct.
178
179          pragma Extensions_Allowed (On);
180          --  Needed to allow Constrained reference here
181
182          if Element_Type'Has_Discriminants
183            and then Item'Constrained
184          then
185             declare
186                RsizS : constant SSE.Storage_Offset :=
187                          SSE.Storage_Offset (Rsiz - 1);
188
189                type SA is new SSE.Storage_Array (0 .. RsizS);
190
191                for SA'Alignment use Standard'Maximum_Alignment;
192                --  We will perform an unchecked conversion of a pointer-to-SA
193                --  into pointer-to-Element_Type. We need to ensure that the
194                --  source is always at least as strictly aligned as the target.
195
196                type SAP   is access all SA;
197                type ItemP is access all Element_Type;
198
199                pragma Warnings (Off);
200                --  We have to turn warnings off for function To_ItemP,
201                --  because it gets analyzed for all types, including ones
202                --  which can't possibly come this way, and for which the
203                --  size of the access types differs.
204
205                function To_ItemP is new Unchecked_Conversion (SAP, ItemP);
206
207                pragma Warnings (On);
208
209                Buffer : aliased SA;
210
211                pragma Unsuppress (Discriminant_Check);
212
213             begin
214                FIO.Read_Buf (AP (File), Buffer'Address, Rsiz);
215                Item := To_ItemP (Buffer'Access).all;
216                return;
217             end;
218          end if;
219
220          --  In the case of a non-definite type, make sure the length is OK.
221          --  We can't do this in the variant record case, because the size is
222          --  based on the current discriminant, so may be apparently wrong.
223
224          if not Element_Type'Has_Discriminants and then Rsiz > Siz then
225             raise Program_Error;
226          end if;
227
228          FIO.Read_Buf (AP (File), Item'Address, Rsiz);
229
230       --  For definite type without discriminants, use actual size of item
231
232       else
233          FIO.Read_Buf (AP (File), Item'Address, Siz);
234       end if;
235    end Read;
236
237    -----------
238    -- Reset --
239    -----------
240
241    procedure Reset (File : in out File_Type; Mode : in File_Mode) is
242    begin
243       FIO.Reset (AP (File), To_FCB (Mode));
244    end Reset;
245
246    procedure Reset (File : in out File_Type) is
247    begin
248       FIO.Reset (AP (File));
249    end Reset;
250
251    -----------
252    -- Write --
253    -----------
254
255    procedure Write (File : in File_Type; Item : in Element_Type) is
256       Siz : constant size_t := (Item'Size + SU - 1) / SU;
257
258    begin
259       FIO.Check_Write_Status (AP (File));
260
261       --  For non-definite types or types with discriminants, write the size
262
263       if not Element_Type'Definite
264         or else Element_Type'Has_Discriminants
265       then
266          FIO.Write_Buf
267            (AP (File), Siz'Address, size_t'Size / System.Storage_Unit);
268       end if;
269
270       FIO.Write_Buf (AP (File), Item'Address, Siz);
271    end Write;
272
273 end Ada.Sequential_IO;