1*0bfacb9bSmrg /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
2760c2415Smrg Contributed by Andy Vaught
3760c2415Smrg Namelist transfer functions contributed by Paul Thomas
4760c2415Smrg F2003 I/O support contributed by Jerry DeLisle
5760c2415Smrg
6760c2415Smrg This file is part of the GNU Fortran runtime library (libgfortran).
7760c2415Smrg
8760c2415Smrg Libgfortran is free software; you can redistribute it and/or modify
9760c2415Smrg it under the terms of the GNU General Public License as published by
10760c2415Smrg the Free Software Foundation; either version 3, or (at your option)
11760c2415Smrg any later version.
12760c2415Smrg
13760c2415Smrg Libgfortran is distributed in the hope that it will be useful,
14760c2415Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
15760c2415Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16760c2415Smrg GNU General Public License for more details.
17760c2415Smrg
18760c2415Smrg Under Section 7 of GPL version 3, you are granted additional
19760c2415Smrg permissions described in the GCC Runtime Library Exception, version
20760c2415Smrg 3.1, as published by the Free Software Foundation.
21760c2415Smrg
22760c2415Smrg You should have received a copy of the GNU General Public License and
23760c2415Smrg a copy of the GCC Runtime Library Exception along with this program;
24760c2415Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25760c2415Smrg <http://www.gnu.org/licenses/>. */
26760c2415Smrg
27760c2415Smrg
28760c2415Smrg /* transfer.c -- Top level handling of data transfer statements. */
29760c2415Smrg
30760c2415Smrg #include "io.h"
31760c2415Smrg #include "fbuf.h"
32760c2415Smrg #include "format.h"
33760c2415Smrg #include "unix.h"
34760c2415Smrg #include "async.h"
35760c2415Smrg #include <string.h>
36760c2415Smrg #include <errno.h>
37760c2415Smrg
38760c2415Smrg
39760c2415Smrg /* Calling conventions: Data transfer statements are unlike other
40760c2415Smrg library calls in that they extend over several calls.
41760c2415Smrg
42760c2415Smrg The first call is always a call to st_read() or st_write(). These
43760c2415Smrg subroutines return no status unless a namelist read or write is
44760c2415Smrg being done, in which case there is the usual status. No further
45760c2415Smrg calls are necessary in this case.
46760c2415Smrg
47760c2415Smrg For other sorts of data transfer, there are zero or more data
48760c2415Smrg transfer statement that depend on the format of the data transfer
49760c2415Smrg statement. For READ (and for backwards compatibily: for WRITE), one has
50760c2415Smrg
51760c2415Smrg transfer_integer
52760c2415Smrg transfer_logical
53760c2415Smrg transfer_character
54760c2415Smrg transfer_character_wide
55760c2415Smrg transfer_real
56760c2415Smrg transfer_complex
57760c2415Smrg transfer_real128
58760c2415Smrg transfer_complex128
59760c2415Smrg
60760c2415Smrg and for WRITE
61760c2415Smrg
62760c2415Smrg transfer_integer_write
63760c2415Smrg transfer_logical_write
64760c2415Smrg transfer_character_write
65760c2415Smrg transfer_character_wide_write
66760c2415Smrg transfer_real_write
67760c2415Smrg transfer_complex_write
68760c2415Smrg transfer_real128_write
69760c2415Smrg transfer_complex128_write
70760c2415Smrg
71760c2415Smrg These subroutines do not return status. The *128 functions
72760c2415Smrg are in the file transfer128.c.
73760c2415Smrg
74760c2415Smrg The last call is a call to st_[read|write]_done(). While
75760c2415Smrg something can easily go wrong with the initial st_read() or
76760c2415Smrg st_write(), an error inhibits any data from actually being
77760c2415Smrg transferred. */
78760c2415Smrg
79760c2415Smrg extern void transfer_integer (st_parameter_dt *, void *, int);
80760c2415Smrg export_proto(transfer_integer);
81760c2415Smrg
82760c2415Smrg extern void transfer_integer_write (st_parameter_dt *, void *, int);
83760c2415Smrg export_proto(transfer_integer_write);
84760c2415Smrg
85760c2415Smrg extern void transfer_real (st_parameter_dt *, void *, int);
86760c2415Smrg export_proto(transfer_real);
87760c2415Smrg
88760c2415Smrg extern void transfer_real_write (st_parameter_dt *, void *, int);
89760c2415Smrg export_proto(transfer_real_write);
90760c2415Smrg
91760c2415Smrg extern void transfer_logical (st_parameter_dt *, void *, int);
92760c2415Smrg export_proto(transfer_logical);
93760c2415Smrg
94760c2415Smrg extern void transfer_logical_write (st_parameter_dt *, void *, int);
95760c2415Smrg export_proto(transfer_logical_write);
96760c2415Smrg
97760c2415Smrg extern void transfer_character (st_parameter_dt *, void *, gfc_charlen_type);
98760c2415Smrg export_proto(transfer_character);
99760c2415Smrg
100760c2415Smrg extern void transfer_character_write (st_parameter_dt *, void *, gfc_charlen_type);
101760c2415Smrg export_proto(transfer_character_write);
102760c2415Smrg
103760c2415Smrg extern void transfer_character_wide (st_parameter_dt *, void *, gfc_charlen_type, int);
104760c2415Smrg export_proto(transfer_character_wide);
105760c2415Smrg
106760c2415Smrg extern void transfer_character_wide_write (st_parameter_dt *,
107760c2415Smrg void *, gfc_charlen_type, int);
108760c2415Smrg export_proto(transfer_character_wide_write);
109760c2415Smrg
110760c2415Smrg extern void transfer_complex (st_parameter_dt *, void *, int);
111760c2415Smrg export_proto(transfer_complex);
112760c2415Smrg
113760c2415Smrg extern void transfer_complex_write (st_parameter_dt *, void *, int);
114760c2415Smrg export_proto(transfer_complex_write);
115760c2415Smrg
116760c2415Smrg extern void transfer_array (st_parameter_dt *, gfc_array_char *, int,
117760c2415Smrg gfc_charlen_type);
118760c2415Smrg export_proto(transfer_array);
119760c2415Smrg
120760c2415Smrg extern void transfer_array_write (st_parameter_dt *, gfc_array_char *, int,
121760c2415Smrg gfc_charlen_type);
122760c2415Smrg export_proto(transfer_array_write);
123760c2415Smrg
124760c2415Smrg /* User defined derived type input/output. */
125760c2415Smrg extern void
126760c2415Smrg transfer_derived (st_parameter_dt *dtp, void *dtio_source, void *dtio_proc);
127760c2415Smrg export_proto(transfer_derived);
128760c2415Smrg
129760c2415Smrg extern void
130760c2415Smrg transfer_derived_write (st_parameter_dt *dtp, void *dtio_source, void *dtio_proc);
131760c2415Smrg export_proto(transfer_derived_write);
132760c2415Smrg
133760c2415Smrg static void us_read (st_parameter_dt *, int);
134760c2415Smrg static void us_write (st_parameter_dt *, int);
135760c2415Smrg static void next_record_r_unf (st_parameter_dt *, int);
136760c2415Smrg static void next_record_w_unf (st_parameter_dt *, int);
137760c2415Smrg
138760c2415Smrg static const st_option advance_opt[] = {
139760c2415Smrg {"yes", ADVANCE_YES},
140760c2415Smrg {"no", ADVANCE_NO},
141760c2415Smrg {NULL, 0}
142760c2415Smrg };
143760c2415Smrg
144760c2415Smrg
145760c2415Smrg static const st_option decimal_opt[] = {
146760c2415Smrg {"point", DECIMAL_POINT},
147760c2415Smrg {"comma", DECIMAL_COMMA},
148760c2415Smrg {NULL, 0}
149760c2415Smrg };
150760c2415Smrg
151760c2415Smrg static const st_option round_opt[] = {
152760c2415Smrg {"up", ROUND_UP},
153760c2415Smrg {"down", ROUND_DOWN},
154760c2415Smrg {"zero", ROUND_ZERO},
155760c2415Smrg {"nearest", ROUND_NEAREST},
156760c2415Smrg {"compatible", ROUND_COMPATIBLE},
157760c2415Smrg {"processor_defined", ROUND_PROCDEFINED},
158760c2415Smrg {NULL, 0}
159760c2415Smrg };
160760c2415Smrg
161760c2415Smrg
162760c2415Smrg static const st_option sign_opt[] = {
163760c2415Smrg {"plus", SIGN_SP},
164760c2415Smrg {"suppress", SIGN_SS},
165760c2415Smrg {"processor_defined", SIGN_S},
166760c2415Smrg {NULL, 0}
167760c2415Smrg };
168760c2415Smrg
169760c2415Smrg static const st_option blank_opt[] = {
170760c2415Smrg {"null", BLANK_NULL},
171760c2415Smrg {"zero", BLANK_ZERO},
172760c2415Smrg {NULL, 0}
173760c2415Smrg };
174760c2415Smrg
175760c2415Smrg static const st_option delim_opt[] = {
176760c2415Smrg {"apostrophe", DELIM_APOSTROPHE},
177760c2415Smrg {"quote", DELIM_QUOTE},
178760c2415Smrg {"none", DELIM_NONE},
179760c2415Smrg {NULL, 0}
180760c2415Smrg };
181760c2415Smrg
182760c2415Smrg static const st_option pad_opt[] = {
183760c2415Smrg {"yes", PAD_YES},
184760c2415Smrg {"no", PAD_NO},
185760c2415Smrg {NULL, 0}
186760c2415Smrg };
187760c2415Smrg
188760c2415Smrg static const st_option async_opt[] = {
189760c2415Smrg {"yes", ASYNC_YES},
190760c2415Smrg {"no", ASYNC_NO},
191760c2415Smrg {NULL, 0}
192760c2415Smrg };
193760c2415Smrg
194760c2415Smrg typedef enum
195760c2415Smrg { FORMATTED_SEQUENTIAL, UNFORMATTED_SEQUENTIAL,
196*0bfacb9bSmrg FORMATTED_DIRECT, UNFORMATTED_DIRECT, FORMATTED_STREAM,
197*0bfacb9bSmrg UNFORMATTED_STREAM, FORMATTED_UNSPECIFIED
198760c2415Smrg }
199760c2415Smrg file_mode;
200760c2415Smrg
201760c2415Smrg
202760c2415Smrg static file_mode
current_mode(st_parameter_dt * dtp)203760c2415Smrg current_mode (st_parameter_dt *dtp)
204760c2415Smrg {
205760c2415Smrg file_mode m;
206760c2415Smrg
207*0bfacb9bSmrg m = FORMATTED_UNSPECIFIED;
208760c2415Smrg
209760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
210760c2415Smrg {
211760c2415Smrg m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
212760c2415Smrg FORMATTED_DIRECT : UNFORMATTED_DIRECT;
213760c2415Smrg }
214760c2415Smrg else if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
215760c2415Smrg {
216760c2415Smrg m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
217760c2415Smrg FORMATTED_SEQUENTIAL : UNFORMATTED_SEQUENTIAL;
218760c2415Smrg }
219760c2415Smrg else if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM)
220760c2415Smrg {
221760c2415Smrg m = dtp->u.p.current_unit->flags.form == FORM_FORMATTED ?
222760c2415Smrg FORMATTED_STREAM : UNFORMATTED_STREAM;
223760c2415Smrg }
224760c2415Smrg
225760c2415Smrg return m;
226760c2415Smrg }
227760c2415Smrg
228760c2415Smrg
229760c2415Smrg /* Mid level data transfer statements. */
230760c2415Smrg
231760c2415Smrg /* Read sequential file - internal unit */
232760c2415Smrg
233760c2415Smrg static char *
read_sf_internal(st_parameter_dt * dtp,size_t * length)234760c2415Smrg read_sf_internal (st_parameter_dt *dtp, size_t *length)
235760c2415Smrg {
236760c2415Smrg static char *empty_string[0];
237760c2415Smrg char *base = NULL;
238760c2415Smrg size_t lorig;
239760c2415Smrg
240760c2415Smrg /* Zero size array gives internal unit len of 0. Nothing to read. */
241760c2415Smrg if (dtp->internal_unit_len == 0
242760c2415Smrg && dtp->u.p.current_unit->pad_status == PAD_NO)
243760c2415Smrg hit_eof (dtp);
244760c2415Smrg
245760c2415Smrg /* There are some cases with mixed DTIO where we have read a character
246760c2415Smrg and saved it in the last character buffer, so we need to backup. */
247760c2415Smrg if (unlikely (dtp->u.p.current_unit->child_dtio > 0 &&
248760c2415Smrg dtp->u.p.current_unit->last_char != EOF - 1))
249760c2415Smrg {
250760c2415Smrg dtp->u.p.current_unit->last_char = EOF - 1;
251760c2415Smrg sseek (dtp->u.p.current_unit->s, -1, SEEK_CUR);
252760c2415Smrg }
253760c2415Smrg
254760c2415Smrg /* To support legacy code we have to scan the input string one byte
255760c2415Smrg at a time because we don't know where an early comma may be and the
256760c2415Smrg requested length could go past the end of a comma shortened
257760c2415Smrg string. We only do this if -std=legacy was given at compile
258760c2415Smrg time. We also do not support this on kind=4 strings. */
259760c2415Smrg if (unlikely(compile_options.warn_std == 0)) // the slow legacy way.
260760c2415Smrg {
261760c2415Smrg size_t n;
262760c2415Smrg size_t tmp = 1;
263760c2415Smrg char *q;
264760c2415Smrg
265760c2415Smrg /* If we have seen an eor previously, return a length of 0. The
266760c2415Smrg caller is responsible for correctly padding the input field. */
267760c2415Smrg if (dtp->u.p.sf_seen_eor)
268760c2415Smrg {
269760c2415Smrg *length = 0;
270760c2415Smrg /* Just return something that isn't a NULL pointer, otherwise the
271760c2415Smrg caller thinks an error occurred. */
272760c2415Smrg return (char*) empty_string;
273760c2415Smrg }
274760c2415Smrg
275760c2415Smrg /* Get the first character of the string to establish the base
276760c2415Smrg address and check for comma or end-of-record condition. */
277760c2415Smrg base = mem_alloc_r (dtp->u.p.current_unit->s, &tmp);
278760c2415Smrg if (tmp == 0)
279760c2415Smrg {
280760c2415Smrg dtp->u.p.sf_seen_eor = 1;
281760c2415Smrg *length = 0;
282760c2415Smrg return (char*) empty_string;
283760c2415Smrg }
284760c2415Smrg if (*base == ',')
285760c2415Smrg {
286760c2415Smrg dtp->u.p.current_unit->bytes_left--;
287760c2415Smrg *length = 0;
288760c2415Smrg return (char*) empty_string;
289760c2415Smrg }
290760c2415Smrg
291760c2415Smrg /* Now we scan the rest and deal with either an end-of-file
292760c2415Smrg condition or a comma, as needed. */
293760c2415Smrg for (n = 1; n < *length; n++)
294760c2415Smrg {
295760c2415Smrg q = mem_alloc_r (dtp->u.p.current_unit->s, &tmp);
296760c2415Smrg if (tmp == 0)
297760c2415Smrg {
298760c2415Smrg hit_eof (dtp);
299760c2415Smrg return NULL;
300760c2415Smrg }
301760c2415Smrg if (*q == ',')
302760c2415Smrg {
303760c2415Smrg dtp->u.p.current_unit->bytes_left -= n;
304760c2415Smrg *length = n;
305760c2415Smrg break;
306760c2415Smrg }
307760c2415Smrg }
308760c2415Smrg }
309760c2415Smrg else // the fast way
310760c2415Smrg {
311760c2415Smrg lorig = *length;
312760c2415Smrg if (is_char4_unit(dtp))
313760c2415Smrg {
314760c2415Smrg gfc_char4_t *p = (gfc_char4_t *) mem_alloc_r4 (dtp->u.p.current_unit->s,
315760c2415Smrg length);
316760c2415Smrg base = fbuf_alloc (dtp->u.p.current_unit, lorig);
317760c2415Smrg for (size_t i = 0; i < *length; i++, p++)
318760c2415Smrg base[i] = *p > 255 ? '?' : (unsigned char) *p;
319760c2415Smrg }
320760c2415Smrg else
321760c2415Smrg base = mem_alloc_r (dtp->u.p.current_unit->s, length);
322760c2415Smrg
323760c2415Smrg if (unlikely (lorig > *length))
324760c2415Smrg {
325760c2415Smrg hit_eof (dtp);
326760c2415Smrg return NULL;
327760c2415Smrg }
328760c2415Smrg }
329760c2415Smrg
330760c2415Smrg dtp->u.p.current_unit->bytes_left -= *length;
331760c2415Smrg
332760c2415Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
333760c2415Smrg dtp->u.p.current_unit->has_size)
334760c2415Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) *length;
335760c2415Smrg
336760c2415Smrg return base;
337760c2415Smrg
338760c2415Smrg }
339760c2415Smrg
340760c2415Smrg /* When reading sequential formatted records we have a problem. We
341760c2415Smrg don't know how long the line is until we read the trailing newline,
342760c2415Smrg and we don't want to read too much. If we read too much, we might
343760c2415Smrg have to do a physical seek backwards depending on how much data is
344760c2415Smrg present, and devices like terminals aren't seekable and would cause
345760c2415Smrg an I/O error.
346760c2415Smrg
347760c2415Smrg Given this, the solution is to read a byte at a time, stopping if
348760c2415Smrg we hit the newline. For small allocations, we use a static buffer.
349760c2415Smrg For larger allocations, we are forced to allocate memory on the
350760c2415Smrg heap. Hopefully this won't happen very often. */
351760c2415Smrg
352760c2415Smrg /* Read sequential file - external unit */
353760c2415Smrg
354760c2415Smrg static char *
read_sf(st_parameter_dt * dtp,size_t * length)355760c2415Smrg read_sf (st_parameter_dt *dtp, size_t *length)
356760c2415Smrg {
357760c2415Smrg static char *empty_string[0];
358760c2415Smrg size_t lorig, n;
359760c2415Smrg int q, q2;
360760c2415Smrg int seen_comma;
361760c2415Smrg
362760c2415Smrg /* If we have seen an eor previously, return a length of 0. The
363760c2415Smrg caller is responsible for correctly padding the input field. */
364760c2415Smrg if (dtp->u.p.sf_seen_eor)
365760c2415Smrg {
366760c2415Smrg *length = 0;
367760c2415Smrg /* Just return something that isn't a NULL pointer, otherwise the
368760c2415Smrg caller thinks an error occurred. */
369760c2415Smrg return (char*) empty_string;
370760c2415Smrg }
371760c2415Smrg
372760c2415Smrg /* There are some cases with mixed DTIO where we have read a character
373760c2415Smrg and saved it in the last character buffer, so we need to backup. */
374760c2415Smrg if (unlikely (dtp->u.p.current_unit->child_dtio > 0 &&
375760c2415Smrg dtp->u.p.current_unit->last_char != EOF - 1))
376760c2415Smrg {
377760c2415Smrg dtp->u.p.current_unit->last_char = EOF - 1;
378760c2415Smrg fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
379760c2415Smrg }
380760c2415Smrg
381760c2415Smrg n = seen_comma = 0;
382760c2415Smrg
383760c2415Smrg /* Read data into format buffer and scan through it. */
384760c2415Smrg lorig = *length;
385760c2415Smrg
386760c2415Smrg while (n < *length)
387760c2415Smrg {
388760c2415Smrg q = fbuf_getc (dtp->u.p.current_unit);
389760c2415Smrg if (q == EOF)
390760c2415Smrg break;
391760c2415Smrg else if (dtp->u.p.current_unit->flags.cc != CC_NONE
392760c2415Smrg && (q == '\n' || q == '\r'))
393760c2415Smrg {
394760c2415Smrg /* Unexpected end of line. Set the position. */
395760c2415Smrg dtp->u.p.sf_seen_eor = 1;
396760c2415Smrg
397760c2415Smrg /* If we see an EOR during non-advancing I/O, we need to skip
398760c2415Smrg the rest of the I/O statement. Set the corresponding flag. */
399760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
400760c2415Smrg dtp->u.p.eor_condition = 1;
401760c2415Smrg
402760c2415Smrg /* If we encounter a CR, it might be a CRLF. */
403760c2415Smrg if (q == '\r') /* Probably a CRLF */
404760c2415Smrg {
405760c2415Smrg /* See if there is an LF. */
406760c2415Smrg q2 = fbuf_getc (dtp->u.p.current_unit);
407760c2415Smrg if (q2 == '\n')
408760c2415Smrg dtp->u.p.sf_seen_eor = 2;
409760c2415Smrg else if (q2 != EOF) /* Oops, seek back. */
410760c2415Smrg fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
411760c2415Smrg }
412760c2415Smrg
413760c2415Smrg /* Without padding, terminate the I/O statement without assigning
414760c2415Smrg the value. With padding, the value still needs to be assigned,
415760c2415Smrg so we can just continue with a short read. */
416760c2415Smrg if (dtp->u.p.current_unit->pad_status == PAD_NO)
417760c2415Smrg {
418760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
419760c2415Smrg return NULL;
420760c2415Smrg }
421760c2415Smrg
422760c2415Smrg *length = n;
423760c2415Smrg goto done;
424760c2415Smrg }
425760c2415Smrg /* Short circuit the read if a comma is found during numeric input.
426760c2415Smrg The flag is set to zero during character reads so that commas in
427760c2415Smrg strings are not ignored */
428760c2415Smrg else if (q == ',')
429760c2415Smrg if (dtp->u.p.sf_read_comma == 1)
430760c2415Smrg {
431760c2415Smrg seen_comma = 1;
432760c2415Smrg notify_std (&dtp->common, GFC_STD_GNU,
433760c2415Smrg "Comma in formatted numeric read.");
434760c2415Smrg break;
435760c2415Smrg }
436760c2415Smrg n++;
437760c2415Smrg }
438760c2415Smrg
439760c2415Smrg *length = n;
440760c2415Smrg
441760c2415Smrg /* A short read implies we hit EOF, unless we hit EOR, a comma, or
442760c2415Smrg some other stuff. Set the relevant flags. */
443760c2415Smrg if (lorig > *length && !dtp->u.p.sf_seen_eor && !seen_comma)
444760c2415Smrg {
445760c2415Smrg if (n > 0)
446760c2415Smrg {
447760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_NO)
448760c2415Smrg {
449760c2415Smrg if (dtp->u.p.current_unit->pad_status == PAD_NO)
450760c2415Smrg {
451760c2415Smrg hit_eof (dtp);
452760c2415Smrg return NULL;
453760c2415Smrg }
454760c2415Smrg else
455760c2415Smrg dtp->u.p.eor_condition = 1;
456760c2415Smrg }
457760c2415Smrg else
458760c2415Smrg dtp->u.p.at_eof = 1;
459760c2415Smrg }
460760c2415Smrg else if (dtp->u.p.advance_status == ADVANCE_NO
461760c2415Smrg || dtp->u.p.current_unit->pad_status == PAD_NO
462760c2415Smrg || dtp->u.p.current_unit->bytes_left
463760c2415Smrg == dtp->u.p.current_unit->recl)
464760c2415Smrg {
465760c2415Smrg hit_eof (dtp);
466760c2415Smrg return NULL;
467760c2415Smrg }
468760c2415Smrg }
469760c2415Smrg
470760c2415Smrg done:
471760c2415Smrg
472760c2415Smrg dtp->u.p.current_unit->bytes_left -= n;
473760c2415Smrg
474760c2415Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
475760c2415Smrg dtp->u.p.current_unit->has_size)
476760c2415Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) n;
477760c2415Smrg
478760c2415Smrg /* We can't call fbuf_getptr before the loop doing fbuf_getc, because
479760c2415Smrg fbuf_getc might reallocate the buffer. So return current pointer
480760c2415Smrg minus all the advances, which is n plus up to two characters
481760c2415Smrg of newline or comma. */
482760c2415Smrg return fbuf_getptr (dtp->u.p.current_unit)
483760c2415Smrg - n - dtp->u.p.sf_seen_eor - seen_comma;
484760c2415Smrg }
485760c2415Smrg
486760c2415Smrg
487760c2415Smrg /* Function for reading the next couple of bytes from the current
488760c2415Smrg file, advancing the current position. We return NULL on end of record or
489760c2415Smrg end of file. This function is only for formatted I/O, unformatted uses
490760c2415Smrg read_block_direct.
491760c2415Smrg
492760c2415Smrg If the read is short, then it is because the current record does not
493760c2415Smrg have enough data to satisfy the read request and the file was
494760c2415Smrg opened with PAD=YES. The caller must assume tailing spaces for
495760c2415Smrg short reads. */
496760c2415Smrg
497760c2415Smrg void *
read_block_form(st_parameter_dt * dtp,size_t * nbytes)498760c2415Smrg read_block_form (st_parameter_dt *dtp, size_t *nbytes)
499760c2415Smrg {
500760c2415Smrg char *source;
501760c2415Smrg size_t norig;
502760c2415Smrg
503760c2415Smrg if (!is_stream_io (dtp))
504760c2415Smrg {
505760c2415Smrg if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
506760c2415Smrg {
507760c2415Smrg /* For preconnected units with default record length, set bytes left
508760c2415Smrg to unit record length and proceed, otherwise error. */
509760c2415Smrg if (dtp->u.p.current_unit->unit_number == options.stdin_unit
510760c2415Smrg && dtp->u.p.current_unit->recl == default_recl)
511760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
512760c2415Smrg else
513760c2415Smrg {
514760c2415Smrg if (unlikely (dtp->u.p.current_unit->pad_status == PAD_NO)
515760c2415Smrg && !is_internal_unit (dtp))
516760c2415Smrg {
517760c2415Smrg /* Not enough data left. */
518760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
519760c2415Smrg return NULL;
520760c2415Smrg }
521760c2415Smrg }
522760c2415Smrg
523760c2415Smrg if (is_internal_unit(dtp))
524760c2415Smrg {
525760c2415Smrg if (*nbytes > 0 && dtp->u.p.current_unit->bytes_left == 0)
526760c2415Smrg {
527760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_NO)
528760c2415Smrg {
529760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
530760c2415Smrg return NULL;
531760c2415Smrg }
532760c2415Smrg }
533760c2415Smrg }
534760c2415Smrg else
535760c2415Smrg {
536760c2415Smrg if (unlikely (dtp->u.p.current_unit->bytes_left == 0))
537760c2415Smrg {
538760c2415Smrg hit_eof (dtp);
539760c2415Smrg return NULL;
540760c2415Smrg }
541760c2415Smrg }
542760c2415Smrg
543760c2415Smrg *nbytes = dtp->u.p.current_unit->bytes_left;
544760c2415Smrg }
545760c2415Smrg }
546760c2415Smrg
547760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED &&
548760c2415Smrg (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
549760c2415Smrg dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
550760c2415Smrg {
551760c2415Smrg if (is_internal_unit (dtp))
552760c2415Smrg source = read_sf_internal (dtp, nbytes);
553760c2415Smrg else
554760c2415Smrg source = read_sf (dtp, nbytes);
555760c2415Smrg
556760c2415Smrg dtp->u.p.current_unit->strm_pos +=
557760c2415Smrg (gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
558760c2415Smrg return source;
559760c2415Smrg }
560760c2415Smrg
561760c2415Smrg /* If we reach here, we can assume it's direct access. */
562760c2415Smrg
563760c2415Smrg dtp->u.p.current_unit->bytes_left -= (gfc_offset) *nbytes;
564760c2415Smrg
565760c2415Smrg norig = *nbytes;
566760c2415Smrg source = fbuf_read (dtp->u.p.current_unit, nbytes);
567760c2415Smrg fbuf_seek (dtp->u.p.current_unit, *nbytes, SEEK_CUR);
568760c2415Smrg
569760c2415Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
570760c2415Smrg dtp->u.p.current_unit->has_size)
571760c2415Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) *nbytes;
572760c2415Smrg
573760c2415Smrg if (norig != *nbytes)
574760c2415Smrg {
575760c2415Smrg /* Short read, this shouldn't happen. */
576760c2415Smrg if (dtp->u.p.current_unit->pad_status == PAD_NO)
577760c2415Smrg {
578760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
579760c2415Smrg source = NULL;
580760c2415Smrg }
581760c2415Smrg }
582760c2415Smrg
583760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) *nbytes;
584760c2415Smrg
585760c2415Smrg return source;
586760c2415Smrg }
587760c2415Smrg
588760c2415Smrg
589760c2415Smrg /* Read a block from a character(kind=4) internal unit, to be transferred into
590760c2415Smrg a character(kind=4) variable. Note: Portions of this code borrowed from
591760c2415Smrg read_sf_internal. */
592760c2415Smrg void *
read_block_form4(st_parameter_dt * dtp,size_t * nbytes)593760c2415Smrg read_block_form4 (st_parameter_dt *dtp, size_t *nbytes)
594760c2415Smrg {
595760c2415Smrg static gfc_char4_t *empty_string[0];
596760c2415Smrg gfc_char4_t *source;
597760c2415Smrg size_t lorig;
598760c2415Smrg
599760c2415Smrg if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
600760c2415Smrg *nbytes = dtp->u.p.current_unit->bytes_left;
601760c2415Smrg
602760c2415Smrg /* Zero size array gives internal unit len of 0. Nothing to read. */
603760c2415Smrg if (dtp->internal_unit_len == 0
604760c2415Smrg && dtp->u.p.current_unit->pad_status == PAD_NO)
605760c2415Smrg hit_eof (dtp);
606760c2415Smrg
607760c2415Smrg /* If we have seen an eor previously, return a length of 0. The
608760c2415Smrg caller is responsible for correctly padding the input field. */
609760c2415Smrg if (dtp->u.p.sf_seen_eor)
610760c2415Smrg {
611760c2415Smrg *nbytes = 0;
612760c2415Smrg /* Just return something that isn't a NULL pointer, otherwise the
613760c2415Smrg caller thinks an error occurred. */
614760c2415Smrg return empty_string;
615760c2415Smrg }
616760c2415Smrg
617760c2415Smrg lorig = *nbytes;
618760c2415Smrg source = (gfc_char4_t *) mem_alloc_r4 (dtp->u.p.current_unit->s, nbytes);
619760c2415Smrg
620760c2415Smrg if (unlikely (lorig > *nbytes))
621760c2415Smrg {
622760c2415Smrg hit_eof (dtp);
623760c2415Smrg return NULL;
624760c2415Smrg }
625760c2415Smrg
626760c2415Smrg dtp->u.p.current_unit->bytes_left -= *nbytes;
627760c2415Smrg
628760c2415Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
629760c2415Smrg dtp->u.p.current_unit->has_size)
630760c2415Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) *nbytes;
631760c2415Smrg
632760c2415Smrg return source;
633760c2415Smrg }
634760c2415Smrg
635760c2415Smrg
636760c2415Smrg /* Reads a block directly into application data space. This is for
637760c2415Smrg unformatted files. */
638760c2415Smrg
639760c2415Smrg static void
read_block_direct(st_parameter_dt * dtp,void * buf,size_t nbytes)640760c2415Smrg read_block_direct (st_parameter_dt *dtp, void *buf, size_t nbytes)
641760c2415Smrg {
642760c2415Smrg ssize_t to_read_record;
643760c2415Smrg ssize_t have_read_record;
644760c2415Smrg ssize_t to_read_subrecord;
645760c2415Smrg ssize_t have_read_subrecord;
646760c2415Smrg int short_record;
647760c2415Smrg
648760c2415Smrg if (is_stream_io (dtp))
649760c2415Smrg {
650760c2415Smrg have_read_record = sread (dtp->u.p.current_unit->s, buf,
651760c2415Smrg nbytes);
652760c2415Smrg if (unlikely (have_read_record < 0))
653760c2415Smrg {
654760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
655760c2415Smrg return;
656760c2415Smrg }
657760c2415Smrg
658760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) have_read_record;
659760c2415Smrg
660760c2415Smrg if (unlikely ((ssize_t) nbytes != have_read_record))
661760c2415Smrg {
662760c2415Smrg /* Short read, e.g. if we hit EOF. For stream files,
663760c2415Smrg we have to set the end-of-file condition. */
664760c2415Smrg hit_eof (dtp);
665760c2415Smrg }
666760c2415Smrg return;
667760c2415Smrg }
668760c2415Smrg
669760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
670760c2415Smrg {
671760c2415Smrg if (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes)
672760c2415Smrg {
673760c2415Smrg short_record = 1;
674760c2415Smrg to_read_record = dtp->u.p.current_unit->bytes_left;
675760c2415Smrg nbytes = to_read_record;
676760c2415Smrg }
677760c2415Smrg else
678760c2415Smrg {
679760c2415Smrg short_record = 0;
680760c2415Smrg to_read_record = nbytes;
681760c2415Smrg }
682760c2415Smrg
683760c2415Smrg dtp->u.p.current_unit->bytes_left -= to_read_record;
684760c2415Smrg
685760c2415Smrg to_read_record = sread (dtp->u.p.current_unit->s, buf, to_read_record);
686760c2415Smrg if (unlikely (to_read_record < 0))
687760c2415Smrg {
688760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
689760c2415Smrg return;
690760c2415Smrg }
691760c2415Smrg
692760c2415Smrg if (to_read_record != (ssize_t) nbytes)
693760c2415Smrg {
694760c2415Smrg /* Short read, e.g. if we hit EOF. Apparently, we read
695760c2415Smrg more than was written to the last record. */
696760c2415Smrg return;
697760c2415Smrg }
698760c2415Smrg
699760c2415Smrg if (unlikely (short_record))
700760c2415Smrg {
701760c2415Smrg generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
702760c2415Smrg }
703760c2415Smrg return;
704760c2415Smrg }
705760c2415Smrg
706760c2415Smrg /* Unformatted sequential. We loop over the subrecords, reading
707760c2415Smrg until the request has been fulfilled or the record has run out
708760c2415Smrg of continuation subrecords. */
709760c2415Smrg
710760c2415Smrg /* Check whether we exceed the total record length. */
711760c2415Smrg
712760c2415Smrg if (dtp->u.p.current_unit->flags.has_recl
713760c2415Smrg && ((gfc_offset) nbytes > dtp->u.p.current_unit->bytes_left))
714760c2415Smrg {
715760c2415Smrg to_read_record = dtp->u.p.current_unit->bytes_left;
716760c2415Smrg short_record = 1;
717760c2415Smrg }
718760c2415Smrg else
719760c2415Smrg {
720760c2415Smrg to_read_record = nbytes;
721760c2415Smrg short_record = 0;
722760c2415Smrg }
723760c2415Smrg have_read_record = 0;
724760c2415Smrg
725760c2415Smrg while(1)
726760c2415Smrg {
727760c2415Smrg if (dtp->u.p.current_unit->bytes_left_subrecord
728760c2415Smrg < (gfc_offset) to_read_record)
729760c2415Smrg {
730760c2415Smrg to_read_subrecord = dtp->u.p.current_unit->bytes_left_subrecord;
731760c2415Smrg to_read_record -= to_read_subrecord;
732760c2415Smrg }
733760c2415Smrg else
734760c2415Smrg {
735760c2415Smrg to_read_subrecord = to_read_record;
736760c2415Smrg to_read_record = 0;
737760c2415Smrg }
738760c2415Smrg
739760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord -= to_read_subrecord;
740760c2415Smrg
741760c2415Smrg have_read_subrecord = sread (dtp->u.p.current_unit->s,
742760c2415Smrg buf + have_read_record, to_read_subrecord);
743760c2415Smrg if (unlikely (have_read_subrecord < 0))
744760c2415Smrg {
745760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
746760c2415Smrg return;
747760c2415Smrg }
748760c2415Smrg
749760c2415Smrg have_read_record += have_read_subrecord;
750760c2415Smrg
751760c2415Smrg if (unlikely (to_read_subrecord != have_read_subrecord))
752760c2415Smrg {
753760c2415Smrg /* Short read, e.g. if we hit EOF. This means the record
754760c2415Smrg structure has been corrupted, or the trailing record
755760c2415Smrg marker would still be present. */
756760c2415Smrg
757760c2415Smrg generate_error (&dtp->common, LIBERROR_CORRUPT_FILE, NULL);
758760c2415Smrg return;
759760c2415Smrg }
760760c2415Smrg
761760c2415Smrg if (to_read_record > 0)
762760c2415Smrg {
763760c2415Smrg if (likely (dtp->u.p.current_unit->continued))
764760c2415Smrg {
765760c2415Smrg next_record_r_unf (dtp, 0);
766760c2415Smrg us_read (dtp, 1);
767760c2415Smrg }
768760c2415Smrg else
769760c2415Smrg {
770760c2415Smrg /* Let's make sure the file position is correctly pre-positioned
771760c2415Smrg for the next read statement. */
772760c2415Smrg
773760c2415Smrg dtp->u.p.current_unit->current_record = 0;
774760c2415Smrg next_record_r_unf (dtp, 0);
775760c2415Smrg generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
776760c2415Smrg return;
777760c2415Smrg }
778760c2415Smrg }
779760c2415Smrg else
780760c2415Smrg {
781760c2415Smrg /* Normal exit, the read request has been fulfilled. */
782760c2415Smrg break;
783760c2415Smrg }
784760c2415Smrg }
785760c2415Smrg
786760c2415Smrg dtp->u.p.current_unit->bytes_left -= have_read_record;
787760c2415Smrg if (unlikely (short_record))
788760c2415Smrg {
789760c2415Smrg generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
790760c2415Smrg return;
791760c2415Smrg }
792760c2415Smrg return;
793760c2415Smrg }
794760c2415Smrg
795760c2415Smrg
796760c2415Smrg /* Function for writing a block of bytes to the current file at the
797760c2415Smrg current position, advancing the file pointer. We are given a length
798760c2415Smrg and return a pointer to a buffer that the caller must (completely)
799760c2415Smrg fill in. Returns NULL on error. */
800760c2415Smrg
801760c2415Smrg void *
write_block(st_parameter_dt * dtp,size_t length)802760c2415Smrg write_block (st_parameter_dt *dtp, size_t length)
803760c2415Smrg {
804760c2415Smrg char *dest;
805760c2415Smrg
806760c2415Smrg if (!is_stream_io (dtp))
807760c2415Smrg {
808760c2415Smrg if (dtp->u.p.current_unit->bytes_left < (gfc_offset) length)
809760c2415Smrg {
810760c2415Smrg /* For preconnected units with default record length, set bytes left
811760c2415Smrg to unit record length and proceed, otherwise error. */
812760c2415Smrg if (likely ((dtp->u.p.current_unit->unit_number
813760c2415Smrg == options.stdout_unit
814760c2415Smrg || dtp->u.p.current_unit->unit_number
815760c2415Smrg == options.stderr_unit)
816760c2415Smrg && dtp->u.p.current_unit->recl == default_recl))
817760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
818760c2415Smrg else
819760c2415Smrg {
820760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
821760c2415Smrg return NULL;
822760c2415Smrg }
823760c2415Smrg }
824760c2415Smrg
825760c2415Smrg dtp->u.p.current_unit->bytes_left -= (gfc_offset) length;
826760c2415Smrg }
827760c2415Smrg
828760c2415Smrg if (is_internal_unit (dtp))
829760c2415Smrg {
830760c2415Smrg if (is_char4_unit(dtp)) /* char4 internel unit. */
831760c2415Smrg {
832760c2415Smrg gfc_char4_t *dest4;
833760c2415Smrg dest4 = mem_alloc_w4 (dtp->u.p.current_unit->s, &length);
834760c2415Smrg if (dest4 == NULL)
835760c2415Smrg {
836760c2415Smrg generate_error (&dtp->common, LIBERROR_END, NULL);
837760c2415Smrg return NULL;
838760c2415Smrg }
839760c2415Smrg return dest4;
840760c2415Smrg }
841760c2415Smrg else
842760c2415Smrg dest = mem_alloc_w (dtp->u.p.current_unit->s, &length);
843760c2415Smrg
844760c2415Smrg if (dest == NULL)
845760c2415Smrg {
846760c2415Smrg generate_error (&dtp->common, LIBERROR_END, NULL);
847760c2415Smrg return NULL;
848760c2415Smrg }
849760c2415Smrg
850760c2415Smrg if (unlikely (dtp->u.p.current_unit->endfile == AT_ENDFILE))
851760c2415Smrg generate_error (&dtp->common, LIBERROR_END, NULL);
852760c2415Smrg }
853760c2415Smrg else
854760c2415Smrg {
855760c2415Smrg dest = fbuf_alloc (dtp->u.p.current_unit, length);
856760c2415Smrg if (dest == NULL)
857760c2415Smrg {
858760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
859760c2415Smrg return NULL;
860760c2415Smrg }
861760c2415Smrg }
862760c2415Smrg
863760c2415Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
864760c2415Smrg dtp->u.p.current_unit->has_size)
865760c2415Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) length;
866760c2415Smrg
867760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) length;
868760c2415Smrg
869760c2415Smrg return dest;
870760c2415Smrg }
871760c2415Smrg
872760c2415Smrg
873760c2415Smrg /* High level interface to swrite(), taking care of errors. This is only
874760c2415Smrg called for unformatted files. There are three cases to consider:
875760c2415Smrg Stream I/O, unformatted direct, unformatted sequential. */
876760c2415Smrg
877760c2415Smrg static bool
write_buf(st_parameter_dt * dtp,void * buf,size_t nbytes)878760c2415Smrg write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
879760c2415Smrg {
880760c2415Smrg
881760c2415Smrg ssize_t have_written;
882760c2415Smrg ssize_t to_write_subrecord;
883760c2415Smrg int short_record;
884760c2415Smrg
885760c2415Smrg /* Stream I/O. */
886760c2415Smrg
887760c2415Smrg if (is_stream_io (dtp))
888760c2415Smrg {
889760c2415Smrg have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
890760c2415Smrg if (unlikely (have_written < 0))
891760c2415Smrg {
892760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
893760c2415Smrg return false;
894760c2415Smrg }
895760c2415Smrg
896760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
897760c2415Smrg
898760c2415Smrg return true;
899760c2415Smrg }
900760c2415Smrg
901760c2415Smrg /* Unformatted direct access. */
902760c2415Smrg
903760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
904760c2415Smrg {
905760c2415Smrg if (unlikely (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes))
906760c2415Smrg {
907760c2415Smrg generate_error (&dtp->common, LIBERROR_DIRECT_EOR, NULL);
908760c2415Smrg return false;
909760c2415Smrg }
910760c2415Smrg
911760c2415Smrg if (buf == NULL && nbytes == 0)
912760c2415Smrg return true;
913760c2415Smrg
914760c2415Smrg have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
915760c2415Smrg if (unlikely (have_written < 0))
916760c2415Smrg {
917760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
918760c2415Smrg return false;
919760c2415Smrg }
920760c2415Smrg
921760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
922760c2415Smrg dtp->u.p.current_unit->bytes_left -= (gfc_offset) have_written;
923760c2415Smrg
924760c2415Smrg return true;
925760c2415Smrg }
926760c2415Smrg
927760c2415Smrg /* Unformatted sequential. */
928760c2415Smrg
929760c2415Smrg have_written = 0;
930760c2415Smrg
931760c2415Smrg if (dtp->u.p.current_unit->flags.has_recl
932760c2415Smrg && (gfc_offset) nbytes > dtp->u.p.current_unit->bytes_left)
933760c2415Smrg {
934760c2415Smrg nbytes = dtp->u.p.current_unit->bytes_left;
935760c2415Smrg short_record = 1;
936760c2415Smrg }
937760c2415Smrg else
938760c2415Smrg {
939760c2415Smrg short_record = 0;
940760c2415Smrg }
941760c2415Smrg
942760c2415Smrg while (1)
943760c2415Smrg {
944760c2415Smrg
945760c2415Smrg to_write_subrecord =
946760c2415Smrg (size_t) dtp->u.p.current_unit->bytes_left_subrecord < nbytes ?
947760c2415Smrg (size_t) dtp->u.p.current_unit->bytes_left_subrecord : nbytes;
948760c2415Smrg
949760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord -=
950760c2415Smrg (gfc_offset) to_write_subrecord;
951760c2415Smrg
952760c2415Smrg to_write_subrecord = swrite (dtp->u.p.current_unit->s,
953760c2415Smrg buf + have_written, to_write_subrecord);
954760c2415Smrg if (unlikely (to_write_subrecord < 0))
955760c2415Smrg {
956760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
957760c2415Smrg return false;
958760c2415Smrg }
959760c2415Smrg
960760c2415Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) to_write_subrecord;
961760c2415Smrg nbytes -= to_write_subrecord;
962760c2415Smrg have_written += to_write_subrecord;
963760c2415Smrg
964760c2415Smrg if (nbytes == 0)
965760c2415Smrg break;
966760c2415Smrg
967760c2415Smrg next_record_w_unf (dtp, 1);
968760c2415Smrg us_write (dtp, 1);
969760c2415Smrg }
970760c2415Smrg dtp->u.p.current_unit->bytes_left -= have_written;
971760c2415Smrg if (unlikely (short_record))
972760c2415Smrg {
973760c2415Smrg generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
974760c2415Smrg return false;
975760c2415Smrg }
976760c2415Smrg return true;
977760c2415Smrg }
978760c2415Smrg
979760c2415Smrg
980760c2415Smrg /* Reverse memcpy - used for byte swapping. */
981760c2415Smrg
982760c2415Smrg static void
reverse_memcpy(void * dest,const void * src,size_t n)983760c2415Smrg reverse_memcpy (void *dest, const void *src, size_t n)
984760c2415Smrg {
985760c2415Smrg char *d, *s;
986760c2415Smrg size_t i;
987760c2415Smrg
988760c2415Smrg d = (char *) dest;
989760c2415Smrg s = (char *) src + n - 1;
990760c2415Smrg
991760c2415Smrg /* Write with ascending order - this is likely faster
992760c2415Smrg on modern architectures because of write combining. */
993760c2415Smrg for (i=0; i<n; i++)
994760c2415Smrg *(d++) = *(s--);
995760c2415Smrg }
996760c2415Smrg
997760c2415Smrg
998760c2415Smrg /* Utility function for byteswapping an array, using the bswap
999760c2415Smrg builtins if possible. dest and src can overlap completely, or then
1000760c2415Smrg they must point to separate objects; partial overlaps are not
1001760c2415Smrg allowed. */
1002760c2415Smrg
1003760c2415Smrg static void
bswap_array(void * dest,const void * src,size_t size,size_t nelems)1004760c2415Smrg bswap_array (void *dest, const void *src, size_t size, size_t nelems)
1005760c2415Smrg {
1006760c2415Smrg const char *ps;
1007760c2415Smrg char *pd;
1008760c2415Smrg
1009760c2415Smrg switch (size)
1010760c2415Smrg {
1011760c2415Smrg case 1:
1012760c2415Smrg break;
1013760c2415Smrg case 2:
1014760c2415Smrg for (size_t i = 0; i < nelems; i++)
1015760c2415Smrg ((uint16_t*)dest)[i] = __builtin_bswap16 (((uint16_t*)src)[i]);
1016760c2415Smrg break;
1017760c2415Smrg case 4:
1018760c2415Smrg for (size_t i = 0; i < nelems; i++)
1019760c2415Smrg ((uint32_t*)dest)[i] = __builtin_bswap32 (((uint32_t*)src)[i]);
1020760c2415Smrg break;
1021760c2415Smrg case 8:
1022760c2415Smrg for (size_t i = 0; i < nelems; i++)
1023760c2415Smrg ((uint64_t*)dest)[i] = __builtin_bswap64 (((uint64_t*)src)[i]);
1024760c2415Smrg break;
1025760c2415Smrg case 12:
1026760c2415Smrg ps = src;
1027760c2415Smrg pd = dest;
1028760c2415Smrg for (size_t i = 0; i < nelems; i++)
1029760c2415Smrg {
1030760c2415Smrg uint32_t tmp;
1031760c2415Smrg memcpy (&tmp, ps, 4);
1032760c2415Smrg *(uint32_t*)pd = __builtin_bswap32 (*(uint32_t*)(ps + 8));
1033760c2415Smrg *(uint32_t*)(pd + 4) = __builtin_bswap32 (*(uint32_t*)(ps + 4));
1034760c2415Smrg *(uint32_t*)(pd + 8) = __builtin_bswap32 (tmp);
1035760c2415Smrg ps += size;
1036760c2415Smrg pd += size;
1037760c2415Smrg }
1038760c2415Smrg break;
1039760c2415Smrg case 16:
1040760c2415Smrg ps = src;
1041760c2415Smrg pd = dest;
1042760c2415Smrg for (size_t i = 0; i < nelems; i++)
1043760c2415Smrg {
1044760c2415Smrg uint64_t tmp;
1045760c2415Smrg memcpy (&tmp, ps, 8);
1046760c2415Smrg *(uint64_t*)pd = __builtin_bswap64 (*(uint64_t*)(ps + 8));
1047760c2415Smrg *(uint64_t*)(pd + 8) = __builtin_bswap64 (tmp);
1048760c2415Smrg ps += size;
1049760c2415Smrg pd += size;
1050760c2415Smrg }
1051760c2415Smrg break;
1052760c2415Smrg default:
1053760c2415Smrg pd = dest;
1054760c2415Smrg if (dest != src)
1055760c2415Smrg {
1056760c2415Smrg ps = src;
1057760c2415Smrg for (size_t i = 0; i < nelems; i++)
1058760c2415Smrg {
1059760c2415Smrg reverse_memcpy (pd, ps, size);
1060760c2415Smrg ps += size;
1061760c2415Smrg pd += size;
1062760c2415Smrg }
1063760c2415Smrg }
1064760c2415Smrg else
1065760c2415Smrg {
1066760c2415Smrg /* In-place byte swap. */
1067760c2415Smrg for (size_t i = 0; i < nelems; i++)
1068760c2415Smrg {
1069760c2415Smrg char tmp, *low = pd, *high = pd + size - 1;
1070760c2415Smrg for (size_t j = 0; j < size/2; j++)
1071760c2415Smrg {
1072760c2415Smrg tmp = *low;
1073760c2415Smrg *low = *high;
1074760c2415Smrg *high = tmp;
1075760c2415Smrg low++;
1076760c2415Smrg high--;
1077760c2415Smrg }
1078760c2415Smrg pd += size;
1079760c2415Smrg }
1080760c2415Smrg }
1081760c2415Smrg }
1082760c2415Smrg }
1083760c2415Smrg
1084760c2415Smrg
1085760c2415Smrg /* Master function for unformatted reads. */
1086760c2415Smrg
1087760c2415Smrg static void
unformatted_read(st_parameter_dt * dtp,bt type,void * dest,int kind,size_t size,size_t nelems)1088760c2415Smrg unformatted_read (st_parameter_dt *dtp, bt type,
1089760c2415Smrg void *dest, int kind, size_t size, size_t nelems)
1090760c2415Smrg {
1091760c2415Smrg if (type == BT_CLASS)
1092760c2415Smrg {
1093760c2415Smrg int unit = dtp->u.p.current_unit->unit_number;
1094760c2415Smrg char tmp_iomsg[IOMSG_LEN] = "";
1095760c2415Smrg char *child_iomsg;
1096760c2415Smrg gfc_charlen_type child_iomsg_len;
1097760c2415Smrg int noiostat;
1098760c2415Smrg int *child_iostat = NULL;
1099760c2415Smrg
1100760c2415Smrg /* Set iostat, intent(out). */
1101760c2415Smrg noiostat = 0;
1102760c2415Smrg child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
1103760c2415Smrg dtp->common.iostat : &noiostat;
1104760c2415Smrg
1105760c2415Smrg /* Set iomsg, intent(inout). */
1106760c2415Smrg if (dtp->common.flags & IOPARM_HAS_IOMSG)
1107760c2415Smrg {
1108760c2415Smrg child_iomsg = dtp->common.iomsg;
1109760c2415Smrg child_iomsg_len = dtp->common.iomsg_len;
1110760c2415Smrg }
1111760c2415Smrg else
1112760c2415Smrg {
1113760c2415Smrg child_iomsg = tmp_iomsg;
1114760c2415Smrg child_iomsg_len = IOMSG_LEN;
1115760c2415Smrg }
1116760c2415Smrg
1117760c2415Smrg /* Call the user defined unformatted READ procedure. */
1118760c2415Smrg dtp->u.p.current_unit->child_dtio++;
1119760c2415Smrg dtp->u.p.ufdtio_ptr (dest, &unit, child_iostat, child_iomsg,
1120760c2415Smrg child_iomsg_len);
1121760c2415Smrg dtp->u.p.current_unit->child_dtio--;
1122760c2415Smrg return;
1123760c2415Smrg }
1124760c2415Smrg
1125760c2415Smrg if (type == BT_CHARACTER)
1126760c2415Smrg size *= GFC_SIZE_OF_CHAR_KIND(kind);
1127760c2415Smrg read_block_direct (dtp, dest, size * nelems);
1128760c2415Smrg
1129760c2415Smrg if (unlikely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_SWAP)
1130760c2415Smrg && kind != 1)
1131760c2415Smrg {
1132760c2415Smrg /* Handle wide chracters. */
1133760c2415Smrg if (type == BT_CHARACTER)
1134760c2415Smrg {
1135760c2415Smrg nelems *= size;
1136760c2415Smrg size = kind;
1137760c2415Smrg }
1138760c2415Smrg
1139760c2415Smrg /* Break up complex into its constituent reals. */
1140760c2415Smrg else if (type == BT_COMPLEX)
1141760c2415Smrg {
1142760c2415Smrg nelems *= 2;
1143760c2415Smrg size /= 2;
1144760c2415Smrg }
1145760c2415Smrg bswap_array (dest, dest, size, nelems);
1146760c2415Smrg }
1147760c2415Smrg }
1148760c2415Smrg
1149760c2415Smrg
1150760c2415Smrg /* Master function for unformatted writes. NOTE: For kind=10 the size is 16
1151760c2415Smrg bytes on 64 bit machines. The unused bytes are not initialized and never
1152760c2415Smrg used, which can show an error with memory checking analyzers like
1153760c2415Smrg valgrind. We us BT_CLASS to denote a User Defined I/O call. */
1154760c2415Smrg
1155760c2415Smrg static void
unformatted_write(st_parameter_dt * dtp,bt type,void * source,int kind,size_t size,size_t nelems)1156760c2415Smrg unformatted_write (st_parameter_dt *dtp, bt type,
1157760c2415Smrg void *source, int kind, size_t size, size_t nelems)
1158760c2415Smrg {
1159760c2415Smrg if (type == BT_CLASS)
1160760c2415Smrg {
1161760c2415Smrg int unit = dtp->u.p.current_unit->unit_number;
1162760c2415Smrg char tmp_iomsg[IOMSG_LEN] = "";
1163760c2415Smrg char *child_iomsg;
1164760c2415Smrg gfc_charlen_type child_iomsg_len;
1165760c2415Smrg int noiostat;
1166760c2415Smrg int *child_iostat = NULL;
1167760c2415Smrg
1168760c2415Smrg /* Set iostat, intent(out). */
1169760c2415Smrg noiostat = 0;
1170760c2415Smrg child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
1171760c2415Smrg dtp->common.iostat : &noiostat;
1172760c2415Smrg
1173760c2415Smrg /* Set iomsg, intent(inout). */
1174760c2415Smrg if (dtp->common.flags & IOPARM_HAS_IOMSG)
1175760c2415Smrg {
1176760c2415Smrg child_iomsg = dtp->common.iomsg;
1177760c2415Smrg child_iomsg_len = dtp->common.iomsg_len;
1178760c2415Smrg }
1179760c2415Smrg else
1180760c2415Smrg {
1181760c2415Smrg child_iomsg = tmp_iomsg;
1182760c2415Smrg child_iomsg_len = IOMSG_LEN;
1183760c2415Smrg }
1184760c2415Smrg
1185760c2415Smrg /* Call the user defined unformatted WRITE procedure. */
1186760c2415Smrg dtp->u.p.current_unit->child_dtio++;
1187760c2415Smrg dtp->u.p.ufdtio_ptr (source, &unit, child_iostat, child_iomsg,
1188760c2415Smrg child_iomsg_len);
1189760c2415Smrg dtp->u.p.current_unit->child_dtio--;
1190760c2415Smrg return;
1191760c2415Smrg }
1192760c2415Smrg
1193760c2415Smrg if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE)
1194760c2415Smrg || kind == 1)
1195760c2415Smrg {
1196760c2415Smrg size_t stride = type == BT_CHARACTER ?
1197760c2415Smrg size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
1198760c2415Smrg
1199760c2415Smrg write_buf (dtp, source, stride * nelems);
1200760c2415Smrg }
1201760c2415Smrg else
1202760c2415Smrg {
1203760c2415Smrg #define BSWAP_BUFSZ 512
1204760c2415Smrg char buffer[BSWAP_BUFSZ];
1205760c2415Smrg char *p;
1206760c2415Smrg size_t nrem;
1207760c2415Smrg
1208760c2415Smrg p = source;
1209760c2415Smrg
1210760c2415Smrg /* Handle wide chracters. */
1211760c2415Smrg if (type == BT_CHARACTER && kind != 1)
1212760c2415Smrg {
1213760c2415Smrg nelems *= size;
1214760c2415Smrg size = kind;
1215760c2415Smrg }
1216760c2415Smrg
1217760c2415Smrg /* Break up complex into its constituent reals. */
1218760c2415Smrg if (type == BT_COMPLEX)
1219760c2415Smrg {
1220760c2415Smrg nelems *= 2;
1221760c2415Smrg size /= 2;
1222760c2415Smrg }
1223760c2415Smrg
1224760c2415Smrg /* By now, all complex variables have been split into their
1225760c2415Smrg constituent reals. */
1226760c2415Smrg
1227760c2415Smrg nrem = nelems;
1228760c2415Smrg do
1229760c2415Smrg {
1230760c2415Smrg size_t nc;
1231760c2415Smrg if (size * nrem > BSWAP_BUFSZ)
1232760c2415Smrg nc = BSWAP_BUFSZ / size;
1233760c2415Smrg else
1234760c2415Smrg nc = nrem;
1235760c2415Smrg
1236760c2415Smrg bswap_array (buffer, p, size, nc);
1237760c2415Smrg write_buf (dtp, buffer, size * nc);
1238760c2415Smrg p += size * nc;
1239760c2415Smrg nrem -= nc;
1240760c2415Smrg }
1241760c2415Smrg while (nrem > 0);
1242760c2415Smrg }
1243760c2415Smrg }
1244760c2415Smrg
1245760c2415Smrg
1246760c2415Smrg /* Return a pointer to the name of a type. */
1247760c2415Smrg
1248760c2415Smrg const char *
type_name(bt type)1249760c2415Smrg type_name (bt type)
1250760c2415Smrg {
1251760c2415Smrg const char *p;
1252760c2415Smrg
1253760c2415Smrg switch (type)
1254760c2415Smrg {
1255760c2415Smrg case BT_INTEGER:
1256760c2415Smrg p = "INTEGER";
1257760c2415Smrg break;
1258760c2415Smrg case BT_LOGICAL:
1259760c2415Smrg p = "LOGICAL";
1260760c2415Smrg break;
1261760c2415Smrg case BT_CHARACTER:
1262760c2415Smrg p = "CHARACTER";
1263760c2415Smrg break;
1264760c2415Smrg case BT_REAL:
1265760c2415Smrg p = "REAL";
1266760c2415Smrg break;
1267760c2415Smrg case BT_COMPLEX:
1268760c2415Smrg p = "COMPLEX";
1269760c2415Smrg break;
1270760c2415Smrg case BT_CLASS:
1271760c2415Smrg p = "CLASS or DERIVED";
1272760c2415Smrg break;
1273760c2415Smrg default:
1274760c2415Smrg internal_error (NULL, "type_name(): Bad type");
1275760c2415Smrg }
1276760c2415Smrg
1277760c2415Smrg return p;
1278760c2415Smrg }
1279760c2415Smrg
1280760c2415Smrg
1281760c2415Smrg /* Write a constant string to the output.
1282760c2415Smrg This is complicated because the string can have doubled delimiters
1283760c2415Smrg in it. The length in the format node is the true length. */
1284760c2415Smrg
1285760c2415Smrg static void
write_constant_string(st_parameter_dt * dtp,const fnode * f)1286760c2415Smrg write_constant_string (st_parameter_dt *dtp, const fnode *f)
1287760c2415Smrg {
1288760c2415Smrg char c, delimiter, *p, *q;
1289760c2415Smrg int length;
1290760c2415Smrg
1291760c2415Smrg length = f->u.string.length;
1292760c2415Smrg if (length == 0)
1293760c2415Smrg return;
1294760c2415Smrg
1295760c2415Smrg p = write_block (dtp, length);
1296760c2415Smrg if (p == NULL)
1297760c2415Smrg return;
1298760c2415Smrg
1299760c2415Smrg q = f->u.string.p;
1300760c2415Smrg delimiter = q[-1];
1301760c2415Smrg
1302760c2415Smrg for (; length > 0; length--)
1303760c2415Smrg {
1304760c2415Smrg c = *p++ = *q++;
1305760c2415Smrg if (c == delimiter && c != 'H' && c != 'h')
1306760c2415Smrg q++; /* Skip the doubled delimiter. */
1307760c2415Smrg }
1308760c2415Smrg }
1309760c2415Smrg
1310760c2415Smrg
1311760c2415Smrg /* Given actual and expected types in a formatted data transfer, make
1312760c2415Smrg sure they agree. If not, an error message is generated. Returns
1313760c2415Smrg nonzero if something went wrong. */
1314760c2415Smrg
1315760c2415Smrg static int
require_type(st_parameter_dt * dtp,bt expected,bt actual,const fnode * f)1316760c2415Smrg require_type (st_parameter_dt *dtp, bt expected, bt actual, const fnode *f)
1317760c2415Smrg {
1318760c2415Smrg #define BUFLEN 100
1319760c2415Smrg char buffer[BUFLEN];
1320760c2415Smrg
1321760c2415Smrg if (actual == expected)
1322760c2415Smrg return 0;
1323760c2415Smrg
1324760c2415Smrg /* Adjust item_count before emitting error message. */
1325760c2415Smrg snprintf (buffer, BUFLEN,
1326760c2415Smrg "Expected %s for item %d in formatted transfer, got %s",
1327760c2415Smrg type_name (expected), dtp->u.p.item_count - 1, type_name (actual));
1328760c2415Smrg
1329760c2415Smrg format_error (dtp, f, buffer);
1330760c2415Smrg return 1;
1331760c2415Smrg }
1332760c2415Smrg
1333760c2415Smrg
1334760c2415Smrg /* Check that the dtio procedure required for formatted IO is present. */
1335760c2415Smrg
1336760c2415Smrg static int
check_dtio_proc(st_parameter_dt * dtp,const fnode * f)1337760c2415Smrg check_dtio_proc (st_parameter_dt *dtp, const fnode *f)
1338760c2415Smrg {
1339760c2415Smrg char buffer[BUFLEN];
1340760c2415Smrg
1341760c2415Smrg if (dtp->u.p.fdtio_ptr != NULL)
1342760c2415Smrg return 0;
1343760c2415Smrg
1344760c2415Smrg snprintf (buffer, BUFLEN,
1345760c2415Smrg "Missing DTIO procedure or intrinsic type passed for item %d "
1346760c2415Smrg "in formatted transfer",
1347760c2415Smrg dtp->u.p.item_count - 1);
1348760c2415Smrg
1349760c2415Smrg format_error (dtp, f, buffer);
1350760c2415Smrg return 1;
1351760c2415Smrg }
1352760c2415Smrg
1353760c2415Smrg
1354760c2415Smrg static int
require_numeric_type(st_parameter_dt * dtp,bt actual,const fnode * f)1355760c2415Smrg require_numeric_type (st_parameter_dt *dtp, bt actual, const fnode *f)
1356760c2415Smrg {
1357760c2415Smrg #define BUFLEN 100
1358760c2415Smrg char buffer[BUFLEN];
1359760c2415Smrg
1360760c2415Smrg if (actual == BT_INTEGER || actual == BT_REAL || actual == BT_COMPLEX)
1361760c2415Smrg return 0;
1362760c2415Smrg
1363760c2415Smrg /* Adjust item_count before emitting error message. */
1364760c2415Smrg snprintf (buffer, BUFLEN,
1365760c2415Smrg "Expected numeric type for item %d in formatted transfer, got %s",
1366760c2415Smrg dtp->u.p.item_count - 1, type_name (actual));
1367760c2415Smrg
1368760c2415Smrg format_error (dtp, f, buffer);
1369760c2415Smrg return 1;
1370760c2415Smrg }
1371760c2415Smrg
1372760c2415Smrg static char *
get_dt_format(char * p,gfc_charlen_type * length)1373760c2415Smrg get_dt_format (char *p, gfc_charlen_type *length)
1374760c2415Smrg {
1375760c2415Smrg char delim = p[-1]; /* The delimiter is always the first character back. */
1376760c2415Smrg char c, *q, *res;
1377760c2415Smrg gfc_charlen_type len = *length; /* This length already correct, less 'DT'. */
1378760c2415Smrg
1379760c2415Smrg res = q = xmalloc (len + 2);
1380760c2415Smrg
1381760c2415Smrg /* Set the beginning of the string to 'DT', length adjusted below. */
1382760c2415Smrg *q++ = 'D';
1383760c2415Smrg *q++ = 'T';
1384760c2415Smrg
1385760c2415Smrg /* The string may contain doubled quotes so scan and skip as needed. */
1386760c2415Smrg for (; len > 0; len--)
1387760c2415Smrg {
1388760c2415Smrg c = *q++ = *p++;
1389760c2415Smrg if (c == delim)
1390760c2415Smrg p++; /* Skip the doubled delimiter. */
1391760c2415Smrg }
1392760c2415Smrg
1393760c2415Smrg /* Adjust the string length by two now that we are done. */
1394760c2415Smrg *length += 2;
1395760c2415Smrg
1396760c2415Smrg return res;
1397760c2415Smrg }
1398760c2415Smrg
1399760c2415Smrg
1400760c2415Smrg /* This function is in the main loop for a formatted data transfer
1401760c2415Smrg statement. It would be natural to implement this as a coroutine
1402760c2415Smrg with the user program, but C makes that awkward. We loop,
1403760c2415Smrg processing format elements. When we actually have to transfer
1404760c2415Smrg data instead of just setting flags, we return control to the user
1405760c2415Smrg program which calls a function that supplies the address and type
1406760c2415Smrg of the next element, then comes back here to process it. */
1407760c2415Smrg
1408760c2415Smrg static void
formatted_transfer_scalar_read(st_parameter_dt * dtp,bt type,void * p,int kind,size_t size)1409760c2415Smrg formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind,
1410760c2415Smrg size_t size)
1411760c2415Smrg {
1412760c2415Smrg int pos, bytes_used;
1413760c2415Smrg const fnode *f;
1414760c2415Smrg format_token t;
1415760c2415Smrg int n;
1416760c2415Smrg int consume_data_flag;
1417760c2415Smrg
1418760c2415Smrg /* Change a complex data item into a pair of reals. */
1419760c2415Smrg
1420760c2415Smrg n = (p == NULL) ? 0 : ((type != BT_COMPLEX) ? 1 : 2);
1421760c2415Smrg if (type == BT_COMPLEX)
1422760c2415Smrg {
1423760c2415Smrg type = BT_REAL;
1424760c2415Smrg size /= 2;
1425760c2415Smrg }
1426760c2415Smrg
1427760c2415Smrg /* If there's an EOR condition, we simulate finalizing the transfer
1428760c2415Smrg by doing nothing. */
1429760c2415Smrg if (dtp->u.p.eor_condition)
1430760c2415Smrg return;
1431760c2415Smrg
1432760c2415Smrg /* Set this flag so that commas in reads cause the read to complete before
1433760c2415Smrg the entire field has been read. The next read field will start right after
1434760c2415Smrg the comma in the stream. (Set to 0 for character reads). */
1435760c2415Smrg dtp->u.p.sf_read_comma =
1436760c2415Smrg dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
1437760c2415Smrg
1438760c2415Smrg for (;;)
1439760c2415Smrg {
1440760c2415Smrg /* If reversion has occurred and there is another real data item,
1441760c2415Smrg then we have to move to the next record. */
1442760c2415Smrg if (dtp->u.p.reversion_flag && n > 0)
1443760c2415Smrg {
1444760c2415Smrg dtp->u.p.reversion_flag = 0;
1445760c2415Smrg next_record (dtp, 0);
1446760c2415Smrg }
1447760c2415Smrg
1448760c2415Smrg consume_data_flag = 1;
1449760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
1450760c2415Smrg break;
1451760c2415Smrg
1452760c2415Smrg f = next_format (dtp);
1453760c2415Smrg if (f == NULL)
1454760c2415Smrg {
1455760c2415Smrg /* No data descriptors left. */
1456760c2415Smrg if (unlikely (n > 0))
1457760c2415Smrg generate_error (&dtp->common, LIBERROR_FORMAT,
1458760c2415Smrg "Insufficient data descriptors in format after reversion");
1459760c2415Smrg return;
1460760c2415Smrg }
1461760c2415Smrg
1462760c2415Smrg t = f->format;
1463760c2415Smrg
1464760c2415Smrg bytes_used = (int)(dtp->u.p.current_unit->recl
1465760c2415Smrg - dtp->u.p.current_unit->bytes_left);
1466760c2415Smrg
1467760c2415Smrg if (is_stream_io(dtp))
1468760c2415Smrg bytes_used = 0;
1469760c2415Smrg
1470760c2415Smrg switch (t)
1471760c2415Smrg {
1472760c2415Smrg case FMT_I:
1473760c2415Smrg if (n == 0)
1474760c2415Smrg goto need_read_data;
1475760c2415Smrg if (require_type (dtp, BT_INTEGER, type, f))
1476760c2415Smrg return;
1477760c2415Smrg read_decimal (dtp, f, p, kind);
1478760c2415Smrg break;
1479760c2415Smrg
1480760c2415Smrg case FMT_B:
1481760c2415Smrg if (n == 0)
1482760c2415Smrg goto need_read_data;
1483760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1484760c2415Smrg && require_numeric_type (dtp, type, f))
1485760c2415Smrg return;
1486760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1487760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1488760c2415Smrg return;
1489760c2415Smrg read_radix (dtp, f, p, kind, 2);
1490760c2415Smrg break;
1491760c2415Smrg
1492760c2415Smrg case FMT_O:
1493760c2415Smrg if (n == 0)
1494760c2415Smrg goto need_read_data;
1495760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1496760c2415Smrg && require_numeric_type (dtp, type, f))
1497760c2415Smrg return;
1498760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1499760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1500760c2415Smrg return;
1501760c2415Smrg read_radix (dtp, f, p, kind, 8);
1502760c2415Smrg break;
1503760c2415Smrg
1504760c2415Smrg case FMT_Z:
1505760c2415Smrg if (n == 0)
1506760c2415Smrg goto need_read_data;
1507760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1508760c2415Smrg && require_numeric_type (dtp, type, f))
1509760c2415Smrg return;
1510760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1511760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1512760c2415Smrg return;
1513760c2415Smrg read_radix (dtp, f, p, kind, 16);
1514760c2415Smrg break;
1515760c2415Smrg
1516760c2415Smrg case FMT_A:
1517760c2415Smrg if (n == 0)
1518760c2415Smrg goto need_read_data;
1519760c2415Smrg
1520760c2415Smrg /* It is possible to have FMT_A with something not BT_CHARACTER such
1521760c2415Smrg as when writing out hollerith strings, so check both type
1522760c2415Smrg and kind before calling wide character routines. */
1523760c2415Smrg if (type == BT_CHARACTER && kind == 4)
1524760c2415Smrg read_a_char4 (dtp, f, p, size);
1525760c2415Smrg else
1526760c2415Smrg read_a (dtp, f, p, size);
1527760c2415Smrg break;
1528760c2415Smrg
1529760c2415Smrg case FMT_L:
1530760c2415Smrg if (n == 0)
1531760c2415Smrg goto need_read_data;
1532760c2415Smrg read_l (dtp, f, p, kind);
1533760c2415Smrg break;
1534760c2415Smrg
1535760c2415Smrg case FMT_D:
1536760c2415Smrg if (n == 0)
1537760c2415Smrg goto need_read_data;
1538760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
1539760c2415Smrg return;
1540760c2415Smrg read_f (dtp, f, p, kind);
1541760c2415Smrg break;
1542760c2415Smrg
1543760c2415Smrg case FMT_DT:
1544760c2415Smrg if (n == 0)
1545760c2415Smrg goto need_read_data;
1546760c2415Smrg
1547760c2415Smrg if (check_dtio_proc (dtp, f))
1548760c2415Smrg return;
1549760c2415Smrg if (require_type (dtp, BT_CLASS, type, f))
1550760c2415Smrg return;
1551760c2415Smrg int unit = dtp->u.p.current_unit->unit_number;
1552760c2415Smrg char dt[] = "DT";
1553760c2415Smrg char tmp_iomsg[IOMSG_LEN] = "";
1554760c2415Smrg char *child_iomsg;
1555760c2415Smrg gfc_charlen_type child_iomsg_len;
1556760c2415Smrg int noiostat;
1557760c2415Smrg int *child_iostat = NULL;
1558760c2415Smrg char *iotype;
1559760c2415Smrg gfc_charlen_type iotype_len = f->u.udf.string_len;
1560760c2415Smrg
1561760c2415Smrg /* Build the iotype string. */
1562760c2415Smrg if (iotype_len == 0)
1563760c2415Smrg {
1564760c2415Smrg iotype_len = 2;
1565760c2415Smrg iotype = dt;
1566760c2415Smrg }
1567760c2415Smrg else
1568760c2415Smrg iotype = get_dt_format (f->u.udf.string, &iotype_len);
1569760c2415Smrg
1570760c2415Smrg /* Set iostat, intent(out). */
1571760c2415Smrg noiostat = 0;
1572760c2415Smrg child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
1573760c2415Smrg dtp->common.iostat : &noiostat;
1574760c2415Smrg
1575760c2415Smrg /* Set iomsg, intent(inout). */
1576760c2415Smrg if (dtp->common.flags & IOPARM_HAS_IOMSG)
1577760c2415Smrg {
1578760c2415Smrg child_iomsg = dtp->common.iomsg;
1579760c2415Smrg child_iomsg_len = dtp->common.iomsg_len;
1580760c2415Smrg }
1581760c2415Smrg else
1582760c2415Smrg {
1583760c2415Smrg child_iomsg = tmp_iomsg;
1584760c2415Smrg child_iomsg_len = IOMSG_LEN;
1585760c2415Smrg }
1586760c2415Smrg
1587760c2415Smrg /* Call the user defined formatted READ procedure. */
1588760c2415Smrg dtp->u.p.current_unit->child_dtio++;
1589760c2415Smrg dtp->u.p.current_unit->last_char = EOF - 1;
1590760c2415Smrg dtp->u.p.fdtio_ptr (p, &unit, iotype, f->u.udf.vlist,
1591760c2415Smrg child_iostat, child_iomsg,
1592760c2415Smrg iotype_len, child_iomsg_len);
1593760c2415Smrg dtp->u.p.current_unit->child_dtio--;
1594760c2415Smrg
1595760c2415Smrg if (f->u.udf.string_len != 0)
1596760c2415Smrg free (iotype);
1597760c2415Smrg /* Note: vlist is freed in free_format_data. */
1598760c2415Smrg break;
1599760c2415Smrg
1600760c2415Smrg case FMT_E:
1601760c2415Smrg if (n == 0)
1602760c2415Smrg goto need_read_data;
1603760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
1604760c2415Smrg return;
1605760c2415Smrg read_f (dtp, f, p, kind);
1606760c2415Smrg break;
1607760c2415Smrg
1608760c2415Smrg case FMT_EN:
1609760c2415Smrg if (n == 0)
1610760c2415Smrg goto need_read_data;
1611760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
1612760c2415Smrg return;
1613760c2415Smrg read_f (dtp, f, p, kind);
1614760c2415Smrg break;
1615760c2415Smrg
1616760c2415Smrg case FMT_ES:
1617760c2415Smrg if (n == 0)
1618760c2415Smrg goto need_read_data;
1619760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
1620760c2415Smrg return;
1621760c2415Smrg read_f (dtp, f, p, kind);
1622760c2415Smrg break;
1623760c2415Smrg
1624760c2415Smrg case FMT_F:
1625760c2415Smrg if (n == 0)
1626760c2415Smrg goto need_read_data;
1627760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
1628760c2415Smrg return;
1629760c2415Smrg read_f (dtp, f, p, kind);
1630760c2415Smrg break;
1631760c2415Smrg
1632760c2415Smrg case FMT_G:
1633760c2415Smrg if (n == 0)
1634760c2415Smrg goto need_read_data;
1635760c2415Smrg switch (type)
1636760c2415Smrg {
1637760c2415Smrg case BT_INTEGER:
1638760c2415Smrg read_decimal (dtp, f, p, kind);
1639760c2415Smrg break;
1640760c2415Smrg case BT_LOGICAL:
1641760c2415Smrg read_l (dtp, f, p, kind);
1642760c2415Smrg break;
1643760c2415Smrg case BT_CHARACTER:
1644760c2415Smrg if (kind == 4)
1645760c2415Smrg read_a_char4 (dtp, f, p, size);
1646760c2415Smrg else
1647760c2415Smrg read_a (dtp, f, p, size);
1648760c2415Smrg break;
1649760c2415Smrg case BT_REAL:
1650760c2415Smrg read_f (dtp, f, p, kind);
1651760c2415Smrg break;
1652760c2415Smrg default:
1653760c2415Smrg internal_error (&dtp->common,
1654760c2415Smrg "formatted_transfer (): Bad type");
1655760c2415Smrg }
1656760c2415Smrg break;
1657760c2415Smrg
1658760c2415Smrg case FMT_STRING:
1659760c2415Smrg consume_data_flag = 0;
1660760c2415Smrg format_error (dtp, f, "Constant string in input format");
1661760c2415Smrg return;
1662760c2415Smrg
1663760c2415Smrg /* Format codes that don't transfer data. */
1664760c2415Smrg case FMT_X:
1665760c2415Smrg case FMT_TR:
1666760c2415Smrg consume_data_flag = 0;
1667760c2415Smrg dtp->u.p.skips += f->u.n;
1668760c2415Smrg pos = bytes_used + dtp->u.p.skips - 1;
1669760c2415Smrg dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
1670760c2415Smrg read_x (dtp, f->u.n);
1671760c2415Smrg break;
1672760c2415Smrg
1673760c2415Smrg case FMT_TL:
1674760c2415Smrg case FMT_T:
1675760c2415Smrg consume_data_flag = 0;
1676760c2415Smrg
1677760c2415Smrg if (f->format == FMT_TL)
1678760c2415Smrg {
1679760c2415Smrg /* Handle the special case when no bytes have been used yet.
1680760c2415Smrg Cannot go below zero. */
1681760c2415Smrg if (bytes_used == 0)
1682760c2415Smrg {
1683760c2415Smrg dtp->u.p.pending_spaces -= f->u.n;
1684760c2415Smrg dtp->u.p.skips -= f->u.n;
1685760c2415Smrg dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
1686760c2415Smrg }
1687760c2415Smrg
1688760c2415Smrg pos = bytes_used - f->u.n;
1689760c2415Smrg }
1690760c2415Smrg else /* FMT_T */
1691760c2415Smrg pos = f->u.n - 1;
1692760c2415Smrg
1693760c2415Smrg /* Standard 10.6.1.1: excessive left tabbing is reset to the
1694760c2415Smrg left tab limit. We do not check if the position has gone
1695760c2415Smrg beyond the end of record because a subsequent tab could
1696760c2415Smrg bring us back again. */
1697760c2415Smrg pos = pos < 0 ? 0 : pos;
1698760c2415Smrg
1699760c2415Smrg dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
1700760c2415Smrg dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
1701760c2415Smrg + pos - dtp->u.p.max_pos;
1702760c2415Smrg dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
1703760c2415Smrg ? 0 : dtp->u.p.pending_spaces;
1704760c2415Smrg if (dtp->u.p.skips == 0)
1705760c2415Smrg break;
1706760c2415Smrg
1707760c2415Smrg /* Adjust everything for end-of-record condition */
1708760c2415Smrg if (dtp->u.p.sf_seen_eor && !is_internal_unit (dtp))
1709760c2415Smrg {
1710760c2415Smrg dtp->u.p.current_unit->bytes_left -= dtp->u.p.sf_seen_eor;
1711760c2415Smrg dtp->u.p.skips -= dtp->u.p.sf_seen_eor;
1712760c2415Smrg bytes_used = pos;
1713760c2415Smrg if (dtp->u.p.pending_spaces == 0)
1714760c2415Smrg dtp->u.p.sf_seen_eor = 0;
1715760c2415Smrg }
1716760c2415Smrg if (dtp->u.p.skips < 0)
1717760c2415Smrg {
1718760c2415Smrg if (is_internal_unit (dtp))
1719760c2415Smrg sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
1720760c2415Smrg else
1721760c2415Smrg fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
1722760c2415Smrg dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
1723760c2415Smrg dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
1724760c2415Smrg }
1725760c2415Smrg else
1726760c2415Smrg read_x (dtp, dtp->u.p.skips);
1727760c2415Smrg break;
1728760c2415Smrg
1729760c2415Smrg case FMT_S:
1730760c2415Smrg consume_data_flag = 0;
1731*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_PROCDEFINED;
1732760c2415Smrg break;
1733760c2415Smrg
1734760c2415Smrg case FMT_SS:
1735760c2415Smrg consume_data_flag = 0;
1736*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_SUPPRESS;
1737760c2415Smrg break;
1738760c2415Smrg
1739760c2415Smrg case FMT_SP:
1740760c2415Smrg consume_data_flag = 0;
1741*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_PLUS;
1742760c2415Smrg break;
1743760c2415Smrg
1744760c2415Smrg case FMT_BN:
1745760c2415Smrg consume_data_flag = 0 ;
1746760c2415Smrg dtp->u.p.blank_status = BLANK_NULL;
1747760c2415Smrg break;
1748760c2415Smrg
1749760c2415Smrg case FMT_BZ:
1750760c2415Smrg consume_data_flag = 0;
1751760c2415Smrg dtp->u.p.blank_status = BLANK_ZERO;
1752760c2415Smrg break;
1753760c2415Smrg
1754760c2415Smrg case FMT_DC:
1755760c2415Smrg consume_data_flag = 0;
1756760c2415Smrg dtp->u.p.current_unit->decimal_status = DECIMAL_COMMA;
1757760c2415Smrg break;
1758760c2415Smrg
1759760c2415Smrg case FMT_DP:
1760760c2415Smrg consume_data_flag = 0;
1761760c2415Smrg dtp->u.p.current_unit->decimal_status = DECIMAL_POINT;
1762760c2415Smrg break;
1763760c2415Smrg
1764760c2415Smrg case FMT_RC:
1765760c2415Smrg consume_data_flag = 0;
1766760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_COMPATIBLE;
1767760c2415Smrg break;
1768760c2415Smrg
1769760c2415Smrg case FMT_RD:
1770760c2415Smrg consume_data_flag = 0;
1771760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_DOWN;
1772760c2415Smrg break;
1773760c2415Smrg
1774760c2415Smrg case FMT_RN:
1775760c2415Smrg consume_data_flag = 0;
1776760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_NEAREST;
1777760c2415Smrg break;
1778760c2415Smrg
1779760c2415Smrg case FMT_RP:
1780760c2415Smrg consume_data_flag = 0;
1781760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_PROCDEFINED;
1782760c2415Smrg break;
1783760c2415Smrg
1784760c2415Smrg case FMT_RU:
1785760c2415Smrg consume_data_flag = 0;
1786760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_UP;
1787760c2415Smrg break;
1788760c2415Smrg
1789760c2415Smrg case FMT_RZ:
1790760c2415Smrg consume_data_flag = 0;
1791760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_ZERO;
1792760c2415Smrg break;
1793760c2415Smrg
1794760c2415Smrg case FMT_P:
1795760c2415Smrg consume_data_flag = 0;
1796760c2415Smrg dtp->u.p.scale_factor = f->u.k;
1797760c2415Smrg break;
1798760c2415Smrg
1799760c2415Smrg case FMT_DOLLAR:
1800760c2415Smrg consume_data_flag = 0;
1801760c2415Smrg dtp->u.p.seen_dollar = 1;
1802760c2415Smrg break;
1803760c2415Smrg
1804760c2415Smrg case FMT_SLASH:
1805760c2415Smrg consume_data_flag = 0;
1806760c2415Smrg dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
1807760c2415Smrg next_record (dtp, 0);
1808760c2415Smrg break;
1809760c2415Smrg
1810760c2415Smrg case FMT_COLON:
1811760c2415Smrg /* A colon descriptor causes us to exit this loop (in
1812760c2415Smrg particular preventing another / descriptor from being
1813760c2415Smrg processed) unless there is another data item to be
1814760c2415Smrg transferred. */
1815760c2415Smrg consume_data_flag = 0;
1816760c2415Smrg if (n == 0)
1817760c2415Smrg return;
1818760c2415Smrg break;
1819760c2415Smrg
1820760c2415Smrg default:
1821760c2415Smrg internal_error (&dtp->common, "Bad format node");
1822760c2415Smrg }
1823760c2415Smrg
1824760c2415Smrg /* Adjust the item count and data pointer. */
1825760c2415Smrg
1826760c2415Smrg if ((consume_data_flag > 0) && (n > 0))
1827760c2415Smrg {
1828760c2415Smrg n--;
1829760c2415Smrg p = ((char *) p) + size;
1830760c2415Smrg }
1831760c2415Smrg
1832760c2415Smrg dtp->u.p.skips = 0;
1833760c2415Smrg
1834760c2415Smrg pos = (int)(dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left);
1835760c2415Smrg dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
1836760c2415Smrg }
1837760c2415Smrg
1838760c2415Smrg return;
1839760c2415Smrg
1840760c2415Smrg /* Come here when we need a data descriptor but don't have one. We
1841760c2415Smrg push the current format node back onto the input, then return and
1842760c2415Smrg let the user program call us back with the data. */
1843760c2415Smrg need_read_data:
1844760c2415Smrg unget_format (dtp, f);
1845760c2415Smrg }
1846760c2415Smrg
1847760c2415Smrg
1848760c2415Smrg static void
formatted_transfer_scalar_write(st_parameter_dt * dtp,bt type,void * p,int kind,size_t size)1849760c2415Smrg formatted_transfer_scalar_write (st_parameter_dt *dtp, bt type, void *p, int kind,
1850760c2415Smrg size_t size)
1851760c2415Smrg {
1852760c2415Smrg gfc_offset pos, bytes_used;
1853760c2415Smrg const fnode *f;
1854760c2415Smrg format_token t;
1855760c2415Smrg int n;
1856760c2415Smrg int consume_data_flag;
1857760c2415Smrg
1858760c2415Smrg /* Change a complex data item into a pair of reals. */
1859760c2415Smrg
1860760c2415Smrg n = (p == NULL) ? 0 : ((type != BT_COMPLEX) ? 1 : 2);
1861760c2415Smrg if (type == BT_COMPLEX)
1862760c2415Smrg {
1863760c2415Smrg type = BT_REAL;
1864760c2415Smrg size /= 2;
1865760c2415Smrg }
1866760c2415Smrg
1867760c2415Smrg /* If there's an EOR condition, we simulate finalizing the transfer
1868760c2415Smrg by doing nothing. */
1869760c2415Smrg if (dtp->u.p.eor_condition)
1870760c2415Smrg return;
1871760c2415Smrg
1872760c2415Smrg /* Set this flag so that commas in reads cause the read to complete before
1873760c2415Smrg the entire field has been read. The next read field will start right after
1874760c2415Smrg the comma in the stream. (Set to 0 for character reads). */
1875760c2415Smrg dtp->u.p.sf_read_comma =
1876760c2415Smrg dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
1877760c2415Smrg
1878760c2415Smrg for (;;)
1879760c2415Smrg {
1880760c2415Smrg /* If reversion has occurred and there is another real data item,
1881760c2415Smrg then we have to move to the next record. */
1882760c2415Smrg if (dtp->u.p.reversion_flag && n > 0)
1883760c2415Smrg {
1884760c2415Smrg dtp->u.p.reversion_flag = 0;
1885760c2415Smrg next_record (dtp, 0);
1886760c2415Smrg }
1887760c2415Smrg
1888760c2415Smrg consume_data_flag = 1;
1889760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
1890760c2415Smrg break;
1891760c2415Smrg
1892760c2415Smrg f = next_format (dtp);
1893760c2415Smrg if (f == NULL)
1894760c2415Smrg {
1895760c2415Smrg /* No data descriptors left. */
1896760c2415Smrg if (unlikely (n > 0))
1897760c2415Smrg generate_error (&dtp->common, LIBERROR_FORMAT,
1898760c2415Smrg "Insufficient data descriptors in format after reversion");
1899760c2415Smrg return;
1900760c2415Smrg }
1901760c2415Smrg
1902760c2415Smrg /* Now discharge T, TR and X movements to the right. This is delayed
1903760c2415Smrg until a data producing format to suppress trailing spaces. */
1904760c2415Smrg
1905760c2415Smrg t = f->format;
1906760c2415Smrg if (dtp->u.p.mode == WRITING && dtp->u.p.skips != 0
1907760c2415Smrg && ((n>0 && ( t == FMT_I || t == FMT_B || t == FMT_O
1908760c2415Smrg || t == FMT_Z || t == FMT_F || t == FMT_E
1909760c2415Smrg || t == FMT_EN || t == FMT_ES || t == FMT_G
1910760c2415Smrg || t == FMT_L || t == FMT_A || t == FMT_D
1911760c2415Smrg || t == FMT_DT))
1912760c2415Smrg || t == FMT_STRING))
1913760c2415Smrg {
1914760c2415Smrg if (dtp->u.p.skips > 0)
1915760c2415Smrg {
1916760c2415Smrg gfc_offset tmp;
1917760c2415Smrg write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
1918760c2415Smrg tmp = dtp->u.p.current_unit->recl
1919760c2415Smrg - dtp->u.p.current_unit->bytes_left;
1920760c2415Smrg dtp->u.p.max_pos =
1921760c2415Smrg dtp->u.p.max_pos > tmp ? dtp->u.p.max_pos : tmp;
1922760c2415Smrg dtp->u.p.skips = 0;
1923760c2415Smrg }
1924760c2415Smrg if (dtp->u.p.skips < 0)
1925760c2415Smrg {
1926760c2415Smrg if (is_internal_unit (dtp))
1927760c2415Smrg sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
1928760c2415Smrg else
1929760c2415Smrg fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
1930760c2415Smrg dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
1931760c2415Smrg }
1932760c2415Smrg dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
1933760c2415Smrg }
1934760c2415Smrg
1935760c2415Smrg bytes_used = dtp->u.p.current_unit->recl
1936760c2415Smrg - dtp->u.p.current_unit->bytes_left;
1937760c2415Smrg
1938760c2415Smrg if (is_stream_io(dtp))
1939760c2415Smrg bytes_used = 0;
1940760c2415Smrg
1941760c2415Smrg switch (t)
1942760c2415Smrg {
1943760c2415Smrg case FMT_I:
1944760c2415Smrg if (n == 0)
1945760c2415Smrg goto need_data;
1946760c2415Smrg if (require_type (dtp, BT_INTEGER, type, f))
1947760c2415Smrg return;
1948760c2415Smrg write_i (dtp, f, p, kind);
1949760c2415Smrg break;
1950760c2415Smrg
1951760c2415Smrg case FMT_B:
1952760c2415Smrg if (n == 0)
1953760c2415Smrg goto need_data;
1954760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1955760c2415Smrg && require_numeric_type (dtp, type, f))
1956760c2415Smrg return;
1957760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1958760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1959760c2415Smrg return;
1960760c2415Smrg write_b (dtp, f, p, kind);
1961760c2415Smrg break;
1962760c2415Smrg
1963760c2415Smrg case FMT_O:
1964760c2415Smrg if (n == 0)
1965760c2415Smrg goto need_data;
1966760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1967760c2415Smrg && require_numeric_type (dtp, type, f))
1968760c2415Smrg return;
1969760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1970760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1971760c2415Smrg return;
1972760c2415Smrg write_o (dtp, f, p, kind);
1973760c2415Smrg break;
1974760c2415Smrg
1975760c2415Smrg case FMT_Z:
1976760c2415Smrg if (n == 0)
1977760c2415Smrg goto need_data;
1978760c2415Smrg if (!(compile_options.allow_std & GFC_STD_GNU)
1979760c2415Smrg && require_numeric_type (dtp, type, f))
1980760c2415Smrg return;
1981760c2415Smrg if (!(compile_options.allow_std & GFC_STD_F2008)
1982760c2415Smrg && require_type (dtp, BT_INTEGER, type, f))
1983760c2415Smrg return;
1984760c2415Smrg write_z (dtp, f, p, kind);
1985760c2415Smrg break;
1986760c2415Smrg
1987760c2415Smrg case FMT_A:
1988760c2415Smrg if (n == 0)
1989760c2415Smrg goto need_data;
1990760c2415Smrg
1991760c2415Smrg /* It is possible to have FMT_A with something not BT_CHARACTER such
1992760c2415Smrg as when writing out hollerith strings, so check both type
1993760c2415Smrg and kind before calling wide character routines. */
1994760c2415Smrg if (type == BT_CHARACTER && kind == 4)
1995760c2415Smrg write_a_char4 (dtp, f, p, size);
1996760c2415Smrg else
1997760c2415Smrg write_a (dtp, f, p, size);
1998760c2415Smrg break;
1999760c2415Smrg
2000760c2415Smrg case FMT_L:
2001760c2415Smrg if (n == 0)
2002760c2415Smrg goto need_data;
2003760c2415Smrg write_l (dtp, f, p, kind);
2004760c2415Smrg break;
2005760c2415Smrg
2006760c2415Smrg case FMT_D:
2007760c2415Smrg if (n == 0)
2008760c2415Smrg goto need_data;
2009760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
2010760c2415Smrg return;
2011*0bfacb9bSmrg if (f->u.real.w == 0)
2012*0bfacb9bSmrg write_real_w0 (dtp, p, kind, f);
2013*0bfacb9bSmrg else
2014760c2415Smrg write_d (dtp, f, p, kind);
2015760c2415Smrg break;
2016760c2415Smrg
2017760c2415Smrg case FMT_DT:
2018760c2415Smrg if (n == 0)
2019760c2415Smrg goto need_data;
2020760c2415Smrg int unit = dtp->u.p.current_unit->unit_number;
2021760c2415Smrg char dt[] = "DT";
2022760c2415Smrg char tmp_iomsg[IOMSG_LEN] = "";
2023760c2415Smrg char *child_iomsg;
2024760c2415Smrg gfc_charlen_type child_iomsg_len;
2025760c2415Smrg int noiostat;
2026760c2415Smrg int *child_iostat = NULL;
2027760c2415Smrg char *iotype;
2028760c2415Smrg gfc_charlen_type iotype_len = f->u.udf.string_len;
2029760c2415Smrg
2030760c2415Smrg /* Build the iotype string. */
2031760c2415Smrg if (iotype_len == 0)
2032760c2415Smrg {
2033760c2415Smrg iotype_len = 2;
2034760c2415Smrg iotype = dt;
2035760c2415Smrg }
2036760c2415Smrg else
2037760c2415Smrg iotype = get_dt_format (f->u.udf.string, &iotype_len);
2038760c2415Smrg
2039760c2415Smrg /* Set iostat, intent(out). */
2040760c2415Smrg noiostat = 0;
2041760c2415Smrg child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
2042760c2415Smrg dtp->common.iostat : &noiostat;
2043760c2415Smrg
2044760c2415Smrg /* Set iomsg, intent(inout). */
2045760c2415Smrg if (dtp->common.flags & IOPARM_HAS_IOMSG)
2046760c2415Smrg {
2047760c2415Smrg child_iomsg = dtp->common.iomsg;
2048760c2415Smrg child_iomsg_len = dtp->common.iomsg_len;
2049760c2415Smrg }
2050760c2415Smrg else
2051760c2415Smrg {
2052760c2415Smrg child_iomsg = tmp_iomsg;
2053760c2415Smrg child_iomsg_len = IOMSG_LEN;
2054760c2415Smrg }
2055760c2415Smrg
2056760c2415Smrg if (check_dtio_proc (dtp, f))
2057760c2415Smrg return;
2058760c2415Smrg
2059760c2415Smrg /* Call the user defined formatted WRITE procedure. */
2060760c2415Smrg dtp->u.p.current_unit->child_dtio++;
2061760c2415Smrg
2062760c2415Smrg dtp->u.p.fdtio_ptr (p, &unit, iotype, f->u.udf.vlist,
2063760c2415Smrg child_iostat, child_iomsg,
2064760c2415Smrg iotype_len, child_iomsg_len);
2065760c2415Smrg dtp->u.p.current_unit->child_dtio--;
2066760c2415Smrg
2067760c2415Smrg if (f->u.udf.string_len != 0)
2068760c2415Smrg free (iotype);
2069760c2415Smrg /* Note: vlist is freed in free_format_data. */
2070760c2415Smrg break;
2071760c2415Smrg
2072760c2415Smrg case FMT_E:
2073760c2415Smrg if (n == 0)
2074760c2415Smrg goto need_data;
2075760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
2076760c2415Smrg return;
2077*0bfacb9bSmrg if (f->u.real.w == 0)
2078*0bfacb9bSmrg write_real_w0 (dtp, p, kind, f);
2079*0bfacb9bSmrg else
2080760c2415Smrg write_e (dtp, f, p, kind);
2081760c2415Smrg break;
2082760c2415Smrg
2083760c2415Smrg case FMT_EN:
2084760c2415Smrg if (n == 0)
2085760c2415Smrg goto need_data;
2086760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
2087760c2415Smrg return;
2088*0bfacb9bSmrg if (f->u.real.w == 0)
2089*0bfacb9bSmrg write_real_w0 (dtp, p, kind, f);
2090*0bfacb9bSmrg else
2091760c2415Smrg write_en (dtp, f, p, kind);
2092760c2415Smrg break;
2093760c2415Smrg
2094760c2415Smrg case FMT_ES:
2095760c2415Smrg if (n == 0)
2096760c2415Smrg goto need_data;
2097760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
2098760c2415Smrg return;
2099*0bfacb9bSmrg if (f->u.real.w == 0)
2100*0bfacb9bSmrg write_real_w0 (dtp, p, kind, f);
2101*0bfacb9bSmrg else
2102760c2415Smrg write_es (dtp, f, p, kind);
2103760c2415Smrg break;
2104760c2415Smrg
2105760c2415Smrg case FMT_F:
2106760c2415Smrg if (n == 0)
2107760c2415Smrg goto need_data;
2108760c2415Smrg if (require_type (dtp, BT_REAL, type, f))
2109760c2415Smrg return;
2110760c2415Smrg write_f (dtp, f, p, kind);
2111760c2415Smrg break;
2112760c2415Smrg
2113760c2415Smrg case FMT_G:
2114760c2415Smrg if (n == 0)
2115760c2415Smrg goto need_data;
2116760c2415Smrg switch (type)
2117760c2415Smrg {
2118760c2415Smrg case BT_INTEGER:
2119760c2415Smrg write_i (dtp, f, p, kind);
2120760c2415Smrg break;
2121760c2415Smrg case BT_LOGICAL:
2122760c2415Smrg write_l (dtp, f, p, kind);
2123760c2415Smrg break;
2124760c2415Smrg case BT_CHARACTER:
2125760c2415Smrg if (kind == 4)
2126760c2415Smrg write_a_char4 (dtp, f, p, size);
2127760c2415Smrg else
2128760c2415Smrg write_a (dtp, f, p, size);
2129760c2415Smrg break;
2130760c2415Smrg case BT_REAL:
2131760c2415Smrg if (f->u.real.w == 0)
2132*0bfacb9bSmrg write_real_w0 (dtp, p, kind, f);
2133760c2415Smrg else
2134760c2415Smrg write_d (dtp, f, p, kind);
2135760c2415Smrg break;
2136760c2415Smrg default:
2137760c2415Smrg internal_error (&dtp->common,
2138760c2415Smrg "formatted_transfer (): Bad type");
2139760c2415Smrg }
2140760c2415Smrg break;
2141760c2415Smrg
2142760c2415Smrg case FMT_STRING:
2143760c2415Smrg consume_data_flag = 0;
2144760c2415Smrg write_constant_string (dtp, f);
2145760c2415Smrg break;
2146760c2415Smrg
2147760c2415Smrg /* Format codes that don't transfer data. */
2148760c2415Smrg case FMT_X:
2149760c2415Smrg case FMT_TR:
2150760c2415Smrg consume_data_flag = 0;
2151760c2415Smrg
2152760c2415Smrg dtp->u.p.skips += f->u.n;
2153760c2415Smrg pos = bytes_used + dtp->u.p.skips - 1;
2154760c2415Smrg dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
2155760c2415Smrg /* Writes occur just before the switch on f->format, above, so
2156760c2415Smrg that trailing blanks are suppressed, unless we are doing a
2157760c2415Smrg non-advancing write in which case we want to output the blanks
2158760c2415Smrg now. */
2159760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_NO)
2160760c2415Smrg {
2161760c2415Smrg write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
2162760c2415Smrg dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
2163760c2415Smrg }
2164760c2415Smrg break;
2165760c2415Smrg
2166760c2415Smrg case FMT_TL:
2167760c2415Smrg case FMT_T:
2168760c2415Smrg consume_data_flag = 0;
2169760c2415Smrg
2170760c2415Smrg if (f->format == FMT_TL)
2171760c2415Smrg {
2172760c2415Smrg
2173760c2415Smrg /* Handle the special case when no bytes have been used yet.
2174760c2415Smrg Cannot go below zero. */
2175760c2415Smrg if (bytes_used == 0)
2176760c2415Smrg {
2177760c2415Smrg dtp->u.p.pending_spaces -= f->u.n;
2178760c2415Smrg dtp->u.p.skips -= f->u.n;
2179760c2415Smrg dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
2180760c2415Smrg }
2181760c2415Smrg
2182760c2415Smrg pos = bytes_used - f->u.n;
2183760c2415Smrg }
2184760c2415Smrg else /* FMT_T */
2185760c2415Smrg pos = f->u.n - dtp->u.p.pending_spaces - 1;
2186760c2415Smrg
2187760c2415Smrg /* Standard 10.6.1.1: excessive left tabbing is reset to the
2188760c2415Smrg left tab limit. We do not check if the position has gone
2189760c2415Smrg beyond the end of record because a subsequent tab could
2190760c2415Smrg bring us back again. */
2191760c2415Smrg pos = pos < 0 ? 0 : pos;
2192760c2415Smrg
2193760c2415Smrg dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
2194760c2415Smrg dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
2195760c2415Smrg + pos - dtp->u.p.max_pos;
2196760c2415Smrg dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
2197760c2415Smrg ? 0 : dtp->u.p.pending_spaces;
2198760c2415Smrg break;
2199760c2415Smrg
2200760c2415Smrg case FMT_S:
2201760c2415Smrg consume_data_flag = 0;
2202*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_PROCDEFINED;
2203760c2415Smrg break;
2204760c2415Smrg
2205760c2415Smrg case FMT_SS:
2206760c2415Smrg consume_data_flag = 0;
2207*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_SUPPRESS;
2208760c2415Smrg break;
2209760c2415Smrg
2210760c2415Smrg case FMT_SP:
2211760c2415Smrg consume_data_flag = 0;
2212*0bfacb9bSmrg dtp->u.p.sign_status = SIGN_PLUS;
2213760c2415Smrg break;
2214760c2415Smrg
2215760c2415Smrg case FMT_BN:
2216760c2415Smrg consume_data_flag = 0 ;
2217760c2415Smrg dtp->u.p.blank_status = BLANK_NULL;
2218760c2415Smrg break;
2219760c2415Smrg
2220760c2415Smrg case FMT_BZ:
2221760c2415Smrg consume_data_flag = 0;
2222760c2415Smrg dtp->u.p.blank_status = BLANK_ZERO;
2223760c2415Smrg break;
2224760c2415Smrg
2225760c2415Smrg case FMT_DC:
2226760c2415Smrg consume_data_flag = 0;
2227760c2415Smrg dtp->u.p.current_unit->decimal_status = DECIMAL_COMMA;
2228760c2415Smrg break;
2229760c2415Smrg
2230760c2415Smrg case FMT_DP:
2231760c2415Smrg consume_data_flag = 0;
2232760c2415Smrg dtp->u.p.current_unit->decimal_status = DECIMAL_POINT;
2233760c2415Smrg break;
2234760c2415Smrg
2235760c2415Smrg case FMT_RC:
2236760c2415Smrg consume_data_flag = 0;
2237760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_COMPATIBLE;
2238760c2415Smrg break;
2239760c2415Smrg
2240760c2415Smrg case FMT_RD:
2241760c2415Smrg consume_data_flag = 0;
2242760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_DOWN;
2243760c2415Smrg break;
2244760c2415Smrg
2245760c2415Smrg case FMT_RN:
2246760c2415Smrg consume_data_flag = 0;
2247760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_NEAREST;
2248760c2415Smrg break;
2249760c2415Smrg
2250760c2415Smrg case FMT_RP:
2251760c2415Smrg consume_data_flag = 0;
2252760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_PROCDEFINED;
2253760c2415Smrg break;
2254760c2415Smrg
2255760c2415Smrg case FMT_RU:
2256760c2415Smrg consume_data_flag = 0;
2257760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_UP;
2258760c2415Smrg break;
2259760c2415Smrg
2260760c2415Smrg case FMT_RZ:
2261760c2415Smrg consume_data_flag = 0;
2262760c2415Smrg dtp->u.p.current_unit->round_status = ROUND_ZERO;
2263760c2415Smrg break;
2264760c2415Smrg
2265760c2415Smrg case FMT_P:
2266760c2415Smrg consume_data_flag = 0;
2267760c2415Smrg dtp->u.p.scale_factor = f->u.k;
2268760c2415Smrg break;
2269760c2415Smrg
2270760c2415Smrg case FMT_DOLLAR:
2271760c2415Smrg consume_data_flag = 0;
2272760c2415Smrg dtp->u.p.seen_dollar = 1;
2273760c2415Smrg break;
2274760c2415Smrg
2275760c2415Smrg case FMT_SLASH:
2276760c2415Smrg consume_data_flag = 0;
2277760c2415Smrg dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
2278760c2415Smrg next_record (dtp, 0);
2279760c2415Smrg break;
2280760c2415Smrg
2281760c2415Smrg case FMT_COLON:
2282760c2415Smrg /* A colon descriptor causes us to exit this loop (in
2283760c2415Smrg particular preventing another / descriptor from being
2284760c2415Smrg processed) unless there is another data item to be
2285760c2415Smrg transferred. */
2286760c2415Smrg consume_data_flag = 0;
2287760c2415Smrg if (n == 0)
2288760c2415Smrg return;
2289760c2415Smrg break;
2290760c2415Smrg
2291760c2415Smrg default:
2292760c2415Smrg internal_error (&dtp->common, "Bad format node");
2293760c2415Smrg }
2294760c2415Smrg
2295760c2415Smrg /* Adjust the item count and data pointer. */
2296760c2415Smrg
2297760c2415Smrg if ((consume_data_flag > 0) && (n > 0))
2298760c2415Smrg {
2299760c2415Smrg n--;
2300760c2415Smrg p = ((char *) p) + size;
2301760c2415Smrg }
2302760c2415Smrg
2303760c2415Smrg pos = dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left;
2304760c2415Smrg dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
2305760c2415Smrg }
2306760c2415Smrg
2307760c2415Smrg return;
2308760c2415Smrg
2309760c2415Smrg /* Come here when we need a data descriptor but don't have one. We
2310760c2415Smrg push the current format node back onto the input, then return and
2311760c2415Smrg let the user program call us back with the data. */
2312760c2415Smrg need_data:
2313760c2415Smrg unget_format (dtp, f);
2314760c2415Smrg }
2315760c2415Smrg
2316760c2415Smrg /* This function is first called from data_init_transfer to initiate the loop
2317760c2415Smrg over each item in the format, transferring data as required. Subsequent
2318760c2415Smrg calls to this function occur for each data item foound in the READ/WRITE
2319760c2415Smrg statement. The item_count is incremented for each call. Since the first
2320760c2415Smrg call is from data_transfer_init, the item_count is always one greater than
2321760c2415Smrg the actual count number of the item being transferred. */
2322760c2415Smrg
2323760c2415Smrg static void
formatted_transfer(st_parameter_dt * dtp,bt type,void * p,int kind,size_t size,size_t nelems)2324760c2415Smrg formatted_transfer (st_parameter_dt *dtp, bt type, void *p, int kind,
2325760c2415Smrg size_t size, size_t nelems)
2326760c2415Smrg {
2327760c2415Smrg size_t elem;
2328760c2415Smrg char *tmp;
2329760c2415Smrg
2330760c2415Smrg tmp = (char *) p;
2331760c2415Smrg size_t stride = type == BT_CHARACTER ?
2332760c2415Smrg size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
2333760c2415Smrg if (dtp->u.p.mode == READING)
2334760c2415Smrg {
2335760c2415Smrg /* Big loop over all the elements. */
2336760c2415Smrg for (elem = 0; elem < nelems; elem++)
2337760c2415Smrg {
2338760c2415Smrg dtp->u.p.item_count++;
2339760c2415Smrg formatted_transfer_scalar_read (dtp, type, tmp + stride*elem, kind, size);
2340760c2415Smrg }
2341760c2415Smrg }
2342760c2415Smrg else
2343760c2415Smrg {
2344760c2415Smrg /* Big loop over all the elements. */
2345760c2415Smrg for (elem = 0; elem < nelems; elem++)
2346760c2415Smrg {
2347760c2415Smrg dtp->u.p.item_count++;
2348760c2415Smrg formatted_transfer_scalar_write (dtp, type, tmp + stride*elem, kind, size);
2349760c2415Smrg }
2350760c2415Smrg }
2351760c2415Smrg }
2352760c2415Smrg
2353760c2415Smrg /* Wrapper function for I/O of scalar types. If this should be an async I/O
2354760c2415Smrg request, queue it. For a synchronous write on an async unit, perform the
2355760c2415Smrg wait operation and return an error. For all synchronous writes, call the
2356760c2415Smrg right transfer function. */
2357760c2415Smrg
2358760c2415Smrg static void
wrap_scalar_transfer(st_parameter_dt * dtp,bt type,void * p,int kind,size_t size,size_t n_elem)2359760c2415Smrg wrap_scalar_transfer (st_parameter_dt *dtp, bt type, void *p, int kind,
2360760c2415Smrg size_t size, size_t n_elem)
2361760c2415Smrg {
2362760c2415Smrg if (dtp->u.p.current_unit && dtp->u.p.current_unit->au)
2363760c2415Smrg {
2364760c2415Smrg if (dtp->u.p.async)
2365760c2415Smrg {
2366760c2415Smrg transfer_args args;
2367760c2415Smrg args.scalar.transfer = dtp->u.p.transfer;
2368760c2415Smrg args.scalar.arg_bt = type;
2369760c2415Smrg args.scalar.data = p;
2370760c2415Smrg args.scalar.i = kind;
2371760c2415Smrg args.scalar.s1 = size;
2372760c2415Smrg args.scalar.s2 = n_elem;
2373760c2415Smrg enqueue_transfer (dtp->u.p.current_unit->au, &args,
2374760c2415Smrg AIO_TRANSFER_SCALAR);
2375760c2415Smrg return;
2376760c2415Smrg }
2377760c2415Smrg }
2378760c2415Smrg /* Come here if there was no asynchronous I/O to be scheduled. */
2379760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2380760c2415Smrg return;
2381760c2415Smrg
2382760c2415Smrg dtp->u.p.transfer (dtp, type, p, kind, size, 1);
2383760c2415Smrg }
2384760c2415Smrg
2385760c2415Smrg
2386760c2415Smrg /* Data transfer entry points. The type of the data entity is
2387760c2415Smrg implicit in the subroutine call. This prevents us from having to
2388760c2415Smrg share a common enum with the compiler. */
2389760c2415Smrg
2390760c2415Smrg void
transfer_integer(st_parameter_dt * dtp,void * p,int kind)2391760c2415Smrg transfer_integer (st_parameter_dt *dtp, void *p, int kind)
2392760c2415Smrg {
2393760c2415Smrg wrap_scalar_transfer (dtp, BT_INTEGER, p, kind, kind, 1);
2394760c2415Smrg }
2395760c2415Smrg
2396760c2415Smrg void
transfer_integer_write(st_parameter_dt * dtp,void * p,int kind)2397760c2415Smrg transfer_integer_write (st_parameter_dt *dtp, void *p, int kind)
2398760c2415Smrg {
2399760c2415Smrg transfer_integer (dtp, p, kind);
2400760c2415Smrg }
2401760c2415Smrg
2402760c2415Smrg void
transfer_real(st_parameter_dt * dtp,void * p,int kind)2403760c2415Smrg transfer_real (st_parameter_dt *dtp, void *p, int kind)
2404760c2415Smrg {
2405760c2415Smrg size_t size;
2406760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2407760c2415Smrg return;
2408760c2415Smrg size = size_from_real_kind (kind);
2409760c2415Smrg wrap_scalar_transfer (dtp, BT_REAL, p, kind, size, 1);
2410760c2415Smrg }
2411760c2415Smrg
2412760c2415Smrg void
transfer_real_write(st_parameter_dt * dtp,void * p,int kind)2413760c2415Smrg transfer_real_write (st_parameter_dt *dtp, void *p, int kind)
2414760c2415Smrg {
2415760c2415Smrg transfer_real (dtp, p, kind);
2416760c2415Smrg }
2417760c2415Smrg
2418760c2415Smrg void
transfer_logical(st_parameter_dt * dtp,void * p,int kind)2419760c2415Smrg transfer_logical (st_parameter_dt *dtp, void *p, int kind)
2420760c2415Smrg {
2421760c2415Smrg wrap_scalar_transfer (dtp, BT_LOGICAL, p, kind, kind, 1);
2422760c2415Smrg }
2423760c2415Smrg
2424760c2415Smrg void
transfer_logical_write(st_parameter_dt * dtp,void * p,int kind)2425760c2415Smrg transfer_logical_write (st_parameter_dt *dtp, void *p, int kind)
2426760c2415Smrg {
2427760c2415Smrg transfer_logical (dtp, p, kind);
2428760c2415Smrg }
2429760c2415Smrg
2430760c2415Smrg void
transfer_character(st_parameter_dt * dtp,void * p,gfc_charlen_type len)2431760c2415Smrg transfer_character (st_parameter_dt *dtp, void *p, gfc_charlen_type len)
2432760c2415Smrg {
2433760c2415Smrg static char *empty_string[0];
2434760c2415Smrg
2435760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2436760c2415Smrg return;
2437760c2415Smrg
2438760c2415Smrg /* Strings of zero length can have p == NULL, which confuses the
2439760c2415Smrg transfer routines into thinking we need more data elements. To avoid
2440760c2415Smrg this, we give them a nice pointer. */
2441760c2415Smrg if (len == 0 && p == NULL)
2442760c2415Smrg p = empty_string;
2443760c2415Smrg
2444760c2415Smrg /* Set kind here to 1. */
2445760c2415Smrg wrap_scalar_transfer (dtp, BT_CHARACTER, p, 1, len, 1);
2446760c2415Smrg }
2447760c2415Smrg
2448760c2415Smrg void
transfer_character_write(st_parameter_dt * dtp,void * p,gfc_charlen_type len)2449760c2415Smrg transfer_character_write (st_parameter_dt *dtp, void *p, gfc_charlen_type len)
2450760c2415Smrg {
2451760c2415Smrg transfer_character (dtp, p, len);
2452760c2415Smrg }
2453760c2415Smrg
2454760c2415Smrg void
transfer_character_wide(st_parameter_dt * dtp,void * p,gfc_charlen_type len,int kind)2455760c2415Smrg transfer_character_wide (st_parameter_dt *dtp, void *p, gfc_charlen_type len, int kind)
2456760c2415Smrg {
2457760c2415Smrg static char *empty_string[0];
2458760c2415Smrg
2459760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2460760c2415Smrg return;
2461760c2415Smrg
2462760c2415Smrg /* Strings of zero length can have p == NULL, which confuses the
2463760c2415Smrg transfer routines into thinking we need more data elements. To avoid
2464760c2415Smrg this, we give them a nice pointer. */
2465760c2415Smrg if (len == 0 && p == NULL)
2466760c2415Smrg p = empty_string;
2467760c2415Smrg
2468760c2415Smrg /* Here we pass the actual kind value. */
2469760c2415Smrg wrap_scalar_transfer (dtp, BT_CHARACTER, p, kind, len, 1);
2470760c2415Smrg }
2471760c2415Smrg
2472760c2415Smrg void
transfer_character_wide_write(st_parameter_dt * dtp,void * p,gfc_charlen_type len,int kind)2473760c2415Smrg transfer_character_wide_write (st_parameter_dt *dtp, void *p, gfc_charlen_type len, int kind)
2474760c2415Smrg {
2475760c2415Smrg transfer_character_wide (dtp, p, len, kind);
2476760c2415Smrg }
2477760c2415Smrg
2478760c2415Smrg void
transfer_complex(st_parameter_dt * dtp,void * p,int kind)2479760c2415Smrg transfer_complex (st_parameter_dt *dtp, void *p, int kind)
2480760c2415Smrg {
2481760c2415Smrg size_t size;
2482760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2483760c2415Smrg return;
2484760c2415Smrg size = size_from_complex_kind (kind);
2485760c2415Smrg wrap_scalar_transfer (dtp, BT_COMPLEX, p, kind, size, 1);
2486760c2415Smrg }
2487760c2415Smrg
2488760c2415Smrg void
transfer_complex_write(st_parameter_dt * dtp,void * p,int kind)2489760c2415Smrg transfer_complex_write (st_parameter_dt *dtp, void *p, int kind)
2490760c2415Smrg {
2491760c2415Smrg transfer_complex (dtp, p, kind);
2492760c2415Smrg }
2493760c2415Smrg
2494760c2415Smrg void
transfer_array_inner(st_parameter_dt * dtp,gfc_array_char * desc,int kind,gfc_charlen_type charlen)2495760c2415Smrg transfer_array_inner (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
2496760c2415Smrg gfc_charlen_type charlen)
2497760c2415Smrg {
2498760c2415Smrg index_type count[GFC_MAX_DIMENSIONS];
2499760c2415Smrg index_type extent[GFC_MAX_DIMENSIONS];
2500760c2415Smrg index_type stride[GFC_MAX_DIMENSIONS];
2501760c2415Smrg index_type stride0, rank, size, n;
2502760c2415Smrg size_t tsize;
2503760c2415Smrg char *data;
2504760c2415Smrg bt iotype;
2505760c2415Smrg
2506760c2415Smrg /* Adjust item_count before emitting error message. */
2507760c2415Smrg
2508760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2509760c2415Smrg return;
2510760c2415Smrg
2511760c2415Smrg iotype = (bt) GFC_DESCRIPTOR_TYPE (desc);
2512760c2415Smrg size = iotype == BT_CHARACTER ? charlen : GFC_DESCRIPTOR_SIZE (desc);
2513760c2415Smrg
2514760c2415Smrg rank = GFC_DESCRIPTOR_RANK (desc);
2515760c2415Smrg
2516760c2415Smrg for (n = 0; n < rank; n++)
2517760c2415Smrg {
2518760c2415Smrg count[n] = 0;
2519760c2415Smrg stride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(desc,n);
2520760c2415Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(desc,n);
2521760c2415Smrg
2522760c2415Smrg /* If the extent of even one dimension is zero, then the entire
2523760c2415Smrg array section contains zero elements, so we return after writing
2524760c2415Smrg a zero array record. */
2525760c2415Smrg if (extent[n] <= 0)
2526760c2415Smrg {
2527760c2415Smrg data = NULL;
2528760c2415Smrg tsize = 0;
2529760c2415Smrg dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize);
2530760c2415Smrg return;
2531760c2415Smrg }
2532760c2415Smrg }
2533760c2415Smrg
2534760c2415Smrg stride0 = stride[0];
2535760c2415Smrg
2536760c2415Smrg /* If the innermost dimension has a stride of 1, we can do the transfer
2537760c2415Smrg in contiguous chunks. */
2538760c2415Smrg if (stride0 == size)
2539760c2415Smrg tsize = extent[0];
2540760c2415Smrg else
2541760c2415Smrg tsize = 1;
2542760c2415Smrg
2543760c2415Smrg data = GFC_DESCRIPTOR_DATA (desc);
2544760c2415Smrg
2545760c2415Smrg /* When reading, we need to check endfile conditions so we do not miss
2546760c2415Smrg an END=label. Make this separate so we do not have an extra test
2547760c2415Smrg in a tight loop when it is not needed. */
2548760c2415Smrg
2549760c2415Smrg if (dtp->u.p.current_unit && dtp->u.p.mode == READING)
2550760c2415Smrg {
2551760c2415Smrg while (data)
2552760c2415Smrg {
2553760c2415Smrg if (unlikely (dtp->u.p.current_unit->endfile == AFTER_ENDFILE))
2554760c2415Smrg return;
2555760c2415Smrg
2556760c2415Smrg dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize);
2557760c2415Smrg data += stride0 * tsize;
2558760c2415Smrg count[0] += tsize;
2559760c2415Smrg n = 0;
2560760c2415Smrg while (count[n] == extent[n])
2561760c2415Smrg {
2562760c2415Smrg count[n] = 0;
2563760c2415Smrg data -= stride[n] * extent[n];
2564760c2415Smrg n++;
2565760c2415Smrg if (n == rank)
2566760c2415Smrg {
2567760c2415Smrg data = NULL;
2568760c2415Smrg break;
2569760c2415Smrg }
2570760c2415Smrg else
2571760c2415Smrg {
2572760c2415Smrg count[n]++;
2573760c2415Smrg data += stride[n];
2574760c2415Smrg }
2575760c2415Smrg }
2576760c2415Smrg }
2577760c2415Smrg }
2578760c2415Smrg else
2579760c2415Smrg {
2580760c2415Smrg while (data)
2581760c2415Smrg {
2582760c2415Smrg dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize);
2583760c2415Smrg data += stride0 * tsize;
2584760c2415Smrg count[0] += tsize;
2585760c2415Smrg n = 0;
2586760c2415Smrg while (count[n] == extent[n])
2587760c2415Smrg {
2588760c2415Smrg count[n] = 0;
2589760c2415Smrg data -= stride[n] * extent[n];
2590760c2415Smrg n++;
2591760c2415Smrg if (n == rank)
2592760c2415Smrg {
2593760c2415Smrg data = NULL;
2594760c2415Smrg break;
2595760c2415Smrg }
2596760c2415Smrg else
2597760c2415Smrg {
2598760c2415Smrg count[n]++;
2599760c2415Smrg data += stride[n];
2600760c2415Smrg }
2601760c2415Smrg }
2602760c2415Smrg }
2603760c2415Smrg }
2604760c2415Smrg }
2605760c2415Smrg
2606760c2415Smrg void
transfer_array(st_parameter_dt * dtp,gfc_array_char * desc,int kind,gfc_charlen_type charlen)2607760c2415Smrg transfer_array (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
2608760c2415Smrg gfc_charlen_type charlen)
2609760c2415Smrg {
2610760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2611760c2415Smrg return;
2612760c2415Smrg
2613760c2415Smrg if (dtp->u.p.current_unit && dtp->u.p.current_unit->au)
2614760c2415Smrg {
2615760c2415Smrg if (dtp->u.p.async)
2616760c2415Smrg {
2617760c2415Smrg transfer_args args;
2618760c2415Smrg size_t sz = sizeof (gfc_array_char)
2619760c2415Smrg + sizeof (descriptor_dimension)
2620760c2415Smrg * GFC_DESCRIPTOR_RANK (desc);
2621760c2415Smrg args.array.desc = xmalloc (sz);
2622760c2415Smrg NOTE ("desc = %p", (void *) args.array.desc);
2623760c2415Smrg memcpy (args.array.desc, desc, sz);
2624760c2415Smrg args.array.kind = kind;
2625760c2415Smrg args.array.charlen = charlen;
2626760c2415Smrg enqueue_transfer (dtp->u.p.current_unit->au, &args,
2627760c2415Smrg AIO_TRANSFER_ARRAY);
2628760c2415Smrg return;
2629760c2415Smrg }
2630760c2415Smrg }
2631760c2415Smrg /* Come here if there was no asynchronous I/O to be scheduled. */
2632760c2415Smrg transfer_array_inner (dtp, desc, kind, charlen);
2633760c2415Smrg }
2634760c2415Smrg
2635760c2415Smrg
2636760c2415Smrg void
transfer_array_write(st_parameter_dt * dtp,gfc_array_char * desc,int kind,gfc_charlen_type charlen)2637760c2415Smrg transfer_array_write (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
2638760c2415Smrg gfc_charlen_type charlen)
2639760c2415Smrg {
2640760c2415Smrg transfer_array (dtp, desc, kind, charlen);
2641760c2415Smrg }
2642760c2415Smrg
2643760c2415Smrg
2644760c2415Smrg /* User defined input/output iomsg. */
2645760c2415Smrg
2646760c2415Smrg #define IOMSG_LEN 256
2647760c2415Smrg
2648760c2415Smrg void
transfer_derived(st_parameter_dt * parent,void * dtio_source,void * dtio_proc)2649760c2415Smrg transfer_derived (st_parameter_dt *parent, void *dtio_source, void *dtio_proc)
2650760c2415Smrg {
2651760c2415Smrg if (parent->u.p.current_unit)
2652760c2415Smrg {
2653760c2415Smrg if (parent->u.p.current_unit->flags.form == FORM_UNFORMATTED)
2654760c2415Smrg parent->u.p.ufdtio_ptr = (unformatted_dtio) dtio_proc;
2655760c2415Smrg else
2656760c2415Smrg parent->u.p.fdtio_ptr = (formatted_dtio) dtio_proc;
2657760c2415Smrg }
2658760c2415Smrg wrap_scalar_transfer (parent, BT_CLASS, dtio_source, 0, 0, 1);
2659760c2415Smrg }
2660760c2415Smrg
2661760c2415Smrg
2662760c2415Smrg /* Preposition a sequential unformatted file while reading. */
2663760c2415Smrg
2664760c2415Smrg static void
us_read(st_parameter_dt * dtp,int continued)2665760c2415Smrg us_read (st_parameter_dt *dtp, int continued)
2666760c2415Smrg {
2667760c2415Smrg ssize_t n, nr;
2668760c2415Smrg GFC_INTEGER_4 i4;
2669760c2415Smrg GFC_INTEGER_8 i8;
2670760c2415Smrg gfc_offset i;
2671760c2415Smrg
2672760c2415Smrg if (compile_options.record_marker == 0)
2673760c2415Smrg n = sizeof (GFC_INTEGER_4);
2674760c2415Smrg else
2675760c2415Smrg n = compile_options.record_marker;
2676760c2415Smrg
2677760c2415Smrg nr = sread (dtp->u.p.current_unit->s, &i, n);
2678760c2415Smrg if (unlikely (nr < 0))
2679760c2415Smrg {
2680760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
2681760c2415Smrg return;
2682760c2415Smrg }
2683760c2415Smrg else if (nr == 0)
2684760c2415Smrg {
2685760c2415Smrg hit_eof (dtp);
2686760c2415Smrg return; /* end of file */
2687760c2415Smrg }
2688760c2415Smrg else if (unlikely (n != nr))
2689760c2415Smrg {
2690760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
2691760c2415Smrg return;
2692760c2415Smrg }
2693760c2415Smrg
2694760c2415Smrg /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
2695760c2415Smrg if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE))
2696760c2415Smrg {
2697760c2415Smrg switch (nr)
2698760c2415Smrg {
2699760c2415Smrg case sizeof(GFC_INTEGER_4):
2700760c2415Smrg memcpy (&i4, &i, sizeof (i4));
2701760c2415Smrg i = i4;
2702760c2415Smrg break;
2703760c2415Smrg
2704760c2415Smrg case sizeof(GFC_INTEGER_8):
2705760c2415Smrg memcpy (&i8, &i, sizeof (i8));
2706760c2415Smrg i = i8;
2707760c2415Smrg break;
2708760c2415Smrg
2709760c2415Smrg default:
2710760c2415Smrg runtime_error ("Illegal value for record marker");
2711760c2415Smrg break;
2712760c2415Smrg }
2713760c2415Smrg }
2714760c2415Smrg else
2715760c2415Smrg {
2716760c2415Smrg uint32_t u32;
2717760c2415Smrg uint64_t u64;
2718760c2415Smrg switch (nr)
2719760c2415Smrg {
2720760c2415Smrg case sizeof(GFC_INTEGER_4):
2721760c2415Smrg memcpy (&u32, &i, sizeof (u32));
2722760c2415Smrg u32 = __builtin_bswap32 (u32);
2723760c2415Smrg memcpy (&i4, &u32, sizeof (i4));
2724760c2415Smrg i = i4;
2725760c2415Smrg break;
2726760c2415Smrg
2727760c2415Smrg case sizeof(GFC_INTEGER_8):
2728760c2415Smrg memcpy (&u64, &i, sizeof (u64));
2729760c2415Smrg u64 = __builtin_bswap64 (u64);
2730760c2415Smrg memcpy (&i8, &u64, sizeof (i8));
2731760c2415Smrg i = i8;
2732760c2415Smrg break;
2733760c2415Smrg
2734760c2415Smrg default:
2735760c2415Smrg runtime_error ("Illegal value for record marker");
2736760c2415Smrg break;
2737760c2415Smrg }
2738760c2415Smrg }
2739760c2415Smrg
2740760c2415Smrg if (i >= 0)
2741760c2415Smrg {
2742760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord = i;
2743760c2415Smrg dtp->u.p.current_unit->continued = 0;
2744760c2415Smrg }
2745760c2415Smrg else
2746760c2415Smrg {
2747760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord = -i;
2748760c2415Smrg dtp->u.p.current_unit->continued = 1;
2749760c2415Smrg }
2750760c2415Smrg
2751760c2415Smrg if (! continued)
2752760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
2753760c2415Smrg }
2754760c2415Smrg
2755760c2415Smrg
2756760c2415Smrg /* Preposition a sequential unformatted file while writing. This
2757760c2415Smrg amount to writing a bogus length that will be filled in later. */
2758760c2415Smrg
2759760c2415Smrg static void
us_write(st_parameter_dt * dtp,int continued)2760760c2415Smrg us_write (st_parameter_dt *dtp, int continued)
2761760c2415Smrg {
2762760c2415Smrg ssize_t nbytes;
2763760c2415Smrg gfc_offset dummy;
2764760c2415Smrg
2765760c2415Smrg dummy = 0;
2766760c2415Smrg
2767760c2415Smrg if (compile_options.record_marker == 0)
2768760c2415Smrg nbytes = sizeof (GFC_INTEGER_4);
2769760c2415Smrg else
2770760c2415Smrg nbytes = compile_options.record_marker ;
2771760c2415Smrg
2772760c2415Smrg if (swrite (dtp->u.p.current_unit->s, &dummy, nbytes) != nbytes)
2773760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
2774760c2415Smrg
2775760c2415Smrg /* For sequential unformatted, if RECL= was not specified in the OPEN
2776760c2415Smrg we write until we have more bytes than can fit in the subrecord
2777760c2415Smrg markers, then we write a new subrecord. */
2778760c2415Smrg
2779760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord =
2780760c2415Smrg dtp->u.p.current_unit->recl_subrecord;
2781760c2415Smrg dtp->u.p.current_unit->continued = continued;
2782760c2415Smrg }
2783760c2415Smrg
2784760c2415Smrg
2785760c2415Smrg /* Position to the next record prior to transfer. We are assumed to
2786760c2415Smrg be before the next record. We also calculate the bytes in the next
2787760c2415Smrg record. */
2788760c2415Smrg
2789760c2415Smrg static void
pre_position(st_parameter_dt * dtp)2790760c2415Smrg pre_position (st_parameter_dt *dtp)
2791760c2415Smrg {
2792760c2415Smrg if (dtp->u.p.current_unit->current_record)
2793760c2415Smrg return; /* Already positioned. */
2794760c2415Smrg
2795760c2415Smrg switch (current_mode (dtp))
2796760c2415Smrg {
2797760c2415Smrg case FORMATTED_STREAM:
2798760c2415Smrg case UNFORMATTED_STREAM:
2799760c2415Smrg /* There are no records with stream I/O. If the position was specified
2800760c2415Smrg data_transfer_init has already positioned the file. If no position
2801760c2415Smrg was specified, we continue from where we last left off. I.e.
2802760c2415Smrg there is nothing to do here. */
2803760c2415Smrg break;
2804760c2415Smrg
2805760c2415Smrg case UNFORMATTED_SEQUENTIAL:
2806760c2415Smrg if (dtp->u.p.mode == READING)
2807760c2415Smrg us_read (dtp, 0);
2808760c2415Smrg else
2809760c2415Smrg us_write (dtp, 0);
2810760c2415Smrg
2811760c2415Smrg break;
2812760c2415Smrg
2813760c2415Smrg case FORMATTED_SEQUENTIAL:
2814760c2415Smrg case FORMATTED_DIRECT:
2815760c2415Smrg case UNFORMATTED_DIRECT:
2816760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
2817760c2415Smrg break;
2818*0bfacb9bSmrg case FORMATTED_UNSPECIFIED:
2819*0bfacb9bSmrg gcc_unreachable ();
2820760c2415Smrg }
2821760c2415Smrg
2822760c2415Smrg dtp->u.p.current_unit->current_record = 1;
2823760c2415Smrg }
2824760c2415Smrg
2825760c2415Smrg
2826760c2415Smrg /* Initialize things for a data transfer. This code is common for
2827760c2415Smrg both reading and writing. */
2828760c2415Smrg
2829760c2415Smrg static void
data_transfer_init(st_parameter_dt * dtp,int read_flag)2830760c2415Smrg data_transfer_init (st_parameter_dt *dtp, int read_flag)
2831760c2415Smrg {
2832760c2415Smrg unit_flags u_flags; /* Used for creating a unit if needed. */
2833760c2415Smrg GFC_INTEGER_4 cf = dtp->common.flags;
2834760c2415Smrg namelist_info *ionml;
2835760c2415Smrg async_unit *au;
2836760c2415Smrg
2837760c2415Smrg NOTE ("data_transfer_init");
2838760c2415Smrg
2839760c2415Smrg ionml = ((cf & IOPARM_DT_IONML_SET) != 0) ? dtp->u.p.ionml : NULL;
2840760c2415Smrg
2841760c2415Smrg memset (&dtp->u.p, 0, sizeof (dtp->u.p));
2842760c2415Smrg
2843760c2415Smrg dtp->u.p.ionml = ionml;
2844760c2415Smrg dtp->u.p.mode = read_flag ? READING : WRITING;
2845760c2415Smrg dtp->u.p.namelist_mode = 0;
2846760c2415Smrg dtp->u.p.cc.len = 0;
2847760c2415Smrg
2848760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
2849760c2415Smrg return;
2850760c2415Smrg
2851760c2415Smrg dtp->u.p.current_unit = get_unit (dtp, 1);
2852760c2415Smrg
2853760c2415Smrg if (dtp->u.p.current_unit == NULL)
2854760c2415Smrg {
2855760c2415Smrg /* This means we tried to access an external unit < 0 without
2856760c2415Smrg having opened it first with NEWUNIT=. */
2857760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
2858760c2415Smrg "Unit number is negative and unit was not already "
2859760c2415Smrg "opened with OPEN(NEWUNIT=...)");
2860760c2415Smrg return;
2861760c2415Smrg }
2862760c2415Smrg else if (dtp->u.p.current_unit->s == NULL)
2863760c2415Smrg { /* Open the unit with some default flags. */
2864760c2415Smrg st_parameter_open opp;
2865760c2415Smrg unit_convert conv;
2866760c2415Smrg NOTE ("Open the unit with some default flags.");
2867760c2415Smrg memset (&u_flags, '\0', sizeof (u_flags));
2868760c2415Smrg u_flags.access = ACCESS_SEQUENTIAL;
2869760c2415Smrg u_flags.action = ACTION_READWRITE;
2870760c2415Smrg
2871760c2415Smrg /* Is it unformatted? */
2872760c2415Smrg if (!(cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT
2873760c2415Smrg | IOPARM_DT_IONML_SET)))
2874760c2415Smrg u_flags.form = FORM_UNFORMATTED;
2875760c2415Smrg else
2876760c2415Smrg u_flags.form = FORM_UNSPECIFIED;
2877760c2415Smrg
2878760c2415Smrg u_flags.delim = DELIM_UNSPECIFIED;
2879760c2415Smrg u_flags.blank = BLANK_UNSPECIFIED;
2880760c2415Smrg u_flags.pad = PAD_UNSPECIFIED;
2881760c2415Smrg u_flags.decimal = DECIMAL_UNSPECIFIED;
2882760c2415Smrg u_flags.encoding = ENCODING_UNSPECIFIED;
2883760c2415Smrg u_flags.async = ASYNC_UNSPECIFIED;
2884760c2415Smrg u_flags.round = ROUND_UNSPECIFIED;
2885760c2415Smrg u_flags.sign = SIGN_UNSPECIFIED;
2886760c2415Smrg u_flags.share = SHARE_UNSPECIFIED;
2887760c2415Smrg u_flags.cc = CC_UNSPECIFIED;
2888760c2415Smrg u_flags.readonly = 0;
2889760c2415Smrg
2890760c2415Smrg u_flags.status = STATUS_UNKNOWN;
2891760c2415Smrg
2892760c2415Smrg conv = get_unformatted_convert (dtp->common.unit);
2893760c2415Smrg
2894760c2415Smrg if (conv == GFC_CONVERT_NONE)
2895760c2415Smrg conv = compile_options.convert;
2896760c2415Smrg
2897760c2415Smrg switch (conv)
2898760c2415Smrg {
2899760c2415Smrg case GFC_CONVERT_NATIVE:
2900760c2415Smrg case GFC_CONVERT_SWAP:
2901760c2415Smrg break;
2902760c2415Smrg
2903760c2415Smrg case GFC_CONVERT_BIG:
2904760c2415Smrg conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
2905760c2415Smrg break;
2906760c2415Smrg
2907760c2415Smrg case GFC_CONVERT_LITTLE:
2908760c2415Smrg conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
2909760c2415Smrg break;
2910760c2415Smrg
2911760c2415Smrg default:
2912760c2415Smrg internal_error (&opp.common, "Illegal value for CONVERT");
2913760c2415Smrg break;
2914760c2415Smrg }
2915760c2415Smrg
2916760c2415Smrg u_flags.convert = conv;
2917760c2415Smrg
2918760c2415Smrg opp.common = dtp->common;
2919760c2415Smrg opp.common.flags &= IOPARM_COMMON_MASK;
2920760c2415Smrg dtp->u.p.current_unit = new_unit (&opp, dtp->u.p.current_unit, &u_flags);
2921760c2415Smrg dtp->common.flags &= ~IOPARM_COMMON_MASK;
2922760c2415Smrg dtp->common.flags |= (opp.common.flags & IOPARM_COMMON_MASK);
2923760c2415Smrg if (dtp->u.p.current_unit == NULL)
2924760c2415Smrg return;
2925760c2415Smrg }
2926760c2415Smrg
2927760c2415Smrg if (dtp->u.p.current_unit->child_dtio == 0)
2928760c2415Smrg {
2929760c2415Smrg if ((cf & IOPARM_DT_HAS_SIZE) != 0)
2930760c2415Smrg {
2931760c2415Smrg dtp->u.p.current_unit->has_size = true;
2932760c2415Smrg /* Initialize the count. */
2933760c2415Smrg dtp->u.p.current_unit->size_used = 0;
2934760c2415Smrg }
2935760c2415Smrg else
2936760c2415Smrg dtp->u.p.current_unit->has_size = false;
2937760c2415Smrg }
2938760c2415Smrg else if (dtp->u.p.current_unit->internal_unit_kind > 0)
2939760c2415Smrg dtp->u.p.unit_is_internal = 1;
2940760c2415Smrg
2941760c2415Smrg if ((cf & IOPARM_DT_HAS_ASYNCHRONOUS) != 0)
2942760c2415Smrg {
2943760c2415Smrg int f;
2944760c2415Smrg f = find_option (&dtp->common, dtp->asynchronous, dtp->asynchronous_len,
2945760c2415Smrg async_opt, "Bad ASYNCHRONOUS in data transfer "
2946760c2415Smrg "statement");
2947760c2415Smrg if (f == ASYNC_YES && dtp->u.p.current_unit->flags.async != ASYNC_YES)
2948760c2415Smrg {
2949760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
2950760c2415Smrg "ASYNCHRONOUS transfer without "
2951760c2415Smrg "ASYHCRONOUS='YES' in OPEN");
2952760c2415Smrg return;
2953760c2415Smrg }
2954760c2415Smrg dtp->u.p.async = f == ASYNC_YES;
2955760c2415Smrg }
2956760c2415Smrg
2957760c2415Smrg au = dtp->u.p.current_unit->au;
2958760c2415Smrg if (au)
2959760c2415Smrg {
2960760c2415Smrg if (dtp->u.p.async)
2961760c2415Smrg {
2962760c2415Smrg /* If this is an asynchronous I/O statement, collect errors and
2963760c2415Smrg return if there are any. */
2964760c2415Smrg if (collect_async_errors (&dtp->common, au))
2965760c2415Smrg return;
2966760c2415Smrg }
2967760c2415Smrg else
2968760c2415Smrg {
2969760c2415Smrg /* Synchronous statement: Perform a wait operation for any pending
2970760c2415Smrg asynchronous I/O. This needs to be done before all other error
2971760c2415Smrg checks. See F2008, 9.6.4.1. */
2972760c2415Smrg if (async_wait (&(dtp->common), au))
2973760c2415Smrg return;
2974760c2415Smrg }
2975760c2415Smrg }
2976760c2415Smrg
2977760c2415Smrg /* Check the action. */
2978760c2415Smrg
2979760c2415Smrg if (read_flag && dtp->u.p.current_unit->flags.action == ACTION_WRITE)
2980760c2415Smrg {
2981760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_ACTION,
2982760c2415Smrg "Cannot read from file opened for WRITE");
2983760c2415Smrg return;
2984760c2415Smrg }
2985760c2415Smrg
2986760c2415Smrg if (!read_flag && dtp->u.p.current_unit->flags.action == ACTION_READ)
2987760c2415Smrg {
2988760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_ACTION,
2989760c2415Smrg "Cannot write to file opened for READ");
2990760c2415Smrg return;
2991760c2415Smrg }
2992760c2415Smrg
2993760c2415Smrg dtp->u.p.first_item = 1;
2994760c2415Smrg
2995760c2415Smrg /* Check the format. */
2996760c2415Smrg
2997760c2415Smrg if ((cf & IOPARM_DT_HAS_FORMAT) != 0)
2998760c2415Smrg parse_format (dtp);
2999760c2415Smrg
3000760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED
3001760c2415Smrg && (cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT))
3002760c2415Smrg != 0)
3003760c2415Smrg {
3004760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3005760c2415Smrg "Format present for UNFORMATTED data transfer");
3006760c2415Smrg return;
3007760c2415Smrg }
3008760c2415Smrg
3009760c2415Smrg if ((cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0 && dtp->u.p.ionml != NULL)
3010760c2415Smrg {
3011760c2415Smrg if ((cf & IOPARM_DT_HAS_FORMAT) != 0)
3012760c2415Smrg {
3013760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3014760c2415Smrg "A format cannot be specified with a namelist");
3015760c2415Smrg return;
3016760c2415Smrg }
3017760c2415Smrg }
3018760c2415Smrg else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED &&
3019760c2415Smrg !(cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT)))
3020760c2415Smrg {
3021760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3022760c2415Smrg "Missing format for FORMATTED data transfer");
3023760c2415Smrg return;
3024760c2415Smrg }
3025760c2415Smrg
3026760c2415Smrg if (is_internal_unit (dtp)
3027760c2415Smrg && dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
3028760c2415Smrg {
3029760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3030760c2415Smrg "Internal file cannot be accessed by UNFORMATTED "
3031760c2415Smrg "data transfer");
3032760c2415Smrg return;
3033760c2415Smrg }
3034760c2415Smrg
3035760c2415Smrg /* Check the record or position number. */
3036760c2415Smrg
3037760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT
3038760c2415Smrg && (cf & IOPARM_DT_HAS_REC) == 0)
3039760c2415Smrg {
3040760c2415Smrg generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
3041760c2415Smrg "Direct access data transfer requires record number");
3042760c2415Smrg return;
3043760c2415Smrg }
3044760c2415Smrg
3045760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
3046760c2415Smrg {
3047760c2415Smrg if ((cf & IOPARM_DT_HAS_REC) != 0)
3048760c2415Smrg {
3049760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3050760c2415Smrg "Record number not allowed for sequential access "
3051760c2415Smrg "data transfer");
3052760c2415Smrg return;
3053760c2415Smrg }
3054760c2415Smrg
3055760c2415Smrg if (compile_options.warn_std &&
3056760c2415Smrg dtp->u.p.current_unit->endfile == AFTER_ENDFILE)
3057760c2415Smrg {
3058760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3059760c2415Smrg "Sequential READ or WRITE not allowed after "
3060760c2415Smrg "EOF marker, possibly use REWIND or BACKSPACE");
3061760c2415Smrg return;
3062760c2415Smrg }
3063760c2415Smrg }
3064760c2415Smrg
3065760c2415Smrg /* Process the ADVANCE option. */
3066760c2415Smrg
3067760c2415Smrg dtp->u.p.advance_status
3068760c2415Smrg = !(cf & IOPARM_DT_HAS_ADVANCE) ? ADVANCE_UNSPECIFIED :
3069760c2415Smrg find_option (&dtp->common, dtp->advance, dtp->advance_len, advance_opt,
3070760c2415Smrg "Bad ADVANCE parameter in data transfer statement");
3071760c2415Smrg
3072760c2415Smrg if (dtp->u.p.advance_status != ADVANCE_UNSPECIFIED)
3073760c2415Smrg {
3074760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
3075760c2415Smrg {
3076760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3077760c2415Smrg "ADVANCE specification conflicts with sequential "
3078760c2415Smrg "access");
3079760c2415Smrg return;
3080760c2415Smrg }
3081760c2415Smrg
3082760c2415Smrg if (is_internal_unit (dtp))
3083760c2415Smrg {
3084760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3085760c2415Smrg "ADVANCE specification conflicts with internal file");
3086760c2415Smrg return;
3087760c2415Smrg }
3088760c2415Smrg
3089760c2415Smrg if ((cf & (IOPARM_DT_HAS_FORMAT | IOPARM_DT_LIST_FORMAT))
3090760c2415Smrg != IOPARM_DT_HAS_FORMAT)
3091760c2415Smrg {
3092760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3093760c2415Smrg "ADVANCE specification requires an explicit format");
3094760c2415Smrg return;
3095760c2415Smrg }
3096760c2415Smrg }
3097760c2415Smrg
3098760c2415Smrg /* Child IO is non-advancing and any ADVANCE= specifier is ignored.
3099760c2415Smrg F2008 9.6.2.4 */
3100760c2415Smrg if (dtp->u.p.current_unit->child_dtio > 0)
3101760c2415Smrg dtp->u.p.advance_status = ADVANCE_NO;
3102760c2415Smrg
3103760c2415Smrg if (read_flag)
3104760c2415Smrg {
3105760c2415Smrg dtp->u.p.current_unit->previous_nonadvancing_write = 0;
3106760c2415Smrg
3107760c2415Smrg if ((cf & IOPARM_EOR) != 0 && dtp->u.p.advance_status != ADVANCE_NO)
3108760c2415Smrg {
3109760c2415Smrg generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
3110760c2415Smrg "EOR specification requires an ADVANCE specification "
3111760c2415Smrg "of NO");
3112760c2415Smrg return;
3113760c2415Smrg }
3114760c2415Smrg
3115760c2415Smrg if ((cf & IOPARM_DT_HAS_SIZE) != 0
3116760c2415Smrg && dtp->u.p.advance_status != ADVANCE_NO)
3117760c2415Smrg {
3118760c2415Smrg generate_error (&dtp->common, LIBERROR_MISSING_OPTION,
3119760c2415Smrg "SIZE specification requires an ADVANCE "
3120760c2415Smrg "specification of NO");
3121760c2415Smrg return;
3122760c2415Smrg }
3123760c2415Smrg }
3124760c2415Smrg else
3125760c2415Smrg { /* Write constraints. */
3126760c2415Smrg if ((cf & IOPARM_END) != 0)
3127760c2415Smrg {
3128760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3129760c2415Smrg "END specification cannot appear in a write "
3130760c2415Smrg "statement");
3131760c2415Smrg return;
3132760c2415Smrg }
3133760c2415Smrg
3134760c2415Smrg if ((cf & IOPARM_EOR) != 0)
3135760c2415Smrg {
3136760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3137760c2415Smrg "EOR specification cannot appear in a write "
3138760c2415Smrg "statement");
3139760c2415Smrg return;
3140760c2415Smrg }
3141760c2415Smrg
3142760c2415Smrg if ((cf & IOPARM_DT_HAS_SIZE) != 0)
3143760c2415Smrg {
3144760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3145760c2415Smrg "SIZE specification cannot appear in a write "
3146760c2415Smrg "statement");
3147760c2415Smrg return;
3148760c2415Smrg }
3149760c2415Smrg }
3150760c2415Smrg
3151760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_UNSPECIFIED)
3152760c2415Smrg dtp->u.p.advance_status = ADVANCE_YES;
3153760c2415Smrg
3154760c2415Smrg /* Check the decimal mode. */
3155760c2415Smrg dtp->u.p.current_unit->decimal_status
3156760c2415Smrg = !(cf & IOPARM_DT_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
3157760c2415Smrg find_option (&dtp->common, dtp->decimal, dtp->decimal_len,
3158760c2415Smrg decimal_opt, "Bad DECIMAL parameter in data transfer "
3159760c2415Smrg "statement");
3160760c2415Smrg
3161760c2415Smrg if (dtp->u.p.current_unit->decimal_status == DECIMAL_UNSPECIFIED)
3162760c2415Smrg dtp->u.p.current_unit->decimal_status = dtp->u.p.current_unit->flags.decimal;
3163760c2415Smrg
3164760c2415Smrg /* Check the round mode. */
3165760c2415Smrg dtp->u.p.current_unit->round_status
3166760c2415Smrg = !(cf & IOPARM_DT_HAS_ROUND) ? ROUND_UNSPECIFIED :
3167760c2415Smrg find_option (&dtp->common, dtp->round, dtp->round_len,
3168760c2415Smrg round_opt, "Bad ROUND parameter in data transfer "
3169760c2415Smrg "statement");
3170760c2415Smrg
3171760c2415Smrg if (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED)
3172760c2415Smrg dtp->u.p.current_unit->round_status = dtp->u.p.current_unit->flags.round;
3173760c2415Smrg
3174760c2415Smrg /* Check the sign mode. */
3175760c2415Smrg dtp->u.p.sign_status
3176760c2415Smrg = !(cf & IOPARM_DT_HAS_SIGN) ? SIGN_UNSPECIFIED :
3177760c2415Smrg find_option (&dtp->common, dtp->sign, dtp->sign_len, sign_opt,
3178760c2415Smrg "Bad SIGN parameter in data transfer statement");
3179760c2415Smrg
3180760c2415Smrg if (dtp->u.p.sign_status == SIGN_UNSPECIFIED)
3181760c2415Smrg dtp->u.p.sign_status = dtp->u.p.current_unit->flags.sign;
3182760c2415Smrg
3183760c2415Smrg /* Check the blank mode. */
3184760c2415Smrg dtp->u.p.blank_status
3185760c2415Smrg = !(cf & IOPARM_DT_HAS_BLANK) ? BLANK_UNSPECIFIED :
3186760c2415Smrg find_option (&dtp->common, dtp->blank, dtp->blank_len,
3187760c2415Smrg blank_opt,
3188760c2415Smrg "Bad BLANK parameter in data transfer statement");
3189760c2415Smrg
3190760c2415Smrg if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
3191760c2415Smrg dtp->u.p.blank_status = dtp->u.p.current_unit->flags.blank;
3192760c2415Smrg
3193760c2415Smrg /* Check the delim mode. */
3194760c2415Smrg dtp->u.p.current_unit->delim_status
3195760c2415Smrg = !(cf & IOPARM_DT_HAS_DELIM) ? DELIM_UNSPECIFIED :
3196760c2415Smrg find_option (&dtp->common, dtp->delim, dtp->delim_len,
3197760c2415Smrg delim_opt, "Bad DELIM parameter in data transfer statement");
3198760c2415Smrg
3199760c2415Smrg if (dtp->u.p.current_unit->delim_status == DELIM_UNSPECIFIED)
3200760c2415Smrg {
3201760c2415Smrg if (ionml && dtp->u.p.current_unit->flags.delim == DELIM_UNSPECIFIED)
3202760c2415Smrg dtp->u.p.current_unit->delim_status = DELIM_QUOTE;
3203760c2415Smrg else
3204760c2415Smrg dtp->u.p.current_unit->delim_status = dtp->u.p.current_unit->flags.delim;
3205760c2415Smrg }
3206760c2415Smrg
3207760c2415Smrg /* Check the pad mode. */
3208760c2415Smrg dtp->u.p.current_unit->pad_status
3209760c2415Smrg = !(cf & IOPARM_DT_HAS_PAD) ? PAD_UNSPECIFIED :
3210760c2415Smrg find_option (&dtp->common, dtp->pad, dtp->pad_len, pad_opt,
3211760c2415Smrg "Bad PAD parameter in data transfer statement");
3212760c2415Smrg
3213760c2415Smrg if (dtp->u.p.current_unit->pad_status == PAD_UNSPECIFIED)
3214760c2415Smrg dtp->u.p.current_unit->pad_status = dtp->u.p.current_unit->flags.pad;
3215760c2415Smrg
3216760c2415Smrg /* Set up the subroutine that will handle the transfers. */
3217760c2415Smrg
3218760c2415Smrg if (read_flag)
3219760c2415Smrg {
3220760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
3221760c2415Smrg dtp->u.p.transfer = unformatted_read;
3222760c2415Smrg else
3223760c2415Smrg {
3224760c2415Smrg if ((cf & IOPARM_DT_LIST_FORMAT) != 0)
3225760c2415Smrg dtp->u.p.transfer = list_formatted_read;
3226760c2415Smrg else
3227760c2415Smrg dtp->u.p.transfer = formatted_transfer;
3228760c2415Smrg }
3229760c2415Smrg }
3230760c2415Smrg else
3231760c2415Smrg {
3232760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED)
3233760c2415Smrg dtp->u.p.transfer = unformatted_write;
3234760c2415Smrg else
3235760c2415Smrg {
3236760c2415Smrg if ((cf & IOPARM_DT_LIST_FORMAT) != 0)
3237760c2415Smrg dtp->u.p.transfer = list_formatted_write;
3238760c2415Smrg else
3239760c2415Smrg dtp->u.p.transfer = formatted_transfer;
3240760c2415Smrg }
3241760c2415Smrg }
3242760c2415Smrg
3243760c2415Smrg if (au && dtp->u.p.async)
3244760c2415Smrg {
3245760c2415Smrg NOTE ("enqueue_data_transfer");
3246760c2415Smrg enqueue_data_transfer_init (au, dtp, read_flag);
3247760c2415Smrg }
3248760c2415Smrg else
3249760c2415Smrg {
3250760c2415Smrg NOTE ("invoking data_transfer_init_worker");
3251760c2415Smrg data_transfer_init_worker (dtp, read_flag);
3252760c2415Smrg }
3253760c2415Smrg }
3254760c2415Smrg
3255760c2415Smrg void
data_transfer_init_worker(st_parameter_dt * dtp,int read_flag)3256760c2415Smrg data_transfer_init_worker (st_parameter_dt *dtp, int read_flag)
3257760c2415Smrg {
3258760c2415Smrg GFC_INTEGER_4 cf = dtp->common.flags;
3259760c2415Smrg
3260760c2415Smrg NOTE ("starting worker...");
3261760c2415Smrg
3262760c2415Smrg if (read_flag && dtp->u.p.current_unit->flags.form != FORM_UNFORMATTED
3263760c2415Smrg && ((cf & IOPARM_DT_LIST_FORMAT) != 0)
3264760c2415Smrg && dtp->u.p.current_unit->child_dtio == 0)
3265760c2415Smrg dtp->u.p.current_unit->last_char = EOF - 1;
3266760c2415Smrg
3267760c2415Smrg /* Check to see if we might be reading what we wrote before */
3268760c2415Smrg
3269760c2415Smrg if (dtp->u.p.mode != dtp->u.p.current_unit->mode
3270760c2415Smrg && !is_internal_unit (dtp))
3271760c2415Smrg {
3272760c2415Smrg int pos = fbuf_reset (dtp->u.p.current_unit);
3273760c2415Smrg if (pos != 0)
3274760c2415Smrg sseek (dtp->u.p.current_unit->s, pos, SEEK_CUR);
3275760c2415Smrg sflush(dtp->u.p.current_unit->s);
3276760c2415Smrg }
3277760c2415Smrg
3278760c2415Smrg /* Check the POS= specifier: that it is in range and that it is used with a
3279760c2415Smrg unit that has been connected for STREAM access. F2003 9.5.1.10. */
3280760c2415Smrg
3281760c2415Smrg if (((cf & IOPARM_DT_HAS_POS) != 0))
3282760c2415Smrg {
3283760c2415Smrg if (is_stream_io (dtp))
3284760c2415Smrg {
3285760c2415Smrg
3286760c2415Smrg if (dtp->pos <= 0)
3287760c2415Smrg {
3288760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3289760c2415Smrg "POS=specifier must be positive");
3290760c2415Smrg return;
3291760c2415Smrg }
3292760c2415Smrg
3293760c2415Smrg if (dtp->pos >= dtp->u.p.current_unit->maxrec)
3294760c2415Smrg {
3295760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3296760c2415Smrg "POS=specifier too large");
3297760c2415Smrg return;
3298760c2415Smrg }
3299760c2415Smrg
3300760c2415Smrg dtp->rec = dtp->pos;
3301760c2415Smrg
3302760c2415Smrg if (dtp->u.p.mode == READING)
3303760c2415Smrg {
3304760c2415Smrg /* Reset the endfile flag; if we hit EOF during reading
3305760c2415Smrg we'll set the flag and generate an error at that point
3306760c2415Smrg rather than worrying about it here. */
3307760c2415Smrg dtp->u.p.current_unit->endfile = NO_ENDFILE;
3308760c2415Smrg }
3309760c2415Smrg
3310760c2415Smrg if (dtp->pos != dtp->u.p.current_unit->strm_pos)
3311760c2415Smrg {
3312760c2415Smrg fbuf_reset (dtp->u.p.current_unit);
3313760c2415Smrg if (sseek (dtp->u.p.current_unit->s, dtp->pos - 1,
3314760c2415Smrg SEEK_SET) < 0)
3315760c2415Smrg {
3316760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3317760c2415Smrg return;
3318760c2415Smrg }
3319760c2415Smrg dtp->u.p.current_unit->strm_pos = dtp->pos;
3320760c2415Smrg }
3321760c2415Smrg }
3322760c2415Smrg else
3323760c2415Smrg {
3324760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3325760c2415Smrg "POS=specifier not allowed, "
3326760c2415Smrg "Try OPEN with ACCESS='stream'");
3327760c2415Smrg return;
3328760c2415Smrg }
3329760c2415Smrg }
3330760c2415Smrg
3331760c2415Smrg
3332760c2415Smrg /* Sanity checks on the record number. */
3333760c2415Smrg if ((cf & IOPARM_DT_HAS_REC) != 0)
3334760c2415Smrg {
3335760c2415Smrg if (dtp->rec <= 0)
3336760c2415Smrg {
3337760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3338760c2415Smrg "Record number must be positive");
3339760c2415Smrg return;
3340760c2415Smrg }
3341760c2415Smrg
3342760c2415Smrg if (dtp->rec >= dtp->u.p.current_unit->maxrec)
3343760c2415Smrg {
3344760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3345760c2415Smrg "Record number too large");
3346760c2415Smrg return;
3347760c2415Smrg }
3348760c2415Smrg
3349760c2415Smrg /* Make sure format buffer is reset. */
3350760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
3351760c2415Smrg fbuf_reset (dtp->u.p.current_unit);
3352760c2415Smrg
3353760c2415Smrg
3354760c2415Smrg /* Check whether the record exists to be read. Only
3355760c2415Smrg a partial record needs to exist. */
3356760c2415Smrg
3357760c2415Smrg if (dtp->u.p.mode == READING && (dtp->rec - 1)
3358760c2415Smrg * dtp->u.p.current_unit->recl >= ssize (dtp->u.p.current_unit->s))
3359760c2415Smrg {
3360760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3361760c2415Smrg "Non-existing record number");
3362760c2415Smrg return;
3363760c2415Smrg }
3364760c2415Smrg
3365760c2415Smrg /* Position the file. */
3366760c2415Smrg if (sseek (dtp->u.p.current_unit->s, (gfc_offset) (dtp->rec - 1)
3367760c2415Smrg * dtp->u.p.current_unit->recl, SEEK_SET) < 0)
3368760c2415Smrg {
3369760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3370760c2415Smrg return;
3371760c2415Smrg }
3372760c2415Smrg
3373760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM)
3374760c2415Smrg {
3375760c2415Smrg generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
3376760c2415Smrg "Record number not allowed for stream access "
3377760c2415Smrg "data transfer");
3378760c2415Smrg return;
3379760c2415Smrg }
3380760c2415Smrg }
3381760c2415Smrg
3382760c2415Smrg /* Bugware for badly written mixed C-Fortran I/O. */
3383760c2415Smrg if (!is_internal_unit (dtp))
3384760c2415Smrg flush_if_preconnected(dtp->u.p.current_unit->s);
3385760c2415Smrg
3386760c2415Smrg dtp->u.p.current_unit->mode = dtp->u.p.mode;
3387760c2415Smrg
3388760c2415Smrg /* Set the maximum position reached from the previous I/O operation. This
3389760c2415Smrg could be greater than zero from a previous non-advancing write. */
3390760c2415Smrg dtp->u.p.max_pos = dtp->u.p.current_unit->saved_pos;
3391760c2415Smrg
3392760c2415Smrg pre_position (dtp);
3393760c2415Smrg
3394760c2415Smrg /* Make sure that we don't do a read after a nonadvancing write. */
3395760c2415Smrg
3396760c2415Smrg if (read_flag)
3397760c2415Smrg {
3398760c2415Smrg if (dtp->u.p.current_unit->read_bad && !is_stream_io (dtp))
3399760c2415Smrg {
3400760c2415Smrg generate_error (&dtp->common, LIBERROR_BAD_OPTION,
3401760c2415Smrg "Cannot READ after a nonadvancing WRITE");
3402760c2415Smrg return;
3403760c2415Smrg }
3404760c2415Smrg }
3405760c2415Smrg else
3406760c2415Smrg {
3407760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_YES && !dtp->u.p.seen_dollar)
3408760c2415Smrg dtp->u.p.current_unit->read_bad = 1;
3409760c2415Smrg }
3410760c2415Smrg
3411760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
3412760c2415Smrg {
3413760c2415Smrg #ifdef HAVE_USELOCALE
3414760c2415Smrg dtp->u.p.old_locale = uselocale (c_locale);
3415760c2415Smrg #else
3416760c2415Smrg __gthread_mutex_lock (&old_locale_lock);
3417760c2415Smrg if (!old_locale_ctr++)
3418760c2415Smrg {
3419760c2415Smrg old_locale = setlocale (LC_NUMERIC, NULL);
3420760c2415Smrg setlocale (LC_NUMERIC, "C");
3421760c2415Smrg }
3422760c2415Smrg __gthread_mutex_unlock (&old_locale_lock);
3423760c2415Smrg #endif
3424760c2415Smrg /* Start the data transfer if we are doing a formatted transfer. */
3425760c2415Smrg if ((cf & (IOPARM_DT_LIST_FORMAT | IOPARM_DT_HAS_NAMELIST_NAME)) == 0
3426760c2415Smrg && dtp->u.p.ionml == NULL)
3427760c2415Smrg formatted_transfer (dtp, 0, NULL, 0, 0, 1);
3428760c2415Smrg }
3429760c2415Smrg }
3430760c2415Smrg
3431760c2415Smrg
3432760c2415Smrg /* Initialize an array_loop_spec given the array descriptor. The function
3433760c2415Smrg returns the index of the last element of the array, and also returns
3434760c2415Smrg starting record, where the first I/O goes to (necessary in case of
3435760c2415Smrg negative strides). */
3436760c2415Smrg
3437760c2415Smrg gfc_offset
init_loop_spec(gfc_array_char * desc,array_loop_spec * ls,gfc_offset * start_record)3438760c2415Smrg init_loop_spec (gfc_array_char *desc, array_loop_spec *ls,
3439760c2415Smrg gfc_offset *start_record)
3440760c2415Smrg {
3441760c2415Smrg int rank = GFC_DESCRIPTOR_RANK(desc);
3442760c2415Smrg int i;
3443760c2415Smrg gfc_offset index;
3444760c2415Smrg int empty;
3445760c2415Smrg
3446760c2415Smrg empty = 0;
3447760c2415Smrg index = 1;
3448760c2415Smrg *start_record = 0;
3449760c2415Smrg
3450760c2415Smrg for (i=0; i<rank; i++)
3451760c2415Smrg {
3452760c2415Smrg ls[i].idx = GFC_DESCRIPTOR_LBOUND(desc,i);
3453760c2415Smrg ls[i].start = GFC_DESCRIPTOR_LBOUND(desc,i);
3454760c2415Smrg ls[i].end = GFC_DESCRIPTOR_UBOUND(desc,i);
3455760c2415Smrg ls[i].step = GFC_DESCRIPTOR_STRIDE(desc,i);
3456760c2415Smrg empty = empty || (GFC_DESCRIPTOR_UBOUND(desc,i)
3457760c2415Smrg < GFC_DESCRIPTOR_LBOUND(desc,i));
3458760c2415Smrg
3459760c2415Smrg if (GFC_DESCRIPTOR_STRIDE(desc,i) > 0)
3460760c2415Smrg {
3461760c2415Smrg index += (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
3462760c2415Smrg * GFC_DESCRIPTOR_STRIDE(desc,i);
3463760c2415Smrg }
3464760c2415Smrg else
3465760c2415Smrg {
3466760c2415Smrg index -= (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
3467760c2415Smrg * GFC_DESCRIPTOR_STRIDE(desc,i);
3468760c2415Smrg *start_record -= (GFC_DESCRIPTOR_EXTENT(desc,i) - 1)
3469760c2415Smrg * GFC_DESCRIPTOR_STRIDE(desc,i);
3470760c2415Smrg }
3471760c2415Smrg }
3472760c2415Smrg
3473760c2415Smrg if (empty)
3474760c2415Smrg return 0;
3475760c2415Smrg else
3476760c2415Smrg return index;
3477760c2415Smrg }
3478760c2415Smrg
3479760c2415Smrg /* Determine the index to the next record in an internal unit array by
3480760c2415Smrg by incrementing through the array_loop_spec. */
3481760c2415Smrg
3482760c2415Smrg gfc_offset
next_array_record(st_parameter_dt * dtp,array_loop_spec * ls,int * finished)3483760c2415Smrg next_array_record (st_parameter_dt *dtp, array_loop_spec *ls, int *finished)
3484760c2415Smrg {
3485760c2415Smrg int i, carry;
3486760c2415Smrg gfc_offset index;
3487760c2415Smrg
3488760c2415Smrg carry = 1;
3489760c2415Smrg index = 0;
3490760c2415Smrg
3491760c2415Smrg for (i = 0; i < dtp->u.p.current_unit->rank; i++)
3492760c2415Smrg {
3493760c2415Smrg if (carry)
3494760c2415Smrg {
3495760c2415Smrg ls[i].idx++;
3496760c2415Smrg if (ls[i].idx > ls[i].end)
3497760c2415Smrg {
3498760c2415Smrg ls[i].idx = ls[i].start;
3499760c2415Smrg carry = 1;
3500760c2415Smrg }
3501760c2415Smrg else
3502760c2415Smrg carry = 0;
3503760c2415Smrg }
3504760c2415Smrg index = index + (ls[i].idx - ls[i].start) * ls[i].step;
3505760c2415Smrg }
3506760c2415Smrg
3507760c2415Smrg *finished = carry;
3508760c2415Smrg
3509760c2415Smrg return index;
3510760c2415Smrg }
3511760c2415Smrg
3512760c2415Smrg
3513760c2415Smrg
3514760c2415Smrg /* Skip to the end of the current record, taking care of an optional
3515760c2415Smrg record marker of size bytes. If the file is not seekable, we
3516760c2415Smrg read chunks of size MAX_READ until we get to the right
3517760c2415Smrg position. */
3518760c2415Smrg
3519760c2415Smrg static void
skip_record(st_parameter_dt * dtp,gfc_offset bytes)3520760c2415Smrg skip_record (st_parameter_dt *dtp, gfc_offset bytes)
3521760c2415Smrg {
3522760c2415Smrg ssize_t rlength, readb;
3523760c2415Smrg #define MAX_READ 4096
3524760c2415Smrg char p[MAX_READ];
3525760c2415Smrg
3526760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord += bytes;
3527760c2415Smrg if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
3528760c2415Smrg return;
3529760c2415Smrg
3530760c2415Smrg /* Direct access files do not generate END conditions,
3531760c2415Smrg only I/O errors. */
3532760c2415Smrg if (sseek (dtp->u.p.current_unit->s,
3533760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
3534760c2415Smrg {
3535760c2415Smrg /* Seeking failed, fall back to seeking by reading data. */
3536760c2415Smrg while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
3537760c2415Smrg {
3538760c2415Smrg rlength =
3539760c2415Smrg (MAX_READ < dtp->u.p.current_unit->bytes_left_subrecord) ?
3540760c2415Smrg MAX_READ : dtp->u.p.current_unit->bytes_left_subrecord;
3541760c2415Smrg
3542760c2415Smrg readb = sread (dtp->u.p.current_unit->s, p, rlength);
3543760c2415Smrg if (readb < 0)
3544760c2415Smrg {
3545760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3546760c2415Smrg return;
3547760c2415Smrg }
3548760c2415Smrg
3549760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord -= readb;
3550760c2415Smrg }
3551760c2415Smrg return;
3552760c2415Smrg }
3553760c2415Smrg dtp->u.p.current_unit->bytes_left_subrecord = 0;
3554760c2415Smrg }
3555760c2415Smrg
3556760c2415Smrg
3557760c2415Smrg /* Advance to the next record reading unformatted files, taking
3558760c2415Smrg care of subrecords. If complete_record is nonzero, we loop
3559760c2415Smrg until all subrecords are cleared. */
3560760c2415Smrg
3561760c2415Smrg static void
next_record_r_unf(st_parameter_dt * dtp,int complete_record)3562760c2415Smrg next_record_r_unf (st_parameter_dt *dtp, int complete_record)
3563760c2415Smrg {
3564760c2415Smrg size_t bytes;
3565760c2415Smrg
3566760c2415Smrg bytes = compile_options.record_marker == 0 ?
3567760c2415Smrg sizeof (GFC_INTEGER_4) : compile_options.record_marker;
3568760c2415Smrg
3569760c2415Smrg while(1)
3570760c2415Smrg {
3571760c2415Smrg
3572760c2415Smrg /* Skip over tail */
3573760c2415Smrg
3574760c2415Smrg skip_record (dtp, bytes);
3575760c2415Smrg
3576760c2415Smrg if ( ! (complete_record && dtp->u.p.current_unit->continued))
3577760c2415Smrg return;
3578760c2415Smrg
3579760c2415Smrg us_read (dtp, 1);
3580760c2415Smrg }
3581760c2415Smrg }
3582760c2415Smrg
3583760c2415Smrg
3584760c2415Smrg static gfc_offset
min_off(gfc_offset a,gfc_offset b)3585760c2415Smrg min_off (gfc_offset a, gfc_offset b)
3586760c2415Smrg {
3587760c2415Smrg return (a < b ? a : b);
3588760c2415Smrg }
3589760c2415Smrg
3590760c2415Smrg
3591760c2415Smrg /* Space to the next record for read mode. */
3592760c2415Smrg
3593760c2415Smrg static void
next_record_r(st_parameter_dt * dtp,int done)3594760c2415Smrg next_record_r (st_parameter_dt *dtp, int done)
3595760c2415Smrg {
3596760c2415Smrg gfc_offset record;
3597760c2415Smrg char p;
3598760c2415Smrg int cc;
3599760c2415Smrg
3600760c2415Smrg switch (current_mode (dtp))
3601760c2415Smrg {
3602760c2415Smrg /* No records in unformatted STREAM I/O. */
3603760c2415Smrg case UNFORMATTED_STREAM:
3604760c2415Smrg return;
3605760c2415Smrg
3606760c2415Smrg case UNFORMATTED_SEQUENTIAL:
3607760c2415Smrg next_record_r_unf (dtp, 1);
3608760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
3609760c2415Smrg break;
3610760c2415Smrg
3611760c2415Smrg case FORMATTED_DIRECT:
3612760c2415Smrg case UNFORMATTED_DIRECT:
3613760c2415Smrg skip_record (dtp, dtp->u.p.current_unit->bytes_left);
3614760c2415Smrg break;
3615760c2415Smrg
3616760c2415Smrg case FORMATTED_STREAM:
3617760c2415Smrg case FORMATTED_SEQUENTIAL:
3618760c2415Smrg /* read_sf has already terminated input because of an '\n', or
3619760c2415Smrg we have hit EOF. */
3620760c2415Smrg if (dtp->u.p.sf_seen_eor)
3621760c2415Smrg {
3622760c2415Smrg dtp->u.p.sf_seen_eor = 0;
3623760c2415Smrg break;
3624760c2415Smrg }
3625760c2415Smrg
3626760c2415Smrg if (is_internal_unit (dtp))
3627760c2415Smrg {
3628760c2415Smrg if (is_array_io (dtp))
3629760c2415Smrg {
3630760c2415Smrg int finished;
3631760c2415Smrg
3632760c2415Smrg record = next_array_record (dtp, dtp->u.p.current_unit->ls,
3633760c2415Smrg &finished);
3634760c2415Smrg if (!done && finished)
3635760c2415Smrg hit_eof (dtp);
3636760c2415Smrg
3637760c2415Smrg /* Now seek to this record. */
3638760c2415Smrg record = record * dtp->u.p.current_unit->recl;
3639760c2415Smrg if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
3640760c2415Smrg {
3641760c2415Smrg generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
3642760c2415Smrg break;
3643760c2415Smrg }
3644760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
3645760c2415Smrg }
3646760c2415Smrg else
3647760c2415Smrg {
3648760c2415Smrg gfc_offset bytes_left = dtp->u.p.current_unit->bytes_left;
3649760c2415Smrg bytes_left = min_off (bytes_left,
3650760c2415Smrg ssize (dtp->u.p.current_unit->s)
3651760c2415Smrg - stell (dtp->u.p.current_unit->s));
3652760c2415Smrg if (sseek (dtp->u.p.current_unit->s,
3653760c2415Smrg bytes_left, SEEK_CUR) < 0)
3654760c2415Smrg {
3655760c2415Smrg generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
3656760c2415Smrg break;
3657760c2415Smrg }
3658760c2415Smrg dtp->u.p.current_unit->bytes_left
3659760c2415Smrg = dtp->u.p.current_unit->recl;
3660760c2415Smrg }
3661760c2415Smrg break;
3662760c2415Smrg }
3663760c2415Smrg else if (dtp->u.p.current_unit->flags.cc != CC_NONE)
3664760c2415Smrg {
3665760c2415Smrg do
3666760c2415Smrg {
3667760c2415Smrg errno = 0;
3668760c2415Smrg cc = fbuf_getc (dtp->u.p.current_unit);
3669760c2415Smrg if (cc == EOF)
3670760c2415Smrg {
3671760c2415Smrg if (errno != 0)
3672760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3673760c2415Smrg else
3674760c2415Smrg {
3675760c2415Smrg if (is_stream_io (dtp)
3676760c2415Smrg || dtp->u.p.current_unit->pad_status == PAD_NO
3677760c2415Smrg || dtp->u.p.current_unit->bytes_left
3678760c2415Smrg == dtp->u.p.current_unit->recl)
3679760c2415Smrg hit_eof (dtp);
3680760c2415Smrg }
3681760c2415Smrg break;
3682760c2415Smrg }
3683760c2415Smrg
3684760c2415Smrg if (is_stream_io (dtp))
3685760c2415Smrg dtp->u.p.current_unit->strm_pos++;
3686760c2415Smrg
3687760c2415Smrg p = (char) cc;
3688760c2415Smrg }
3689760c2415Smrg while (p != '\n');
3690760c2415Smrg }
3691760c2415Smrg break;
3692*0bfacb9bSmrg case FORMATTED_UNSPECIFIED:
3693*0bfacb9bSmrg gcc_unreachable ();
3694760c2415Smrg }
3695760c2415Smrg }
3696760c2415Smrg
3697760c2415Smrg
3698760c2415Smrg /* Small utility function to write a record marker, taking care of
3699760c2415Smrg byte swapping and of choosing the correct size. */
3700760c2415Smrg
3701760c2415Smrg static int
write_us_marker(st_parameter_dt * dtp,const gfc_offset buf)3702760c2415Smrg write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
3703760c2415Smrg {
3704760c2415Smrg size_t len;
3705760c2415Smrg GFC_INTEGER_4 buf4;
3706760c2415Smrg GFC_INTEGER_8 buf8;
3707760c2415Smrg
3708760c2415Smrg if (compile_options.record_marker == 0)
3709760c2415Smrg len = sizeof (GFC_INTEGER_4);
3710760c2415Smrg else
3711760c2415Smrg len = compile_options.record_marker;
3712760c2415Smrg
3713760c2415Smrg /* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
3714760c2415Smrg if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE))
3715760c2415Smrg {
3716760c2415Smrg switch (len)
3717760c2415Smrg {
3718760c2415Smrg case sizeof (GFC_INTEGER_4):
3719760c2415Smrg buf4 = buf;
3720760c2415Smrg return swrite (dtp->u.p.current_unit->s, &buf4, len);
3721760c2415Smrg break;
3722760c2415Smrg
3723760c2415Smrg case sizeof (GFC_INTEGER_8):
3724760c2415Smrg buf8 = buf;
3725760c2415Smrg return swrite (dtp->u.p.current_unit->s, &buf8, len);
3726760c2415Smrg break;
3727760c2415Smrg
3728760c2415Smrg default:
3729760c2415Smrg runtime_error ("Illegal value for record marker");
3730760c2415Smrg break;
3731760c2415Smrg }
3732760c2415Smrg }
3733760c2415Smrg else
3734760c2415Smrg {
3735760c2415Smrg uint32_t u32;
3736760c2415Smrg uint64_t u64;
3737760c2415Smrg switch (len)
3738760c2415Smrg {
3739760c2415Smrg case sizeof (GFC_INTEGER_4):
3740760c2415Smrg buf4 = buf;
3741760c2415Smrg memcpy (&u32, &buf4, sizeof (u32));
3742760c2415Smrg u32 = __builtin_bswap32 (u32);
3743760c2415Smrg return swrite (dtp->u.p.current_unit->s, &u32, len);
3744760c2415Smrg break;
3745760c2415Smrg
3746760c2415Smrg case sizeof (GFC_INTEGER_8):
3747760c2415Smrg buf8 = buf;
3748760c2415Smrg memcpy (&u64, &buf8, sizeof (u64));
3749760c2415Smrg u64 = __builtin_bswap64 (u64);
3750760c2415Smrg return swrite (dtp->u.p.current_unit->s, &u64, len);
3751760c2415Smrg break;
3752760c2415Smrg
3753760c2415Smrg default:
3754760c2415Smrg runtime_error ("Illegal value for record marker");
3755760c2415Smrg break;
3756760c2415Smrg }
3757760c2415Smrg }
3758760c2415Smrg
3759760c2415Smrg }
3760760c2415Smrg
3761760c2415Smrg /* Position to the next (sub)record in write mode for
3762760c2415Smrg unformatted sequential files. */
3763760c2415Smrg
3764760c2415Smrg static void
next_record_w_unf(st_parameter_dt * dtp,int next_subrecord)3765760c2415Smrg next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
3766760c2415Smrg {
3767760c2415Smrg gfc_offset m, m_write, record_marker;
3768760c2415Smrg
3769760c2415Smrg /* Bytes written. */
3770760c2415Smrg m = dtp->u.p.current_unit->recl_subrecord
3771760c2415Smrg - dtp->u.p.current_unit->bytes_left_subrecord;
3772760c2415Smrg
3773760c2415Smrg if (compile_options.record_marker == 0)
3774760c2415Smrg record_marker = sizeof (GFC_INTEGER_4);
3775760c2415Smrg else
3776760c2415Smrg record_marker = compile_options.record_marker;
3777760c2415Smrg
3778760c2415Smrg /* Seek to the head and overwrite the bogus length with the real
3779760c2415Smrg length. */
3780760c2415Smrg
3781760c2415Smrg if (unlikely (sseek (dtp->u.p.current_unit->s, - m - record_marker,
3782760c2415Smrg SEEK_CUR) < 0))
3783760c2415Smrg goto io_error;
3784760c2415Smrg
3785760c2415Smrg if (next_subrecord)
3786760c2415Smrg m_write = -m;
3787760c2415Smrg else
3788760c2415Smrg m_write = m;
3789760c2415Smrg
3790760c2415Smrg if (unlikely (write_us_marker (dtp, m_write) < 0))
3791760c2415Smrg goto io_error;
3792760c2415Smrg
3793760c2415Smrg /* Seek past the end of the current record. */
3794760c2415Smrg
3795760c2415Smrg if (unlikely (sseek (dtp->u.p.current_unit->s, m, SEEK_CUR) < 0))
3796760c2415Smrg goto io_error;
3797760c2415Smrg
3798760c2415Smrg /* Write the length tail. If we finish a record containing
3799760c2415Smrg subrecords, we write out the negative length. */
3800760c2415Smrg
3801760c2415Smrg if (dtp->u.p.current_unit->continued)
3802760c2415Smrg m_write = -m;
3803760c2415Smrg else
3804760c2415Smrg m_write = m;
3805760c2415Smrg
3806760c2415Smrg if (unlikely (write_us_marker (dtp, m_write) < 0))
3807760c2415Smrg goto io_error;
3808760c2415Smrg
3809760c2415Smrg return;
3810760c2415Smrg
3811760c2415Smrg io_error:
3812760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3813760c2415Smrg return;
3814760c2415Smrg
3815760c2415Smrg }
3816760c2415Smrg
3817760c2415Smrg
3818760c2415Smrg /* Utility function like memset() but operating on streams. Return
3819760c2415Smrg value is same as for POSIX write(). */
3820760c2415Smrg
3821760c2415Smrg static gfc_offset
sset(stream * s,int c,gfc_offset nbyte)3822760c2415Smrg sset (stream *s, int c, gfc_offset nbyte)
3823760c2415Smrg {
3824760c2415Smrg #define WRITE_CHUNK 256
3825760c2415Smrg char p[WRITE_CHUNK];
3826760c2415Smrg gfc_offset bytes_left;
3827760c2415Smrg ssize_t trans;
3828760c2415Smrg
3829760c2415Smrg if (nbyte < WRITE_CHUNK)
3830760c2415Smrg memset (p, c, nbyte);
3831760c2415Smrg else
3832760c2415Smrg memset (p, c, WRITE_CHUNK);
3833760c2415Smrg
3834760c2415Smrg bytes_left = nbyte;
3835760c2415Smrg while (bytes_left > 0)
3836760c2415Smrg {
3837760c2415Smrg trans = (bytes_left < WRITE_CHUNK) ? bytes_left : WRITE_CHUNK;
3838760c2415Smrg trans = swrite (s, p, trans);
3839760c2415Smrg if (trans <= 0)
3840760c2415Smrg return trans;
3841760c2415Smrg bytes_left -= trans;
3842760c2415Smrg }
3843760c2415Smrg
3844760c2415Smrg return nbyte - bytes_left;
3845760c2415Smrg }
3846760c2415Smrg
3847760c2415Smrg
3848760c2415Smrg /* Finish up a record according to the legacy carriagecontrol type, based
3849760c2415Smrg on the first character in the record. */
3850760c2415Smrg
3851760c2415Smrg static void
next_record_cc(st_parameter_dt * dtp)3852760c2415Smrg next_record_cc (st_parameter_dt *dtp)
3853760c2415Smrg {
3854760c2415Smrg /* Only valid with CARRIAGECONTROL=FORTRAN. */
3855760c2415Smrg if (dtp->u.p.current_unit->flags.cc != CC_FORTRAN)
3856760c2415Smrg return;
3857760c2415Smrg
3858760c2415Smrg fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
3859760c2415Smrg if (dtp->u.p.cc.len > 0)
3860760c2415Smrg {
3861760c2415Smrg char *p = fbuf_alloc (dtp->u.p.current_unit, dtp->u.p.cc.len);
3862760c2415Smrg if (!p)
3863760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
3864760c2415Smrg
3865760c2415Smrg /* Output CR for the first character with default CC setting. */
3866760c2415Smrg *(p++) = dtp->u.p.cc.u.end;
3867760c2415Smrg if (dtp->u.p.cc.len > 1)
3868760c2415Smrg *p = dtp->u.p.cc.u.end;
3869760c2415Smrg }
3870760c2415Smrg }
3871760c2415Smrg
3872760c2415Smrg /* Position to the next record in write mode. */
3873760c2415Smrg
3874760c2415Smrg static void
next_record_w(st_parameter_dt * dtp,int done)3875760c2415Smrg next_record_w (st_parameter_dt *dtp, int done)
3876760c2415Smrg {
3877760c2415Smrg gfc_offset max_pos_off;
3878760c2415Smrg
3879760c2415Smrg /* Zero counters for X- and T-editing. */
3880760c2415Smrg max_pos_off = dtp->u.p.max_pos;
3881760c2415Smrg dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
3882760c2415Smrg
3883760c2415Smrg switch (current_mode (dtp))
3884760c2415Smrg {
3885760c2415Smrg /* No records in unformatted STREAM I/O. */
3886760c2415Smrg case UNFORMATTED_STREAM:
3887760c2415Smrg return;
3888760c2415Smrg
3889760c2415Smrg case FORMATTED_DIRECT:
3890760c2415Smrg if (dtp->u.p.current_unit->bytes_left == 0)
3891760c2415Smrg break;
3892760c2415Smrg
3893760c2415Smrg fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
3894760c2415Smrg fbuf_flush (dtp->u.p.current_unit, WRITING);
3895760c2415Smrg if (sset (dtp->u.p.current_unit->s, ' ',
3896760c2415Smrg dtp->u.p.current_unit->bytes_left)
3897760c2415Smrg != dtp->u.p.current_unit->bytes_left)
3898760c2415Smrg goto io_error;
3899760c2415Smrg
3900760c2415Smrg break;
3901760c2415Smrg
3902760c2415Smrg case UNFORMATTED_DIRECT:
3903760c2415Smrg if (dtp->u.p.current_unit->bytes_left > 0)
3904760c2415Smrg {
3905760c2415Smrg gfc_offset length = dtp->u.p.current_unit->bytes_left;
3906760c2415Smrg if (sset (dtp->u.p.current_unit->s, 0, length) != length)
3907760c2415Smrg goto io_error;
3908760c2415Smrg }
3909760c2415Smrg break;
3910760c2415Smrg
3911760c2415Smrg case UNFORMATTED_SEQUENTIAL:
3912760c2415Smrg next_record_w_unf (dtp, 0);
3913760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
3914760c2415Smrg break;
3915760c2415Smrg
3916760c2415Smrg case FORMATTED_STREAM:
3917760c2415Smrg case FORMATTED_SEQUENTIAL:
3918760c2415Smrg
3919760c2415Smrg if (is_internal_unit (dtp))
3920760c2415Smrg {
3921760c2415Smrg char *p;
3922760c2415Smrg /* Internal unit, so must fit in memory. */
3923760c2415Smrg size_t length, m;
3924760c2415Smrg size_t max_pos = max_pos_off;
3925760c2415Smrg if (is_array_io (dtp))
3926760c2415Smrg {
3927760c2415Smrg int finished;
3928760c2415Smrg
3929760c2415Smrg length = dtp->u.p.current_unit->bytes_left;
3930760c2415Smrg
3931760c2415Smrg /* If the farthest position reached is greater than current
3932760c2415Smrg position, adjust the position and set length to pad out
3933760c2415Smrg whats left. Otherwise just pad whats left.
3934760c2415Smrg (for character array unit) */
3935760c2415Smrg m = dtp->u.p.current_unit->recl
3936760c2415Smrg - dtp->u.p.current_unit->bytes_left;
3937760c2415Smrg if (max_pos > m)
3938760c2415Smrg {
3939760c2415Smrg length = (max_pos - m);
3940760c2415Smrg if (sseek (dtp->u.p.current_unit->s,
3941760c2415Smrg length, SEEK_CUR) < 0)
3942760c2415Smrg {
3943760c2415Smrg generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
3944760c2415Smrg return;
3945760c2415Smrg }
3946760c2415Smrg length = ((size_t) dtp->u.p.current_unit->recl - max_pos);
3947760c2415Smrg }
3948760c2415Smrg
3949760c2415Smrg p = write_block (dtp, length);
3950760c2415Smrg if (p == NULL)
3951760c2415Smrg return;
3952760c2415Smrg
3953760c2415Smrg if (unlikely (is_char4_unit (dtp)))
3954760c2415Smrg {
3955760c2415Smrg gfc_char4_t *p4 = (gfc_char4_t *) p;
3956760c2415Smrg memset4 (p4, ' ', length);
3957760c2415Smrg }
3958760c2415Smrg else
3959760c2415Smrg memset (p, ' ', length);
3960760c2415Smrg
3961760c2415Smrg /* Now that the current record has been padded out,
3962760c2415Smrg determine where the next record in the array is.
3963760c2415Smrg Note that this can return a negative value, so it
3964760c2415Smrg needs to be assigned to a signed value. */
3965760c2415Smrg gfc_offset record = next_array_record
3966760c2415Smrg (dtp, dtp->u.p.current_unit->ls, &finished);
3967760c2415Smrg if (finished)
3968760c2415Smrg dtp->u.p.current_unit->endfile = AT_ENDFILE;
3969760c2415Smrg
3970760c2415Smrg /* Now seek to this record */
3971760c2415Smrg record = record * dtp->u.p.current_unit->recl;
3972760c2415Smrg
3973760c2415Smrg if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
3974760c2415Smrg {
3975760c2415Smrg generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
3976760c2415Smrg return;
3977760c2415Smrg }
3978760c2415Smrg
3979760c2415Smrg dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
3980760c2415Smrg }
3981760c2415Smrg else
3982760c2415Smrg {
3983760c2415Smrg length = 1;
3984760c2415Smrg
3985760c2415Smrg /* If this is the last call to next_record move to the farthest
3986760c2415Smrg position reached and set length to pad out the remainder
3987760c2415Smrg of the record. (for character scaler unit) */
3988760c2415Smrg if (done)
3989760c2415Smrg {
3990760c2415Smrg m = dtp->u.p.current_unit->recl
3991760c2415Smrg - dtp->u.p.current_unit->bytes_left;
3992760c2415Smrg if (max_pos > m)
3993760c2415Smrg {
3994760c2415Smrg length = max_pos - m;
3995760c2415Smrg if (sseek (dtp->u.p.current_unit->s,
3996760c2415Smrg length, SEEK_CUR) < 0)
3997760c2415Smrg {
3998760c2415Smrg generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
3999760c2415Smrg return;
4000760c2415Smrg }
4001760c2415Smrg length = (size_t) dtp->u.p.current_unit->recl
4002760c2415Smrg - max_pos;
4003760c2415Smrg }
4004760c2415Smrg else
4005760c2415Smrg length = dtp->u.p.current_unit->bytes_left;
4006760c2415Smrg }
4007760c2415Smrg if (length > 0)
4008760c2415Smrg {
4009760c2415Smrg p = write_block (dtp, length);
4010760c2415Smrg if (p == NULL)
4011760c2415Smrg return;
4012760c2415Smrg
4013760c2415Smrg if (unlikely (is_char4_unit (dtp)))
4014760c2415Smrg {
4015760c2415Smrg gfc_char4_t *p4 = (gfc_char4_t *) p;
4016760c2415Smrg memset4 (p4, (gfc_char4_t) ' ', length);
4017760c2415Smrg }
4018760c2415Smrg else
4019760c2415Smrg memset (p, ' ', length);
4020760c2415Smrg }
4021760c2415Smrg }
4022760c2415Smrg }
4023760c2415Smrg /* Handle legacy CARRIAGECONTROL line endings. */
4024760c2415Smrg else if (dtp->u.p.current_unit->flags.cc == CC_FORTRAN)
4025760c2415Smrg next_record_cc (dtp);
4026760c2415Smrg else
4027760c2415Smrg {
4028760c2415Smrg /* Skip newlines for CC=CC_NONE. */
4029760c2415Smrg const int len = (dtp->u.p.current_unit->flags.cc == CC_NONE)
4030760c2415Smrg ? 0
4031760c2415Smrg #ifdef HAVE_CRLF
4032760c2415Smrg : 2;
4033760c2415Smrg #else
4034760c2415Smrg : 1;
4035760c2415Smrg #endif
4036760c2415Smrg fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
4037760c2415Smrg if (dtp->u.p.current_unit->flags.cc != CC_NONE)
4038760c2415Smrg {
4039760c2415Smrg char *p = fbuf_alloc (dtp->u.p.current_unit, len);
4040760c2415Smrg if (!p)
4041760c2415Smrg goto io_error;
4042760c2415Smrg #ifdef HAVE_CRLF
4043760c2415Smrg *(p++) = '\r';
4044760c2415Smrg #endif
4045760c2415Smrg *p = '\n';
4046760c2415Smrg }
4047760c2415Smrg if (is_stream_io (dtp))
4048760c2415Smrg {
4049760c2415Smrg dtp->u.p.current_unit->strm_pos += len;
4050760c2415Smrg if (dtp->u.p.current_unit->strm_pos
4051760c2415Smrg < ssize (dtp->u.p.current_unit->s))
4052760c2415Smrg unit_truncate (dtp->u.p.current_unit,
4053760c2415Smrg dtp->u.p.current_unit->strm_pos - 1,
4054760c2415Smrg &dtp->common);
4055760c2415Smrg }
4056760c2415Smrg }
4057760c2415Smrg
4058760c2415Smrg break;
4059*0bfacb9bSmrg case FORMATTED_UNSPECIFIED:
4060*0bfacb9bSmrg gcc_unreachable ();
4061760c2415Smrg
4062760c2415Smrg io_error:
4063760c2415Smrg generate_error (&dtp->common, LIBERROR_OS, NULL);
4064760c2415Smrg break;
4065760c2415Smrg }
4066760c2415Smrg }
4067760c2415Smrg
4068760c2415Smrg /* Position to the next record, which means moving to the end of the
4069760c2415Smrg current record. This can happen under several different
4070760c2415Smrg conditions. If the done flag is not set, we get ready to process
4071760c2415Smrg the next record. */
4072760c2415Smrg
4073760c2415Smrg void
next_record(st_parameter_dt * dtp,int done)4074760c2415Smrg next_record (st_parameter_dt *dtp, int done)
4075760c2415Smrg {
4076760c2415Smrg gfc_offset fp; /* File position. */
4077760c2415Smrg
4078760c2415Smrg dtp->u.p.current_unit->read_bad = 0;
4079760c2415Smrg
4080760c2415Smrg if (dtp->u.p.mode == READING)
4081760c2415Smrg next_record_r (dtp, done);
4082760c2415Smrg else
4083760c2415Smrg next_record_w (dtp, done);
4084760c2415Smrg
4085760c2415Smrg fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
4086760c2415Smrg
4087760c2415Smrg if (!is_stream_io (dtp))
4088760c2415Smrg {
4089760c2415Smrg /* Since we have changed the position, set it to unspecified so
4090760c2415Smrg that INQUIRE(POSITION=) knows it needs to look into it. */
4091760c2415Smrg if (done)
4092760c2415Smrg dtp->u.p.current_unit->flags.position = POSITION_UNSPECIFIED;
4093760c2415Smrg
4094760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4095760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
4096760c2415Smrg {
4097760c2415Smrg fp = stell (dtp->u.p.current_unit->s);
4098760c2415Smrg /* Calculate next record, rounding up partial records. */
4099760c2415Smrg dtp->u.p.current_unit->last_record =
4100760c2415Smrg (fp + dtp->u.p.current_unit->recl) /
4101760c2415Smrg dtp->u.p.current_unit->recl - 1;
4102760c2415Smrg }
4103760c2415Smrg else
4104760c2415Smrg dtp->u.p.current_unit->last_record++;
4105760c2415Smrg }
4106760c2415Smrg
4107760c2415Smrg if (!done)
4108760c2415Smrg pre_position (dtp);
4109760c2415Smrg
4110760c2415Smrg smarkeor (dtp->u.p.current_unit->s);
4111760c2415Smrg }
4112760c2415Smrg
4113760c2415Smrg
4114760c2415Smrg /* Finalize the current data transfer. For a nonadvancing transfer,
4115760c2415Smrg this means advancing to the next record. For internal units close the
4116760c2415Smrg stream associated with the unit. */
4117760c2415Smrg
4118760c2415Smrg static void
finalize_transfer(st_parameter_dt * dtp)4119760c2415Smrg finalize_transfer (st_parameter_dt *dtp)
4120760c2415Smrg {
4121760c2415Smrg GFC_INTEGER_4 cf = dtp->common.flags;
4122760c2415Smrg
4123760c2415Smrg if ((dtp->u.p.ionml != NULL)
4124760c2415Smrg && (cf & IOPARM_DT_HAS_NAMELIST_NAME) != 0)
4125760c2415Smrg {
4126760c2415Smrg dtp->u.p.namelist_mode = 1;
4127760c2415Smrg if ((cf & IOPARM_DT_NAMELIST_READ_MODE) != 0)
4128760c2415Smrg namelist_read (dtp);
4129760c2415Smrg else
4130760c2415Smrg namelist_write (dtp);
4131760c2415Smrg }
4132760c2415Smrg
4133760c2415Smrg if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
4134760c2415Smrg *dtp->size = dtp->u.p.current_unit->size_used;
4135760c2415Smrg
4136760c2415Smrg if (dtp->u.p.eor_condition)
4137760c2415Smrg {
4138760c2415Smrg generate_error (&dtp->common, LIBERROR_EOR, NULL);
4139760c2415Smrg goto done;
4140760c2415Smrg }
4141760c2415Smrg
4142760c2415Smrg if (dtp->u.p.current_unit && (dtp->u.p.current_unit->child_dtio > 0))
4143760c2415Smrg {
4144760c2415Smrg if (cf & IOPARM_DT_HAS_FORMAT)
4145760c2415Smrg {
4146760c2415Smrg free (dtp->u.p.fmt);
4147760c2415Smrg free (dtp->format);
4148760c2415Smrg }
4149760c2415Smrg return;
4150760c2415Smrg }
4151760c2415Smrg
4152760c2415Smrg if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
4153760c2415Smrg {
4154760c2415Smrg if (dtp->u.p.current_unit && current_mode (dtp) == UNFORMATTED_SEQUENTIAL)
4155760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4156760c2415Smrg goto done;
4157760c2415Smrg }
4158760c2415Smrg
4159760c2415Smrg dtp->u.p.transfer = NULL;
4160760c2415Smrg if (dtp->u.p.current_unit == NULL)
4161760c2415Smrg goto done;
4162760c2415Smrg
4163760c2415Smrg if ((cf & IOPARM_DT_LIST_FORMAT) != 0 && dtp->u.p.mode == READING)
4164760c2415Smrg {
4165760c2415Smrg finish_list_read (dtp);
4166760c2415Smrg goto done;
4167760c2415Smrg }
4168760c2415Smrg
4169760c2415Smrg if (dtp->u.p.mode == WRITING)
4170760c2415Smrg dtp->u.p.current_unit->previous_nonadvancing_write
4171760c2415Smrg = dtp->u.p.advance_status == ADVANCE_NO;
4172760c2415Smrg
4173760c2415Smrg if (is_stream_io (dtp))
4174760c2415Smrg {
4175760c2415Smrg if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
4176760c2415Smrg && dtp->u.p.advance_status != ADVANCE_NO)
4177760c2415Smrg next_record (dtp, 1);
4178760c2415Smrg
4179760c2415Smrg goto done;
4180760c2415Smrg }
4181760c2415Smrg
4182760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4183760c2415Smrg
4184760c2415Smrg if (!is_internal_unit (dtp) && dtp->u.p.seen_dollar)
4185760c2415Smrg {
4186760c2415Smrg fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
4187760c2415Smrg dtp->u.p.seen_dollar = 0;
4188760c2415Smrg goto done;
4189760c2415Smrg }
4190760c2415Smrg
4191760c2415Smrg /* For non-advancing I/O, save the current maximum position for use in the
4192760c2415Smrg next I/O operation if needed. */
4193760c2415Smrg if (dtp->u.p.advance_status == ADVANCE_NO)
4194760c2415Smrg {
4195760c2415Smrg if (dtp->u.p.skips > 0)
4196760c2415Smrg {
4197760c2415Smrg int tmp;
4198760c2415Smrg write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
4199760c2415Smrg tmp = (int)(dtp->u.p.current_unit->recl
4200760c2415Smrg - dtp->u.p.current_unit->bytes_left);
4201760c2415Smrg dtp->u.p.max_pos =
4202760c2415Smrg dtp->u.p.max_pos > tmp ? dtp->u.p.max_pos : tmp;
4203760c2415Smrg dtp->u.p.skips = 0;
4204760c2415Smrg }
4205760c2415Smrg int bytes_written = (int) (dtp->u.p.current_unit->recl
4206760c2415Smrg - dtp->u.p.current_unit->bytes_left);
4207760c2415Smrg dtp->u.p.current_unit->saved_pos =
4208760c2415Smrg dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
4209760c2415Smrg fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
4210760c2415Smrg goto done;
4211760c2415Smrg }
4212760c2415Smrg else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
4213760c2415Smrg && dtp->u.p.mode == WRITING && !is_internal_unit (dtp))
4214760c2415Smrg fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
4215760c2415Smrg
4216760c2415Smrg dtp->u.p.current_unit->saved_pos = 0;
4217760c2415Smrg dtp->u.p.current_unit->last_char = EOF - 1;
4218760c2415Smrg next_record (dtp, 1);
4219760c2415Smrg
4220760c2415Smrg done:
4221760c2415Smrg
4222760c2415Smrg if (dtp->u.p.unit_is_internal)
4223760c2415Smrg {
4224760c2415Smrg /* The unit structure may be reused later so clear the
4225760c2415Smrg internal unit kind. */
4226760c2415Smrg dtp->u.p.current_unit->internal_unit_kind = 0;
4227760c2415Smrg
4228760c2415Smrg fbuf_destroy (dtp->u.p.current_unit);
4229760c2415Smrg if (dtp->u.p.current_unit
4230760c2415Smrg && (dtp->u.p.current_unit->child_dtio == 0)
4231760c2415Smrg && dtp->u.p.current_unit->s)
4232760c2415Smrg {
4233760c2415Smrg sclose (dtp->u.p.current_unit->s);
4234760c2415Smrg dtp->u.p.current_unit->s = NULL;
4235760c2415Smrg }
4236760c2415Smrg }
4237760c2415Smrg
4238760c2415Smrg #ifdef HAVE_USELOCALE
4239760c2415Smrg if (dtp->u.p.old_locale != (locale_t) 0)
4240760c2415Smrg {
4241760c2415Smrg uselocale (dtp->u.p.old_locale);
4242760c2415Smrg dtp->u.p.old_locale = (locale_t) 0;
4243760c2415Smrg }
4244760c2415Smrg #else
4245760c2415Smrg __gthread_mutex_lock (&old_locale_lock);
4246760c2415Smrg if (!--old_locale_ctr)
4247760c2415Smrg {
4248760c2415Smrg setlocale (LC_NUMERIC, old_locale);
4249760c2415Smrg old_locale = NULL;
4250760c2415Smrg }
4251760c2415Smrg __gthread_mutex_unlock (&old_locale_lock);
4252760c2415Smrg #endif
4253760c2415Smrg }
4254760c2415Smrg
4255760c2415Smrg /* Transfer function for IOLENGTH. It doesn't actually do any
4256760c2415Smrg data transfer, it just updates the length counter. */
4257760c2415Smrg
4258760c2415Smrg static void
iolength_transfer(st_parameter_dt * dtp,bt type,void * dest,int kind,size_t size,size_t nelems)4259760c2415Smrg iolength_transfer (st_parameter_dt *dtp, bt type __attribute__((unused)),
4260760c2415Smrg void *dest __attribute__ ((unused)),
4261760c2415Smrg int kind __attribute__((unused)),
4262760c2415Smrg size_t size, size_t nelems)
4263760c2415Smrg {
4264760c2415Smrg if ((dtp->common.flags & IOPARM_DT_HAS_IOLENGTH) != 0)
4265760c2415Smrg *dtp->iolength += (GFC_IO_INT) (size * nelems);
4266760c2415Smrg }
4267760c2415Smrg
4268760c2415Smrg
4269760c2415Smrg /* Initialize the IOLENGTH data transfer. This function is in essence
4270760c2415Smrg a very much simplified version of data_transfer_init(), because it
4271760c2415Smrg doesn't have to deal with units at all. */
4272760c2415Smrg
4273760c2415Smrg static void
iolength_transfer_init(st_parameter_dt * dtp)4274760c2415Smrg iolength_transfer_init (st_parameter_dt *dtp)
4275760c2415Smrg {
4276760c2415Smrg if ((dtp->common.flags & IOPARM_DT_HAS_IOLENGTH) != 0)
4277760c2415Smrg *dtp->iolength = 0;
4278760c2415Smrg
4279760c2415Smrg memset (&dtp->u.p, 0, sizeof (dtp->u.p));
4280760c2415Smrg
4281760c2415Smrg /* Set up the subroutine that will handle the transfers. */
4282760c2415Smrg
4283760c2415Smrg dtp->u.p.transfer = iolength_transfer;
4284760c2415Smrg }
4285760c2415Smrg
4286760c2415Smrg
4287760c2415Smrg /* Library entry point for the IOLENGTH form of the INQUIRE
4288760c2415Smrg statement. The IOLENGTH form requires no I/O to be performed, but
4289760c2415Smrg it must still be a runtime library call so that we can determine
4290760c2415Smrg the iolength for dynamic arrays and such. */
4291760c2415Smrg
4292760c2415Smrg extern void st_iolength (st_parameter_dt *);
4293760c2415Smrg export_proto(st_iolength);
4294760c2415Smrg
4295760c2415Smrg void
st_iolength(st_parameter_dt * dtp)4296760c2415Smrg st_iolength (st_parameter_dt *dtp)
4297760c2415Smrg {
4298760c2415Smrg library_start (&dtp->common);
4299760c2415Smrg iolength_transfer_init (dtp);
4300760c2415Smrg }
4301760c2415Smrg
4302760c2415Smrg extern void st_iolength_done (st_parameter_dt *);
4303760c2415Smrg export_proto(st_iolength_done);
4304760c2415Smrg
4305760c2415Smrg void
st_iolength_done(st_parameter_dt * dtp)4306760c2415Smrg st_iolength_done (st_parameter_dt *dtp __attribute__((unused)))
4307760c2415Smrg {
4308760c2415Smrg free_ionml (dtp);
4309760c2415Smrg library_end ();
4310760c2415Smrg }
4311760c2415Smrg
4312760c2415Smrg
4313760c2415Smrg /* The READ statement. */
4314760c2415Smrg
4315760c2415Smrg extern void st_read (st_parameter_dt *);
4316760c2415Smrg export_proto(st_read);
4317760c2415Smrg
4318760c2415Smrg void
st_read(st_parameter_dt * dtp)4319760c2415Smrg st_read (st_parameter_dt *dtp)
4320760c2415Smrg {
4321760c2415Smrg library_start (&dtp->common);
4322760c2415Smrg
4323760c2415Smrg data_transfer_init (dtp, 1);
4324760c2415Smrg }
4325760c2415Smrg
4326760c2415Smrg extern void st_read_done (st_parameter_dt *);
4327760c2415Smrg export_proto(st_read_done);
4328760c2415Smrg
4329760c2415Smrg void
st_read_done_worker(st_parameter_dt * dtp)4330760c2415Smrg st_read_done_worker (st_parameter_dt *dtp)
4331760c2415Smrg {
4332760c2415Smrg finalize_transfer (dtp);
4333760c2415Smrg
4334760c2415Smrg free_ionml (dtp);
4335760c2415Smrg
4336760c2415Smrg /* If this is a parent READ statement we do not need to retain the
4337760c2415Smrg internal unit structure for child use. */
4338760c2415Smrg if (dtp->u.p.current_unit != NULL
4339760c2415Smrg && dtp->u.p.current_unit->child_dtio == 0)
4340760c2415Smrg {
4341760c2415Smrg if (dtp->u.p.unit_is_internal)
4342760c2415Smrg {
4343760c2415Smrg if ((dtp->common.flags & IOPARM_DT_HAS_UDTIO) == 0)
4344760c2415Smrg {
4345760c2415Smrg free (dtp->u.p.current_unit->filename);
4346760c2415Smrg dtp->u.p.current_unit->filename = NULL;
4347760c2415Smrg if (dtp->u.p.current_unit->ls)
4348760c2415Smrg free (dtp->u.p.current_unit->ls);
4349760c2415Smrg dtp->u.p.current_unit->ls = NULL;
4350760c2415Smrg }
4351760c2415Smrg newunit_free (dtp->common.unit);
4352760c2415Smrg }
4353760c2415Smrg if (dtp->u.p.unit_is_internal || dtp->u.p.format_not_saved)
4354760c2415Smrg {
4355760c2415Smrg free_format_data (dtp->u.p.fmt);
4356760c2415Smrg free_format (dtp);
4357760c2415Smrg }
4358760c2415Smrg }
4359760c2415Smrg }
4360760c2415Smrg
4361760c2415Smrg void
st_read_done(st_parameter_dt * dtp)4362760c2415Smrg st_read_done (st_parameter_dt *dtp)
4363760c2415Smrg {
4364760c2415Smrg if (dtp->u.p.current_unit)
4365760c2415Smrg {
4366760c2415Smrg if (dtp->u.p.current_unit->au)
4367760c2415Smrg {
4368760c2415Smrg if (dtp->common.flags & IOPARM_DT_HAS_ID)
4369760c2415Smrg *dtp->id = enqueue_done_id (dtp->u.p.current_unit->au, AIO_READ_DONE);
4370760c2415Smrg else
4371760c2415Smrg {
4372760c2415Smrg if (dtp->u.p.async)
4373760c2415Smrg enqueue_done (dtp->u.p.current_unit->au, AIO_READ_DONE);
4374760c2415Smrg }
4375760c2415Smrg }
4376760c2415Smrg else
4377760c2415Smrg st_read_done_worker (dtp);
4378760c2415Smrg
4379760c2415Smrg unlock_unit (dtp->u.p.current_unit);
4380760c2415Smrg }
4381760c2415Smrg
4382760c2415Smrg library_end ();
4383760c2415Smrg }
4384760c2415Smrg
4385760c2415Smrg extern void st_write (st_parameter_dt *);
4386760c2415Smrg export_proto (st_write);
4387760c2415Smrg
4388760c2415Smrg void
st_write(st_parameter_dt * dtp)4389760c2415Smrg st_write (st_parameter_dt *dtp)
4390760c2415Smrg {
4391760c2415Smrg library_start (&dtp->common);
4392760c2415Smrg data_transfer_init (dtp, 0);
4393760c2415Smrg }
4394760c2415Smrg
4395760c2415Smrg
4396760c2415Smrg void
st_write_done_worker(st_parameter_dt * dtp)4397760c2415Smrg st_write_done_worker (st_parameter_dt *dtp)
4398760c2415Smrg {
4399760c2415Smrg finalize_transfer (dtp);
4400760c2415Smrg
4401760c2415Smrg if (dtp->u.p.current_unit != NULL
4402760c2415Smrg && dtp->u.p.current_unit->child_dtio == 0)
4403760c2415Smrg {
4404760c2415Smrg /* Deal with endfile conditions associated with sequential files. */
4405760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
4406760c2415Smrg switch (dtp->u.p.current_unit->endfile)
4407760c2415Smrg {
4408760c2415Smrg case AT_ENDFILE: /* Remain at the endfile record. */
4409760c2415Smrg break;
4410760c2415Smrg
4411760c2415Smrg case AFTER_ENDFILE:
4412760c2415Smrg dtp->u.p.current_unit->endfile = AT_ENDFILE; /* Just at it now. */
4413760c2415Smrg break;
4414760c2415Smrg
4415760c2415Smrg case NO_ENDFILE:
4416760c2415Smrg /* Get rid of whatever is after this record. */
4417760c2415Smrg if (!is_internal_unit (dtp))
4418760c2415Smrg unit_truncate (dtp->u.p.current_unit,
4419760c2415Smrg stell (dtp->u.p.current_unit->s),
4420760c2415Smrg &dtp->common);
4421760c2415Smrg dtp->u.p.current_unit->endfile = AT_ENDFILE;
4422760c2415Smrg break;
4423760c2415Smrg }
4424760c2415Smrg
4425760c2415Smrg free_ionml (dtp);
4426760c2415Smrg
4427760c2415Smrg /* If this is a parent WRITE statement we do not need to retain the
4428760c2415Smrg internal unit structure for child use. */
4429760c2415Smrg if (dtp->u.p.unit_is_internal)
4430760c2415Smrg {
4431760c2415Smrg if ((dtp->common.flags & IOPARM_DT_HAS_UDTIO) == 0)
4432760c2415Smrg {
4433760c2415Smrg free (dtp->u.p.current_unit->filename);
4434760c2415Smrg dtp->u.p.current_unit->filename = NULL;
4435760c2415Smrg if (dtp->u.p.current_unit->ls)
4436760c2415Smrg free (dtp->u.p.current_unit->ls);
4437760c2415Smrg dtp->u.p.current_unit->ls = NULL;
4438760c2415Smrg }
4439760c2415Smrg newunit_free (dtp->common.unit);
4440760c2415Smrg }
4441760c2415Smrg if (dtp->u.p.unit_is_internal || dtp->u.p.format_not_saved)
4442760c2415Smrg {
4443760c2415Smrg free_format_data (dtp->u.p.fmt);
4444760c2415Smrg free_format (dtp);
4445760c2415Smrg }
4446760c2415Smrg }
4447760c2415Smrg }
4448760c2415Smrg
4449760c2415Smrg extern void st_write_done (st_parameter_dt *);
4450760c2415Smrg export_proto(st_write_done);
4451760c2415Smrg
4452760c2415Smrg void
st_write_done(st_parameter_dt * dtp)4453760c2415Smrg st_write_done (st_parameter_dt *dtp)
4454760c2415Smrg {
4455760c2415Smrg if (dtp->u.p.current_unit)
4456760c2415Smrg {
4457760c2415Smrg if (dtp->u.p.current_unit->au && dtp->u.p.async)
4458760c2415Smrg {
4459760c2415Smrg if (dtp->common.flags & IOPARM_DT_HAS_ID)
4460760c2415Smrg *dtp->id = enqueue_done_id (dtp->u.p.current_unit->au,
4461760c2415Smrg AIO_WRITE_DONE);
4462760c2415Smrg else
4463760c2415Smrg {
4464760c2415Smrg /* We perform synchronous I/O on an asynchronous unit, so no need
4465760c2415Smrg to enqueue AIO_READ_DONE. */
4466760c2415Smrg if (dtp->u.p.async)
4467760c2415Smrg enqueue_done (dtp->u.p.current_unit->au, AIO_WRITE_DONE);
4468760c2415Smrg }
4469760c2415Smrg }
4470760c2415Smrg else
4471760c2415Smrg st_write_done_worker (dtp);
4472760c2415Smrg
4473760c2415Smrg unlock_unit (dtp->u.p.current_unit);
4474760c2415Smrg }
4475760c2415Smrg
4476760c2415Smrg library_end ();
4477760c2415Smrg }
4478760c2415Smrg
4479760c2415Smrg /* Wait operation. We need to keep around the do-nothing version
4480760c2415Smrg of st_wait for compatibility with previous versions, which had marked
4481760c2415Smrg the argument as unused (and thus liable to be removed).
4482760c2415Smrg
4483760c2415Smrg TODO: remove at next bump in version number. */
4484760c2415Smrg
4485760c2415Smrg void
st_wait(st_parameter_wait * wtp)4486760c2415Smrg st_wait (st_parameter_wait *wtp __attribute__((unused)))
4487760c2415Smrg {
4488760c2415Smrg return;
4489760c2415Smrg }
4490760c2415Smrg
4491760c2415Smrg void
st_wait_async(st_parameter_wait * wtp)4492760c2415Smrg st_wait_async (st_parameter_wait *wtp)
4493760c2415Smrg {
4494760c2415Smrg gfc_unit *u = find_unit (wtp->common.unit);
4495*0bfacb9bSmrg if (ASYNC_IO && u && u->au)
4496760c2415Smrg {
4497760c2415Smrg if (wtp->common.flags & IOPARM_WAIT_HAS_ID)
4498760c2415Smrg async_wait_id (&(wtp->common), u->au, *wtp->id);
4499760c2415Smrg else
4500760c2415Smrg async_wait (&(wtp->common), u->au);
4501760c2415Smrg }
4502760c2415Smrg
4503760c2415Smrg unlock_unit (u);
4504760c2415Smrg }
4505760c2415Smrg
4506760c2415Smrg
4507760c2415Smrg /* Receives the scalar information for namelist objects and stores it
4508760c2415Smrg in a linked list of namelist_info types. */
4509760c2415Smrg
4510760c2415Smrg static void
set_nml_var(st_parameter_dt * dtp,void * var_addr,char * var_name,GFC_INTEGER_4 len,gfc_charlen_type string_length,dtype_type dtype,void * dtio_sub,void * vtable)4511760c2415Smrg set_nml_var (st_parameter_dt *dtp, void *var_addr, char *var_name,
4512760c2415Smrg GFC_INTEGER_4 len, gfc_charlen_type string_length,
4513760c2415Smrg dtype_type dtype, void *dtio_sub, void *vtable)
4514760c2415Smrg {
4515760c2415Smrg namelist_info *t1 = NULL;
4516760c2415Smrg namelist_info *nml;
4517760c2415Smrg size_t var_name_len = strlen (var_name);
4518760c2415Smrg
4519760c2415Smrg nml = (namelist_info*) xmalloc (sizeof (namelist_info));
4520760c2415Smrg
4521760c2415Smrg nml->mem_pos = var_addr;
4522760c2415Smrg nml->dtio_sub = dtio_sub;
4523760c2415Smrg nml->vtable = vtable;
4524760c2415Smrg
4525760c2415Smrg nml->var_name = (char*) xmalloc (var_name_len + 1);
4526760c2415Smrg memcpy (nml->var_name, var_name, var_name_len);
4527760c2415Smrg nml->var_name[var_name_len] = '\0';
4528760c2415Smrg
4529760c2415Smrg nml->len = (int) len;
4530760c2415Smrg nml->string_length = (index_type) string_length;
4531760c2415Smrg
4532760c2415Smrg nml->var_rank = (int) (dtype.rank);
4533760c2415Smrg nml->size = (index_type) (dtype.elem_len);
4534760c2415Smrg nml->type = (bt) (dtype.type);
4535760c2415Smrg
4536760c2415Smrg if (nml->var_rank > 0)
4537760c2415Smrg {
4538760c2415Smrg nml->dim = (descriptor_dimension*)
4539760c2415Smrg xmallocarray (nml->var_rank, sizeof (descriptor_dimension));
4540760c2415Smrg nml->ls = (array_loop_spec*)
4541760c2415Smrg xmallocarray (nml->var_rank, sizeof (array_loop_spec));
4542760c2415Smrg }
4543760c2415Smrg else
4544760c2415Smrg {
4545760c2415Smrg nml->dim = NULL;
4546760c2415Smrg nml->ls = NULL;
4547760c2415Smrg }
4548760c2415Smrg
4549760c2415Smrg nml->next = NULL;
4550760c2415Smrg
4551760c2415Smrg if ((dtp->common.flags & IOPARM_DT_IONML_SET) == 0)
4552760c2415Smrg {
4553760c2415Smrg dtp->common.flags |= IOPARM_DT_IONML_SET;
4554760c2415Smrg dtp->u.p.ionml = nml;
4555760c2415Smrg }
4556760c2415Smrg else
4557760c2415Smrg {
4558760c2415Smrg for (t1 = dtp->u.p.ionml; t1->next; t1 = t1->next);
4559760c2415Smrg t1->next = nml;
4560760c2415Smrg }
4561760c2415Smrg }
4562760c2415Smrg
4563760c2415Smrg extern void st_set_nml_var (st_parameter_dt *dtp, void *, char *,
4564760c2415Smrg GFC_INTEGER_4, gfc_charlen_type, dtype_type);
4565760c2415Smrg export_proto(st_set_nml_var);
4566760c2415Smrg
4567760c2415Smrg void
st_set_nml_var(st_parameter_dt * dtp,void * var_addr,char * var_name,GFC_INTEGER_4 len,gfc_charlen_type string_length,dtype_type dtype)4568760c2415Smrg st_set_nml_var (st_parameter_dt *dtp, void *var_addr, char *var_name,
4569760c2415Smrg GFC_INTEGER_4 len, gfc_charlen_type string_length,
4570760c2415Smrg dtype_type dtype)
4571760c2415Smrg {
4572760c2415Smrg set_nml_var (dtp, var_addr, var_name, len, string_length,
4573760c2415Smrg dtype, NULL, NULL);
4574760c2415Smrg }
4575760c2415Smrg
4576760c2415Smrg
4577760c2415Smrg /* Essentially the same as previous but carrying the dtio procedure
4578760c2415Smrg and the vtable as additional arguments. */
4579760c2415Smrg extern void st_set_nml_dtio_var (st_parameter_dt *dtp, void *, char *,
4580760c2415Smrg GFC_INTEGER_4, gfc_charlen_type, dtype_type,
4581760c2415Smrg void *, void *);
4582760c2415Smrg export_proto(st_set_nml_dtio_var);
4583760c2415Smrg
4584760c2415Smrg
4585760c2415Smrg void
st_set_nml_dtio_var(st_parameter_dt * dtp,void * var_addr,char * var_name,GFC_INTEGER_4 len,gfc_charlen_type string_length,dtype_type dtype,void * dtio_sub,void * vtable)4586760c2415Smrg st_set_nml_dtio_var (st_parameter_dt *dtp, void *var_addr, char *var_name,
4587760c2415Smrg GFC_INTEGER_4 len, gfc_charlen_type string_length,
4588760c2415Smrg dtype_type dtype, void *dtio_sub, void *vtable)
4589760c2415Smrg {
4590760c2415Smrg set_nml_var (dtp, var_addr, var_name, len, string_length,
4591760c2415Smrg dtype, dtio_sub, vtable);
4592760c2415Smrg }
4593760c2415Smrg
4594760c2415Smrg /* Store the dimensional information for the namelist object. */
4595760c2415Smrg extern void st_set_nml_var_dim (st_parameter_dt *, GFC_INTEGER_4,
4596760c2415Smrg index_type, index_type,
4597760c2415Smrg index_type);
4598760c2415Smrg export_proto(st_set_nml_var_dim);
4599760c2415Smrg
4600760c2415Smrg void
st_set_nml_var_dim(st_parameter_dt * dtp,GFC_INTEGER_4 n_dim,index_type stride,index_type lbound,index_type ubound)4601760c2415Smrg st_set_nml_var_dim (st_parameter_dt *dtp, GFC_INTEGER_4 n_dim,
4602760c2415Smrg index_type stride, index_type lbound,
4603760c2415Smrg index_type ubound)
4604760c2415Smrg {
4605760c2415Smrg namelist_info *nml;
4606760c2415Smrg int n;
4607760c2415Smrg
4608760c2415Smrg n = (int)n_dim;
4609760c2415Smrg
4610760c2415Smrg for (nml = dtp->u.p.ionml; nml->next; nml = nml->next);
4611760c2415Smrg
4612760c2415Smrg GFC_DIMENSION_SET(nml->dim[n],lbound,ubound,stride);
4613760c2415Smrg }
4614760c2415Smrg
4615760c2415Smrg
4616760c2415Smrg /* Once upon a time, a poor innocent Fortran program was reading a
4617760c2415Smrg file, when suddenly it hit the end-of-file (EOF). Unfortunately
4618760c2415Smrg the OS doesn't tell whether we're at the EOF or whether we already
4619760c2415Smrg went past it. Luckily our hero, libgfortran, keeps track of this.
4620760c2415Smrg Call this function when you detect an EOF condition. See Section
4621760c2415Smrg 9.10.2 in F2003. */
4622760c2415Smrg
4623760c2415Smrg void
hit_eof(st_parameter_dt * dtp)4624760c2415Smrg hit_eof (st_parameter_dt *dtp)
4625760c2415Smrg {
4626760c2415Smrg dtp->u.p.current_unit->flags.position = POSITION_APPEND;
4627760c2415Smrg
4628760c2415Smrg if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
4629760c2415Smrg switch (dtp->u.p.current_unit->endfile)
4630760c2415Smrg {
4631760c2415Smrg case NO_ENDFILE:
4632760c2415Smrg case AT_ENDFILE:
4633760c2415Smrg generate_error (&dtp->common, LIBERROR_END, NULL);
4634760c2415Smrg if (!is_internal_unit (dtp) && !dtp->u.p.namelist_mode)
4635760c2415Smrg {
4636760c2415Smrg dtp->u.p.current_unit->endfile = AFTER_ENDFILE;
4637760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4638760c2415Smrg }
4639760c2415Smrg else
4640760c2415Smrg dtp->u.p.current_unit->endfile = AT_ENDFILE;
4641760c2415Smrg break;
4642760c2415Smrg
4643760c2415Smrg case AFTER_ENDFILE:
4644760c2415Smrg generate_error (&dtp->common, LIBERROR_ENDFILE, NULL);
4645760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4646760c2415Smrg break;
4647760c2415Smrg }
4648760c2415Smrg else
4649760c2415Smrg {
4650760c2415Smrg /* Non-sequential files don't have an ENDFILE record, so we
4651760c2415Smrg can't be at AFTER_ENDFILE. */
4652760c2415Smrg dtp->u.p.current_unit->endfile = AT_ENDFILE;
4653760c2415Smrg generate_error (&dtp->common, LIBERROR_END, NULL);
4654760c2415Smrg dtp->u.p.current_unit->current_record = 0;
4655760c2415Smrg }
4656760c2415Smrg }
4657