OSDN Git Service

2008-05-27 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-sequio.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT RUN-TIME 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-2008, 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,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, 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 Ada.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 Ada.Unchecked_Conversion (File_Mode, FCB.File_Mode);
60    function To_SIO is new Ada.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       AFCB : aliased AP;
70       for AFCB'Address use File'Address;
71       pragma Import (Ada, AFCB);
72    begin
73       FIO.Close (AFCB'Access);
74    end Close;
75
76    ------------
77    -- Create --
78    ------------
79
80    procedure Create
81      (File : in out File_Type;
82       Mode : File_Mode := Out_File;
83       Name : String := "";
84       Form : String := "")
85    is
86    begin
87       SIO.Create (FP (File), To_FCB (Mode), Name, Form);
88    end Create;
89
90    ------------
91    -- Delete --
92    ------------
93
94    procedure Delete (File : in out File_Type) is
95       AFCB : aliased AP;
96       for AFCB'Address use File'Address;
97       pragma Import (Ada, AFCB);
98    begin
99       FIO.Delete (AFCB'Access);
100    end Delete;
101
102    -----------------
103    -- End_Of_File --
104    -----------------
105
106    function End_Of_File (File : File_Type) return Boolean is
107    begin
108       return FIO.End_Of_File (AP (File));
109    end End_Of_File;
110
111    ----------
112    -- Form --
113    ----------
114
115    function Form (File : File_Type) return String is
116    begin
117       return FIO.Form (AP (File));
118    end Form;
119
120    -------------
121    -- Is_Open --
122    -------------
123
124    function Is_Open (File : File_Type) return Boolean is
125    begin
126       return FIO.Is_Open (AP (File));
127    end Is_Open;
128
129    ----------
130    -- Mode --
131    ----------
132
133    function Mode (File : File_Type) return File_Mode is
134    begin
135       return To_SIO (FIO.Mode (AP (File)));
136    end Mode;
137
138    ----------
139    -- Name --
140    ----------
141
142    function Name (File : File_Type) return String is
143    begin
144       return FIO.Name (AP (File));
145    end Name;
146
147    ----------
148    -- Open --
149    ----------
150
151    procedure Open
152      (File : in out File_Type;
153       Mode : File_Mode;
154       Name : String;
155       Form : String := "")
156    is
157    begin
158       SIO.Open (FP (File), To_FCB (Mode), Name, Form);
159    end Open;
160
161    ----------
162    -- Read --
163    ----------
164
165    procedure Read (File : File_Type; Item : out Element_Type) is
166       Siz  : constant size_t := (Item'Size + SU - 1) / SU;
167       Rsiz : size_t;
168
169    begin
170       FIO.Check_Read_Status (AP (File));
171
172       --  For non-definite type or type with discriminants, read size and
173       --  raise Program_Error if it is larger than the size of the item.
174
175       if not Element_Type'Definite
176         or else Element_Type'Has_Discriminants
177       then
178          FIO.Read_Buf
179            (AP (File), Rsiz'Address, size_t'Size / System.Storage_Unit);
180
181          --  For a type with discriminants, we have to read into a temporary
182          --  buffer if Item is constrained, to check that the discriminants
183          --  are correct.
184
185          pragma Extensions_Allowed (On);
186          --  Needed to allow Constrained reference here
187
188          if Element_Type'Has_Discriminants
189            and then Item'Constrained
190          then
191             declare
192                RsizS : constant SSE.Storage_Offset :=
193                          SSE.Storage_Offset (Rsiz - 1);
194
195                type SA is new SSE.Storage_Array (0 .. RsizS);
196
197                for SA'Alignment use Standard'Maximum_Alignment;
198                --  We will perform an unchecked conversion of a pointer-to-SA
199                --  into pointer-to-Element_Type. We need to ensure that the
200                --  source is always at least as strictly aligned as the target.
201
202                type SAP   is access all SA;
203                type ItemP is access all Element_Type;
204
205                pragma Warnings (Off);
206                --  We have to turn warnings off for function To_ItemP,
207                --  because it gets analyzed for all types, including ones
208                --  which can't possibly come this way, and for which the
209                --  size of the access types differs.
210
211                function To_ItemP is new Ada.Unchecked_Conversion (SAP, ItemP);
212
213                pragma Warnings (On);
214
215                Buffer : aliased SA;
216
217                pragma Unsuppress (Discriminant_Check);
218
219             begin
220                FIO.Read_Buf (AP (File), Buffer'Address, Rsiz);
221                Item := To_ItemP (Buffer'Access).all;
222                return;
223             end;
224          end if;
225
226          --  In the case of a non-definite type, make sure the length is OK.
227          --  We can't do this in the variant record case, because the size is
228          --  based on the current discriminant, so may be apparently wrong.
229
230          if not Element_Type'Has_Discriminants and then Rsiz > Siz then
231             raise Program_Error;
232          end if;
233
234          FIO.Read_Buf (AP (File), Item'Address, Rsiz);
235
236       --  For definite type without discriminants, use actual size of item
237
238       else
239          FIO.Read_Buf (AP (File), Item'Address, Siz);
240       end if;
241    end Read;
242
243    -----------
244    -- Reset --
245    -----------
246
247    procedure Reset (File : in out File_Type; Mode : File_Mode) is
248       AFCB : aliased AP;
249       for AFCB'Address use File'Address;
250       pragma Import (Ada, AFCB);
251    begin
252       FIO.Reset (AFCB'Access, To_FCB (Mode));
253    end Reset;
254
255    procedure Reset (File : in out File_Type) is
256       AFCB : aliased AP;
257       for AFCB'Address use File'Address;
258       pragma Import (Ada, AFCB);
259    begin
260       FIO.Reset (AFCB'Access);
261    end Reset;
262
263    -----------
264    -- Write --
265    -----------
266
267    procedure Write (File : File_Type; Item : Element_Type) is
268       Siz : constant size_t := (Item'Size + SU - 1) / SU;
269
270    begin
271       FIO.Check_Write_Status (AP (File));
272
273       --  For non-definite types or types with discriminants, write the size
274
275       if not Element_Type'Definite
276         or else Element_Type'Has_Discriminants
277       then
278          FIO.Write_Buf
279            (AP (File), Siz'Address, size_t'Size / System.Storage_Unit);
280       end if;
281
282       FIO.Write_Buf (AP (File), Item'Address, Siz);
283    end Write;
284
285 end Ada.Sequential_IO;