xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/io/read.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg /* Copyright (C) 2002-2022 Free Software Foundation, Inc.
2181254a7Smrg    Contributed by Andy Vaught
3181254a7Smrg    F2003 I/O support contributed by Jerry DeLisle
4181254a7Smrg 
5181254a7Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6181254a7Smrg 
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or modify
8181254a7Smrg it under the terms of the GNU General Public License as published by
9181254a7Smrg the Free Software Foundation; either version 3, or (at your option)
10181254a7Smrg any later version.
11181254a7Smrg 
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg 
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg 
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>.  */
25181254a7Smrg 
26181254a7Smrg #include "io.h"
27181254a7Smrg #include "fbuf.h"
28181254a7Smrg #include "format.h"
29181254a7Smrg #include "unix.h"
30181254a7Smrg #include <string.h>
31181254a7Smrg #include <assert.h>
32181254a7Smrg #include "async.h"
33181254a7Smrg 
34181254a7Smrg typedef unsigned char uchar;
35181254a7Smrg 
36181254a7Smrg /* read.c -- Deal with formatted reads */
37181254a7Smrg 
38181254a7Smrg 
39181254a7Smrg /* set_integer()-- All of the integer assignments come here to
40181254a7Smrg    actually place the value into memory.  */
41181254a7Smrg 
42181254a7Smrg void
set_integer(void * dest,GFC_INTEGER_LARGEST value,int length)43181254a7Smrg set_integer (void *dest, GFC_INTEGER_LARGEST value, int length)
44181254a7Smrg {
45181254a7Smrg   NOTE ("set_integer: %lld %p", (long long int) value, dest);
46181254a7Smrg   switch (length)
47181254a7Smrg     {
48181254a7Smrg #ifdef HAVE_GFC_INTEGER_16
49*b1e83836Smrg #ifdef HAVE_GFC_REAL_17
50*b1e83836Smrg     case 17:
51*b1e83836Smrg       {
52*b1e83836Smrg 	GFC_INTEGER_16 tmp = value;
53*b1e83836Smrg 	memcpy (dest, (void *) &tmp, 16);
54*b1e83836Smrg       }
55*b1e83836Smrg       break;
56*b1e83836Smrg #endif
57181254a7Smrg /* length=10 comes about for kind=10 real/complex BOZ, cf. PR41711. */
58181254a7Smrg     case 10:
59181254a7Smrg     case 16:
60181254a7Smrg       {
61181254a7Smrg 	GFC_INTEGER_16 tmp = value;
62181254a7Smrg 	memcpy (dest, (void *) &tmp, length);
63181254a7Smrg       }
64181254a7Smrg       break;
65181254a7Smrg #endif
66181254a7Smrg     case 8:
67181254a7Smrg       {
68181254a7Smrg 	GFC_INTEGER_8 tmp = value;
69181254a7Smrg 	memcpy (dest, (void *) &tmp, length);
70181254a7Smrg       }
71181254a7Smrg       break;
72181254a7Smrg     case 4:
73181254a7Smrg       {
74181254a7Smrg 	GFC_INTEGER_4 tmp = value;
75181254a7Smrg 	memcpy (dest, (void *) &tmp, length);
76181254a7Smrg       }
77181254a7Smrg       break;
78181254a7Smrg     case 2:
79181254a7Smrg       {
80181254a7Smrg 	GFC_INTEGER_2 tmp = value;
81181254a7Smrg 	memcpy (dest, (void *) &tmp, length);
82181254a7Smrg       }
83181254a7Smrg       break;
84181254a7Smrg     case 1:
85181254a7Smrg       {
86181254a7Smrg 	GFC_INTEGER_1 tmp = value;
87181254a7Smrg 	memcpy (dest, (void *) &tmp, length);
88181254a7Smrg       }
89181254a7Smrg       break;
90181254a7Smrg     default:
91181254a7Smrg       internal_error (NULL, "Bad integer kind");
92181254a7Smrg     }
93181254a7Smrg }
94181254a7Smrg 
95181254a7Smrg 
96181254a7Smrg /* Max signed value of size give by length argument.  */
97181254a7Smrg 
98181254a7Smrg GFC_UINTEGER_LARGEST
si_max(int length)99181254a7Smrg si_max (int length)
100181254a7Smrg {
101181254a7Smrg #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
102181254a7Smrg   GFC_UINTEGER_LARGEST value;
103181254a7Smrg #endif
104181254a7Smrg 
105181254a7Smrg   switch (length)
106181254a7Smrg     {
107*b1e83836Smrg #if defined HAVE_GFC_REAL_17
108*b1e83836Smrg     case 17:
109*b1e83836Smrg       value = 1;
110*b1e83836Smrg       for (int n = 1; n < 4 * 16; n++)
111*b1e83836Smrg 	value = (value << 2) + 3;
112*b1e83836Smrg       return value;
113*b1e83836Smrg #endif
114181254a7Smrg #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
115181254a7Smrg     case 16:
116181254a7Smrg     case 10:
117181254a7Smrg       value = 1;
118181254a7Smrg       for (int n = 1; n < 4 * length; n++)
119181254a7Smrg         value = (value << 2) + 3;
120181254a7Smrg       return value;
121181254a7Smrg #endif
122181254a7Smrg     case 8:
123181254a7Smrg       return GFC_INTEGER_8_HUGE;
124181254a7Smrg     case 4:
125181254a7Smrg       return GFC_INTEGER_4_HUGE;
126181254a7Smrg     case 2:
127181254a7Smrg       return GFC_INTEGER_2_HUGE;
128181254a7Smrg     case 1:
129181254a7Smrg       return GFC_INTEGER_1_HUGE;
130181254a7Smrg     default:
131181254a7Smrg       internal_error (NULL, "Bad integer kind");
132181254a7Smrg     }
133181254a7Smrg }
134181254a7Smrg 
135181254a7Smrg 
136181254a7Smrg /* convert_real()-- Convert a character representation of a floating
137181254a7Smrg    point number to the machine number.  Returns nonzero if there is an
138181254a7Smrg    invalid input.  Note: many architectures (e.g. IA-64, HP-PA)
139181254a7Smrg    require that the storage pointed to by the dest argument is
140181254a7Smrg    properly aligned for the type in question.  */
141181254a7Smrg 
142181254a7Smrg int
convert_real(st_parameter_dt * dtp,void * dest,const char * buffer,int length)143181254a7Smrg convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
144181254a7Smrg {
145181254a7Smrg   char *endptr = NULL;
146181254a7Smrg   int round_mode, old_round_mode;
147181254a7Smrg 
148181254a7Smrg   switch (dtp->u.p.current_unit->round_status)
149181254a7Smrg     {
150181254a7Smrg       case ROUND_COMPATIBLE:
151181254a7Smrg 	/* FIXME: As NEAREST but round away from zero for a tie.  */
152181254a7Smrg       case ROUND_UNSPECIFIED:
153181254a7Smrg 	/* Should not occur.  */
154181254a7Smrg       case ROUND_PROCDEFINED:
155181254a7Smrg 	round_mode = ROUND_NEAREST;
156181254a7Smrg 	break;
157181254a7Smrg       default:
158181254a7Smrg 	round_mode = dtp->u.p.current_unit->round_status;
159181254a7Smrg 	break;
160181254a7Smrg     }
161181254a7Smrg 
162181254a7Smrg   old_round_mode = get_fpu_rounding_mode();
163181254a7Smrg   set_fpu_rounding_mode (round_mode);
164181254a7Smrg 
165181254a7Smrg   switch (length)
166181254a7Smrg     {
167181254a7Smrg     case 4:
168181254a7Smrg       *((GFC_REAL_4*) dest) =
169181254a7Smrg #if defined(HAVE_STRTOF)
170181254a7Smrg 	gfc_strtof (buffer, &endptr);
171181254a7Smrg #else
172181254a7Smrg 	(GFC_REAL_4) gfc_strtod (buffer, &endptr);
173181254a7Smrg #endif
174181254a7Smrg       break;
175181254a7Smrg 
176181254a7Smrg     case 8:
177181254a7Smrg       *((GFC_REAL_8*) dest) = gfc_strtod (buffer, &endptr);
178181254a7Smrg       break;
179181254a7Smrg 
180181254a7Smrg #if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
181181254a7Smrg     case 10:
182181254a7Smrg       *((GFC_REAL_10*) dest) = gfc_strtold (buffer, &endptr);
183181254a7Smrg       break;
184181254a7Smrg #endif
185181254a7Smrg 
186181254a7Smrg #if defined(HAVE_GFC_REAL_16)
187181254a7Smrg # if defined(GFC_REAL_16_IS_FLOAT128)
188181254a7Smrg     case 16:
189181254a7Smrg       *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
190181254a7Smrg       break;
191181254a7Smrg # elif defined(HAVE_STRTOLD)
192181254a7Smrg     case 16:
193181254a7Smrg       *((GFC_REAL_16*) dest) = gfc_strtold (buffer, &endptr);
194181254a7Smrg       break;
195181254a7Smrg # endif
196181254a7Smrg #endif
197181254a7Smrg 
198*b1e83836Smrg #if defined(HAVE_GFC_REAL_17)
199*b1e83836Smrg     case 17:
200*b1e83836Smrg # if defined(POWER_IEEE128)
201*b1e83836Smrg       *((GFC_REAL_17*) dest) = __strtoieee128 (buffer, &endptr);
202*b1e83836Smrg # else
203*b1e83836Smrg       *((GFC_REAL_17*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
204*b1e83836Smrg # endif
205*b1e83836Smrg       break;
206*b1e83836Smrg #endif
207*b1e83836Smrg 
208181254a7Smrg     default:
209181254a7Smrg       internal_error (&dtp->common, "Unsupported real kind during IO");
210181254a7Smrg     }
211181254a7Smrg 
212181254a7Smrg   set_fpu_rounding_mode (old_round_mode);
213181254a7Smrg 
214181254a7Smrg   if (buffer == endptr)
215181254a7Smrg     {
216181254a7Smrg       generate_error (&dtp->common, LIBERROR_READ_VALUE,
217181254a7Smrg   		      "Error during floating point read");
218181254a7Smrg       next_record (dtp, 1);
219181254a7Smrg       return 1;
220181254a7Smrg     }
221181254a7Smrg 
222181254a7Smrg   return 0;
223181254a7Smrg }
224181254a7Smrg 
225181254a7Smrg /* convert_infnan()-- Convert character INF/NAN representation to the
226181254a7Smrg    machine number.  Note: many architectures (e.g. IA-64, HP-PA) require
227181254a7Smrg    that the storage pointed to by the dest argument is properly aligned
228181254a7Smrg    for the type in question.  */
229181254a7Smrg 
230181254a7Smrg int
convert_infnan(st_parameter_dt * dtp,void * dest,const char * buffer,int length)231181254a7Smrg convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer,
232181254a7Smrg 	        int length)
233181254a7Smrg {
234181254a7Smrg   const char *s = buffer;
235181254a7Smrg   int is_inf, plus = 1;
236181254a7Smrg 
237181254a7Smrg   if (*s == '+')
238181254a7Smrg     s++;
239181254a7Smrg   else if (*s == '-')
240181254a7Smrg     {
241181254a7Smrg       s++;
242181254a7Smrg       plus = 0;
243181254a7Smrg     }
244181254a7Smrg 
245181254a7Smrg   is_inf = *s == 'i';
246181254a7Smrg 
247181254a7Smrg   switch (length)
248181254a7Smrg     {
249181254a7Smrg     case 4:
250181254a7Smrg       if (is_inf)
251181254a7Smrg 	*((GFC_REAL_4*) dest) = plus ? __builtin_inff () : -__builtin_inff ();
252181254a7Smrg       else
253181254a7Smrg 	*((GFC_REAL_4*) dest) = plus ? __builtin_nanf ("") : -__builtin_nanf ("");
254181254a7Smrg       break;
255181254a7Smrg 
256181254a7Smrg     case 8:
257181254a7Smrg       if (is_inf)
258181254a7Smrg 	*((GFC_REAL_8*) dest) = plus ? __builtin_inf () : -__builtin_inf ();
259181254a7Smrg       else
260181254a7Smrg 	*((GFC_REAL_8*) dest) = plus ? __builtin_nan ("") : -__builtin_nan ("");
261181254a7Smrg       break;
262181254a7Smrg 
263181254a7Smrg #if defined(HAVE_GFC_REAL_10)
264181254a7Smrg     case 10:
265181254a7Smrg       if (is_inf)
266181254a7Smrg 	*((GFC_REAL_10*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
267181254a7Smrg       else
268181254a7Smrg 	*((GFC_REAL_10*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
269181254a7Smrg       break;
270181254a7Smrg #endif
271181254a7Smrg 
272181254a7Smrg #if defined(HAVE_GFC_REAL_16)
273181254a7Smrg # if defined(GFC_REAL_16_IS_FLOAT128)
274181254a7Smrg     case 16:
275181254a7Smrg       *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
276181254a7Smrg       break;
277181254a7Smrg # else
278181254a7Smrg     case 16:
279181254a7Smrg       if (is_inf)
280181254a7Smrg 	*((GFC_REAL_16*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
281181254a7Smrg       else
282181254a7Smrg 	*((GFC_REAL_16*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
283181254a7Smrg       break;
284181254a7Smrg # endif
285181254a7Smrg #endif
286181254a7Smrg 
287*b1e83836Smrg #if defined(HAVE_GFC_REAL_17)
288*b1e83836Smrg     case 17:
289*b1e83836Smrg       if (is_inf)
290*b1e83836Smrg 	*((GFC_REAL_17*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
291*b1e83836Smrg       else
292*b1e83836Smrg 	*((GFC_REAL_17*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
293*b1e83836Smrg       break;
294*b1e83836Smrg #endif
295*b1e83836Smrg 
296181254a7Smrg     default:
297181254a7Smrg       internal_error (&dtp->common, "Unsupported real kind during IO");
298181254a7Smrg     }
299181254a7Smrg 
300181254a7Smrg   return 0;
301181254a7Smrg }
302181254a7Smrg 
303181254a7Smrg 
304181254a7Smrg /* read_l()-- Read a logical value */
305181254a7Smrg 
306181254a7Smrg void
read_l(st_parameter_dt * dtp,const fnode * f,char * dest,int length)307181254a7Smrg read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
308181254a7Smrg {
309181254a7Smrg   char *p;
310181254a7Smrg   size_t w;
311181254a7Smrg 
312181254a7Smrg   w = f->u.w;
313181254a7Smrg 
314181254a7Smrg   p = read_block_form (dtp, &w);
315181254a7Smrg 
316181254a7Smrg   if (p == NULL)
317181254a7Smrg     return;
318181254a7Smrg 
319181254a7Smrg   while (*p == ' ')
320181254a7Smrg     {
321181254a7Smrg       if (--w == 0)
322181254a7Smrg 	goto bad;
323181254a7Smrg       p++;
324181254a7Smrg     }
325181254a7Smrg 
326181254a7Smrg   if (*p == '.')
327181254a7Smrg     {
328181254a7Smrg       if (--w == 0)
329181254a7Smrg 	goto bad;
330181254a7Smrg       p++;
331181254a7Smrg     }
332181254a7Smrg 
333181254a7Smrg   switch (*p)
334181254a7Smrg     {
335181254a7Smrg     case 't':
336181254a7Smrg     case 'T':
337181254a7Smrg       set_integer (dest, (GFC_INTEGER_LARGEST) 1, length);
338181254a7Smrg       break;
339181254a7Smrg     case 'f':
340181254a7Smrg     case 'F':
341181254a7Smrg       set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
342181254a7Smrg       break;
343181254a7Smrg     default:
344181254a7Smrg     bad:
345181254a7Smrg       generate_error (&dtp->common, LIBERROR_READ_VALUE,
346181254a7Smrg 		      "Bad value on logical read");
347181254a7Smrg       next_record (dtp, 1);
348181254a7Smrg       break;
349181254a7Smrg     }
350181254a7Smrg }
351181254a7Smrg 
352181254a7Smrg 
353181254a7Smrg static gfc_char4_t
read_utf8(st_parameter_dt * dtp,size_t * nbytes)354181254a7Smrg read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
355181254a7Smrg {
356181254a7Smrg   static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
357181254a7Smrg   static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
358181254a7Smrg   size_t nb, nread;
359181254a7Smrg   gfc_char4_t c;
360181254a7Smrg   char *s;
361181254a7Smrg 
362181254a7Smrg   *nbytes = 1;
363181254a7Smrg 
364181254a7Smrg   s = read_block_form (dtp, nbytes);
365181254a7Smrg   if (s == NULL)
366181254a7Smrg     return 0;
367181254a7Smrg 
368181254a7Smrg   /* If this is a short read, just return.  */
369181254a7Smrg   if (*nbytes == 0)
370181254a7Smrg     return 0;
371181254a7Smrg 
372181254a7Smrg   c = (uchar) s[0];
373181254a7Smrg   if (c < 0x80)
374181254a7Smrg     return c;
375181254a7Smrg 
376181254a7Smrg   /* The number of leading 1-bits in the first byte indicates how many
377181254a7Smrg      bytes follow.  */
378181254a7Smrg   for (nb = 2; nb < 7; nb++)
379181254a7Smrg     if ((c & ~masks[nb-1]) == patns[nb-1])
380181254a7Smrg       goto found;
381181254a7Smrg   goto invalid;
382181254a7Smrg 
383181254a7Smrg  found:
384181254a7Smrg   c = (c & masks[nb-1]);
385181254a7Smrg   nread = nb - 1;
386181254a7Smrg 
387181254a7Smrg   s = read_block_form (dtp, &nread);
388181254a7Smrg   if (s == NULL)
389181254a7Smrg     return 0;
390181254a7Smrg   /* Decode the bytes read.  */
391181254a7Smrg   for (size_t i = 1; i < nb; i++)
392181254a7Smrg     {
393181254a7Smrg       gfc_char4_t n = *s++;
394181254a7Smrg 
395181254a7Smrg       if ((n & 0xC0) != 0x80)
396181254a7Smrg 	goto invalid;
397181254a7Smrg 
398181254a7Smrg       c = ((c << 6) + (n & 0x3F));
399181254a7Smrg     }
400181254a7Smrg 
401181254a7Smrg   /* Make sure the shortest possible encoding was used.  */
402181254a7Smrg   if (c <=      0x7F && nb > 1) goto invalid;
403181254a7Smrg   if (c <=     0x7FF && nb > 2) goto invalid;
404181254a7Smrg   if (c <=    0xFFFF && nb > 3) goto invalid;
405181254a7Smrg   if (c <=  0x1FFFFF && nb > 4) goto invalid;
406181254a7Smrg   if (c <= 0x3FFFFFF && nb > 5) goto invalid;
407181254a7Smrg 
408181254a7Smrg   /* Make sure the character is valid.  */
409181254a7Smrg   if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
410181254a7Smrg     goto invalid;
411181254a7Smrg 
412181254a7Smrg   return c;
413181254a7Smrg 
414181254a7Smrg  invalid:
415181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
416181254a7Smrg   return (gfc_char4_t) '?';
417181254a7Smrg }
418181254a7Smrg 
419181254a7Smrg 
420181254a7Smrg static void
read_utf8_char1(st_parameter_dt * dtp,char * p,size_t len,size_t width)421181254a7Smrg read_utf8_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
422181254a7Smrg {
423181254a7Smrg   gfc_char4_t c;
424181254a7Smrg   char *dest;
425181254a7Smrg   size_t nbytes, j;
426181254a7Smrg 
427181254a7Smrg   len = (width < len) ? len : width;
428181254a7Smrg 
429181254a7Smrg   dest = (char *) p;
430181254a7Smrg 
431181254a7Smrg   /* Proceed with decoding one character at a time.  */
432181254a7Smrg   for (j = 0; j < len; j++, dest++)
433181254a7Smrg     {
434181254a7Smrg       c = read_utf8 (dtp, &nbytes);
435181254a7Smrg 
436181254a7Smrg       /* Check for a short read and if so, break out.  */
437181254a7Smrg       if (nbytes == 0)
438181254a7Smrg 	break;
439181254a7Smrg 
440181254a7Smrg       *dest = c > 255 ? '?' : (uchar) c;
441181254a7Smrg     }
442181254a7Smrg 
443181254a7Smrg   /* If there was a short read, pad the remaining characters.  */
444181254a7Smrg   for (size_t i = j; i < len; i++)
445181254a7Smrg     *dest++ = ' ';
446181254a7Smrg   return;
447181254a7Smrg }
448181254a7Smrg 
449181254a7Smrg static void
read_default_char1(st_parameter_dt * dtp,char * p,size_t len,size_t width)450181254a7Smrg read_default_char1 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
451181254a7Smrg {
452181254a7Smrg   char *s;
453181254a7Smrg   size_t m;
454181254a7Smrg 
455181254a7Smrg   s = read_block_form (dtp, &width);
456181254a7Smrg 
457181254a7Smrg   if (s == NULL)
458181254a7Smrg     return;
459181254a7Smrg   if (width > len)
460181254a7Smrg      s += (width - len);
461181254a7Smrg 
462181254a7Smrg   m = (width > len) ? len : width;
463181254a7Smrg   memcpy (p, s, m);
464181254a7Smrg 
465181254a7Smrg   if (len > width)
466181254a7Smrg     memset (p + m, ' ', len - width);
467181254a7Smrg }
468181254a7Smrg 
469181254a7Smrg 
470181254a7Smrg static void
read_utf8_char4(st_parameter_dt * dtp,void * p,size_t len,size_t width)471181254a7Smrg read_utf8_char4 (st_parameter_dt *dtp, void *p, size_t len, size_t width)
472181254a7Smrg {
473181254a7Smrg   gfc_char4_t *dest;
474181254a7Smrg   size_t nbytes, j;
475181254a7Smrg 
476181254a7Smrg   len = (width < len) ? len : width;
477181254a7Smrg 
478181254a7Smrg   dest = (gfc_char4_t *) p;
479181254a7Smrg 
480181254a7Smrg   /* Proceed with decoding one character at a time.  */
481181254a7Smrg   for (j = 0; j < len; j++, dest++)
482181254a7Smrg     {
483181254a7Smrg       *dest = read_utf8 (dtp, &nbytes);
484181254a7Smrg 
485181254a7Smrg       /* Check for a short read and if so, break out.  */
486181254a7Smrg       if (nbytes == 0)
487181254a7Smrg 	break;
488181254a7Smrg     }
489181254a7Smrg 
490181254a7Smrg   /* If there was a short read, pad the remaining characters.  */
491181254a7Smrg   for (size_t i = j; i < len; i++)
492181254a7Smrg     *dest++ = (gfc_char4_t) ' ';
493181254a7Smrg   return;
494181254a7Smrg }
495181254a7Smrg 
496181254a7Smrg 
497181254a7Smrg static void
read_default_char4(st_parameter_dt * dtp,char * p,size_t len,size_t width)498181254a7Smrg read_default_char4 (st_parameter_dt *dtp, char *p, size_t len, size_t width)
499181254a7Smrg {
500181254a7Smrg   size_t m, n;
501181254a7Smrg   gfc_char4_t *dest;
502181254a7Smrg 
503181254a7Smrg   if (is_char4_unit(dtp))
504181254a7Smrg     {
505181254a7Smrg       gfc_char4_t *s4;
506181254a7Smrg 
507181254a7Smrg       s4 = (gfc_char4_t *) read_block_form4 (dtp, &width);
508181254a7Smrg 
509181254a7Smrg       if (s4 == NULL)
510181254a7Smrg 	return;
511181254a7Smrg       if (width > len)
512181254a7Smrg 	 s4 += (width - len);
513181254a7Smrg 
514181254a7Smrg       m = (width > len) ? len : width;
515181254a7Smrg 
516181254a7Smrg       dest = (gfc_char4_t *) p;
517181254a7Smrg 
518181254a7Smrg       for (n = 0; n < m; n++)
519181254a7Smrg 	*dest++ = *s4++;
520181254a7Smrg 
521181254a7Smrg       if (len > width)
522181254a7Smrg 	{
523181254a7Smrg 	  for (n = 0; n < len - width; n++)
524181254a7Smrg 	    *dest++ = (gfc_char4_t) ' ';
525181254a7Smrg 	}
526181254a7Smrg     }
527181254a7Smrg   else
528181254a7Smrg     {
529181254a7Smrg       char *s;
530181254a7Smrg 
531181254a7Smrg       s = read_block_form (dtp, &width);
532181254a7Smrg 
533181254a7Smrg       if (s == NULL)
534181254a7Smrg 	return;
535181254a7Smrg       if (width > len)
536181254a7Smrg 	 s += (width - len);
537181254a7Smrg 
538181254a7Smrg       m = (width > len) ? len : width;
539181254a7Smrg 
540181254a7Smrg       dest = (gfc_char4_t *) p;
541181254a7Smrg 
542181254a7Smrg       for (n = 0; n < m; n++, dest++, s++)
543181254a7Smrg 	*dest = (unsigned char ) *s;
544181254a7Smrg 
545181254a7Smrg       if (len > width)
546181254a7Smrg 	{
547181254a7Smrg 	  for (n = 0; n < len - width; n++, dest++)
548181254a7Smrg 	    *dest = (unsigned char) ' ';
549181254a7Smrg 	}
550181254a7Smrg     }
551181254a7Smrg }
552181254a7Smrg 
553181254a7Smrg 
554181254a7Smrg /* read_a()-- Read a character record into a KIND=1 character destination,
555181254a7Smrg    processing UTF-8 encoding if necessary.  */
556181254a7Smrg 
557181254a7Smrg void
read_a(st_parameter_dt * dtp,const fnode * f,char * p,size_t length)558181254a7Smrg read_a (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
559181254a7Smrg {
560181254a7Smrg   size_t w;
561181254a7Smrg 
562181254a7Smrg   if (f->u.w == -1) /* '(A)' edit descriptor  */
563181254a7Smrg     w = length;
564181254a7Smrg   else
565181254a7Smrg     w = f->u.w;
566181254a7Smrg 
567181254a7Smrg   /* Read in w characters, treating comma as not a separator.  */
568181254a7Smrg   dtp->u.p.sf_read_comma = 0;
569181254a7Smrg 
570181254a7Smrg   if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
571181254a7Smrg     read_utf8_char1 (dtp, p, length, w);
572181254a7Smrg   else
573181254a7Smrg     read_default_char1 (dtp, p, length, w);
574181254a7Smrg 
575181254a7Smrg   dtp->u.p.sf_read_comma =
576181254a7Smrg     dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
577181254a7Smrg }
578181254a7Smrg 
579181254a7Smrg 
580181254a7Smrg /* read_a_char4()-- Read a character record into a KIND=4 character destination,
581181254a7Smrg    processing UTF-8 encoding if necessary.  */
582181254a7Smrg 
583181254a7Smrg void
read_a_char4(st_parameter_dt * dtp,const fnode * f,char * p,size_t length)584181254a7Smrg read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, size_t length)
585181254a7Smrg {
586181254a7Smrg   size_t w;
587181254a7Smrg 
588181254a7Smrg   if (f->u.w == -1) /* '(A)' edit descriptor  */
589181254a7Smrg     w = length;
590181254a7Smrg   else
591181254a7Smrg     w = f->u.w;
592181254a7Smrg 
593181254a7Smrg   /* Read in w characters, treating comma as not a separator.  */
594181254a7Smrg   dtp->u.p.sf_read_comma = 0;
595181254a7Smrg 
596181254a7Smrg   if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
597181254a7Smrg     read_utf8_char4 (dtp, p, length, w);
598181254a7Smrg   else
599181254a7Smrg     read_default_char4 (dtp, p, length, w);
600181254a7Smrg 
601181254a7Smrg   dtp->u.p.sf_read_comma =
602181254a7Smrg     dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
603181254a7Smrg }
604181254a7Smrg 
605181254a7Smrg /* eat_leading_spaces()-- Given a character pointer and a width,
606181254a7Smrg    ignore the leading spaces.  */
607181254a7Smrg 
608181254a7Smrg static char *
eat_leading_spaces(size_t * width,char * p)609181254a7Smrg eat_leading_spaces (size_t *width, char *p)
610181254a7Smrg {
611181254a7Smrg   for (;;)
612181254a7Smrg     {
613181254a7Smrg       if (*width == 0 || *p != ' ')
614181254a7Smrg 	break;
615181254a7Smrg 
616181254a7Smrg       (*width)--;
617181254a7Smrg       p++;
618181254a7Smrg     }
619181254a7Smrg 
620181254a7Smrg   return p;
621181254a7Smrg }
622181254a7Smrg 
623181254a7Smrg 
624181254a7Smrg static char
next_char(st_parameter_dt * dtp,char ** p,size_t * w)625181254a7Smrg next_char (st_parameter_dt *dtp, char **p, size_t *w)
626181254a7Smrg {
627181254a7Smrg   char c, *q;
628181254a7Smrg 
629181254a7Smrg   if (*w == 0)
630181254a7Smrg     return '\0';
631181254a7Smrg 
632181254a7Smrg   q = *p;
633181254a7Smrg   c = *q++;
634181254a7Smrg   *p = q;
635181254a7Smrg 
636181254a7Smrg   (*w)--;
637181254a7Smrg 
638181254a7Smrg   if (c != ' ')
639181254a7Smrg     return c;
640181254a7Smrg   if (dtp->u.p.blank_status != BLANK_UNSPECIFIED)
641181254a7Smrg     return ' ';  /* return a blank to signal a null */
642181254a7Smrg 
643181254a7Smrg   /* At this point, the rest of the field has to be trailing blanks */
644181254a7Smrg 
645181254a7Smrg   while (*w > 0)
646181254a7Smrg     {
647181254a7Smrg       if (*q++ != ' ')
648181254a7Smrg 	return '?';
649181254a7Smrg       (*w)--;
650181254a7Smrg     }
651181254a7Smrg 
652181254a7Smrg   *p = q;
653181254a7Smrg   return '\0';
654181254a7Smrg }
655181254a7Smrg 
656181254a7Smrg 
657181254a7Smrg /* read_decimal()-- Read a decimal integer value.  The values here are
658181254a7Smrg    signed values. */
659181254a7Smrg 
660181254a7Smrg void
read_decimal(st_parameter_dt * dtp,const fnode * f,char * dest,int length)661181254a7Smrg read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
662181254a7Smrg {
663181254a7Smrg   GFC_UINTEGER_LARGEST value, maxv, maxv_10;
664181254a7Smrg   GFC_INTEGER_LARGEST v;
665181254a7Smrg   size_t w;
666181254a7Smrg   int negative;
667181254a7Smrg   char c, *p;
668181254a7Smrg 
669181254a7Smrg   w = f->u.w;
670181254a7Smrg 
671fb8a8121Smrg   /* This is a legacy extension, and the frontend will only allow such cases
672fb8a8121Smrg    * through when -fdec-format-defaults is passed.
673fb8a8121Smrg    */
674fb8a8121Smrg   if (w == (size_t) DEFAULT_WIDTH)
675fb8a8121Smrg     w = default_width_for_integer (length);
676fb8a8121Smrg 
677181254a7Smrg   p = read_block_form (dtp, &w);
678181254a7Smrg 
679181254a7Smrg   if (p == NULL)
680181254a7Smrg     return;
681181254a7Smrg 
682181254a7Smrg   p = eat_leading_spaces (&w, p);
683181254a7Smrg   if (w == 0)
684181254a7Smrg     {
685181254a7Smrg       set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
686181254a7Smrg       return;
687181254a7Smrg     }
688181254a7Smrg 
689181254a7Smrg   negative = 0;
690181254a7Smrg 
691181254a7Smrg   switch (*p)
692181254a7Smrg     {
693181254a7Smrg     case '-':
694181254a7Smrg       negative = 1;
695181254a7Smrg       /* Fall through */
696181254a7Smrg 
697181254a7Smrg     case '+':
698181254a7Smrg       p++;
699181254a7Smrg       if (--w == 0)
700181254a7Smrg 	goto bad;
701181254a7Smrg       /* Fall through */
702181254a7Smrg 
703181254a7Smrg     default:
704181254a7Smrg       break;
705181254a7Smrg     }
706181254a7Smrg 
707181254a7Smrg   maxv = si_max (length);
708181254a7Smrg   if (negative)
709181254a7Smrg     maxv++;
710181254a7Smrg   maxv_10 = maxv / 10;
711181254a7Smrg 
712181254a7Smrg   /* At this point we have a digit-string */
713181254a7Smrg   value = 0;
714181254a7Smrg 
715181254a7Smrg   for (;;)
716181254a7Smrg     {
717181254a7Smrg       c = next_char (dtp, &p, &w);
718181254a7Smrg       if (c == '\0')
719181254a7Smrg 	break;
720181254a7Smrg 
721181254a7Smrg       if (c == ' ')
722181254a7Smrg         {
723181254a7Smrg 	  if (dtp->u.p.blank_status == BLANK_NULL)
724181254a7Smrg 	    {
725181254a7Smrg 	      /* Skip spaces.  */
726181254a7Smrg 	      for ( ; w > 0; p++, w--)
727181254a7Smrg 		if (*p != ' ') break;
728181254a7Smrg 	      continue;
729181254a7Smrg 	    }
730181254a7Smrg 	  if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
731181254a7Smrg         }
732181254a7Smrg 
733181254a7Smrg       if (c < '0' || c > '9')
734181254a7Smrg 	goto bad;
735181254a7Smrg 
736181254a7Smrg       if (value > maxv_10)
737181254a7Smrg 	goto overflow;
738181254a7Smrg 
739181254a7Smrg       c -= '0';
740181254a7Smrg       value = 10 * value;
741181254a7Smrg 
742181254a7Smrg       if (value > maxv - c)
743181254a7Smrg 	goto overflow;
744181254a7Smrg       value += c;
745181254a7Smrg     }
746181254a7Smrg 
747181254a7Smrg   if (negative)
748181254a7Smrg     v = -value;
749181254a7Smrg   else
750181254a7Smrg     v = value;
751181254a7Smrg 
752181254a7Smrg   set_integer (dest, v, length);
753181254a7Smrg   return;
754181254a7Smrg 
755181254a7Smrg  bad:
756181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_VALUE,
757181254a7Smrg 		  "Bad value during integer read");
758181254a7Smrg   next_record (dtp, 1);
759181254a7Smrg   return;
760181254a7Smrg 
761181254a7Smrg  overflow:
762181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
763181254a7Smrg 		  "Value overflowed during integer read");
764181254a7Smrg   next_record (dtp, 1);
765181254a7Smrg 
766181254a7Smrg }
767181254a7Smrg 
768181254a7Smrg 
769181254a7Smrg /* read_radix()-- This function reads values for non-decimal radixes.
770181254a7Smrg    The difference here is that we treat the values here as unsigned
771181254a7Smrg    values for the purposes of overflow.  If minus sign is present and
772181254a7Smrg    the top bit is set, the value will be incorrect. */
773181254a7Smrg 
774181254a7Smrg void
read_radix(st_parameter_dt * dtp,const fnode * f,char * dest,int length,int radix)775181254a7Smrg read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
776181254a7Smrg 	    int radix)
777181254a7Smrg {
778181254a7Smrg   GFC_UINTEGER_LARGEST value, maxv, maxv_r;
779181254a7Smrg   GFC_INTEGER_LARGEST v;
780181254a7Smrg   size_t w;
781181254a7Smrg   int negative;
782181254a7Smrg   char c, *p;
783181254a7Smrg 
784181254a7Smrg   w = f->u.w;
785181254a7Smrg 
786181254a7Smrg   p = read_block_form (dtp, &w);
787181254a7Smrg 
788181254a7Smrg   if (p == NULL)
789181254a7Smrg     return;
790181254a7Smrg 
791181254a7Smrg   p = eat_leading_spaces (&w, p);
792181254a7Smrg   if (w == 0)
793181254a7Smrg     {
794181254a7Smrg       set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
795181254a7Smrg       return;
796181254a7Smrg     }
797181254a7Smrg 
798181254a7Smrg   /* Maximum unsigned value, assuming two's complement.  */
799181254a7Smrg   maxv = 2 * si_max (length) + 1;
800181254a7Smrg   maxv_r = maxv / radix;
801181254a7Smrg 
802181254a7Smrg   negative = 0;
803181254a7Smrg   value = 0;
804181254a7Smrg 
805181254a7Smrg   switch (*p)
806181254a7Smrg     {
807181254a7Smrg     case '-':
808181254a7Smrg       negative = 1;
809181254a7Smrg       /* Fall through */
810181254a7Smrg 
811181254a7Smrg     case '+':
812181254a7Smrg       p++;
813181254a7Smrg       if (--w == 0)
814181254a7Smrg 	goto bad;
815181254a7Smrg       /* Fall through */
816181254a7Smrg 
817181254a7Smrg     default:
818181254a7Smrg       break;
819181254a7Smrg     }
820181254a7Smrg 
821181254a7Smrg   /* At this point we have a digit-string */
822181254a7Smrg   value = 0;
823181254a7Smrg 
824181254a7Smrg   for (;;)
825181254a7Smrg     {
826181254a7Smrg       c = next_char (dtp, &p, &w);
827181254a7Smrg       if (c == '\0')
828181254a7Smrg 	break;
829181254a7Smrg       if (c == ' ')
830181254a7Smrg         {
831181254a7Smrg 	  if (dtp->u.p.blank_status == BLANK_NULL) continue;
832181254a7Smrg 	  if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
833181254a7Smrg         }
834181254a7Smrg 
835181254a7Smrg       switch (radix)
836181254a7Smrg 	{
837181254a7Smrg 	case 2:
838181254a7Smrg 	  if (c < '0' || c > '1')
839181254a7Smrg 	    goto bad;
840181254a7Smrg 	  break;
841181254a7Smrg 
842181254a7Smrg 	case 8:
843181254a7Smrg 	  if (c < '0' || c > '7')
844181254a7Smrg 	    goto bad;
845181254a7Smrg 	  break;
846181254a7Smrg 
847181254a7Smrg 	case 16:
848181254a7Smrg 	  switch (c)
849181254a7Smrg 	    {
850181254a7Smrg 	    case '0':
851181254a7Smrg 	    case '1':
852181254a7Smrg 	    case '2':
853181254a7Smrg 	    case '3':
854181254a7Smrg 	    case '4':
855181254a7Smrg 	    case '5':
856181254a7Smrg 	    case '6':
857181254a7Smrg 	    case '7':
858181254a7Smrg 	    case '8':
859181254a7Smrg 	    case '9':
860181254a7Smrg 	      break;
861181254a7Smrg 
862181254a7Smrg 	    case 'a':
863181254a7Smrg 	    case 'b':
864181254a7Smrg 	    case 'c':
865181254a7Smrg 	    case 'd':
866181254a7Smrg 	    case 'e':
867181254a7Smrg 	    case 'f':
868181254a7Smrg 	      c = c - 'a' + '9' + 1;
869181254a7Smrg 	      break;
870181254a7Smrg 
871181254a7Smrg 	    case 'A':
872181254a7Smrg 	    case 'B':
873181254a7Smrg 	    case 'C':
874181254a7Smrg 	    case 'D':
875181254a7Smrg 	    case 'E':
876181254a7Smrg 	    case 'F':
877181254a7Smrg 	      c = c - 'A' + '9' + 1;
878181254a7Smrg 	      break;
879181254a7Smrg 
880181254a7Smrg 	    default:
881181254a7Smrg 	      goto bad;
882181254a7Smrg 	    }
883181254a7Smrg 
884181254a7Smrg 	  break;
885181254a7Smrg 	}
886181254a7Smrg 
887181254a7Smrg       if (value > maxv_r)
888181254a7Smrg 	goto overflow;
889181254a7Smrg 
890181254a7Smrg       c -= '0';
891181254a7Smrg       value = radix * value;
892181254a7Smrg 
893181254a7Smrg       if (maxv - c < value)
894181254a7Smrg 	goto overflow;
895181254a7Smrg       value += c;
896181254a7Smrg     }
897181254a7Smrg 
898181254a7Smrg   v = value;
899181254a7Smrg   if (negative)
900181254a7Smrg     v = -v;
901181254a7Smrg 
902181254a7Smrg   set_integer (dest, v, length);
903181254a7Smrg   return;
904181254a7Smrg 
905181254a7Smrg  bad:
906181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_VALUE,
907181254a7Smrg 		  "Bad value during integer read");
908181254a7Smrg   next_record (dtp, 1);
909181254a7Smrg   return;
910181254a7Smrg 
911181254a7Smrg  overflow:
912181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
913181254a7Smrg 		  "Value overflowed during integer read");
914181254a7Smrg   next_record (dtp, 1);
915181254a7Smrg 
916181254a7Smrg }
917181254a7Smrg 
918181254a7Smrg 
919181254a7Smrg /* read_f()-- Read a floating point number with F-style editing, which
920181254a7Smrg    is what all of the other floating point descriptors behave as.  The
921181254a7Smrg    tricky part is that optional spaces are allowed after an E or D,
922181254a7Smrg    and the implicit decimal point if a decimal point is not present in
923181254a7Smrg    the input.  */
924181254a7Smrg 
925181254a7Smrg void
read_f(st_parameter_dt * dtp,const fnode * f,char * dest,int length)926181254a7Smrg read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
927181254a7Smrg {
928181254a7Smrg #define READF_TMP 50
929181254a7Smrg   char tmp[READF_TMP];
930181254a7Smrg   size_t buf_size = 0;
931181254a7Smrg   size_t w;
932181254a7Smrg   int seen_dp, exponent;
933181254a7Smrg   int exponent_sign;
934181254a7Smrg   const char *p;
935181254a7Smrg   char *buffer;
936181254a7Smrg   char *out;
937181254a7Smrg   int seen_int_digit; /* Seen a digit before the decimal point?  */
938181254a7Smrg   int seen_dec_digit; /* Seen a digit after the decimal point?  */
939181254a7Smrg 
940181254a7Smrg   seen_dp = 0;
941181254a7Smrg   seen_int_digit = 0;
942181254a7Smrg   seen_dec_digit = 0;
943181254a7Smrg   exponent_sign = 1;
944181254a7Smrg   exponent = 0;
945181254a7Smrg   w = f->u.w;
946181254a7Smrg   buffer = tmp;
947181254a7Smrg 
948181254a7Smrg   /* Read in the next block.  */
949181254a7Smrg   p = read_block_form (dtp, &w);
950181254a7Smrg   if (p == NULL)
951181254a7Smrg     return;
952181254a7Smrg   p = eat_leading_spaces (&w, (char*) p);
953181254a7Smrg   if (w == 0)
954181254a7Smrg     goto zero;
955181254a7Smrg 
956181254a7Smrg   /* In this buffer we're going to re-format the number cleanly to be parsed
957181254a7Smrg      by convert_real in the end; this assures we're using strtod from the
958181254a7Smrg      C library for parsing and thus probably get the best accuracy possible.
959181254a7Smrg      This process may add a '+0.0' in front of the number as well as change the
960181254a7Smrg      exponent because of an implicit decimal point or the like.  Thus allocating
961181254a7Smrg      strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
962181254a7Smrg      original buffer had should be enough.  */
963181254a7Smrg   buf_size = w + 11;
964181254a7Smrg   if (buf_size > READF_TMP)
965181254a7Smrg     buffer = xmalloc (buf_size);
966181254a7Smrg 
967181254a7Smrg   out = buffer;
968181254a7Smrg 
969181254a7Smrg   /* Optional sign */
970181254a7Smrg   if (*p == '-' || *p == '+')
971181254a7Smrg     {
972181254a7Smrg       if (*p == '-')
973181254a7Smrg 	*(out++) = '-';
974181254a7Smrg       ++p;
975181254a7Smrg       --w;
976181254a7Smrg     }
977181254a7Smrg 
978181254a7Smrg   p = eat_leading_spaces (&w, (char*) p);
979181254a7Smrg   if (w == 0)
980181254a7Smrg     goto zero;
981181254a7Smrg 
982181254a7Smrg   /* Check for Infinity or NaN.  */
983181254a7Smrg   if (unlikely ((w >= 3 && (*p == 'i' || *p == 'I' || *p == 'n' || *p == 'N'))))
984181254a7Smrg     {
985181254a7Smrg       int seen_paren = 0;
986181254a7Smrg       char *save = out;
987181254a7Smrg 
988181254a7Smrg       /* Scan through the buffer keeping track of spaces and parenthesis. We
989181254a7Smrg 	 null terminate the string as soon as we see a left paren or if we are
990181254a7Smrg 	 BLANK_NULL mode.  Leading spaces have already been skipped above,
991181254a7Smrg 	 trailing spaces are ignored by converting to '\0'. A space
992181254a7Smrg 	 between "NaN" and the optional perenthesis is not permitted.  */
993181254a7Smrg       while (w > 0)
994181254a7Smrg 	{
995*b1e83836Smrg 	  *out = safe_tolower (*p);
996181254a7Smrg 	  switch (*p)
997181254a7Smrg 	    {
998181254a7Smrg 	    case ' ':
999181254a7Smrg 	      if (dtp->u.p.blank_status == BLANK_ZERO)
1000181254a7Smrg 		{
1001181254a7Smrg 		  *out = '0';
1002181254a7Smrg 		  break;
1003181254a7Smrg 		}
1004181254a7Smrg 	      *out = '\0';
1005181254a7Smrg 	      if (seen_paren == 1)
1006181254a7Smrg 	        goto bad_float;
1007181254a7Smrg 	      break;
1008181254a7Smrg 	    case '(':
1009181254a7Smrg 	      seen_paren++;
1010181254a7Smrg 	      *out = '\0';
1011181254a7Smrg 	      break;
1012181254a7Smrg 	    case ')':
1013181254a7Smrg 	      if (seen_paren++ != 1)
1014181254a7Smrg 		goto bad_float;
1015181254a7Smrg 	      break;
1016181254a7Smrg 	    default:
1017*b1e83836Smrg 	      if (!safe_isalnum (*out))
1018181254a7Smrg 		goto bad_float;
1019181254a7Smrg 	    }
1020181254a7Smrg 	  --w;
1021181254a7Smrg 	  ++p;
1022181254a7Smrg 	  ++out;
1023181254a7Smrg 	}
1024181254a7Smrg 
1025181254a7Smrg       *out = '\0';
1026181254a7Smrg 
1027181254a7Smrg       if (seen_paren != 0 && seen_paren != 2)
1028181254a7Smrg 	goto bad_float;
1029181254a7Smrg 
1030181254a7Smrg       if ((strcmp (save, "inf") == 0) || (strcmp (save, "infinity") == 0))
1031181254a7Smrg 	{
1032181254a7Smrg 	   if (seen_paren)
1033181254a7Smrg 	     goto bad_float;
1034181254a7Smrg 	}
1035181254a7Smrg       else if (strcmp (save, "nan") != 0)
1036181254a7Smrg 	goto bad_float;
1037181254a7Smrg 
1038181254a7Smrg       convert_infnan (dtp, dest, buffer, length);
1039181254a7Smrg       if (buf_size > READF_TMP)
1040181254a7Smrg 	free (buffer);
1041181254a7Smrg       return;
1042181254a7Smrg     }
1043181254a7Smrg 
1044181254a7Smrg   /* Process the mantissa string.  */
1045181254a7Smrg   while (w > 0)
1046181254a7Smrg     {
1047181254a7Smrg       switch (*p)
1048181254a7Smrg 	{
1049181254a7Smrg 	case ',':
1050181254a7Smrg 	  if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA)
1051181254a7Smrg 	    goto bad_float;
1052181254a7Smrg 	  /* Fall through.  */
1053181254a7Smrg 	case '.':
1054181254a7Smrg 	  if (seen_dp)
1055181254a7Smrg 	    goto bad_float;
1056181254a7Smrg 	  if (!seen_int_digit)
1057181254a7Smrg 	    *(out++) = '0';
1058181254a7Smrg 	  *(out++) = '.';
1059181254a7Smrg 	  seen_dp = 1;
1060181254a7Smrg 	  break;
1061181254a7Smrg 
1062181254a7Smrg 	case ' ':
1063181254a7Smrg 	  if (dtp->u.p.blank_status == BLANK_ZERO)
1064181254a7Smrg 	    {
1065181254a7Smrg 	      *(out++) = '0';
1066181254a7Smrg 	      goto found_digit;
1067181254a7Smrg 	    }
1068181254a7Smrg 	  else if (dtp->u.p.blank_status == BLANK_NULL)
1069181254a7Smrg 	    break;
1070181254a7Smrg 	  else
1071181254a7Smrg 	    /* TODO: Should we check instead that there are only trailing
1072181254a7Smrg 	       blanks here, as is done below for exponents?  */
1073181254a7Smrg 	    goto done;
1074181254a7Smrg 	  /* Fall through.  */
1075181254a7Smrg 	case '0':
1076181254a7Smrg 	case '1':
1077181254a7Smrg 	case '2':
1078181254a7Smrg 	case '3':
1079181254a7Smrg 	case '4':
1080181254a7Smrg 	case '5':
1081181254a7Smrg 	case '6':
1082181254a7Smrg 	case '7':
1083181254a7Smrg 	case '8':
1084181254a7Smrg 	case '9':
1085181254a7Smrg 	  *(out++) = *p;
1086181254a7Smrg found_digit:
1087181254a7Smrg 	  if (!seen_dp)
1088181254a7Smrg 	    seen_int_digit = 1;
1089181254a7Smrg 	  else
1090181254a7Smrg 	    seen_dec_digit = 1;
1091181254a7Smrg 	  break;
1092181254a7Smrg 
1093181254a7Smrg 	case '-':
1094181254a7Smrg 	case '+':
1095181254a7Smrg 	  goto exponent;
1096181254a7Smrg 
1097181254a7Smrg 	case 'e':
1098181254a7Smrg 	case 'E':
1099181254a7Smrg 	case 'd':
1100181254a7Smrg 	case 'D':
1101181254a7Smrg 	case 'q':
1102181254a7Smrg 	case 'Q':
1103181254a7Smrg 	  ++p;
1104181254a7Smrg 	  --w;
1105181254a7Smrg 	  goto exponent;
1106181254a7Smrg 
1107181254a7Smrg 	default:
1108181254a7Smrg 	  goto bad_float;
1109181254a7Smrg 	}
1110181254a7Smrg 
1111181254a7Smrg       ++p;
1112181254a7Smrg       --w;
1113181254a7Smrg     }
1114181254a7Smrg 
1115181254a7Smrg   /* No exponent has been seen, so we use the current scale factor.  */
1116181254a7Smrg   exponent = - dtp->u.p.scale_factor;
1117181254a7Smrg   goto done;
1118181254a7Smrg 
1119181254a7Smrg   /* At this point the start of an exponent has been found.  */
1120181254a7Smrg exponent:
1121181254a7Smrg   p = eat_leading_spaces (&w, (char*) p);
1122181254a7Smrg   if (*p == '-' || *p == '+')
1123181254a7Smrg     {
1124181254a7Smrg       if (*p == '-')
1125181254a7Smrg 	exponent_sign = -1;
1126181254a7Smrg       ++p;
1127181254a7Smrg       --w;
1128181254a7Smrg     }
1129181254a7Smrg 
1130181254a7Smrg   /* At this point a digit string is required.  We calculate the value
1131181254a7Smrg      of the exponent in order to take account of the scale factor and
1132181254a7Smrg      the d parameter before explict conversion takes place.  */
1133181254a7Smrg 
1134181254a7Smrg   if (w == 0)
1135181254a7Smrg     {
1136181254a7Smrg       /* Extension: allow default exponent of 0 when omitted.  */
1137181254a7Smrg       if (dtp->common.flags & IOPARM_DT_DEC_EXT)
1138181254a7Smrg 	goto done;
1139181254a7Smrg       else
1140181254a7Smrg 	goto bad_float;
1141181254a7Smrg     }
1142181254a7Smrg 
1143181254a7Smrg   if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
1144181254a7Smrg     {
1145*b1e83836Smrg       while (w > 0 && safe_isdigit (*p))
1146181254a7Smrg 	{
1147181254a7Smrg 	  exponent *= 10;
1148181254a7Smrg 	  exponent += *p - '0';
1149181254a7Smrg 	  ++p;
1150181254a7Smrg 	  --w;
1151181254a7Smrg 	}
1152181254a7Smrg 
1153181254a7Smrg       /* Only allow trailing blanks.  */
1154181254a7Smrg       while (w > 0)
1155181254a7Smrg 	{
1156181254a7Smrg 	  if (*p != ' ')
1157181254a7Smrg 	    goto bad_float;
1158181254a7Smrg 	  ++p;
1159181254a7Smrg 	  --w;
1160181254a7Smrg 	}
1161181254a7Smrg     }
1162181254a7Smrg   else  /* BZ or BN status is enabled.  */
1163181254a7Smrg     {
1164181254a7Smrg       while (w > 0)
1165181254a7Smrg 	{
1166181254a7Smrg 	  if (*p == ' ')
1167181254a7Smrg 	    {
1168181254a7Smrg 	      if (dtp->u.p.blank_status == BLANK_ZERO)
1169181254a7Smrg 		exponent *= 10;
1170181254a7Smrg 	      else
1171181254a7Smrg 		assert (dtp->u.p.blank_status == BLANK_NULL);
1172181254a7Smrg 	    }
1173*b1e83836Smrg 	  else if (!safe_isdigit (*p))
1174181254a7Smrg 	    goto bad_float;
1175181254a7Smrg 	  else
1176181254a7Smrg 	    {
1177181254a7Smrg 	      exponent *= 10;
1178181254a7Smrg 	      exponent += *p - '0';
1179181254a7Smrg 	    }
1180181254a7Smrg 
1181181254a7Smrg 	  ++p;
1182181254a7Smrg 	  --w;
1183181254a7Smrg 	}
1184181254a7Smrg     }
1185181254a7Smrg 
1186181254a7Smrg   exponent *= exponent_sign;
1187181254a7Smrg 
1188181254a7Smrg done:
1189181254a7Smrg   /* Use the precision specified in the format if no decimal point has been
1190181254a7Smrg      seen.  */
1191181254a7Smrg   if (!seen_dp)
1192181254a7Smrg     exponent -= f->u.real.d;
1193181254a7Smrg 
1194181254a7Smrg   /* Output a trailing '0' after decimal point if not yet found.  */
1195181254a7Smrg   if (seen_dp && !seen_dec_digit)
1196181254a7Smrg     *(out++) = '0';
1197181254a7Smrg   /* Handle input of style "E+NN" by inserting a 0 for the
1198181254a7Smrg      significand.  */
1199181254a7Smrg   else if (!seen_int_digit && !seen_dec_digit)
1200181254a7Smrg     {
1201181254a7Smrg       notify_std (&dtp->common, GFC_STD_LEGACY,
1202181254a7Smrg 		  "REAL input of style 'E+NN'");
1203181254a7Smrg       *(out++) = '0';
1204181254a7Smrg     }
1205181254a7Smrg 
1206181254a7Smrg   /* Print out the exponent to finish the reformatted number.  Maximum 4
1207181254a7Smrg      digits for the exponent.  */
1208181254a7Smrg   if (exponent != 0)
1209181254a7Smrg     {
1210181254a7Smrg       int dig;
1211181254a7Smrg 
1212181254a7Smrg       *(out++) = 'e';
1213181254a7Smrg       if (exponent < 0)
1214181254a7Smrg 	{
1215181254a7Smrg 	  *(out++) = '-';
1216181254a7Smrg 	  exponent = - exponent;
1217181254a7Smrg 	}
1218181254a7Smrg 
1219181254a7Smrg       if (exponent >= 10000)
1220181254a7Smrg 	goto bad_float;
1221181254a7Smrg 
1222181254a7Smrg       for (dig = 3; dig >= 0; --dig)
1223181254a7Smrg 	{
1224181254a7Smrg 	  out[dig] = (char) ('0' + exponent % 10);
1225181254a7Smrg 	  exponent /= 10;
1226181254a7Smrg 	}
1227181254a7Smrg       out += 4;
1228181254a7Smrg     }
1229181254a7Smrg   *(out++) = '\0';
1230181254a7Smrg 
1231181254a7Smrg   /* Do the actual conversion.  */
1232181254a7Smrg   convert_real (dtp, dest, buffer, length);
1233181254a7Smrg   if (buf_size > READF_TMP)
1234181254a7Smrg     free (buffer);
1235181254a7Smrg   return;
1236181254a7Smrg 
1237181254a7Smrg   /* The value read is zero.  */
1238181254a7Smrg zero:
1239181254a7Smrg   switch (length)
1240181254a7Smrg     {
1241181254a7Smrg       case 4:
1242181254a7Smrg 	*((GFC_REAL_4 *) dest) = 0.0;
1243181254a7Smrg 	break;
1244181254a7Smrg 
1245181254a7Smrg       case 8:
1246181254a7Smrg 	*((GFC_REAL_8 *) dest) = 0.0;
1247181254a7Smrg 	break;
1248181254a7Smrg 
1249181254a7Smrg #ifdef HAVE_GFC_REAL_10
1250181254a7Smrg       case 10:
1251181254a7Smrg 	*((GFC_REAL_10 *) dest) = 0.0;
1252181254a7Smrg 	break;
1253181254a7Smrg #endif
1254181254a7Smrg 
1255181254a7Smrg #ifdef HAVE_GFC_REAL_16
1256181254a7Smrg       case 16:
1257181254a7Smrg 	*((GFC_REAL_16 *) dest) = 0.0;
1258181254a7Smrg 	break;
1259181254a7Smrg #endif
1260181254a7Smrg 
1261*b1e83836Smrg #ifdef HAVE_GFC_REAL_17
1262*b1e83836Smrg       case 17:
1263*b1e83836Smrg 	*((GFC_REAL_17 *) dest) = 0.0;
1264*b1e83836Smrg 	break;
1265*b1e83836Smrg #endif
1266*b1e83836Smrg 
1267181254a7Smrg       default:
1268181254a7Smrg 	internal_error (&dtp->common, "Unsupported real kind during IO");
1269181254a7Smrg     }
1270181254a7Smrg   return;
1271181254a7Smrg 
1272181254a7Smrg bad_float:
1273181254a7Smrg   if (buf_size > READF_TMP)
1274181254a7Smrg     free (buffer);
1275181254a7Smrg   generate_error (&dtp->common, LIBERROR_READ_VALUE,
1276181254a7Smrg 		  "Bad value during floating point read");
1277181254a7Smrg   next_record (dtp, 1);
1278181254a7Smrg   return;
1279181254a7Smrg }
1280181254a7Smrg 
1281181254a7Smrg 
1282181254a7Smrg /* read_x()-- Deal with the X/TR descriptor.  We just read some data
1283181254a7Smrg    and never look at it. */
1284181254a7Smrg 
1285181254a7Smrg void
read_x(st_parameter_dt * dtp,size_t n)1286181254a7Smrg read_x (st_parameter_dt *dtp, size_t n)
1287181254a7Smrg {
1288181254a7Smrg   size_t length;
1289181254a7Smrg   int q, q2;
1290181254a7Smrg 
1291181254a7Smrg   if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
1292181254a7Smrg       && dtp->u.p.current_unit->bytes_left < (gfc_offset) n)
1293181254a7Smrg     n = dtp->u.p.current_unit->bytes_left;
1294181254a7Smrg 
1295181254a7Smrg   if (n == 0)
1296181254a7Smrg     return;
1297181254a7Smrg 
1298181254a7Smrg   length = n;
1299181254a7Smrg 
1300181254a7Smrg   if (is_internal_unit (dtp))
1301181254a7Smrg     {
1302181254a7Smrg       mem_alloc_r (dtp->u.p.current_unit->s, &length);
1303181254a7Smrg       if (unlikely (length < n))
1304181254a7Smrg 	n = length;
1305181254a7Smrg       goto done;
1306181254a7Smrg     }
1307181254a7Smrg 
1308181254a7Smrg   if (dtp->u.p.sf_seen_eor)
1309181254a7Smrg     return;
1310181254a7Smrg 
1311181254a7Smrg   n = 0;
1312181254a7Smrg   while (n < length)
1313181254a7Smrg     {
1314181254a7Smrg       q = fbuf_getc (dtp->u.p.current_unit);
1315181254a7Smrg       if (q == EOF)
1316181254a7Smrg 	break;
1317181254a7Smrg       else if (dtp->u.p.current_unit->flags.cc != CC_NONE
1318181254a7Smrg 	       && (q == '\n' || q == '\r'))
1319181254a7Smrg 	{
1320181254a7Smrg 	  /* Unexpected end of line. Set the position.  */
1321181254a7Smrg 	  dtp->u.p.sf_seen_eor = 1;
1322181254a7Smrg 
1323181254a7Smrg 	  /* If we see an EOR during non-advancing I/O, we need to skip
1324181254a7Smrg 	     the rest of the I/O statement.  Set the corresponding flag.  */
1325181254a7Smrg 	  if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
1326181254a7Smrg 	    dtp->u.p.eor_condition = 1;
1327181254a7Smrg 
1328181254a7Smrg 	  /* If we encounter a CR, it might be a CRLF.  */
1329181254a7Smrg 	  if (q == '\r') /* Probably a CRLF */
1330181254a7Smrg 	    {
1331181254a7Smrg 	      /* See if there is an LF.  */
1332181254a7Smrg 	      q2 = fbuf_getc (dtp->u.p.current_unit);
1333181254a7Smrg 	      if (q2 == '\n')
1334181254a7Smrg 		dtp->u.p.sf_seen_eor = 2;
1335181254a7Smrg 	      else if (q2 != EOF) /* Oops, seek back.  */
1336181254a7Smrg 		fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
1337181254a7Smrg 	    }
1338181254a7Smrg 	  goto done;
1339181254a7Smrg 	}
1340181254a7Smrg       n++;
1341181254a7Smrg     }
1342181254a7Smrg 
1343181254a7Smrg  done:
1344181254a7Smrg   if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
1345181254a7Smrg       dtp->u.p.current_unit->has_size)
1346181254a7Smrg     dtp->u.p.current_unit->size_used += (GFC_IO_INT) n;
1347181254a7Smrg   dtp->u.p.current_unit->bytes_left -= n;
1348181254a7Smrg   dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
1349181254a7Smrg }
1350181254a7Smrg 
1351