annotate libgfortran/io/read.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Copyright (C) 2002-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
2 Contributed by Andy Vaught
kono
parents:
diff changeset
3 F2003 I/O support contributed by Jerry DeLisle
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of the GNU Fortran runtime library (libgfortran).
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 Libgfortran is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 Libgfortran is distributed in the hope that it will be useful,
kono
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
15 GNU General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
18 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
19 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
22 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
24 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 #include "io.h"
kono
parents:
diff changeset
27 #include "fbuf.h"
kono
parents:
diff changeset
28 #include "format.h"
kono
parents:
diff changeset
29 #include "unix.h"
kono
parents:
diff changeset
30 #include <string.h>
kono
parents:
diff changeset
31 #include <ctype.h>
kono
parents:
diff changeset
32 #include <assert.h>
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 typedef unsigned char uchar;
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 /* read.c -- Deal with formatted reads */
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 /* set_integer()-- All of the integer assignments come here to
kono
parents:
diff changeset
40 actually place the value into memory. */
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 void
kono
parents:
diff changeset
43 set_integer (void *dest, GFC_INTEGER_LARGEST value, int length)
kono
parents:
diff changeset
44 {
kono
parents:
diff changeset
45 switch (length)
kono
parents:
diff changeset
46 {
kono
parents:
diff changeset
47 #ifdef HAVE_GFC_INTEGER_16
kono
parents:
diff changeset
48 /* length=10 comes about for kind=10 real/complex BOZ, cf. PR41711. */
kono
parents:
diff changeset
49 case 10:
kono
parents:
diff changeset
50 case 16:
kono
parents:
diff changeset
51 {
kono
parents:
diff changeset
52 GFC_INTEGER_16 tmp = value;
kono
parents:
diff changeset
53 memcpy (dest, (void *) &tmp, length);
kono
parents:
diff changeset
54 }
kono
parents:
diff changeset
55 break;
kono
parents:
diff changeset
56 #endif
kono
parents:
diff changeset
57 case 8:
kono
parents:
diff changeset
58 {
kono
parents:
diff changeset
59 GFC_INTEGER_8 tmp = value;
kono
parents:
diff changeset
60 memcpy (dest, (void *) &tmp, length);
kono
parents:
diff changeset
61 }
kono
parents:
diff changeset
62 break;
kono
parents:
diff changeset
63 case 4:
kono
parents:
diff changeset
64 {
kono
parents:
diff changeset
65 GFC_INTEGER_4 tmp = value;
kono
parents:
diff changeset
66 memcpy (dest, (void *) &tmp, length);
kono
parents:
diff changeset
67 }
kono
parents:
diff changeset
68 break;
kono
parents:
diff changeset
69 case 2:
kono
parents:
diff changeset
70 {
kono
parents:
diff changeset
71 GFC_INTEGER_2 tmp = value;
kono
parents:
diff changeset
72 memcpy (dest, (void *) &tmp, length);
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74 break;
kono
parents:
diff changeset
75 case 1:
kono
parents:
diff changeset
76 {
kono
parents:
diff changeset
77 GFC_INTEGER_1 tmp = value;
kono
parents:
diff changeset
78 memcpy (dest, (void *) &tmp, length);
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80 break;
kono
parents:
diff changeset
81 default:
kono
parents:
diff changeset
82 internal_error (NULL, "Bad integer kind");
kono
parents:
diff changeset
83 }
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 /* Max signed value of size give by length argument. */
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 GFC_UINTEGER_LARGEST
kono
parents:
diff changeset
90 si_max (int length)
kono
parents:
diff changeset
91 {
kono
parents:
diff changeset
92 #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
kono
parents:
diff changeset
93 GFC_UINTEGER_LARGEST value;
kono
parents:
diff changeset
94 #endif
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 switch (length)
kono
parents:
diff changeset
97 {
kono
parents:
diff changeset
98 #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10
kono
parents:
diff changeset
99 case 16:
kono
parents:
diff changeset
100 case 10:
kono
parents:
diff changeset
101 value = 1;
kono
parents:
diff changeset
102 for (int n = 1; n < 4 * length; n++)
kono
parents:
diff changeset
103 value = (value << 2) + 3;
kono
parents:
diff changeset
104 return value;
kono
parents:
diff changeset
105 #endif
kono
parents:
diff changeset
106 case 8:
kono
parents:
diff changeset
107 return GFC_INTEGER_8_HUGE;
kono
parents:
diff changeset
108 case 4:
kono
parents:
diff changeset
109 return GFC_INTEGER_4_HUGE;
kono
parents:
diff changeset
110 case 2:
kono
parents:
diff changeset
111 return GFC_INTEGER_2_HUGE;
kono
parents:
diff changeset
112 case 1:
kono
parents:
diff changeset
113 return GFC_INTEGER_1_HUGE;
kono
parents:
diff changeset
114 default:
kono
parents:
diff changeset
115 internal_error (NULL, "Bad integer kind");
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117 }
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 /* convert_real()-- Convert a character representation of a floating
kono
parents:
diff changeset
121 point number to the machine number. Returns nonzero if there is an
kono
parents:
diff changeset
122 invalid input. Note: many architectures (e.g. IA-64, HP-PA)
kono
parents:
diff changeset
123 require that the storage pointed to by the dest argument is
kono
parents:
diff changeset
124 properly aligned for the type in question. */
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 int
kono
parents:
diff changeset
127 convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
kono
parents:
diff changeset
128 {
kono
parents:
diff changeset
129 char *endptr = NULL;
kono
parents:
diff changeset
130 int round_mode, old_round_mode;
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 switch (dtp->u.p.current_unit->round_status)
kono
parents:
diff changeset
133 {
kono
parents:
diff changeset
134 case ROUND_COMPATIBLE:
kono
parents:
diff changeset
135 /* FIXME: As NEAREST but round away from zero for a tie. */
kono
parents:
diff changeset
136 case ROUND_UNSPECIFIED:
kono
parents:
diff changeset
137 /* Should not occur. */
kono
parents:
diff changeset
138 case ROUND_PROCDEFINED:
kono
parents:
diff changeset
139 round_mode = ROUND_NEAREST;
kono
parents:
diff changeset
140 break;
kono
parents:
diff changeset
141 default:
kono
parents:
diff changeset
142 round_mode = dtp->u.p.current_unit->round_status;
kono
parents:
diff changeset
143 break;
kono
parents:
diff changeset
144 }
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 old_round_mode = get_fpu_rounding_mode();
kono
parents:
diff changeset
147 set_fpu_rounding_mode (round_mode);
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 switch (length)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 case 4:
kono
parents:
diff changeset
152 *((GFC_REAL_4*) dest) =
kono
parents:
diff changeset
153 #if defined(HAVE_STRTOF)
kono
parents:
diff changeset
154 gfc_strtof (buffer, &endptr);
kono
parents:
diff changeset
155 #else
kono
parents:
diff changeset
156 (GFC_REAL_4) gfc_strtod (buffer, &endptr);
kono
parents:
diff changeset
157 #endif
kono
parents:
diff changeset
158 break;
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 case 8:
kono
parents:
diff changeset
161 *((GFC_REAL_8*) dest) = gfc_strtod (buffer, &endptr);
kono
parents:
diff changeset
162 break;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 #if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
kono
parents:
diff changeset
165 case 10:
kono
parents:
diff changeset
166 *((GFC_REAL_10*) dest) = gfc_strtold (buffer, &endptr);
kono
parents:
diff changeset
167 break;
kono
parents:
diff changeset
168 #endif
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 #if defined(HAVE_GFC_REAL_16)
kono
parents:
diff changeset
171 # if defined(GFC_REAL_16_IS_FLOAT128)
kono
parents:
diff changeset
172 case 16:
kono
parents:
diff changeset
173 *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr);
kono
parents:
diff changeset
174 break;
kono
parents:
diff changeset
175 # elif defined(HAVE_STRTOLD)
kono
parents:
diff changeset
176 case 16:
kono
parents:
diff changeset
177 *((GFC_REAL_16*) dest) = gfc_strtold (buffer, &endptr);
kono
parents:
diff changeset
178 break;
kono
parents:
diff changeset
179 # endif
kono
parents:
diff changeset
180 #endif
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 default:
kono
parents:
diff changeset
183 internal_error (&dtp->common, "Unsupported real kind during IO");
kono
parents:
diff changeset
184 }
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 set_fpu_rounding_mode (old_round_mode);
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 if (buffer == endptr)
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 generate_error (&dtp->common, LIBERROR_READ_VALUE,
kono
parents:
diff changeset
191 "Error during floating point read");
kono
parents:
diff changeset
192 next_record (dtp, 1);
kono
parents:
diff changeset
193 return 1;
kono
parents:
diff changeset
194 }
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 return 0;
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 /* convert_infnan()-- Convert character INF/NAN representation to the
kono
parents:
diff changeset
200 machine number. Note: many architectures (e.g. IA-64, HP-PA) require
kono
parents:
diff changeset
201 that the storage pointed to by the dest argument is properly aligned
kono
parents:
diff changeset
202 for the type in question. */
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 int
kono
parents:
diff changeset
205 convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer,
kono
parents:
diff changeset
206 int length)
kono
parents:
diff changeset
207 {
kono
parents:
diff changeset
208 const char *s = buffer;
kono
parents:
diff changeset
209 int is_inf, plus = 1;
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 if (*s == '+')
kono
parents:
diff changeset
212 s++;
kono
parents:
diff changeset
213 else if (*s == '-')
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 s++;
kono
parents:
diff changeset
216 plus = 0;
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 is_inf = *s == 'i';
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 switch (length)
kono
parents:
diff changeset
222 {
kono
parents:
diff changeset
223 case 4:
kono
parents:
diff changeset
224 if (is_inf)
kono
parents:
diff changeset
225 *((GFC_REAL_4*) dest) = plus ? __builtin_inff () : -__builtin_inff ();
kono
parents:
diff changeset
226 else
kono
parents:
diff changeset
227 *((GFC_REAL_4*) dest) = plus ? __builtin_nanf ("") : -__builtin_nanf ("");
kono
parents:
diff changeset
228 break;
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 case 8:
kono
parents:
diff changeset
231 if (is_inf)
kono
parents:
diff changeset
232 *((GFC_REAL_8*) dest) = plus ? __builtin_inf () : -__builtin_inf ();
kono
parents:
diff changeset
233 else
kono
parents:
diff changeset
234 *((GFC_REAL_8*) dest) = plus ? __builtin_nan ("") : -__builtin_nan ("");
kono
parents:
diff changeset
235 break;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 #if defined(HAVE_GFC_REAL_10)
kono
parents:
diff changeset
238 case 10:
kono
parents:
diff changeset
239 if (is_inf)
kono
parents:
diff changeset
240 *((GFC_REAL_10*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
kono
parents:
diff changeset
241 else
kono
parents:
diff changeset
242 *((GFC_REAL_10*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
kono
parents:
diff changeset
243 break;
kono
parents:
diff changeset
244 #endif
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 #if defined(HAVE_GFC_REAL_16)
kono
parents:
diff changeset
247 # if defined(GFC_REAL_16_IS_FLOAT128)
kono
parents:
diff changeset
248 case 16:
kono
parents:
diff changeset
249 *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL);
kono
parents:
diff changeset
250 break;
kono
parents:
diff changeset
251 # else
kono
parents:
diff changeset
252 case 16:
kono
parents:
diff changeset
253 if (is_inf)
kono
parents:
diff changeset
254 *((GFC_REAL_16*) dest) = plus ? __builtin_infl () : -__builtin_infl ();
kono
parents:
diff changeset
255 else
kono
parents:
diff changeset
256 *((GFC_REAL_16*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl ("");
kono
parents:
diff changeset
257 break;
kono
parents:
diff changeset
258 # endif
kono
parents:
diff changeset
259 #endif
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 default:
kono
parents:
diff changeset
262 internal_error (&dtp->common, "Unsupported real kind during IO");
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 return 0;
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 /* read_l()-- Read a logical value */
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 void
kono
parents:
diff changeset
272 read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
kono
parents:
diff changeset
273 {
kono
parents:
diff changeset
274 char *p;
kono
parents:
diff changeset
275 int w;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 w = f->u.w;
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 p = read_block_form (dtp, &w);
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 if (p == NULL)
kono
parents:
diff changeset
282 return;
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 while (*p == ' ')
kono
parents:
diff changeset
285 {
kono
parents:
diff changeset
286 if (--w == 0)
kono
parents:
diff changeset
287 goto bad;
kono
parents:
diff changeset
288 p++;
kono
parents:
diff changeset
289 }
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 if (*p == '.')
kono
parents:
diff changeset
292 {
kono
parents:
diff changeset
293 if (--w == 0)
kono
parents:
diff changeset
294 goto bad;
kono
parents:
diff changeset
295 p++;
kono
parents:
diff changeset
296 }
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 switch (*p)
kono
parents:
diff changeset
299 {
kono
parents:
diff changeset
300 case 't':
kono
parents:
diff changeset
301 case 'T':
kono
parents:
diff changeset
302 set_integer (dest, (GFC_INTEGER_LARGEST) 1, length);
kono
parents:
diff changeset
303 break;
kono
parents:
diff changeset
304 case 'f':
kono
parents:
diff changeset
305 case 'F':
kono
parents:
diff changeset
306 set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
kono
parents:
diff changeset
307 break;
kono
parents:
diff changeset
308 default:
kono
parents:
diff changeset
309 bad:
kono
parents:
diff changeset
310 generate_error (&dtp->common, LIBERROR_READ_VALUE,
kono
parents:
diff changeset
311 "Bad value on logical read");
kono
parents:
diff changeset
312 next_record (dtp, 1);
kono
parents:
diff changeset
313 break;
kono
parents:
diff changeset
314 }
kono
parents:
diff changeset
315 }
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 static gfc_char4_t
kono
parents:
diff changeset
319 read_utf8 (st_parameter_dt *dtp, int *nbytes)
kono
parents:
diff changeset
320 {
kono
parents:
diff changeset
321 static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
kono
parents:
diff changeset
322 static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
kono
parents:
diff changeset
323 int i, nb, nread;
kono
parents:
diff changeset
324 gfc_char4_t c;
kono
parents:
diff changeset
325 char *s;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 *nbytes = 1;
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 s = read_block_form (dtp, nbytes);
kono
parents:
diff changeset
330 if (s == NULL)
kono
parents:
diff changeset
331 return 0;
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 /* If this is a short read, just return. */
kono
parents:
diff changeset
334 if (*nbytes == 0)
kono
parents:
diff changeset
335 return 0;
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 c = (uchar) s[0];
kono
parents:
diff changeset
338 if (c < 0x80)
kono
parents:
diff changeset
339 return c;
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 /* The number of leading 1-bits in the first byte indicates how many
kono
parents:
diff changeset
342 bytes follow. */
kono
parents:
diff changeset
343 for (nb = 2; nb < 7; nb++)
kono
parents:
diff changeset
344 if ((c & ~masks[nb-1]) == patns[nb-1])
kono
parents:
diff changeset
345 goto found;
kono
parents:
diff changeset
346 goto invalid;
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 found:
kono
parents:
diff changeset
349 c = (c & masks[nb-1]);
kono
parents:
diff changeset
350 nread = nb - 1;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 s = read_block_form (dtp, &nread);
kono
parents:
diff changeset
353 if (s == NULL)
kono
parents:
diff changeset
354 return 0;
kono
parents:
diff changeset
355 /* Decode the bytes read. */
kono
parents:
diff changeset
356 for (i = 1; i < nb; i++)
kono
parents:
diff changeset
357 {
kono
parents:
diff changeset
358 gfc_char4_t n = *s++;
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 if ((n & 0xC0) != 0x80)
kono
parents:
diff changeset
361 goto invalid;
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 c = ((c << 6) + (n & 0x3F));
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 /* Make sure the shortest possible encoding was used. */
kono
parents:
diff changeset
367 if (c <= 0x7F && nb > 1) goto invalid;
kono
parents:
diff changeset
368 if (c <= 0x7FF && nb > 2) goto invalid;
kono
parents:
diff changeset
369 if (c <= 0xFFFF && nb > 3) goto invalid;
kono
parents:
diff changeset
370 if (c <= 0x1FFFFF && nb > 4) goto invalid;
kono
parents:
diff changeset
371 if (c <= 0x3FFFFFF && nb > 5) goto invalid;
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 /* Make sure the character is valid. */
kono
parents:
diff changeset
374 if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
kono
parents:
diff changeset
375 goto invalid;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 return c;
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 invalid:
kono
parents:
diff changeset
380 generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
kono
parents:
diff changeset
381 return (gfc_char4_t) '?';
kono
parents:
diff changeset
382 }
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 static void
kono
parents:
diff changeset
386 read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width)
kono
parents:
diff changeset
387 {
kono
parents:
diff changeset
388 gfc_char4_t c;
kono
parents:
diff changeset
389 char *dest;
kono
parents:
diff changeset
390 int nbytes;
kono
parents:
diff changeset
391 int i, j;
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 len = (width < len) ? len : width;
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 dest = (char *) p;
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 /* Proceed with decoding one character at a time. */
kono
parents:
diff changeset
398 for (j = 0; j < len; j++, dest++)
kono
parents:
diff changeset
399 {
kono
parents:
diff changeset
400 c = read_utf8 (dtp, &nbytes);
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 /* Check for a short read and if so, break out. */
kono
parents:
diff changeset
403 if (nbytes == 0)
kono
parents:
diff changeset
404 break;
kono
parents:
diff changeset
405
kono
parents:
diff changeset
406 *dest = c > 255 ? '?' : (uchar) c;
kono
parents:
diff changeset
407 }
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 /* If there was a short read, pad the remaining characters. */
kono
parents:
diff changeset
410 for (i = j; i < len; i++)
kono
parents:
diff changeset
411 *dest++ = ' ';
kono
parents:
diff changeset
412 return;
kono
parents:
diff changeset
413 }
kono
parents:
diff changeset
414
kono
parents:
diff changeset
415 static void
kono
parents:
diff changeset
416 read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width)
kono
parents:
diff changeset
417 {
kono
parents:
diff changeset
418 char *s;
kono
parents:
diff changeset
419 int m, n;
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 s = read_block_form (dtp, &width);
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 if (s == NULL)
kono
parents:
diff changeset
424 return;
kono
parents:
diff changeset
425 if (width > len)
kono
parents:
diff changeset
426 s += (width - len);
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 m = (width > len) ? len : width;
kono
parents:
diff changeset
429 memcpy (p, s, m);
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431 n = len - width;
kono
parents:
diff changeset
432 if (n > 0)
kono
parents:
diff changeset
433 memset (p + m, ' ', n);
kono
parents:
diff changeset
434 }
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 static void
kono
parents:
diff changeset
438 read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width)
kono
parents:
diff changeset
439 {
kono
parents:
diff changeset
440 gfc_char4_t *dest;
kono
parents:
diff changeset
441 int nbytes;
kono
parents:
diff changeset
442 int i, j;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 len = (width < len) ? len : width;
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446 dest = (gfc_char4_t *) p;
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 /* Proceed with decoding one character at a time. */
kono
parents:
diff changeset
449 for (j = 0; j < len; j++, dest++)
kono
parents:
diff changeset
450 {
kono
parents:
diff changeset
451 *dest = read_utf8 (dtp, &nbytes);
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 /* Check for a short read and if so, break out. */
kono
parents:
diff changeset
454 if (nbytes == 0)
kono
parents:
diff changeset
455 break;
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 /* If there was a short read, pad the remaining characters. */
kono
parents:
diff changeset
459 for (i = j; i < len; i++)
kono
parents:
diff changeset
460 *dest++ = (gfc_char4_t) ' ';
kono
parents:
diff changeset
461 return;
kono
parents:
diff changeset
462 }
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 static void
kono
parents:
diff changeset
466 read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
kono
parents:
diff changeset
467 {
kono
parents:
diff changeset
468 int m, n;
kono
parents:
diff changeset
469 gfc_char4_t *dest;
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 if (is_char4_unit(dtp))
kono
parents:
diff changeset
472 {
kono
parents:
diff changeset
473 gfc_char4_t *s4;
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 s4 = (gfc_char4_t *) read_block_form4 (dtp, &width);
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 if (s4 == NULL)
kono
parents:
diff changeset
478 return;
kono
parents:
diff changeset
479 if (width > len)
kono
parents:
diff changeset
480 s4 += (width - len);
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 m = ((int) width > len) ? len : (int) width;
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 dest = (gfc_char4_t *) p;
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 for (n = 0; n < m; n++)
kono
parents:
diff changeset
487 *dest++ = *s4++;
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 for (n = 0; n < len - (int) width; n++)
kono
parents:
diff changeset
490 *dest++ = (gfc_char4_t) ' ';
kono
parents:
diff changeset
491 }
kono
parents:
diff changeset
492 else
kono
parents:
diff changeset
493 {
kono
parents:
diff changeset
494 char *s;
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 s = read_block_form (dtp, &width);
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 if (s == NULL)
kono
parents:
diff changeset
499 return;
kono
parents:
diff changeset
500 if (width > len)
kono
parents:
diff changeset
501 s += (width - len);
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 m = ((int) width > len) ? len : (int) width;
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 dest = (gfc_char4_t *) p;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 for (n = 0; n < m; n++, dest++, s++)
kono
parents:
diff changeset
508 *dest = (unsigned char ) *s;
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 for (n = 0; n < len - (int) width; n++, dest++)
kono
parents:
diff changeset
511 *dest = (unsigned char) ' ';
kono
parents:
diff changeset
512 }
kono
parents:
diff changeset
513 }
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 /* read_a()-- Read a character record into a KIND=1 character destination,
kono
parents:
diff changeset
517 processing UTF-8 encoding if necessary. */
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 void
kono
parents:
diff changeset
520 read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
kono
parents:
diff changeset
521 {
kono
parents:
diff changeset
522 int wi;
kono
parents:
diff changeset
523 int w;
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 wi = f->u.w;
kono
parents:
diff changeset
526 if (wi == -1) /* '(A)' edit descriptor */
kono
parents:
diff changeset
527 wi = length;
kono
parents:
diff changeset
528 w = wi;
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 /* Read in w characters, treating comma as not a separator. */
kono
parents:
diff changeset
531 dtp->u.p.sf_read_comma = 0;
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
kono
parents:
diff changeset
534 read_utf8_char1 (dtp, p, length, w);
kono
parents:
diff changeset
535 else
kono
parents:
diff changeset
536 read_default_char1 (dtp, p, length, w);
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 dtp->u.p.sf_read_comma =
kono
parents:
diff changeset
539 dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
kono
parents:
diff changeset
540 }
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 /* read_a_char4()-- Read a character record into a KIND=4 character destination,
kono
parents:
diff changeset
544 processing UTF-8 encoding if necessary. */
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 void
kono
parents:
diff changeset
547 read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
kono
parents:
diff changeset
548 {
kono
parents:
diff changeset
549 int w;
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 w = f->u.w;
kono
parents:
diff changeset
552 if (w == -1) /* '(A)' edit descriptor */
kono
parents:
diff changeset
553 w = length;
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 /* Read in w characters, treating comma as not a separator. */
kono
parents:
diff changeset
556 dtp->u.p.sf_read_comma = 0;
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
kono
parents:
diff changeset
559 read_utf8_char4 (dtp, p, length, w);
kono
parents:
diff changeset
560 else
kono
parents:
diff changeset
561 read_default_char4 (dtp, p, length, w);
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 dtp->u.p.sf_read_comma =
kono
parents:
diff changeset
564 dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
kono
parents:
diff changeset
565 }
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 /* eat_leading_spaces()-- Given a character pointer and a width,
kono
parents:
diff changeset
568 ignore the leading spaces. */
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 static char *
kono
parents:
diff changeset
571 eat_leading_spaces (int *width, char *p)
kono
parents:
diff changeset
572 {
kono
parents:
diff changeset
573 for (;;)
kono
parents:
diff changeset
574 {
kono
parents:
diff changeset
575 if (*width == 0 || *p != ' ')
kono
parents:
diff changeset
576 break;
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 (*width)--;
kono
parents:
diff changeset
579 p++;
kono
parents:
diff changeset
580 }
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 return p;
kono
parents:
diff changeset
583 }
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 static char
kono
parents:
diff changeset
587 next_char (st_parameter_dt *dtp, char **p, int *w)
kono
parents:
diff changeset
588 {
kono
parents:
diff changeset
589 char c, *q;
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 if (*w == 0)
kono
parents:
diff changeset
592 return '\0';
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 q = *p;
kono
parents:
diff changeset
595 c = *q++;
kono
parents:
diff changeset
596 *p = q;
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 (*w)--;
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 if (c != ' ')
kono
parents:
diff changeset
601 return c;
kono
parents:
diff changeset
602 if (dtp->u.p.blank_status != BLANK_UNSPECIFIED)
kono
parents:
diff changeset
603 return ' '; /* return a blank to signal a null */
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 /* At this point, the rest of the field has to be trailing blanks */
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 while (*w > 0)
kono
parents:
diff changeset
608 {
kono
parents:
diff changeset
609 if (*q++ != ' ')
kono
parents:
diff changeset
610 return '?';
kono
parents:
diff changeset
611 (*w)--;
kono
parents:
diff changeset
612 }
kono
parents:
diff changeset
613
kono
parents:
diff changeset
614 *p = q;
kono
parents:
diff changeset
615 return '\0';
kono
parents:
diff changeset
616 }
kono
parents:
diff changeset
617
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 /* read_decimal()-- Read a decimal integer value. The values here are
kono
parents:
diff changeset
620 signed values. */
kono
parents:
diff changeset
621
kono
parents:
diff changeset
622 void
kono
parents:
diff changeset
623 read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
kono
parents:
diff changeset
624 {
kono
parents:
diff changeset
625 GFC_UINTEGER_LARGEST value, maxv, maxv_10;
kono
parents:
diff changeset
626 GFC_INTEGER_LARGEST v;
kono
parents:
diff changeset
627 int w, negative;
kono
parents:
diff changeset
628 char c, *p;
kono
parents:
diff changeset
629
kono
parents:
diff changeset
630 w = f->u.w;
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 p = read_block_form (dtp, &w);
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 if (p == NULL)
kono
parents:
diff changeset
635 return;
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 p = eat_leading_spaces (&w, p);
kono
parents:
diff changeset
638 if (w == 0)
kono
parents:
diff changeset
639 {
kono
parents:
diff changeset
640 set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
kono
parents:
diff changeset
641 return;
kono
parents:
diff changeset
642 }
kono
parents:
diff changeset
643
kono
parents:
diff changeset
644 negative = 0;
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 switch (*p)
kono
parents:
diff changeset
647 {
kono
parents:
diff changeset
648 case '-':
kono
parents:
diff changeset
649 negative = 1;
kono
parents:
diff changeset
650 /* Fall through */
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 case '+':
kono
parents:
diff changeset
653 p++;
kono
parents:
diff changeset
654 if (--w == 0)
kono
parents:
diff changeset
655 goto bad;
kono
parents:
diff changeset
656 /* Fall through */
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 default:
kono
parents:
diff changeset
659 break;
kono
parents:
diff changeset
660 }
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 maxv = si_max (length);
kono
parents:
diff changeset
663 if (negative)
kono
parents:
diff changeset
664 maxv++;
kono
parents:
diff changeset
665 maxv_10 = maxv / 10;
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 /* At this point we have a digit-string */
kono
parents:
diff changeset
668 value = 0;
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 for (;;)
kono
parents:
diff changeset
671 {
kono
parents:
diff changeset
672 c = next_char (dtp, &p, &w);
kono
parents:
diff changeset
673 if (c == '\0')
kono
parents:
diff changeset
674 break;
kono
parents:
diff changeset
675
kono
parents:
diff changeset
676 if (c == ' ')
kono
parents:
diff changeset
677 {
kono
parents:
diff changeset
678 if (dtp->u.p.blank_status == BLANK_NULL)
kono
parents:
diff changeset
679 {
kono
parents:
diff changeset
680 /* Skip spaces. */
kono
parents:
diff changeset
681 for ( ; w > 0; p++, w--)
kono
parents:
diff changeset
682 if (*p != ' ') break;
kono
parents:
diff changeset
683 continue;
kono
parents:
diff changeset
684 }
kono
parents:
diff changeset
685 if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
kono
parents:
diff changeset
686 }
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 if (c < '0' || c > '9')
kono
parents:
diff changeset
689 goto bad;
kono
parents:
diff changeset
690
kono
parents:
diff changeset
691 if (value > maxv_10)
kono
parents:
diff changeset
692 goto overflow;
kono
parents:
diff changeset
693
kono
parents:
diff changeset
694 c -= '0';
kono
parents:
diff changeset
695 value = 10 * value;
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 if (value > maxv - c)
kono
parents:
diff changeset
698 goto overflow;
kono
parents:
diff changeset
699 value += c;
kono
parents:
diff changeset
700 }
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 if (negative)
kono
parents:
diff changeset
703 v = -value;
kono
parents:
diff changeset
704 else
kono
parents:
diff changeset
705 v = value;
kono
parents:
diff changeset
706
kono
parents:
diff changeset
707 set_integer (dest, v, length);
kono
parents:
diff changeset
708 return;
kono
parents:
diff changeset
709
kono
parents:
diff changeset
710 bad:
kono
parents:
diff changeset
711 generate_error (&dtp->common, LIBERROR_READ_VALUE,
kono
parents:
diff changeset
712 "Bad value during integer read");
kono
parents:
diff changeset
713 next_record (dtp, 1);
kono
parents:
diff changeset
714 return;
kono
parents:
diff changeset
715
kono
parents:
diff changeset
716 overflow:
kono
parents:
diff changeset
717 generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
kono
parents:
diff changeset
718 "Value overflowed during integer read");
kono
parents:
diff changeset
719 next_record (dtp, 1);
kono
parents:
diff changeset
720
kono
parents:
diff changeset
721 }
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 /* read_radix()-- This function reads values for non-decimal radixes.
kono
parents:
diff changeset
725 The difference here is that we treat the values here as unsigned
kono
parents:
diff changeset
726 values for the purposes of overflow. If minus sign is present and
kono
parents:
diff changeset
727 the top bit is set, the value will be incorrect. */
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 void
kono
parents:
diff changeset
730 read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
kono
parents:
diff changeset
731 int radix)
kono
parents:
diff changeset
732 {
kono
parents:
diff changeset
733 GFC_UINTEGER_LARGEST value, maxv, maxv_r;
kono
parents:
diff changeset
734 GFC_INTEGER_LARGEST v;
kono
parents:
diff changeset
735 int w, negative;
kono
parents:
diff changeset
736 char c, *p;
kono
parents:
diff changeset
737
kono
parents:
diff changeset
738 w = f->u.w;
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 p = read_block_form (dtp, &w);
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 if (p == NULL)
kono
parents:
diff changeset
743 return;
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 p = eat_leading_spaces (&w, p);
kono
parents:
diff changeset
746 if (w == 0)
kono
parents:
diff changeset
747 {
kono
parents:
diff changeset
748 set_integer (dest, (GFC_INTEGER_LARGEST) 0, length);
kono
parents:
diff changeset
749 return;
kono
parents:
diff changeset
750 }
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 /* Maximum unsigned value, assuming two's complement. */
kono
parents:
diff changeset
753 maxv = 2 * si_max (length) + 1;
kono
parents:
diff changeset
754 maxv_r = maxv / radix;
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 negative = 0;
kono
parents:
diff changeset
757 value = 0;
kono
parents:
diff changeset
758
kono
parents:
diff changeset
759 switch (*p)
kono
parents:
diff changeset
760 {
kono
parents:
diff changeset
761 case '-':
kono
parents:
diff changeset
762 negative = 1;
kono
parents:
diff changeset
763 /* Fall through */
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 case '+':
kono
parents:
diff changeset
766 p++;
kono
parents:
diff changeset
767 if (--w == 0)
kono
parents:
diff changeset
768 goto bad;
kono
parents:
diff changeset
769 /* Fall through */
kono
parents:
diff changeset
770
kono
parents:
diff changeset
771 default:
kono
parents:
diff changeset
772 break;
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 /* At this point we have a digit-string */
kono
parents:
diff changeset
776 value = 0;
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 for (;;)
kono
parents:
diff changeset
779 {
kono
parents:
diff changeset
780 c = next_char (dtp, &p, &w);
kono
parents:
diff changeset
781 if (c == '\0')
kono
parents:
diff changeset
782 break;
kono
parents:
diff changeset
783 if (c == ' ')
kono
parents:
diff changeset
784 {
kono
parents:
diff changeset
785 if (dtp->u.p.blank_status == BLANK_NULL) continue;
kono
parents:
diff changeset
786 if (dtp->u.p.blank_status == BLANK_ZERO) c = '0';
kono
parents:
diff changeset
787 }
kono
parents:
diff changeset
788
kono
parents:
diff changeset
789 switch (radix)
kono
parents:
diff changeset
790 {
kono
parents:
diff changeset
791 case 2:
kono
parents:
diff changeset
792 if (c < '0' || c > '1')
kono
parents:
diff changeset
793 goto bad;
kono
parents:
diff changeset
794 break;
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 case 8:
kono
parents:
diff changeset
797 if (c < '0' || c > '7')
kono
parents:
diff changeset
798 goto bad;
kono
parents:
diff changeset
799 break;
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 case 16:
kono
parents:
diff changeset
802 switch (c)
kono
parents:
diff changeset
803 {
kono
parents:
diff changeset
804 case '0':
kono
parents:
diff changeset
805 case '1':
kono
parents:
diff changeset
806 case '2':
kono
parents:
diff changeset
807 case '3':
kono
parents:
diff changeset
808 case '4':
kono
parents:
diff changeset
809 case '5':
kono
parents:
diff changeset
810 case '6':
kono
parents:
diff changeset
811 case '7':
kono
parents:
diff changeset
812 case '8':
kono
parents:
diff changeset
813 case '9':
kono
parents:
diff changeset
814 break;
kono
parents:
diff changeset
815
kono
parents:
diff changeset
816 case 'a':
kono
parents:
diff changeset
817 case 'b':
kono
parents:
diff changeset
818 case 'c':
kono
parents:
diff changeset
819 case 'd':
kono
parents:
diff changeset
820 case 'e':
kono
parents:
diff changeset
821 case 'f':
kono
parents:
diff changeset
822 c = c - 'a' + '9' + 1;
kono
parents:
diff changeset
823 break;
kono
parents:
diff changeset
824
kono
parents:
diff changeset
825 case 'A':
kono
parents:
diff changeset
826 case 'B':
kono
parents:
diff changeset
827 case 'C':
kono
parents:
diff changeset
828 case 'D':
kono
parents:
diff changeset
829 case 'E':
kono
parents:
diff changeset
830 case 'F':
kono
parents:
diff changeset
831 c = c - 'A' + '9' + 1;
kono
parents:
diff changeset
832 break;
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 default:
kono
parents:
diff changeset
835 goto bad;
kono
parents:
diff changeset
836 }
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 break;
kono
parents:
diff changeset
839 }
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 if (value > maxv_r)
kono
parents:
diff changeset
842 goto overflow;
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 c -= '0';
kono
parents:
diff changeset
845 value = radix * value;
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 if (maxv - c < value)
kono
parents:
diff changeset
848 goto overflow;
kono
parents:
diff changeset
849 value += c;
kono
parents:
diff changeset
850 }
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 v = value;
kono
parents:
diff changeset
853 if (negative)
kono
parents:
diff changeset
854 v = -v;
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 set_integer (dest, v, length);
kono
parents:
diff changeset
857 return;
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 bad:
kono
parents:
diff changeset
860 generate_error (&dtp->common, LIBERROR_READ_VALUE,
kono
parents:
diff changeset
861 "Bad value during integer read");
kono
parents:
diff changeset
862 next_record (dtp, 1);
kono
parents:
diff changeset
863 return;
kono
parents:
diff changeset
864
kono
parents:
diff changeset
865 overflow:
kono
parents:
diff changeset
866 generate_error (&dtp->common, LIBERROR_READ_OVERFLOW,
kono
parents:
diff changeset
867 "Value overflowed during integer read");
kono
parents:
diff changeset
868 next_record (dtp, 1);
kono
parents:
diff changeset
869
kono
parents:
diff changeset
870 }
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 /* read_f()-- Read a floating point number with F-style editing, which
kono
parents:
diff changeset
874 is what all of the other floating point descriptors behave as. The
kono
parents:
diff changeset
875 tricky part is that optional spaces are allowed after an E or D,
kono
parents:
diff changeset
876 and the implicit decimal point if a decimal point is not present in
kono
parents:
diff changeset
877 the input. */
kono
parents:
diff changeset
878
kono
parents:
diff changeset
879 void
kono
parents:
diff changeset
880 read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
kono
parents:
diff changeset
881 {
kono
parents:
diff changeset
882 #define READF_TMP 50
kono
parents:
diff changeset
883 char tmp[READF_TMP];
kono
parents:
diff changeset
884 size_t buf_size = 0;
kono
parents:
diff changeset
885 int w, seen_dp, exponent;
kono
parents:
diff changeset
886 int exponent_sign;
kono
parents:
diff changeset
887 const char *p;
kono
parents:
diff changeset
888 char *buffer;
kono
parents:
diff changeset
889 char *out;
kono
parents:
diff changeset
890 int seen_int_digit; /* Seen a digit before the decimal point? */
kono
parents:
diff changeset
891 int seen_dec_digit; /* Seen a digit after the decimal point? */
kono
parents:
diff changeset
892
kono
parents:
diff changeset
893 seen_dp = 0;
kono
parents:
diff changeset
894 seen_int_digit = 0;
kono
parents:
diff changeset
895 seen_dec_digit = 0;
kono
parents:
diff changeset
896 exponent_sign = 1;
kono
parents:
diff changeset
897 exponent = 0;
kono
parents:
diff changeset
898 w = f->u.w;
kono
parents:
diff changeset
899 buffer = tmp;
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 /* Read in the next block. */
kono
parents:
diff changeset
902 p = read_block_form (dtp, &w);
kono
parents:
diff changeset
903 if (p == NULL)
kono
parents:
diff changeset
904 return;
kono
parents:
diff changeset
905 p = eat_leading_spaces (&w, (char*) p);
kono
parents:
diff changeset
906 if (w == 0)
kono
parents:
diff changeset
907 goto zero;
kono
parents:
diff changeset
908
kono
parents:
diff changeset
909 /* In this buffer we're going to re-format the number cleanly to be parsed
kono
parents:
diff changeset
910 by convert_real in the end; this assures we're using strtod from the
kono
parents:
diff changeset
911 C library for parsing and thus probably get the best accuracy possible.
kono
parents:
diff changeset
912 This process may add a '+0.0' in front of the number as well as change the
kono
parents:
diff changeset
913 exponent because of an implicit decimal point or the like. Thus allocating
kono
parents:
diff changeset
914 strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
kono
parents:
diff changeset
915 original buffer had should be enough. */
kono
parents:
diff changeset
916 buf_size = w + 11;
kono
parents:
diff changeset
917 if (buf_size > READF_TMP)
kono
parents:
diff changeset
918 buffer = xmalloc (buf_size);
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 out = buffer;
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 /* Optional sign */
kono
parents:
diff changeset
923 if (*p == '-' || *p == '+')
kono
parents:
diff changeset
924 {
kono
parents:
diff changeset
925 if (*p == '-')
kono
parents:
diff changeset
926 *(out++) = '-';
kono
parents:
diff changeset
927 ++p;
kono
parents:
diff changeset
928 --w;
kono
parents:
diff changeset
929 }
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 p = eat_leading_spaces (&w, (char*) p);
kono
parents:
diff changeset
932 if (w == 0)
kono
parents:
diff changeset
933 goto zero;
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 /* Check for Infinity or NaN. */
kono
parents:
diff changeset
936 if (unlikely ((w >= 3 && (*p == 'i' || *p == 'I' || *p == 'n' || *p == 'N'))))
kono
parents:
diff changeset
937 {
kono
parents:
diff changeset
938 int seen_paren = 0;
kono
parents:
diff changeset
939 char *save = out;
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 /* Scan through the buffer keeping track of spaces and parenthesis. We
kono
parents:
diff changeset
942 null terminate the string as soon as we see a left paren or if we are
kono
parents:
diff changeset
943 BLANK_NULL mode. Leading spaces have already been skipped above,
kono
parents:
diff changeset
944 trailing spaces are ignored by converting to '\0'. A space
kono
parents:
diff changeset
945 between "NaN" and the optional perenthesis is not permitted. */
kono
parents:
diff changeset
946 while (w > 0)
kono
parents:
diff changeset
947 {
kono
parents:
diff changeset
948 *out = tolower (*p);
kono
parents:
diff changeset
949 switch (*p)
kono
parents:
diff changeset
950 {
kono
parents:
diff changeset
951 case ' ':
kono
parents:
diff changeset
952 if (dtp->u.p.blank_status == BLANK_ZERO)
kono
parents:
diff changeset
953 {
kono
parents:
diff changeset
954 *out = '0';
kono
parents:
diff changeset
955 break;
kono
parents:
diff changeset
956 }
kono
parents:
diff changeset
957 *out = '\0';
kono
parents:
diff changeset
958 if (seen_paren == 1)
kono
parents:
diff changeset
959 goto bad_float;
kono
parents:
diff changeset
960 break;
kono
parents:
diff changeset
961 case '(':
kono
parents:
diff changeset
962 seen_paren++;
kono
parents:
diff changeset
963 *out = '\0';
kono
parents:
diff changeset
964 break;
kono
parents:
diff changeset
965 case ')':
kono
parents:
diff changeset
966 if (seen_paren++ != 1)
kono
parents:
diff changeset
967 goto bad_float;
kono
parents:
diff changeset
968 break;
kono
parents:
diff changeset
969 default:
kono
parents:
diff changeset
970 if (!isalnum (*out))
kono
parents:
diff changeset
971 goto bad_float;
kono
parents:
diff changeset
972 }
kono
parents:
diff changeset
973 --w;
kono
parents:
diff changeset
974 ++p;
kono
parents:
diff changeset
975 ++out;
kono
parents:
diff changeset
976 }
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 *out = '\0';
kono
parents:
diff changeset
979
kono
parents:
diff changeset
980 if (seen_paren != 0 && seen_paren != 2)
kono
parents:
diff changeset
981 goto bad_float;
kono
parents:
diff changeset
982
kono
parents:
diff changeset
983 if ((strcmp (save, "inf") == 0) || (strcmp (save, "infinity") == 0))
kono
parents:
diff changeset
984 {
kono
parents:
diff changeset
985 if (seen_paren)
kono
parents:
diff changeset
986 goto bad_float;
kono
parents:
diff changeset
987 }
kono
parents:
diff changeset
988 else if (strcmp (save, "nan") != 0)
kono
parents:
diff changeset
989 goto bad_float;
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 convert_infnan (dtp, dest, buffer, length);
kono
parents:
diff changeset
992 if (buf_size > READF_TMP)
kono
parents:
diff changeset
993 free (buffer);
kono
parents:
diff changeset
994 return;
kono
parents:
diff changeset
995 }
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 /* Process the mantissa string. */
kono
parents:
diff changeset
998 while (w > 0)
kono
parents:
diff changeset
999 {
kono
parents:
diff changeset
1000 switch (*p)
kono
parents:
diff changeset
1001 {
kono
parents:
diff changeset
1002 case ',':
kono
parents:
diff changeset
1003 if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA)
kono
parents:
diff changeset
1004 goto bad_float;
kono
parents:
diff changeset
1005 /* Fall through. */
kono
parents:
diff changeset
1006 case '.':
kono
parents:
diff changeset
1007 if (seen_dp)
kono
parents:
diff changeset
1008 goto bad_float;
kono
parents:
diff changeset
1009 if (!seen_int_digit)
kono
parents:
diff changeset
1010 *(out++) = '0';
kono
parents:
diff changeset
1011 *(out++) = '.';
kono
parents:
diff changeset
1012 seen_dp = 1;
kono
parents:
diff changeset
1013 break;
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 case ' ':
kono
parents:
diff changeset
1016 if (dtp->u.p.blank_status == BLANK_ZERO)
kono
parents:
diff changeset
1017 {
kono
parents:
diff changeset
1018 *(out++) = '0';
kono
parents:
diff changeset
1019 goto found_digit;
kono
parents:
diff changeset
1020 }
kono
parents:
diff changeset
1021 else if (dtp->u.p.blank_status == BLANK_NULL)
kono
parents:
diff changeset
1022 break;
kono
parents:
diff changeset
1023 else
kono
parents:
diff changeset
1024 /* TODO: Should we check instead that there are only trailing
kono
parents:
diff changeset
1025 blanks here, as is done below for exponents? */
kono
parents:
diff changeset
1026 goto done;
kono
parents:
diff changeset
1027 /* Fall through. */
kono
parents:
diff changeset
1028 case '0':
kono
parents:
diff changeset
1029 case '1':
kono
parents:
diff changeset
1030 case '2':
kono
parents:
diff changeset
1031 case '3':
kono
parents:
diff changeset
1032 case '4':
kono
parents:
diff changeset
1033 case '5':
kono
parents:
diff changeset
1034 case '6':
kono
parents:
diff changeset
1035 case '7':
kono
parents:
diff changeset
1036 case '8':
kono
parents:
diff changeset
1037 case '9':
kono
parents:
diff changeset
1038 *(out++) = *p;
kono
parents:
diff changeset
1039 found_digit:
kono
parents:
diff changeset
1040 if (!seen_dp)
kono
parents:
diff changeset
1041 seen_int_digit = 1;
kono
parents:
diff changeset
1042 else
kono
parents:
diff changeset
1043 seen_dec_digit = 1;
kono
parents:
diff changeset
1044 break;
kono
parents:
diff changeset
1045
kono
parents:
diff changeset
1046 case '-':
kono
parents:
diff changeset
1047 case '+':
kono
parents:
diff changeset
1048 goto exponent;
kono
parents:
diff changeset
1049
kono
parents:
diff changeset
1050 case 'e':
kono
parents:
diff changeset
1051 case 'E':
kono
parents:
diff changeset
1052 case 'd':
kono
parents:
diff changeset
1053 case 'D':
kono
parents:
diff changeset
1054 case 'q':
kono
parents:
diff changeset
1055 case 'Q':
kono
parents:
diff changeset
1056 ++p;
kono
parents:
diff changeset
1057 --w;
kono
parents:
diff changeset
1058 goto exponent;
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 default:
kono
parents:
diff changeset
1061 goto bad_float;
kono
parents:
diff changeset
1062 }
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064 ++p;
kono
parents:
diff changeset
1065 --w;
kono
parents:
diff changeset
1066 }
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 /* No exponent has been seen, so we use the current scale factor. */
kono
parents:
diff changeset
1069 exponent = - dtp->u.p.scale_factor;
kono
parents:
diff changeset
1070 goto done;
kono
parents:
diff changeset
1071
kono
parents:
diff changeset
1072 /* At this point the start of an exponent has been found. */
kono
parents:
diff changeset
1073 exponent:
kono
parents:
diff changeset
1074 p = eat_leading_spaces (&w, (char*) p);
kono
parents:
diff changeset
1075 if (*p == '-' || *p == '+')
kono
parents:
diff changeset
1076 {
kono
parents:
diff changeset
1077 if (*p == '-')
kono
parents:
diff changeset
1078 exponent_sign = -1;
kono
parents:
diff changeset
1079 ++p;
kono
parents:
diff changeset
1080 --w;
kono
parents:
diff changeset
1081 }
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 /* At this point a digit string is required. We calculate the value
kono
parents:
diff changeset
1084 of the exponent in order to take account of the scale factor and
kono
parents:
diff changeset
1085 the d parameter before explict conversion takes place. */
kono
parents:
diff changeset
1086
kono
parents:
diff changeset
1087 if (w == 0)
kono
parents:
diff changeset
1088 {
kono
parents:
diff changeset
1089 /* Extension: allow default exponent of 0 when omitted. */
kono
parents:
diff changeset
1090 if (dtp->common.flags & IOPARM_DT_DEFAULT_EXP)
kono
parents:
diff changeset
1091 goto done;
kono
parents:
diff changeset
1092 else
kono
parents:
diff changeset
1093 goto bad_float;
kono
parents:
diff changeset
1094 }
kono
parents:
diff changeset
1095
kono
parents:
diff changeset
1096 if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
kono
parents:
diff changeset
1097 {
kono
parents:
diff changeset
1098 while (w > 0 && isdigit (*p))
kono
parents:
diff changeset
1099 {
kono
parents:
diff changeset
1100 exponent *= 10;
kono
parents:
diff changeset
1101 exponent += *p - '0';
kono
parents:
diff changeset
1102 ++p;
kono
parents:
diff changeset
1103 --w;
kono
parents:
diff changeset
1104 }
kono
parents:
diff changeset
1105
kono
parents:
diff changeset
1106 /* Only allow trailing blanks. */
kono
parents:
diff changeset
1107 while (w > 0)
kono
parents:
diff changeset
1108 {
kono
parents:
diff changeset
1109 if (*p != ' ')
kono
parents:
diff changeset
1110 goto bad_float;
kono
parents:
diff changeset
1111 ++p;
kono
parents:
diff changeset
1112 --w;
kono
parents:
diff changeset
1113 }
kono
parents:
diff changeset
1114 }
kono
parents:
diff changeset
1115 else /* BZ or BN status is enabled. */
kono
parents:
diff changeset
1116 {
kono
parents:
diff changeset
1117 while (w > 0)
kono
parents:
diff changeset
1118 {
kono
parents:
diff changeset
1119 if (*p == ' ')
kono
parents:
diff changeset
1120 {
kono
parents:
diff changeset
1121 if (dtp->u.p.blank_status == BLANK_ZERO)
kono
parents:
diff changeset
1122 exponent *= 10;
kono
parents:
diff changeset
1123 else
kono
parents:
diff changeset
1124 assert (dtp->u.p.blank_status == BLANK_NULL);
kono
parents:
diff changeset
1125 }
kono
parents:
diff changeset
1126 else if (!isdigit (*p))
kono
parents:
diff changeset
1127 goto bad_float;
kono
parents:
diff changeset
1128 else
kono
parents:
diff changeset
1129 {
kono
parents:
diff changeset
1130 exponent *= 10;
kono
parents:
diff changeset
1131 exponent += *p - '0';
kono
parents:
diff changeset
1132 }
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 ++p;
kono
parents:
diff changeset
1135 --w;
kono
parents:
diff changeset
1136 }
kono
parents:
diff changeset
1137 }
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139 exponent *= exponent_sign;
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 done:
kono
parents:
diff changeset
1142 /* Use the precision specified in the format if no decimal point has been
kono
parents:
diff changeset
1143 seen. */
kono
parents:
diff changeset
1144 if (!seen_dp)
kono
parents:
diff changeset
1145 exponent -= f->u.real.d;
kono
parents:
diff changeset
1146
kono
parents:
diff changeset
1147 /* Output a trailing '0' after decimal point if not yet found. */
kono
parents:
diff changeset
1148 if (seen_dp && !seen_dec_digit)
kono
parents:
diff changeset
1149 *(out++) = '0';
kono
parents:
diff changeset
1150 /* Handle input of style "E+NN" by inserting a 0 for the
kono
parents:
diff changeset
1151 significand. */
kono
parents:
diff changeset
1152 else if (!seen_int_digit && !seen_dec_digit)
kono
parents:
diff changeset
1153 {
kono
parents:
diff changeset
1154 notify_std (&dtp->common, GFC_STD_LEGACY,
kono
parents:
diff changeset
1155 "REAL input of style 'E+NN'");
kono
parents:
diff changeset
1156 *(out++) = '0';
kono
parents:
diff changeset
1157 }
kono
parents:
diff changeset
1158
kono
parents:
diff changeset
1159 /* Print out the exponent to finish the reformatted number. Maximum 4
kono
parents:
diff changeset
1160 digits for the exponent. */
kono
parents:
diff changeset
1161 if (exponent != 0)
kono
parents:
diff changeset
1162 {
kono
parents:
diff changeset
1163 int dig;
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 *(out++) = 'e';
kono
parents:
diff changeset
1166 if (exponent < 0)
kono
parents:
diff changeset
1167 {
kono
parents:
diff changeset
1168 *(out++) = '-';
kono
parents:
diff changeset
1169 exponent = - exponent;
kono
parents:
diff changeset
1170 }
kono
parents:
diff changeset
1171
kono
parents:
diff changeset
1172 if (exponent >= 10000)
kono
parents:
diff changeset
1173 goto bad_float;
kono
parents:
diff changeset
1174
kono
parents:
diff changeset
1175 for (dig = 3; dig >= 0; --dig)
kono
parents:
diff changeset
1176 {
kono
parents:
diff changeset
1177 out[dig] = (char) ('0' + exponent % 10);
kono
parents:
diff changeset
1178 exponent /= 10;
kono
parents:
diff changeset
1179 }
kono
parents:
diff changeset
1180 out += 4;
kono
parents:
diff changeset
1181 }
kono
parents:
diff changeset
1182 *(out++) = '\0';
kono
parents:
diff changeset
1183
kono
parents:
diff changeset
1184 /* Do the actual conversion. */
kono
parents:
diff changeset
1185 convert_real (dtp, dest, buffer, length);
kono
parents:
diff changeset
1186 if (buf_size > READF_TMP)
kono
parents:
diff changeset
1187 free (buffer);
kono
parents:
diff changeset
1188 return;
kono
parents:
diff changeset
1189
kono
parents:
diff changeset
1190 /* The value read is zero. */
kono
parents:
diff changeset
1191 zero:
kono
parents:
diff changeset
1192 switch (length)
kono
parents:
diff changeset
1193 {
kono
parents:
diff changeset
1194 case 4:
kono
parents:
diff changeset
1195 *((GFC_REAL_4 *) dest) = 0.0;
kono
parents:
diff changeset
1196 break;
kono
parents:
diff changeset
1197
kono
parents:
diff changeset
1198 case 8:
kono
parents:
diff changeset
1199 *((GFC_REAL_8 *) dest) = 0.0;
kono
parents:
diff changeset
1200 break;
kono
parents:
diff changeset
1201
kono
parents:
diff changeset
1202 #ifdef HAVE_GFC_REAL_10
kono
parents:
diff changeset
1203 case 10:
kono
parents:
diff changeset
1204 *((GFC_REAL_10 *) dest) = 0.0;
kono
parents:
diff changeset
1205 break;
kono
parents:
diff changeset
1206 #endif
kono
parents:
diff changeset
1207
kono
parents:
diff changeset
1208 #ifdef HAVE_GFC_REAL_16
kono
parents:
diff changeset
1209 case 16:
kono
parents:
diff changeset
1210 *((GFC_REAL_16 *) dest) = 0.0;
kono
parents:
diff changeset
1211 break;
kono
parents:
diff changeset
1212 #endif
kono
parents:
diff changeset
1213
kono
parents:
diff changeset
1214 default:
kono
parents:
diff changeset
1215 internal_error (&dtp->common, "Unsupported real kind during IO");
kono
parents:
diff changeset
1216 }
kono
parents:
diff changeset
1217 return;
kono
parents:
diff changeset
1218
kono
parents:
diff changeset
1219 bad_float:
kono
parents:
diff changeset
1220 if (buf_size > READF_TMP)
kono
parents:
diff changeset
1221 free (buffer);
kono
parents:
diff changeset
1222 generate_error (&dtp->common, LIBERROR_READ_VALUE,
kono
parents:
diff changeset
1223 "Bad value during floating point read");
kono
parents:
diff changeset
1224 next_record (dtp, 1);
kono
parents:
diff changeset
1225 return;
kono
parents:
diff changeset
1226 }
kono
parents:
diff changeset
1227
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 /* read_x()-- Deal with the X/TR descriptor. We just read some data
kono
parents:
diff changeset
1230 and never look at it. */
kono
parents:
diff changeset
1231
kono
parents:
diff changeset
1232 void
kono
parents:
diff changeset
1233 read_x (st_parameter_dt *dtp, int n)
kono
parents:
diff changeset
1234 {
kono
parents:
diff changeset
1235 int length, q, q2;
kono
parents:
diff changeset
1236
kono
parents:
diff changeset
1237 if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
kono
parents:
diff changeset
1238 && dtp->u.p.current_unit->bytes_left < n)
kono
parents:
diff changeset
1239 n = dtp->u.p.current_unit->bytes_left;
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 if (n == 0)
kono
parents:
diff changeset
1242 return;
kono
parents:
diff changeset
1243
kono
parents:
diff changeset
1244 length = n;
kono
parents:
diff changeset
1245
kono
parents:
diff changeset
1246 if (is_internal_unit (dtp))
kono
parents:
diff changeset
1247 {
kono
parents:
diff changeset
1248 mem_alloc_r (dtp->u.p.current_unit->s, &length);
kono
parents:
diff changeset
1249 if (unlikely (length < n))
kono
parents:
diff changeset
1250 n = length;
kono
parents:
diff changeset
1251 goto done;
kono
parents:
diff changeset
1252 }
kono
parents:
diff changeset
1253
kono
parents:
diff changeset
1254 if (dtp->u.p.sf_seen_eor)
kono
parents:
diff changeset
1255 return;
kono
parents:
diff changeset
1256
kono
parents:
diff changeset
1257 n = 0;
kono
parents:
diff changeset
1258 while (n < length)
kono
parents:
diff changeset
1259 {
kono
parents:
diff changeset
1260 q = fbuf_getc (dtp->u.p.current_unit);
kono
parents:
diff changeset
1261 if (q == EOF)
kono
parents:
diff changeset
1262 break;
kono
parents:
diff changeset
1263 else if (dtp->u.p.current_unit->flags.cc != CC_NONE
kono
parents:
diff changeset
1264 && (q == '\n' || q == '\r'))
kono
parents:
diff changeset
1265 {
kono
parents:
diff changeset
1266 /* Unexpected end of line. Set the position. */
kono
parents:
diff changeset
1267 dtp->u.p.sf_seen_eor = 1;
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 /* If we see an EOR during non-advancing I/O, we need to skip
kono
parents:
diff changeset
1270 the rest of the I/O statement. Set the corresponding flag. */
kono
parents:
diff changeset
1271 if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
kono
parents:
diff changeset
1272 dtp->u.p.eor_condition = 1;
kono
parents:
diff changeset
1273
kono
parents:
diff changeset
1274 /* If we encounter a CR, it might be a CRLF. */
kono
parents:
diff changeset
1275 if (q == '\r') /* Probably a CRLF */
kono
parents:
diff changeset
1276 {
kono
parents:
diff changeset
1277 /* See if there is an LF. */
kono
parents:
diff changeset
1278 q2 = fbuf_getc (dtp->u.p.current_unit);
kono
parents:
diff changeset
1279 if (q2 == '\n')
kono
parents:
diff changeset
1280 dtp->u.p.sf_seen_eor = 2;
kono
parents:
diff changeset
1281 else if (q2 != EOF) /* Oops, seek back. */
kono
parents:
diff changeset
1282 fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
kono
parents:
diff changeset
1283 }
kono
parents:
diff changeset
1284 goto done;
kono
parents:
diff changeset
1285 }
kono
parents:
diff changeset
1286 n++;
kono
parents:
diff changeset
1287 }
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 done:
kono
parents:
diff changeset
1290 if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
kono
parents:
diff changeset
1291 dtp->u.p.current_unit->has_size)
kono
parents:
diff changeset
1292 dtp->u.p.current_unit->size_used += (GFC_IO_INT) n;
kono
parents:
diff changeset
1293 dtp->u.p.current_unit->bytes_left -= n;
kono
parents:
diff changeset
1294 dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
kono
parents:
diff changeset
1295 }
kono
parents:
diff changeset
1296