1*4c3eb207Smrg /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
2627f7eb2Smrg Contributed by Andy Vaught
3627f7eb2Smrg F2003 I/O support contributed by Jerry DeLisle
4627f7eb2Smrg
5627f7eb2Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6627f7eb2Smrg
7627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or modify
8627f7eb2Smrg it under the terms of the GNU General Public License as published by
9627f7eb2Smrg the Free Software Foundation; either version 3, or (at your option)
10627f7eb2Smrg any later version.
11627f7eb2Smrg
12627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15627f7eb2Smrg GNU General Public License for more details.
16627f7eb2Smrg
17627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg
21627f7eb2Smrg You should have received a copy of the GNU General Public License and
22627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24627f7eb2Smrg <http://www.gnu.org/licenses/>. */
25627f7eb2Smrg
26627f7eb2Smrg #include "io.h"
27627f7eb2Smrg #include "fbuf.h"
28627f7eb2Smrg #include "format.h"
29627f7eb2Smrg #include "unix.h"
30627f7eb2Smrg #include <string.h>
31627f7eb2Smrg #include <ctype.h>
32627f7eb2Smrg #include <assert.h>
33627f7eb2Smrg #include "async.h"
34627f7eb2Smrg
35627f7eb2Smrg typedef unsigned char uchar;
36627f7eb2Smrg
37627f7eb2Smrg /* read.c -- Deal with formatted reads */
38627f7eb2Smrg
39627f7eb2Smrg
40627f7eb2Smrg /* set_integer()-- All of the integer assignments come here to
41627f7eb2Smrg actually place the value into memory. */
42627f7eb2Smrg
43627f7eb2Smrg void
set_integer(void * dest,GFC_INTEGER_LARGEST value,int length)44627f7eb2Smrg set_integer (void *dest, GFC_INTEGER_LARGEST value, int length)
45627f7eb2Smrg {
46627f7eb2Smrg NOTE ("set_integer: %lld %p", (long long int) value, dest);
47627f7eb2Smrg switch (length)
48627f7eb2Smrg {
49627f7eb2Smrg #ifdef HAVE_GFC_INTEGER_16
50627f7eb2Smrg /* length=10 comes about for kind=10 real/complex BOZ, cf. PR41711. */
51627f7eb2Smrg case 10:
52627f7eb2Smrg case 16:
53627f7eb2Smrg {
54627f7eb2Smrg GFC_INTEGER_16 tmp = value;
55627f7eb2Smrg memcpy (dest, (void *) &tmp, length);
56627f7eb2Smrg }
57627f7eb2Smrg break;
58627f7eb2Smrg #endif
59627f7eb2Smrg case 8:
60627f7eb2Smrg {
61627f7eb2Smrg GFC_INTEGER_8 tmp = value;
62627f7eb2Smrg memcpy (dest, (void *) &tmp, length);
63627f7eb2Smrg }
64627f7eb2Smrg break;
65627f7eb2Smrg case 4:
66627f7eb2Smrg {
67627f7eb2Smrg GFC_INTEGER_4 tmp = value;
68627f7eb2Smrg memcpy (dest, (void *) &tmp, length);
69627f7eb2Smrg }
70627f7eb2Smrg break;
71627f7eb2Smrg case 2:
72627f7eb2Smrg {
73627f7eb2Smrg GFC_INTEGER_2 tmp = value;
74627f7eb2Smrg memcpy (dest, (void *) &tmp, length);
75627f7eb2Smrg }
76627f7eb2Smrg break;
77627f7eb2Smrg case 1:
78627f7eb2Smrg {
79627f7eb2Smrg GFC_INTEGER_1 tmp = value;
80627f7eb2Smrg memcpy (dest, (void *) &tmp, length);
81627f7eb2Smrg }
82627f7eb2Smrg break;
83627f7eb2Smrg default:
84627f7eb2Smrg internal_error (NULL, "Bad integer kind");
85627f7eb2Smrg }
86627f7eb2Smrg }
87627f7eb2Smrg
88627f7eb2Smrg
89627f7eb2Smrg /* Max signed value of size give by length argument. */
90627f7eb2Smrg
91627f7eb2Smrg GFC_UINTEGER_LARGEST
si_max(int length)92627f7eb2Smrg si_max (int length)
93627f7eb2Smrg {
94627f7eb2Smrg #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
95627f7eb2Smrg GFC_UINTEGER_LARGEST value;
96627f7eb2Smrg #endif
97627f7eb2Smrg
98627f7eb2Smrg switch (length)
99627f7eb2Smrg {
100627f7eb2Smrg #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
101627f7eb2Smrg case 16:
102627f7eb2Smrg case 10:
103627f7eb2Smrg value = 1;
104627f7eb2Smrg for (int n = 1; n < 4 * length; n++)
105627f7eb2Smrg value = (value << 2) + 3;
106627f7eb2Smrg return value;
107627f7eb2Smrg #endif
108627f7eb2Smrg case 8:
109627f7eb2Smrg return GFC_INTEGER_8_HUGE;
110627f7eb2Smrg case 4:
111627f7eb2Smrg return GFC_INTEGER_4_HUGE;
112627f7eb2Smrg case 2:
113627f7eb2Smrg return GFC_INTEGER_2_HUGE;
114627f7eb2Smrg case 1:
115627f7eb2Smrg return GFC_INTEGER_1_HUGE;
116627f7eb2Smrg default:
117627f7eb2Smrg internal_error (NULL, "Bad integer kind");
118627f7eb2Smrg }
119627f7eb2Smrg }
120627f7eb2Smrg
121627f7eb2Smrg
122627f7eb2Smrg /* convert_real()-- Convert a character representation of a floating
123627f7eb2Smrg point number to the machine number. Returns nonzero if there is an
124627f7eb2Smrg invalid input. Note: many architectures (e.g. IA-64, HP-PA)
125627f7eb2Smrg require that the storage pointed to by the dest argument is
126627f7eb2Smrg properly aligned for the type in question. */
127627f7eb2Smrg
128627f7eb2Smrg int
convert_real(st_parameter_dt * dtp,void * dest,const char * buffer,int length)129627f7eb2Smrg convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
130627f7eb2Smrg {
131627f7eb2Smrg char *endptr = NULL;
132627f7eb2Smrg int round_mode, old_round_mode;
133627f7eb2Smrg
134627f7eb2Smrg switch (dtp->u.p.current_unit->round_status)
135627f7eb2Smrg {
136627f7eb2Smrg case ROUND_COMPATIBLE:
137627f7eb2Smrg /* FIXME: As NEAREST but round away from zero for a tie. */
138627f7eb2Smrg case ROUND_UNSPECIFIED:
139627f7eb2Smrg /* Should not occur. */
140627f7eb2Smrg case ROUND_PROCDEFINED:
141627f7eb2Smrg round_mode = ROUND_NEAREST;
142627f7eb2Smrg break;
143627f7eb2Smrg default:
144627f7eb2Smrg round_mode = dtp->u.p.current_unit->round_status;
145627f7eb2Smrg break;
146627f7eb2Smrg }
147627f7eb2Smrg
148627f7eb2Smrg old_round_mode = get_fpu_rounding_mode();
149627f7eb2Smrg set_fpu_rounding_mode (round_mode);
150627f7eb2Smrg
151627f7eb2Smrg switch (length)
152627f7eb2Smrg {
153627f7eb2Smrg case 4:
154627f7eb2Smrg *((GFC_REAL_4*) dest) =
155627f7eb2Smrg #if defined(HAVE_STRTOF)
156627f7eb2Smrg gfc_strtof (buffer, &endptr);
157627f7eb2Smrg #else
158627f7eb2Smrg (GFC_REAL_4) gfc_strtod (buffer, &endptr);
159627f7eb2Smrg #endif
160627f7eb2Smrg break;
161627f7eb2Smrg
162627f7eb2Smrg case 8:
163627f7eb2Smrg *((GFC_REAL_8*) dest) = gfc_strtod (buffer, &endptr);
164627f7eb2Smrg break;
165627f7eb2Smrg
166627f7eb2Smrg #if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
167627f7eb2Smrg case 10:
168627f7eb2Smrg *((GFC_REAL_10*) dest) = gfc_strtold (buffer, &endptr);
169627f7eb2Smrg break;
170627f7eb2Smrg #endif
171627f7eb2Smrg
172627f7eb2Smrg #if defined(HAVE_GFC_REAL_16)
173627f7eb2Smrg # if defined(GFC_REAL_16_IS_FLOAT128)
174627f7eb2Smrg case 16:
175627f7eb2Smrg *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
176627f7eb2Smrg break;
177627f7eb2Smrg # elif defined(HAVE_STRTOLD)
178627f7eb2Smrg case 16:
179627f7eb2Smrg *((GFC_REAL_16*) dest) = gfc_strtold (buffer, &endptr);
180627f7eb2Smrg break;
181627f7eb2Smrg # endif
182627f7eb2Smrg #endif
183627f7eb2Smrg
184627f7eb2Smrg default:
185627f7eb2Smrg internal_error (&dtp->common, "Unsupported real kind during IO");
186627f7eb2Smrg }
187627f7eb2Smrg
188627f7eb2Smrg set_fpu_rounding_mode (old_round_mode);
189627f7eb2Smrg
190627f7eb2Smrg if (buffer == endptr)
191627f7eb2Smrg {
192627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE,
193627f7eb2Smrg "Error during floating point read");
194627f7eb2Smrg next_record (dtp, 1);
195627f7eb2Smrg return 1;
196627f7eb2Smrg }
197627f7eb2Smrg
198627f7eb2Smrg return 0;
199627f7eb2Smrg }
200627f7eb2Smrg
201627f7eb2Smrg /* convert_infnan()-- Convert character INF/NAN representation to the
202627f7eb2Smrg machine number. Note: many architectures (e.g. IA-64, HP-PA) require
203627f7eb2Smrg that the storage pointed to by the dest argument is properly aligned
204627f7eb2Smrg for the type in question. */
205627f7eb2Smrg
206627f7eb2Smrg int
convert_infnan(st_parameter_dt * dtp,void * dest,const char * buffer,int length)207627f7eb2Smrg convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer,
208627f7eb2Smrg int length)
209627f7eb2Smrg {
210627f7eb2Smrg const char *s = buffer;
211627f7eb2Smrg int is_inf, plus = 1;
212627f7eb2Smrg
213627f7eb2Smrg if (*s == '+')
214627f7eb2Smrg s++;
215627f7eb2Smrg else if (*s == '-')
216627f7eb2Smrg {
217627f7eb2Smrg s++;
218627f7eb2Smrg plus = 0;
219627f7eb2Smrg }
220627f7eb2Smrg
221627f7eb2Smrg is_inf = *s == 'i';
222627f7eb2Smrg
223627f7eb2Smrg switch (length)
224627f7eb2Smrg {
225627f7eb2Smrg case 4:
226627f7eb2Smrg if (is_inf)
227627f7eb2Smrg *((GFC_REAL_4*) dest) = plus ? __builtin_inff () : -__builtin_inff ();
228627f7eb2Smrg else
229627f7eb2Smrg *((GFC_REAL_4*) dest) = plus ? __builtin_nanf ("") : -__builtin_nanf ("");
230627f7eb2Smrg break;
231627f7eb2Smrg
232627f7eb2Smrg case 8:
233627f7eb2Smrg if (is_inf)
234627f7eb2Smrg *((GFC_REAL_8*) dest) = plus ? __builtin_inf () : -__builtin_inf ();
235627f7eb2Smrg else
236627f7eb2Smrg *((GFC_REAL_8*) dest) = plus ? __builtin_nan ("") : -__builtin_nan ("");
237627f7eb2Smrg break;
238627f7eb2Smrg
239627f7eb2Smrg #if defined(HAVE_GFC_REAL_10)
240627f7eb2Smrg case 10:
241627f7eb2Smrg if (is_inf)
242627f7eb2Smrg *((GFC_REAL_10*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
243627f7eb2Smrg else
244627f7eb2Smrg *((GFC_REAL_10*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
245627f7eb2Smrg break;
246627f7eb2Smrg #endif
247627f7eb2Smrg
248627f7eb2Smrg #if defined(HAVE_GFC_REAL_16)
249627f7eb2Smrg # if defined(GFC_REAL_16_IS_FLOAT128)
250627f7eb2Smrg case 16:
251627f7eb2Smrg *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
252627f7eb2Smrg break;
253627f7eb2Smrg # else
254627f7eb2Smrg case 16:
255627f7eb2Smrg if (is_inf)
256627f7eb2Smrg *((GFC_REAL_16*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
257627f7eb2Smrg else
258627f7eb2Smrg *((GFC_REAL_16*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
259627f7eb2Smrg break;
260627f7eb2Smrg # endif
261627f7eb2Smrg #endif
262627f7eb2Smrg
263627f7eb2Smrg default:
264627f7eb2Smrg internal_error (&dtp->common, "Unsupported real kind during IO");
265627f7eb2Smrg }
266627f7eb2Smrg
267627f7eb2Smrg return 0;
268627f7eb2Smrg }
269627f7eb2Smrg
270627f7eb2Smrg
271627f7eb2Smrg /* read_l()-- Read a logical value */
272627f7eb2Smrg
273627f7eb2Smrg void
read_l(st_parameter_dt * dtp,const fnode * f,char * dest,int length)274627f7eb2Smrg read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
275627f7eb2Smrg {
276627f7eb2Smrg char *p;
277627f7eb2Smrg size_t w;
278627f7eb2Smrg
279627f7eb2Smrg w = f->u.w;
280627f7eb2Smrg
281627f7eb2Smrg p = read_block_form (dtp, &w);
282627f7eb2Smrg
283627f7eb2Smrg if (p == NULL)
284627f7eb2Smrg return;
285627f7eb2Smrg
286627f7eb2Smrg while (*p == ' ')
287627f7eb2Smrg {
288627f7eb2Smrg if (--w == 0)
289627f7eb2Smrg goto bad;
290627f7eb2Smrg p++;
291627f7eb2Smrg }
292627f7eb2Smrg
293627f7eb2Smrg if (*p == '.')
294627f7eb2Smrg {
295627f7eb2Smrg if (--w == 0)
296627f7eb2Smrg goto bad;
297627f7eb2Smrg p++;
298627f7eb2Smrg }
299627f7eb2Smrg
300627f7eb2Smrg switch (*p)
301627f7eb2Smrg {
302627f7eb2Smrg case 't':
303627f7eb2Smrg case 'T':
304627f7eb2Smrg set_integer (dest, (GFC_INTEGER_LARGEST) 1, length);
305627f7eb2Smrg break;
306627f7eb2Smrg case 'f':
307627f7eb2Smrg case 'F':
308627f7eb2Smrg set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
309627f7eb2Smrg break;
310627f7eb2Smrg default:
311627f7eb2Smrg bad:
312627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE,
313627f7eb2Smrg "Bad value on logical read");
314627f7eb2Smrg next_record (dtp, 1);
315627f7eb2Smrg break;
316627f7eb2Smrg }
317627f7eb2Smrg }
318627f7eb2Smrg
319627f7eb2Smrg
320627f7eb2Smrg static gfc_char4_t
read_utf8(st_parameter_dt * dtp,size_t * nbytes)321627f7eb2Smrg read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
322627f7eb2Smrg {
323627f7eb2Smrg static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
324627f7eb2Smrg static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
325627f7eb2Smrg size_t nb, nread;
326627f7eb2Smrg gfc_char4_t c;
327627f7eb2Smrg char *s;
328627f7eb2Smrg
329627f7eb2Smrg *nbytes = 1;
330627f7eb2Smrg
331627f7eb2Smrg s = read_block_form (dtp, nbytes);
332627f7eb2Smrg if (s == NULL)
333627f7eb2Smrg return 0;
334627f7eb2Smrg
335627f7eb2Smrg /* If this is a short read, just return. */
336627f7eb2Smrg if (*nbytes == 0)
337627f7eb2Smrg return 0;
338627f7eb2Smrg
339627f7eb2Smrg c = (uchar) s[0];
340627f7eb2Smrg if (c < 0x80)
341627f7eb2Smrg return c;
342627f7eb2Smrg
343627f7eb2Smrg /* The number of leading 1-bits in the first byte indicates how many
344627f7eb2Smrg bytes follow. */
345627f7eb2Smrg for (nb = 2; nb < 7; nb++)
346627f7eb2Smrg if ((c & ~masks[nb-1]) == patns[nb-1])
347627f7eb2Smrg goto found;
348627f7eb2Smrg goto invalid;
349627f7eb2Smrg
350627f7eb2Smrg found:
351627f7eb2Smrg c = (c & masks[nb-1]);
352627f7eb2Smrg nread = nb - 1;
353627f7eb2Smrg
354627f7eb2Smrg s = read_block_form (dtp, &nread);
355627f7eb2Smrg if (s == NULL)
356627f7eb2Smrg return 0;
357627f7eb2Smrg /* Decode the bytes read. */
358627f7eb2Smrg for (size_t i = 1; i < nb; i++)
359627f7eb2Smrg {
360627f7eb2Smrg gfc_char4_t n = *s++;
361627f7eb2Smrg
362627f7eb2Smrg if ((n & 0xC0) != 0x80)
363627f7eb2Smrg goto invalid;
364627f7eb2Smrg
365627f7eb2Smrg c = ((c << 6) + (n & 0x3F));
366627f7eb2Smrg }
367627f7eb2Smrg
368627f7eb2Smrg /* Make sure the shortest possible encoding was used. */
369627f7eb2Smrg if (c <= 0x7F && nb > 1) goto invalid;
370627f7eb2Smrg if (c <= 0x7FF && nb > 2) goto invalid;
371627f7eb2Smrg if (c <= 0xFFFF && nb > 3) goto invalid;
372627f7eb2Smrg if (c <= 0x1FFFFF && nb > 4) goto invalid;
373627f7eb2Smrg if (c <= 0x3FFFFFF && nb > 5) goto invalid;
374627f7eb2Smrg
375627f7eb2Smrg /* Make sure the character is valid. */
376627f7eb2Smrg if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
377627f7eb2Smrg goto invalid;
378627f7eb2Smrg
379627f7eb2Smrg return c;
380627f7eb2Smrg
381627f7eb2Smrg invalid:
382627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
383627f7eb2Smrg return (gfc_char4_t) '?';
384627f7eb2Smrg }
385627f7eb2Smrg
386627f7eb2Smrg
387627f7eb2Smrg static void
read_utf8_char1(st_parameter_dt * dtp,char * p,size_t len,size_t width)388627f7eb2Smrg read_utf8_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
389627f7eb2Smrg {
390627f7eb2Smrg gfc_char4_t c;
391627f7eb2Smrg char *dest;
392627f7eb2Smrg size_t nbytes, j;
393627f7eb2Smrg
394627f7eb2Smrg len = (width < len) ? len : width;
395627f7eb2Smrg
396627f7eb2Smrg dest = (char *) p;
397627f7eb2Smrg
398627f7eb2Smrg /* Proceed with decoding one character at a time. */
399627f7eb2Smrg for (j = 0; j < len; j++, dest++)
400627f7eb2Smrg {
401627f7eb2Smrg c = read_utf8 (dtp, &nbytes);
402627f7eb2Smrg
403627f7eb2Smrg /* Check for a short read and if so, break out. */
404627f7eb2Smrg if (nbytes == 0)
405627f7eb2Smrg break;
406627f7eb2Smrg
407627f7eb2Smrg *dest = c > 255 ? '?' : (uchar) c;
408627f7eb2Smrg }
409627f7eb2Smrg
410627f7eb2Smrg /* If there was a short read, pad the remaining characters. */
411627f7eb2Smrg for (size_t i = j; i < len; i++)
412627f7eb2Smrg *dest++ = ' ';
413627f7eb2Smrg return;
414627f7eb2Smrg }
415627f7eb2Smrg
416627f7eb2Smrg static void
read_default_char1(st_parameter_dt * dtp,char * p,size_t len,size_t width)417627f7eb2Smrg read_default_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
418627f7eb2Smrg {
419627f7eb2Smrg char *s;
420627f7eb2Smrg size_t m;
421627f7eb2Smrg
422627f7eb2Smrg s = read_block_form (dtp, &width);
423627f7eb2Smrg
424627f7eb2Smrg if (s == NULL)
425627f7eb2Smrg return;
426627f7eb2Smrg if (width > len)
427627f7eb2Smrg s += (width - len);
428627f7eb2Smrg
429627f7eb2Smrg m = (width > len) ? len : width;
430627f7eb2Smrg memcpy (p, s, m);
431627f7eb2Smrg
432627f7eb2Smrg if (len > width)
433627f7eb2Smrg memset (p + m, ' ', len - width);
434627f7eb2Smrg }
435627f7eb2Smrg
436627f7eb2Smrg
437627f7eb2Smrg static void
read_utf8_char4(st_parameter_dt * dtp,void * p,size_t len,size_t width)438627f7eb2Smrg read_utf8_char4 (st_parameter_dt *dtp, void *p, size_t len, size_t width)
439627f7eb2Smrg {
440627f7eb2Smrg gfc_char4_t *dest;
441627f7eb2Smrg size_t nbytes, j;
442627f7eb2Smrg
443627f7eb2Smrg len = (width < len) ? len : width;
444627f7eb2Smrg
445627f7eb2Smrg dest = (gfc_char4_t *) p;
446627f7eb2Smrg
447627f7eb2Smrg /* Proceed with decoding one character at a time. */
448627f7eb2Smrg for (j = 0; j < len; j++, dest++)
449627f7eb2Smrg {
450627f7eb2Smrg *dest = read_utf8 (dtp, &nbytes);
451627f7eb2Smrg
452627f7eb2Smrg /* Check for a short read and if so, break out. */
453627f7eb2Smrg if (nbytes == 0)
454627f7eb2Smrg break;
455627f7eb2Smrg }
456627f7eb2Smrg
457627f7eb2Smrg /* If there was a short read, pad the remaining characters. */
458627f7eb2Smrg for (size_t i = j; i < len; i++)
459627f7eb2Smrg *dest++ = (gfc_char4_t) ' ';
460627f7eb2Smrg return;
461627f7eb2Smrg }
462627f7eb2Smrg
463627f7eb2Smrg
464627f7eb2Smrg static void
read_default_char4(st_parameter_dt * dtp,char * p,size_t len,size_t width)465627f7eb2Smrg read_default_char4 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
466627f7eb2Smrg {
467627f7eb2Smrg size_t m, n;
468627f7eb2Smrg gfc_char4_t *dest;
469627f7eb2Smrg
470627f7eb2Smrg if (is_char4_unit(dtp))
471627f7eb2Smrg {
472627f7eb2Smrg gfc_char4_t *s4;
473627f7eb2Smrg
474627f7eb2Smrg s4 = (gfc_char4_t *) read_block_form4 (dtp, &width);
475627f7eb2Smrg
476627f7eb2Smrg if (s4 == NULL)
477627f7eb2Smrg return;
478627f7eb2Smrg if (width > len)
479627f7eb2Smrg s4 += (width - len);
480627f7eb2Smrg
481627f7eb2Smrg m = (width > len) ? len : width;
482627f7eb2Smrg
483627f7eb2Smrg dest = (gfc_char4_t *) p;
484627f7eb2Smrg
485627f7eb2Smrg for (n = 0; n < m; n++)
486627f7eb2Smrg *dest++ = *s4++;
487627f7eb2Smrg
488627f7eb2Smrg if (len > width)
489627f7eb2Smrg {
490627f7eb2Smrg for (n = 0; n < len - width; n++)
491627f7eb2Smrg *dest++ = (gfc_char4_t) ' ';
492627f7eb2Smrg }
493627f7eb2Smrg }
494627f7eb2Smrg else
495627f7eb2Smrg {
496627f7eb2Smrg char *s;
497627f7eb2Smrg
498627f7eb2Smrg s = read_block_form (dtp, &width);
499627f7eb2Smrg
500627f7eb2Smrg if (s == NULL)
501627f7eb2Smrg return;
502627f7eb2Smrg if (width > len)
503627f7eb2Smrg s += (width - len);
504627f7eb2Smrg
505627f7eb2Smrg m = (width > len) ? len : width;
506627f7eb2Smrg
507627f7eb2Smrg dest = (gfc_char4_t *) p;
508627f7eb2Smrg
509627f7eb2Smrg for (n = 0; n < m; n++, dest++, s++)
510627f7eb2Smrg *dest = (unsigned char ) *s;
511627f7eb2Smrg
512627f7eb2Smrg if (len > width)
513627f7eb2Smrg {
514627f7eb2Smrg for (n = 0; n < len - width; n++, dest++)
515627f7eb2Smrg *dest = (unsigned char) ' ';
516627f7eb2Smrg }
517627f7eb2Smrg }
518627f7eb2Smrg }
519627f7eb2Smrg
520627f7eb2Smrg
521627f7eb2Smrg /* read_a()-- Read a character record into a KIND=1 character destination,
522627f7eb2Smrg processing UTF-8 encoding if necessary. */
523627f7eb2Smrg
524627f7eb2Smrg void
read_a(st_parameter_dt * dtp,const fnode * f,char * p,size_t length)525627f7eb2Smrg read_a (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
526627f7eb2Smrg {
527627f7eb2Smrg size_t w;
528627f7eb2Smrg
529627f7eb2Smrg if (f->u.w == -1) /* '(A)' edit descriptor */
530627f7eb2Smrg w = length;
531627f7eb2Smrg else
532627f7eb2Smrg w = f->u.w;
533627f7eb2Smrg
534627f7eb2Smrg /* Read in w characters, treating comma as not a separator. */
535627f7eb2Smrg dtp->u.p.sf_read_comma = 0;
536627f7eb2Smrg
537627f7eb2Smrg if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
538627f7eb2Smrg read_utf8_char1 (dtp, p, length, w);
539627f7eb2Smrg else
540627f7eb2Smrg read_default_char1 (dtp, p, length, w);
541627f7eb2Smrg
542627f7eb2Smrg dtp->u.p.sf_read_comma =
543627f7eb2Smrg dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
544627f7eb2Smrg }
545627f7eb2Smrg
546627f7eb2Smrg
547627f7eb2Smrg /* read_a_char4()-- Read a character record into a KIND=4 character destination,
548627f7eb2Smrg processing UTF-8 encoding if necessary. */
549627f7eb2Smrg
550627f7eb2Smrg void
read_a_char4(st_parameter_dt * dtp,const fnode * f,char * p,size_t length)551627f7eb2Smrg read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
552627f7eb2Smrg {
553627f7eb2Smrg size_t w;
554627f7eb2Smrg
555627f7eb2Smrg if (f->u.w == -1) /* '(A)' edit descriptor */
556627f7eb2Smrg w = length;
557627f7eb2Smrg else
558627f7eb2Smrg w = f->u.w;
559627f7eb2Smrg
560627f7eb2Smrg /* Read in w characters, treating comma as not a separator. */
561627f7eb2Smrg dtp->u.p.sf_read_comma = 0;
562627f7eb2Smrg
563627f7eb2Smrg if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
564627f7eb2Smrg read_utf8_char4 (dtp, p, length, w);
565627f7eb2Smrg else
566627f7eb2Smrg read_default_char4 (dtp, p, length, w);
567627f7eb2Smrg
568627f7eb2Smrg dtp->u.p.sf_read_comma =
569627f7eb2Smrg dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
570627f7eb2Smrg }
571627f7eb2Smrg
572627f7eb2Smrg /* eat_leading_spaces()-- Given a character pointer and a width,
573627f7eb2Smrg ignore the leading spaces. */
574627f7eb2Smrg
575627f7eb2Smrg static char *
eat_leading_spaces(size_t * width,char * p)576627f7eb2Smrg eat_leading_spaces (size_t *width, char *p)
577627f7eb2Smrg {
578627f7eb2Smrg for (;;)
579627f7eb2Smrg {
580627f7eb2Smrg if (*width == 0 || *p != ' ')
581627f7eb2Smrg break;
582627f7eb2Smrg
583627f7eb2Smrg (*width)--;
584627f7eb2Smrg p++;
585627f7eb2Smrg }
586627f7eb2Smrg
587627f7eb2Smrg return p;
588627f7eb2Smrg }
589627f7eb2Smrg
590627f7eb2Smrg
591627f7eb2Smrg static char
next_char(st_parameter_dt * dtp,char ** p,size_t * w)592627f7eb2Smrg next_char (st_parameter_dt *dtp, char **p, size_t *w)
593627f7eb2Smrg {
594627f7eb2Smrg char c, *q;
595627f7eb2Smrg
596627f7eb2Smrg if (*w == 0)
597627f7eb2Smrg return '\0';
598627f7eb2Smrg
599627f7eb2Smrg q = *p;
600627f7eb2Smrg c = *q++;
601627f7eb2Smrg *p = q;
602627f7eb2Smrg
603627f7eb2Smrg (*w)--;
604627f7eb2Smrg
605627f7eb2Smrg if (c != ' ')
606627f7eb2Smrg return c;
607627f7eb2Smrg if (dtp->u.p.blank_status != BLANK_UNSPECIFIED)
608627f7eb2Smrg return ' '; /* return a blank to signal a null */
609627f7eb2Smrg
610627f7eb2Smrg /* At this point, the rest of the field has to be trailing blanks */
611627f7eb2Smrg
612627f7eb2Smrg while (*w > 0)
613627f7eb2Smrg {
614627f7eb2Smrg if (*q++ != ' ')
615627f7eb2Smrg return '?';
616627f7eb2Smrg (*w)--;
617627f7eb2Smrg }
618627f7eb2Smrg
619627f7eb2Smrg *p = q;
620627f7eb2Smrg return '\0';
621627f7eb2Smrg }
622627f7eb2Smrg
623627f7eb2Smrg
624627f7eb2Smrg /* read_decimal()-- Read a decimal integer value. The values here are
625627f7eb2Smrg signed values. */
626627f7eb2Smrg
627627f7eb2Smrg void
read_decimal(st_parameter_dt * dtp,const fnode * f,char * dest,int length)628627f7eb2Smrg read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
629627f7eb2Smrg {
630627f7eb2Smrg GFC_UINTEGER_LARGEST value, maxv, maxv_10;
631627f7eb2Smrg GFC_INTEGER_LARGEST v;
632627f7eb2Smrg size_t w;
633627f7eb2Smrg int negative;
634627f7eb2Smrg char c, *p;
635627f7eb2Smrg
636627f7eb2Smrg w = f->u.w;
637627f7eb2Smrg
638*4c3eb207Smrg /* This is a legacy extension, and the frontend will only allow such cases
639*4c3eb207Smrg * through when -fdec-format-defaults is passed.
640*4c3eb207Smrg */
641*4c3eb207Smrg if (w == (size_t) DEFAULT_WIDTH)
642*4c3eb207Smrg w = default_width_for_integer (length);
643*4c3eb207Smrg
644627f7eb2Smrg p = read_block_form (dtp, &w);
645627f7eb2Smrg
646627f7eb2Smrg if (p == NULL)
647627f7eb2Smrg return;
648627f7eb2Smrg
649627f7eb2Smrg p = eat_leading_spaces (&w, p);
650627f7eb2Smrg if (w == 0)
651627f7eb2Smrg {
652627f7eb2Smrg set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
653627f7eb2Smrg return;
654627f7eb2Smrg }
655627f7eb2Smrg
656627f7eb2Smrg negative = 0;
657627f7eb2Smrg
658627f7eb2Smrg switch (*p)
659627f7eb2Smrg {
660627f7eb2Smrg case '-':
661627f7eb2Smrg negative = 1;
662627f7eb2Smrg /* Fall through */
663627f7eb2Smrg
664627f7eb2Smrg case '+':
665627f7eb2Smrg p++;
666627f7eb2Smrg if (--w == 0)
667627f7eb2Smrg goto bad;
668627f7eb2Smrg /* Fall through */
669627f7eb2Smrg
670627f7eb2Smrg default:
671627f7eb2Smrg break;
672627f7eb2Smrg }
673627f7eb2Smrg
674627f7eb2Smrg maxv = si_max (length);
675627f7eb2Smrg if (negative)
676627f7eb2Smrg maxv++;
677627f7eb2Smrg maxv_10 = maxv / 10;
678627f7eb2Smrg
679627f7eb2Smrg /* At this point we have a digit-string */
680627f7eb2Smrg value = 0;
681627f7eb2Smrg
682627f7eb2Smrg for (;;)
683627f7eb2Smrg {
684627f7eb2Smrg c = next_char (dtp, &p, &w);
685627f7eb2Smrg if (c == '\0')
686627f7eb2Smrg break;
687627f7eb2Smrg
688627f7eb2Smrg if (c == ' ')
689627f7eb2Smrg {
690627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_NULL)
691627f7eb2Smrg {
692627f7eb2Smrg /* Skip spaces. */
693627f7eb2Smrg for ( ; w > 0; p++, w--)
694627f7eb2Smrg if (*p != ' ') break;
695627f7eb2Smrg continue;
696627f7eb2Smrg }
697627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
698627f7eb2Smrg }
699627f7eb2Smrg
700627f7eb2Smrg if (c < '0' || c > '9')
701627f7eb2Smrg goto bad;
702627f7eb2Smrg
703627f7eb2Smrg if (value > maxv_10)
704627f7eb2Smrg goto overflow;
705627f7eb2Smrg
706627f7eb2Smrg c -= '0';
707627f7eb2Smrg value = 10 * value;
708627f7eb2Smrg
709627f7eb2Smrg if (value > maxv - c)
710627f7eb2Smrg goto overflow;
711627f7eb2Smrg value += c;
712627f7eb2Smrg }
713627f7eb2Smrg
714627f7eb2Smrg if (negative)
715627f7eb2Smrg v = -value;
716627f7eb2Smrg else
717627f7eb2Smrg v = value;
718627f7eb2Smrg
719627f7eb2Smrg set_integer (dest, v, length);
720627f7eb2Smrg return;
721627f7eb2Smrg
722627f7eb2Smrg bad:
723627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE,
724627f7eb2Smrg "Bad value during integer read");
725627f7eb2Smrg next_record (dtp, 1);
726627f7eb2Smrg return;
727627f7eb2Smrg
728627f7eb2Smrg overflow:
729627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
730627f7eb2Smrg "Value overflowed during integer read");
731627f7eb2Smrg next_record (dtp, 1);
732627f7eb2Smrg
733627f7eb2Smrg }
734627f7eb2Smrg
735627f7eb2Smrg
736627f7eb2Smrg /* read_radix()-- This function reads values for non-decimal radixes.
737627f7eb2Smrg The difference here is that we treat the values here as unsigned
738627f7eb2Smrg values for the purposes of overflow. If minus sign is present and
739627f7eb2Smrg the top bit is set, the value will be incorrect. */
740627f7eb2Smrg
741627f7eb2Smrg void
read_radix(st_parameter_dt * dtp,const fnode * f,char * dest,int length,int radix)742627f7eb2Smrg read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
743627f7eb2Smrg int radix)
744627f7eb2Smrg {
745627f7eb2Smrg GFC_UINTEGER_LARGEST value, maxv, maxv_r;
746627f7eb2Smrg GFC_INTEGER_LARGEST v;
747627f7eb2Smrg size_t w;
748627f7eb2Smrg int negative;
749627f7eb2Smrg char c, *p;
750627f7eb2Smrg
751627f7eb2Smrg w = f->u.w;
752627f7eb2Smrg
753627f7eb2Smrg p = read_block_form (dtp, &w);
754627f7eb2Smrg
755627f7eb2Smrg if (p == NULL)
756627f7eb2Smrg return;
757627f7eb2Smrg
758627f7eb2Smrg p = eat_leading_spaces (&w, p);
759627f7eb2Smrg if (w == 0)
760627f7eb2Smrg {
761627f7eb2Smrg set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
762627f7eb2Smrg return;
763627f7eb2Smrg }
764627f7eb2Smrg
765627f7eb2Smrg /* Maximum unsigned value, assuming two's complement. */
766627f7eb2Smrg maxv = 2 * si_max (length) + 1;
767627f7eb2Smrg maxv_r = maxv / radix;
768627f7eb2Smrg
769627f7eb2Smrg negative = 0;
770627f7eb2Smrg value = 0;
771627f7eb2Smrg
772627f7eb2Smrg switch (*p)
773627f7eb2Smrg {
774627f7eb2Smrg case '-':
775627f7eb2Smrg negative = 1;
776627f7eb2Smrg /* Fall through */
777627f7eb2Smrg
778627f7eb2Smrg case '+':
779627f7eb2Smrg p++;
780627f7eb2Smrg if (--w == 0)
781627f7eb2Smrg goto bad;
782627f7eb2Smrg /* Fall through */
783627f7eb2Smrg
784627f7eb2Smrg default:
785627f7eb2Smrg break;
786627f7eb2Smrg }
787627f7eb2Smrg
788627f7eb2Smrg /* At this point we have a digit-string */
789627f7eb2Smrg value = 0;
790627f7eb2Smrg
791627f7eb2Smrg for (;;)
792627f7eb2Smrg {
793627f7eb2Smrg c = next_char (dtp, &p, &w);
794627f7eb2Smrg if (c == '\0')
795627f7eb2Smrg break;
796627f7eb2Smrg if (c == ' ')
797627f7eb2Smrg {
798627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_NULL) continue;
799627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
800627f7eb2Smrg }
801627f7eb2Smrg
802627f7eb2Smrg switch (radix)
803627f7eb2Smrg {
804627f7eb2Smrg case 2:
805627f7eb2Smrg if (c < '0' || c > '1')
806627f7eb2Smrg goto bad;
807627f7eb2Smrg break;
808627f7eb2Smrg
809627f7eb2Smrg case 8:
810627f7eb2Smrg if (c < '0' || c > '7')
811627f7eb2Smrg goto bad;
812627f7eb2Smrg break;
813627f7eb2Smrg
814627f7eb2Smrg case 16:
815627f7eb2Smrg switch (c)
816627f7eb2Smrg {
817627f7eb2Smrg case '0':
818627f7eb2Smrg case '1':
819627f7eb2Smrg case '2':
820627f7eb2Smrg case '3':
821627f7eb2Smrg case '4':
822627f7eb2Smrg case '5':
823627f7eb2Smrg case '6':
824627f7eb2Smrg case '7':
825627f7eb2Smrg case '8':
826627f7eb2Smrg case '9':
827627f7eb2Smrg break;
828627f7eb2Smrg
829627f7eb2Smrg case 'a':
830627f7eb2Smrg case 'b':
831627f7eb2Smrg case 'c':
832627f7eb2Smrg case 'd':
833627f7eb2Smrg case 'e':
834627f7eb2Smrg case 'f':
835627f7eb2Smrg c = c - 'a' + '9' + 1;
836627f7eb2Smrg break;
837627f7eb2Smrg
838627f7eb2Smrg case 'A':
839627f7eb2Smrg case 'B':
840627f7eb2Smrg case 'C':
841627f7eb2Smrg case 'D':
842627f7eb2Smrg case 'E':
843627f7eb2Smrg case 'F':
844627f7eb2Smrg c = c - 'A' + '9' + 1;
845627f7eb2Smrg break;
846627f7eb2Smrg
847627f7eb2Smrg default:
848627f7eb2Smrg goto bad;
849627f7eb2Smrg }
850627f7eb2Smrg
851627f7eb2Smrg break;
852627f7eb2Smrg }
853627f7eb2Smrg
854627f7eb2Smrg if (value > maxv_r)
855627f7eb2Smrg goto overflow;
856627f7eb2Smrg
857627f7eb2Smrg c -= '0';
858627f7eb2Smrg value = radix * value;
859627f7eb2Smrg
860627f7eb2Smrg if (maxv - c < value)
861627f7eb2Smrg goto overflow;
862627f7eb2Smrg value += c;
863627f7eb2Smrg }
864627f7eb2Smrg
865627f7eb2Smrg v = value;
866627f7eb2Smrg if (negative)
867627f7eb2Smrg v = -v;
868627f7eb2Smrg
869627f7eb2Smrg set_integer (dest, v, length);
870627f7eb2Smrg return;
871627f7eb2Smrg
872627f7eb2Smrg bad:
873627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE,
874627f7eb2Smrg "Bad value during integer read");
875627f7eb2Smrg next_record (dtp, 1);
876627f7eb2Smrg return;
877627f7eb2Smrg
878627f7eb2Smrg overflow:
879627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
880627f7eb2Smrg "Value overflowed during integer read");
881627f7eb2Smrg next_record (dtp, 1);
882627f7eb2Smrg
883627f7eb2Smrg }
884627f7eb2Smrg
885627f7eb2Smrg
886627f7eb2Smrg /* read_f()-- Read a floating point number with F-style editing, which
887627f7eb2Smrg is what all of the other floating point descriptors behave as. The
888627f7eb2Smrg tricky part is that optional spaces are allowed after an E or D,
889627f7eb2Smrg and the implicit decimal point if a decimal point is not present in
890627f7eb2Smrg the input. */
891627f7eb2Smrg
892627f7eb2Smrg void
read_f(st_parameter_dt * dtp,const fnode * f,char * dest,int length)893627f7eb2Smrg read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
894627f7eb2Smrg {
895627f7eb2Smrg #define READF_TMP 50
896627f7eb2Smrg char tmp[READF_TMP];
897627f7eb2Smrg size_t buf_size = 0;
898627f7eb2Smrg size_t w;
899627f7eb2Smrg int seen_dp, exponent;
900627f7eb2Smrg int exponent_sign;
901627f7eb2Smrg const char *p;
902627f7eb2Smrg char *buffer;
903627f7eb2Smrg char *out;
904627f7eb2Smrg int seen_int_digit; /* Seen a digit before the decimal point? */
905627f7eb2Smrg int seen_dec_digit; /* Seen a digit after the decimal point? */
906627f7eb2Smrg
907627f7eb2Smrg seen_dp = 0;
908627f7eb2Smrg seen_int_digit = 0;
909627f7eb2Smrg seen_dec_digit = 0;
910627f7eb2Smrg exponent_sign = 1;
911627f7eb2Smrg exponent = 0;
912627f7eb2Smrg w = f->u.w;
913627f7eb2Smrg buffer = tmp;
914627f7eb2Smrg
915627f7eb2Smrg /* Read in the next block. */
916627f7eb2Smrg p = read_block_form (dtp, &w);
917627f7eb2Smrg if (p == NULL)
918627f7eb2Smrg return;
919627f7eb2Smrg p = eat_leading_spaces (&w, (char*) p);
920627f7eb2Smrg if (w == 0)
921627f7eb2Smrg goto zero;
922627f7eb2Smrg
923627f7eb2Smrg /* In this buffer we're going to re-format the number cleanly to be parsed
924627f7eb2Smrg by convert_real in the end; this assures we're using strtod from the
925627f7eb2Smrg C library for parsing and thus probably get the best accuracy possible.
926627f7eb2Smrg This process may add a '+0.0' in front of the number as well as change the
927627f7eb2Smrg exponent because of an implicit decimal point or the like. Thus allocating
928627f7eb2Smrg strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
929627f7eb2Smrg original buffer had should be enough. */
930627f7eb2Smrg buf_size = w + 11;
931627f7eb2Smrg if (buf_size > READF_TMP)
932627f7eb2Smrg buffer = xmalloc (buf_size);
933627f7eb2Smrg
934627f7eb2Smrg out = buffer;
935627f7eb2Smrg
936627f7eb2Smrg /* Optional sign */
937627f7eb2Smrg if (*p == '-' || *p == '+')
938627f7eb2Smrg {
939627f7eb2Smrg if (*p == '-')
940627f7eb2Smrg *(out++) = '-';
941627f7eb2Smrg ++p;
942627f7eb2Smrg --w;
943627f7eb2Smrg }
944627f7eb2Smrg
945627f7eb2Smrg p = eat_leading_spaces (&w, (char*) p);
946627f7eb2Smrg if (w == 0)
947627f7eb2Smrg goto zero;
948627f7eb2Smrg
949627f7eb2Smrg /* Check for Infinity or NaN. */
950627f7eb2Smrg if (unlikely ((w >= 3 && (*p == 'i' || *p == 'I' || *p == 'n' || *p == 'N'))))
951627f7eb2Smrg {
952627f7eb2Smrg int seen_paren = 0;
953627f7eb2Smrg char *save = out;
954627f7eb2Smrg
955627f7eb2Smrg /* Scan through the buffer keeping track of spaces and parenthesis. We
956627f7eb2Smrg null terminate the string as soon as we see a left paren or if we are
957627f7eb2Smrg BLANK_NULL mode. Leading spaces have already been skipped above,
958627f7eb2Smrg trailing spaces are ignored by converting to '\0'. A space
959627f7eb2Smrg between "NaN" and the optional perenthesis is not permitted. */
960627f7eb2Smrg while (w > 0)
961627f7eb2Smrg {
962627f7eb2Smrg *out = tolower (*p);
963627f7eb2Smrg switch (*p)
964627f7eb2Smrg {
965627f7eb2Smrg case ' ':
966627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_ZERO)
967627f7eb2Smrg {
968627f7eb2Smrg *out = '0';
969627f7eb2Smrg break;
970627f7eb2Smrg }
971627f7eb2Smrg *out = '\0';
972627f7eb2Smrg if (seen_paren == 1)
973627f7eb2Smrg goto bad_float;
974627f7eb2Smrg break;
975627f7eb2Smrg case '(':
976627f7eb2Smrg seen_paren++;
977627f7eb2Smrg *out = '\0';
978627f7eb2Smrg break;
979627f7eb2Smrg case ')':
980627f7eb2Smrg if (seen_paren++ != 1)
981627f7eb2Smrg goto bad_float;
982627f7eb2Smrg break;
983627f7eb2Smrg default:
984627f7eb2Smrg if (!isalnum (*out))
985627f7eb2Smrg goto bad_float;
986627f7eb2Smrg }
987627f7eb2Smrg --w;
988627f7eb2Smrg ++p;
989627f7eb2Smrg ++out;
990627f7eb2Smrg }
991627f7eb2Smrg
992627f7eb2Smrg *out = '\0';
993627f7eb2Smrg
994627f7eb2Smrg if (seen_paren != 0 && seen_paren != 2)
995627f7eb2Smrg goto bad_float;
996627f7eb2Smrg
997627f7eb2Smrg if ((strcmp (save, "inf") == 0) || (strcmp (save, "infinity") == 0))
998627f7eb2Smrg {
999627f7eb2Smrg if (seen_paren)
1000627f7eb2Smrg goto bad_float;
1001627f7eb2Smrg }
1002627f7eb2Smrg else if (strcmp (save, "nan") != 0)
1003627f7eb2Smrg goto bad_float;
1004627f7eb2Smrg
1005627f7eb2Smrg convert_infnan (dtp, dest, buffer, length);
1006627f7eb2Smrg if (buf_size > READF_TMP)
1007627f7eb2Smrg free (buffer);
1008627f7eb2Smrg return;
1009627f7eb2Smrg }
1010627f7eb2Smrg
1011627f7eb2Smrg /* Process the mantissa string. */
1012627f7eb2Smrg while (w > 0)
1013627f7eb2Smrg {
1014627f7eb2Smrg switch (*p)
1015627f7eb2Smrg {
1016627f7eb2Smrg case ',':
1017627f7eb2Smrg if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA)
1018627f7eb2Smrg goto bad_float;
1019627f7eb2Smrg /* Fall through. */
1020627f7eb2Smrg case '.':
1021627f7eb2Smrg if (seen_dp)
1022627f7eb2Smrg goto bad_float;
1023627f7eb2Smrg if (!seen_int_digit)
1024627f7eb2Smrg *(out++) = '0';
1025627f7eb2Smrg *(out++) = '.';
1026627f7eb2Smrg seen_dp = 1;
1027627f7eb2Smrg break;
1028627f7eb2Smrg
1029627f7eb2Smrg case ' ':
1030627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_ZERO)
1031627f7eb2Smrg {
1032627f7eb2Smrg *(out++) = '0';
1033627f7eb2Smrg goto found_digit;
1034627f7eb2Smrg }
1035627f7eb2Smrg else if (dtp->u.p.blank_status == BLANK_NULL)
1036627f7eb2Smrg break;
1037627f7eb2Smrg else
1038627f7eb2Smrg /* TODO: Should we check instead that there are only trailing
1039627f7eb2Smrg blanks here, as is done below for exponents? */
1040627f7eb2Smrg goto done;
1041627f7eb2Smrg /* Fall through. */
1042627f7eb2Smrg case '0':
1043627f7eb2Smrg case '1':
1044627f7eb2Smrg case '2':
1045627f7eb2Smrg case '3':
1046627f7eb2Smrg case '4':
1047627f7eb2Smrg case '5':
1048627f7eb2Smrg case '6':
1049627f7eb2Smrg case '7':
1050627f7eb2Smrg case '8':
1051627f7eb2Smrg case '9':
1052627f7eb2Smrg *(out++) = *p;
1053627f7eb2Smrg found_digit:
1054627f7eb2Smrg if (!seen_dp)
1055627f7eb2Smrg seen_int_digit = 1;
1056627f7eb2Smrg else
1057627f7eb2Smrg seen_dec_digit = 1;
1058627f7eb2Smrg break;
1059627f7eb2Smrg
1060627f7eb2Smrg case '-':
1061627f7eb2Smrg case '+':
1062627f7eb2Smrg goto exponent;
1063627f7eb2Smrg
1064627f7eb2Smrg case 'e':
1065627f7eb2Smrg case 'E':
1066627f7eb2Smrg case 'd':
1067627f7eb2Smrg case 'D':
1068627f7eb2Smrg case 'q':
1069627f7eb2Smrg case 'Q':
1070627f7eb2Smrg ++p;
1071627f7eb2Smrg --w;
1072627f7eb2Smrg goto exponent;
1073627f7eb2Smrg
1074627f7eb2Smrg default:
1075627f7eb2Smrg goto bad_float;
1076627f7eb2Smrg }
1077627f7eb2Smrg
1078627f7eb2Smrg ++p;
1079627f7eb2Smrg --w;
1080627f7eb2Smrg }
1081627f7eb2Smrg
1082627f7eb2Smrg /* No exponent has been seen, so we use the current scale factor. */
1083627f7eb2Smrg exponent = - dtp->u.p.scale_factor;
1084627f7eb2Smrg goto done;
1085627f7eb2Smrg
1086627f7eb2Smrg /* At this point the start of an exponent has been found. */
1087627f7eb2Smrg exponent:
1088627f7eb2Smrg p = eat_leading_spaces (&w, (char*) p);
1089627f7eb2Smrg if (*p == '-' || *p == '+')
1090627f7eb2Smrg {
1091627f7eb2Smrg if (*p == '-')
1092627f7eb2Smrg exponent_sign = -1;
1093627f7eb2Smrg ++p;
1094627f7eb2Smrg --w;
1095627f7eb2Smrg }
1096627f7eb2Smrg
1097627f7eb2Smrg /* At this point a digit string is required. We calculate the value
1098627f7eb2Smrg of the exponent in order to take account of the scale factor and
1099627f7eb2Smrg the d parameter before explict conversion takes place. */
1100627f7eb2Smrg
1101627f7eb2Smrg if (w == 0)
1102627f7eb2Smrg {
1103627f7eb2Smrg /* Extension: allow default exponent of 0 when omitted. */
1104627f7eb2Smrg if (dtp->common.flags & IOPARM_DT_DEC_EXT)
1105627f7eb2Smrg goto done;
1106627f7eb2Smrg else
1107627f7eb2Smrg goto bad_float;
1108627f7eb2Smrg }
1109627f7eb2Smrg
1110627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
1111627f7eb2Smrg {
1112627f7eb2Smrg while (w > 0 && isdigit (*p))
1113627f7eb2Smrg {
1114627f7eb2Smrg exponent *= 10;
1115627f7eb2Smrg exponent += *p - '0';
1116627f7eb2Smrg ++p;
1117627f7eb2Smrg --w;
1118627f7eb2Smrg }
1119627f7eb2Smrg
1120627f7eb2Smrg /* Only allow trailing blanks. */
1121627f7eb2Smrg while (w > 0)
1122627f7eb2Smrg {
1123627f7eb2Smrg if (*p != ' ')
1124627f7eb2Smrg goto bad_float;
1125627f7eb2Smrg ++p;
1126627f7eb2Smrg --w;
1127627f7eb2Smrg }
1128627f7eb2Smrg }
1129627f7eb2Smrg else /* BZ or BN status is enabled. */
1130627f7eb2Smrg {
1131627f7eb2Smrg while (w > 0)
1132627f7eb2Smrg {
1133627f7eb2Smrg if (*p == ' ')
1134627f7eb2Smrg {
1135627f7eb2Smrg if (dtp->u.p.blank_status == BLANK_ZERO)
1136627f7eb2Smrg exponent *= 10;
1137627f7eb2Smrg else
1138627f7eb2Smrg assert (dtp->u.p.blank_status == BLANK_NULL);
1139627f7eb2Smrg }
1140627f7eb2Smrg else if (!isdigit (*p))
1141627f7eb2Smrg goto bad_float;
1142627f7eb2Smrg else
1143627f7eb2Smrg {
1144627f7eb2Smrg exponent *= 10;
1145627f7eb2Smrg exponent += *p - '0';
1146627f7eb2Smrg }
1147627f7eb2Smrg
1148627f7eb2Smrg ++p;
1149627f7eb2Smrg --w;
1150627f7eb2Smrg }
1151627f7eb2Smrg }
1152627f7eb2Smrg
1153627f7eb2Smrg exponent *= exponent_sign;
1154627f7eb2Smrg
1155627f7eb2Smrg done:
1156627f7eb2Smrg /* Use the precision specified in the format if no decimal point has been
1157627f7eb2Smrg seen. */
1158627f7eb2Smrg if (!seen_dp)
1159627f7eb2Smrg exponent -= f->u.real.d;
1160627f7eb2Smrg
1161627f7eb2Smrg /* Output a trailing '0' after decimal point if not yet found. */
1162627f7eb2Smrg if (seen_dp && !seen_dec_digit)
1163627f7eb2Smrg *(out++) = '0';
1164627f7eb2Smrg /* Handle input of style "E+NN" by inserting a 0 for the
1165627f7eb2Smrg significand. */
1166627f7eb2Smrg else if (!seen_int_digit && !seen_dec_digit)
1167627f7eb2Smrg {
1168627f7eb2Smrg notify_std (&dtp->common, GFC_STD_LEGACY,
1169627f7eb2Smrg "REAL input of style 'E+NN'");
1170627f7eb2Smrg *(out++) = '0';
1171627f7eb2Smrg }
1172627f7eb2Smrg
1173627f7eb2Smrg /* Print out the exponent to finish the reformatted number. Maximum 4
1174627f7eb2Smrg digits for the exponent. */
1175627f7eb2Smrg if (exponent != 0)
1176627f7eb2Smrg {
1177627f7eb2Smrg int dig;
1178627f7eb2Smrg
1179627f7eb2Smrg *(out++) = 'e';
1180627f7eb2Smrg if (exponent < 0)
1181627f7eb2Smrg {
1182627f7eb2Smrg *(out++) = '-';
1183627f7eb2Smrg exponent = - exponent;
1184627f7eb2Smrg }
1185627f7eb2Smrg
1186627f7eb2Smrg if (exponent >= 10000)
1187627f7eb2Smrg goto bad_float;
1188627f7eb2Smrg
1189627f7eb2Smrg for (dig = 3; dig >= 0; --dig)
1190627f7eb2Smrg {
1191627f7eb2Smrg out[dig] = (char) ('0' + exponent % 10);
1192627f7eb2Smrg exponent /= 10;
1193627f7eb2Smrg }
1194627f7eb2Smrg out += 4;
1195627f7eb2Smrg }
1196627f7eb2Smrg *(out++) = '\0';
1197627f7eb2Smrg
1198627f7eb2Smrg /* Do the actual conversion. */
1199627f7eb2Smrg convert_real (dtp, dest, buffer, length);
1200627f7eb2Smrg if (buf_size > READF_TMP)
1201627f7eb2Smrg free (buffer);
1202627f7eb2Smrg return;
1203627f7eb2Smrg
1204627f7eb2Smrg /* The value read is zero. */
1205627f7eb2Smrg zero:
1206627f7eb2Smrg switch (length)
1207627f7eb2Smrg {
1208627f7eb2Smrg case 4:
1209627f7eb2Smrg *((GFC_REAL_4 *) dest) = 0.0;
1210627f7eb2Smrg break;
1211627f7eb2Smrg
1212627f7eb2Smrg case 8:
1213627f7eb2Smrg *((GFC_REAL_8 *) dest) = 0.0;
1214627f7eb2Smrg break;
1215627f7eb2Smrg
1216627f7eb2Smrg #ifdef HAVE_GFC_REAL_10
1217627f7eb2Smrg case 10:
1218627f7eb2Smrg *((GFC_REAL_10 *) dest) = 0.0;
1219627f7eb2Smrg break;
1220627f7eb2Smrg #endif
1221627f7eb2Smrg
1222627f7eb2Smrg #ifdef HAVE_GFC_REAL_16
1223627f7eb2Smrg case 16:
1224627f7eb2Smrg *((GFC_REAL_16 *) dest) = 0.0;
1225627f7eb2Smrg break;
1226627f7eb2Smrg #endif
1227627f7eb2Smrg
1228627f7eb2Smrg default:
1229627f7eb2Smrg internal_error (&dtp->common, "Unsupported real kind during IO");
1230627f7eb2Smrg }
1231627f7eb2Smrg return;
1232627f7eb2Smrg
1233627f7eb2Smrg bad_float:
1234627f7eb2Smrg if (buf_size > READF_TMP)
1235627f7eb2Smrg free (buffer);
1236627f7eb2Smrg generate_error (&dtp->common, LIBERROR_READ_VALUE,
1237627f7eb2Smrg "Bad value during floating point read");
1238627f7eb2Smrg next_record (dtp, 1);
1239627f7eb2Smrg return;
1240627f7eb2Smrg }
1241627f7eb2Smrg
1242627f7eb2Smrg
1243627f7eb2Smrg /* read_x()-- Deal with the X/TR descriptor. We just read some data
1244627f7eb2Smrg and never look at it. */
1245627f7eb2Smrg
1246627f7eb2Smrg void
read_x(st_parameter_dt * dtp,size_t n)1247627f7eb2Smrg read_x (st_parameter_dt *dtp, size_t n)
1248627f7eb2Smrg {
1249627f7eb2Smrg size_t length;
1250627f7eb2Smrg int q, q2;
1251627f7eb2Smrg
1252627f7eb2Smrg if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
1253627f7eb2Smrg && dtp->u.p.current_unit->bytes_left < (gfc_offset) n)
1254627f7eb2Smrg n = dtp->u.p.current_unit->bytes_left;
1255627f7eb2Smrg
1256627f7eb2Smrg if (n == 0)
1257627f7eb2Smrg return;
1258627f7eb2Smrg
1259627f7eb2Smrg length = n;
1260627f7eb2Smrg
1261627f7eb2Smrg if (is_internal_unit (dtp))
1262627f7eb2Smrg {
1263627f7eb2Smrg mem_alloc_r (dtp->u.p.current_unit->s, &length);
1264627f7eb2Smrg if (unlikely (length < n))
1265627f7eb2Smrg n = length;
1266627f7eb2Smrg goto done;
1267627f7eb2Smrg }
1268627f7eb2Smrg
1269627f7eb2Smrg if (dtp->u.p.sf_seen_eor)
1270627f7eb2Smrg return;
1271627f7eb2Smrg
1272627f7eb2Smrg n = 0;
1273627f7eb2Smrg while (n < length)
1274627f7eb2Smrg {
1275627f7eb2Smrg q = fbuf_getc (dtp->u.p.current_unit);
1276627f7eb2Smrg if (q == EOF)
1277627f7eb2Smrg break;
1278627f7eb2Smrg else if (dtp->u.p.current_unit->flags.cc != CC_NONE
1279627f7eb2Smrg && (q == '\n' || q == '\r'))
1280627f7eb2Smrg {
1281627f7eb2Smrg /* Unexpected end of line. Set the position. */
1282627f7eb2Smrg dtp->u.p.sf_seen_eor = 1;
1283627f7eb2Smrg
1284627f7eb2Smrg /* If we see an EOR during non-advancing I/O, we need to skip
1285627f7eb2Smrg the rest of the I/O statement. Set the corresponding flag. */
1286627f7eb2Smrg if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
1287627f7eb2Smrg dtp->u.p.eor_condition = 1;
1288627f7eb2Smrg
1289627f7eb2Smrg /* If we encounter a CR, it might be a CRLF. */
1290627f7eb2Smrg if (q == '\r') /* Probably a CRLF */
1291627f7eb2Smrg {
1292627f7eb2Smrg /* See if there is an LF. */
1293627f7eb2Smrg q2 = fbuf_getc (dtp->u.p.current_unit);
1294627f7eb2Smrg if (q2 == '\n')
1295627f7eb2Smrg dtp->u.p.sf_seen_eor = 2;
1296627f7eb2Smrg else if (q2 != EOF) /* Oops, seek back. */
1297627f7eb2Smrg fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
1298627f7eb2Smrg }
1299627f7eb2Smrg goto done;
1300627f7eb2Smrg }
1301627f7eb2Smrg n++;
1302627f7eb2Smrg }
1303627f7eb2Smrg
1304627f7eb2Smrg done:
1305627f7eb2Smrg if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
1306627f7eb2Smrg dtp->u.p.current_unit->has_size)
1307627f7eb2Smrg dtp->u.p.current_unit->size_used += (GFC_IO_INT) n;
1308627f7eb2Smrg dtp->u.p.current_unit->bytes_left -= n;
1309627f7eb2Smrg dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
1310627f7eb2Smrg }
1311627f7eb2Smrg
1312