annotate libgfortran/io/list_read.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1 /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
2 Contributed by Andy Vaught
kono
parents:
diff changeset
3 Namelist input contributed by Paul Thomas
kono
parents:
diff changeset
4 F2003 I/O support contributed by Jerry DeLisle
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of the GNU Fortran runtime library (libgfortran).
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 Libgfortran is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
9 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
10 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
11 any later version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 Libgfortran is distributed in the hope that it will be useful,
kono
parents:
diff changeset
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
16 GNU General Public License for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
19 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
20 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
23 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
25 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #include "io.h"
kono
parents:
diff changeset
29 #include "fbuf.h"
kono
parents:
diff changeset
30 #include "unix.h"
kono
parents:
diff changeset
31 #include <string.h>
kono
parents:
diff changeset
32 #include <ctype.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
kono
parents:
diff changeset
37 /* List directed input. Several parsing subroutines are practically
kono
parents:
diff changeset
38 reimplemented from formatted input, the reason being that there are
kono
parents:
diff changeset
39 all kinds of small differences between formatted and list directed
kono
parents:
diff changeset
40 parsing. */
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 /* Subroutines for reading characters from the input. Because a
kono
parents:
diff changeset
44 repeat count is ambiguous with an integer, we have to read the
kono
parents:
diff changeset
45 whole digit string before seeing if there is a '*' which signals
kono
parents:
diff changeset
46 the repeat count. Since we can have a lot of potential leading
kono
parents:
diff changeset
47 zeros, we have to be able to back up by arbitrary amount. Because
kono
parents:
diff changeset
48 the input might not be seekable, we have to buffer the data
kono
parents:
diff changeset
49 ourselves. */
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 #define CASE_DIGITS case '0': case '1': case '2': case '3': case '4': \
kono
parents:
diff changeset
52 case '5': case '6': case '7': case '8': case '9'
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 #define CASE_SEPARATORS /* Fall through. */ \
kono
parents:
diff changeset
55 case ' ': case ',': case '/': case '\n': \
kono
parents:
diff changeset
56 case '\t': case '\r': case ';'
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 /* This macro assumes that we're operating on a variable. */
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 #define is_separator(c) (c == '/' || c == ',' || c == '\n' || c == ' ' \
kono
parents:
diff changeset
61 || c == '\t' || c == '\r' || c == ';' || \
kono
parents:
diff changeset
62 (dtp->u.p.namelist_mode && c == '!'))
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* Maximum repeat count. Less than ten times the maximum signed int32. */
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 #define MAX_REPEAT 200000000
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 #define MSGLEN 100
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* Wrappers for calling the current worker functions. */
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 #define next_char(dtp) ((dtp)->u.p.current_unit->next_char_fn_ptr (dtp))
kono
parents:
diff changeset
75 #define push_char(dtp, c) ((dtp)->u.p.current_unit->push_char_fn_ptr (dtp, c))
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 /* Worker function to save a default KIND=1 character to a string
kono
parents:
diff changeset
78 buffer, enlarging it as necessary. */
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 static void
kono
parents:
diff changeset
81 push_char_default (st_parameter_dt *dtp, int c)
kono
parents:
diff changeset
82 {
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 if (dtp->u.p.saved_string == NULL)
kono
parents:
diff changeset
86 {
kono
parents:
diff changeset
87 /* Plain malloc should suffice here, zeroing not needed? */
kono
parents:
diff changeset
88 dtp->u.p.saved_string = xcalloc (SCRATCH_SIZE, 1);
kono
parents:
diff changeset
89 dtp->u.p.saved_length = SCRATCH_SIZE;
kono
parents:
diff changeset
90 dtp->u.p.saved_used = 0;
kono
parents:
diff changeset
91 }
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
kono
parents:
diff changeset
94 {
kono
parents:
diff changeset
95 dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
kono
parents:
diff changeset
96 dtp->u.p.saved_string =
kono
parents:
diff changeset
97 xrealloc (dtp->u.p.saved_string, dtp->u.p.saved_length);
kono
parents:
diff changeset
98 }
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 dtp->u.p.saved_string[dtp->u.p.saved_used++] = (char) c;
kono
parents:
diff changeset
101 }
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 /* Worker function to save a KIND=4 character to a string buffer,
kono
parents:
diff changeset
105 enlarging the buffer as necessary. */
kono
parents:
diff changeset
106 static void
kono
parents:
diff changeset
107 push_char4 (st_parameter_dt *dtp, int c)
kono
parents:
diff changeset
108 {
kono
parents:
diff changeset
109 gfc_char4_t *p = (gfc_char4_t *) dtp->u.p.saved_string;
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 if (p == NULL)
kono
parents:
diff changeset
112 {
kono
parents:
diff changeset
113 dtp->u.p.saved_string = xcalloc (SCRATCH_SIZE, sizeof (gfc_char4_t));
kono
parents:
diff changeset
114 dtp->u.p.saved_length = SCRATCH_SIZE;
kono
parents:
diff changeset
115 dtp->u.p.saved_used = 0;
kono
parents:
diff changeset
116 p = (gfc_char4_t *) dtp->u.p.saved_string;
kono
parents:
diff changeset
117 }
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
kono
parents:
diff changeset
120 {
kono
parents:
diff changeset
121 dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
kono
parents:
diff changeset
122 dtp->u.p.saved_string =
kono
parents:
diff changeset
123 xrealloc (dtp->u.p.saved_string,
kono
parents:
diff changeset
124 dtp->u.p.saved_length * sizeof (gfc_char4_t));
kono
parents:
diff changeset
125 p = (gfc_char4_t *) dtp->u.p.saved_string;
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 p[dtp->u.p.saved_used++] = c;
kono
parents:
diff changeset
129 }
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* Free the input buffer if necessary. */
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 static void
kono
parents:
diff changeset
135 free_saved (st_parameter_dt *dtp)
kono
parents:
diff changeset
136 {
kono
parents:
diff changeset
137 if (dtp->u.p.saved_string == NULL)
kono
parents:
diff changeset
138 return;
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 free (dtp->u.p.saved_string);
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 dtp->u.p.saved_string = NULL;
kono
parents:
diff changeset
143 dtp->u.p.saved_used = 0;
kono
parents:
diff changeset
144 }
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 /* Free the line buffer if necessary. */
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 static void
kono
parents:
diff changeset
150 free_line (st_parameter_dt *dtp)
kono
parents:
diff changeset
151 {
kono
parents:
diff changeset
152 dtp->u.p.line_buffer_pos = 0;
kono
parents:
diff changeset
153 dtp->u.p.line_buffer_enabled = 0;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 if (dtp->u.p.line_buffer == NULL)
kono
parents:
diff changeset
156 return;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 free (dtp->u.p.line_buffer);
kono
parents:
diff changeset
159 dtp->u.p.line_buffer = NULL;
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 /* Unget saves the last character so when reading the next character,
kono
parents:
diff changeset
164 we need to check to see if there is a character waiting. Similar,
kono
parents:
diff changeset
165 if the line buffer is being used to read_logical, check it too. */
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 static int
kono
parents:
diff changeset
168 check_buffers (st_parameter_dt *dtp)
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 int c;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 c = '\0';
kono
parents:
diff changeset
173 if (dtp->u.p.current_unit->last_char != EOF - 1)
kono
parents:
diff changeset
174 {
kono
parents:
diff changeset
175 dtp->u.p.at_eol = 0;
kono
parents:
diff changeset
176 c = dtp->u.p.current_unit->last_char;
kono
parents:
diff changeset
177 dtp->u.p.current_unit->last_char = EOF - 1;
kono
parents:
diff changeset
178 goto done;
kono
parents:
diff changeset
179 }
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 /* Read from line_buffer if enabled. */
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 if (dtp->u.p.line_buffer_enabled)
kono
parents:
diff changeset
184 {
kono
parents:
diff changeset
185 dtp->u.p.at_eol = 0;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 c = dtp->u.p.line_buffer[dtp->u.p.line_buffer_pos];
kono
parents:
diff changeset
188 if (c != '\0' && dtp->u.p.line_buffer_pos < 64)
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 dtp->u.p.line_buffer[dtp->u.p.line_buffer_pos] = '\0';
kono
parents:
diff changeset
191 dtp->u.p.line_buffer_pos++;
kono
parents:
diff changeset
192 goto done;
kono
parents:
diff changeset
193 }
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 dtp->u.p.line_buffer_pos = 0;
kono
parents:
diff changeset
196 dtp->u.p.line_buffer_enabled = 0;
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 done:
kono
parents:
diff changeset
200 dtp->u.p.at_eol = (c == '\n' || c == '\r' || c == EOF);
kono
parents:
diff changeset
201 return c;
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 /* Worker function for default character encoded file. */
kono
parents:
diff changeset
206 static int
kono
parents:
diff changeset
207 next_char_default (st_parameter_dt *dtp)
kono
parents:
diff changeset
208 {
kono
parents:
diff changeset
209 int c;
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 /* Always check the unget and line buffer first. */
kono
parents:
diff changeset
212 if ((c = check_buffers (dtp)))
kono
parents:
diff changeset
213 return c;
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 c = fbuf_getc (dtp->u.p.current_unit);
kono
parents:
diff changeset
216 if (c != EOF && is_stream_io (dtp))
kono
parents:
diff changeset
217 dtp->u.p.current_unit->strm_pos++;
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 dtp->u.p.at_eol = (c == '\n' || c == EOF);
kono
parents:
diff changeset
220 return c;
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 /* Worker function for internal and array I/O units. */
kono
parents:
diff changeset
225 static int
kono
parents:
diff changeset
226 next_char_internal (st_parameter_dt *dtp)
kono
parents:
diff changeset
227 {
kono
parents:
diff changeset
228 ssize_t length;
kono
parents:
diff changeset
229 gfc_offset record;
kono
parents:
diff changeset
230 int c;
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* Always check the unget and line buffer first. */
kono
parents:
diff changeset
233 if ((c = check_buffers (dtp)))
kono
parents:
diff changeset
234 return c;
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 /* Handle the end-of-record and end-of-file conditions for
kono
parents:
diff changeset
237 internal array unit. */
kono
parents:
diff changeset
238 if (is_array_io (dtp))
kono
parents:
diff changeset
239 {
kono
parents:
diff changeset
240 if (dtp->u.p.at_eof)
kono
parents:
diff changeset
241 return EOF;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* Check for "end-of-record" condition. */
kono
parents:
diff changeset
244 if (dtp->u.p.current_unit->bytes_left == 0)
kono
parents:
diff changeset
245 {
kono
parents:
diff changeset
246 int finished;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 c = '\n';
kono
parents:
diff changeset
249 record = next_array_record (dtp, dtp->u.p.current_unit->ls,
kono
parents:
diff changeset
250 &finished);
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 /* Check for "end-of-file" condition. */
kono
parents:
diff changeset
253 if (finished)
kono
parents:
diff changeset
254 {
kono
parents:
diff changeset
255 dtp->u.p.at_eof = 1;
kono
parents:
diff changeset
256 goto done;
kono
parents:
diff changeset
257 }
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 record *= dtp->u.p.current_unit->recl;
kono
parents:
diff changeset
260 if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
kono
parents:
diff changeset
261 return EOF;
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
kono
parents:
diff changeset
264 goto done;
kono
parents:
diff changeset
265 }
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 /* Get the next character and handle end-of-record conditions. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
269 if (likely (dtp->u.p.current_unit->bytes_left > 0))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
270 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
271 if (unlikely (is_char4_unit(dtp))) /* Check for kind=4 internal unit. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
272 length = sread (dtp->u.p.current_unit->s, &c, 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
273 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
274 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
275 char cc;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
276 length = sread (dtp->u.p.current_unit->s, &cc, 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
277 c = cc;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
278 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
279 }
111
kono
parents:
diff changeset
280 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
281 length = 0;
111
kono
parents:
diff changeset
282
kono
parents:
diff changeset
283 if (unlikely (length < 0))
kono
parents:
diff changeset
284 {
kono
parents:
diff changeset
285 generate_error (&dtp->common, LIBERROR_OS, NULL);
kono
parents:
diff changeset
286 return '\0';
kono
parents:
diff changeset
287 }
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 if (is_array_io (dtp))
kono
parents:
diff changeset
290 {
kono
parents:
diff changeset
291 /* Check whether we hit EOF. */
kono
parents:
diff changeset
292 if (unlikely (length == 0))
kono
parents:
diff changeset
293 {
kono
parents:
diff changeset
294 generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
kono
parents:
diff changeset
295 return '\0';
kono
parents:
diff changeset
296 }
kono
parents:
diff changeset
297 }
kono
parents:
diff changeset
298 else
kono
parents:
diff changeset
299 {
kono
parents:
diff changeset
300 if (dtp->u.p.at_eof)
kono
parents:
diff changeset
301 return EOF;
kono
parents:
diff changeset
302 if (length == 0)
kono
parents:
diff changeset
303 {
kono
parents:
diff changeset
304 c = '\n';
kono
parents:
diff changeset
305 dtp->u.p.at_eof = 1;
kono
parents:
diff changeset
306 }
kono
parents:
diff changeset
307 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
308 dtp->u.p.current_unit->bytes_left--;
111
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 done:
kono
parents:
diff changeset
311 dtp->u.p.at_eol = (c == '\n' || c == EOF);
kono
parents:
diff changeset
312 return c;
kono
parents:
diff changeset
313 }
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 /* Worker function for UTF encoded files. */
kono
parents:
diff changeset
317 static int
kono
parents:
diff changeset
318 next_char_utf8 (st_parameter_dt *dtp)
kono
parents:
diff changeset
319 {
kono
parents:
diff changeset
320 static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
kono
parents:
diff changeset
321 static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
kono
parents:
diff changeset
322 int i, nb;
kono
parents:
diff changeset
323 gfc_char4_t c;
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 /* Always check the unget and line buffer first. */
kono
parents:
diff changeset
326 if (!(c = check_buffers (dtp)))
kono
parents:
diff changeset
327 c = fbuf_getc (dtp->u.p.current_unit);
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 if (c < 0x80)
kono
parents:
diff changeset
330 goto utf_done;
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 /* The number of leading 1-bits in the first byte indicates how many
kono
parents:
diff changeset
333 bytes follow. */
kono
parents:
diff changeset
334 for (nb = 2; nb < 7; nb++)
kono
parents:
diff changeset
335 if ((c & ~masks[nb-1]) == patns[nb-1])
kono
parents:
diff changeset
336 goto found;
kono
parents:
diff changeset
337 goto invalid;
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 found:
kono
parents:
diff changeset
340 c = (c & masks[nb-1]);
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 /* Decode the bytes read. */
kono
parents:
diff changeset
343 for (i = 1; i < nb; i++)
kono
parents:
diff changeset
344 {
kono
parents:
diff changeset
345 gfc_char4_t n = fbuf_getc (dtp->u.p.current_unit);
kono
parents:
diff changeset
346 if ((n & 0xC0) != 0x80)
kono
parents:
diff changeset
347 goto invalid;
kono
parents:
diff changeset
348 c = ((c << 6) + (n & 0x3F));
kono
parents:
diff changeset
349 }
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 /* Make sure the shortest possible encoding was used. */
kono
parents:
diff changeset
352 if (c <= 0x7F && nb > 1) goto invalid;
kono
parents:
diff changeset
353 if (c <= 0x7FF && nb > 2) goto invalid;
kono
parents:
diff changeset
354 if (c <= 0xFFFF && nb > 3) goto invalid;
kono
parents:
diff changeset
355 if (c <= 0x1FFFFF && nb > 4) goto invalid;
kono
parents:
diff changeset
356 if (c <= 0x3FFFFFF && nb > 5) goto invalid;
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 /* Make sure the character is valid. */
kono
parents:
diff changeset
359 if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
kono
parents:
diff changeset
360 goto invalid;
kono
parents:
diff changeset
361
kono
parents:
diff changeset
362 utf_done:
kono
parents:
diff changeset
363 dtp->u.p.at_eol = (c == '\n' || c == (gfc_char4_t) EOF);
kono
parents:
diff changeset
364 return (int) c;
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 invalid:
kono
parents:
diff changeset
367 generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
kono
parents:
diff changeset
368 return (gfc_char4_t) '?';
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 /* Push a character back onto the input. */
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 static void
kono
parents:
diff changeset
374 unget_char (st_parameter_dt *dtp, int c)
kono
parents:
diff changeset
375 {
kono
parents:
diff changeset
376 dtp->u.p.current_unit->last_char = c;
kono
parents:
diff changeset
377 }
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 /* Skip over spaces in the input. Returns the nonspace character that
kono
parents:
diff changeset
381 terminated the eating and also places it back on the input. */
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 static int
kono
parents:
diff changeset
384 eat_spaces (st_parameter_dt *dtp)
kono
parents:
diff changeset
385 {
kono
parents:
diff changeset
386 int c;
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 /* If internal character array IO, peak ahead and seek past spaces.
kono
parents:
diff changeset
389 This is an optimization unique to character arrays with large
kono
parents:
diff changeset
390 character lengths (PR38199). This code eliminates numerous calls
kono
parents:
diff changeset
391 to next_character. */
kono
parents:
diff changeset
392 if (is_array_io (dtp) && (dtp->u.p.current_unit->last_char == EOF - 1))
kono
parents:
diff changeset
393 {
kono
parents:
diff changeset
394 gfc_offset offset = stell (dtp->u.p.current_unit->s);
kono
parents:
diff changeset
395 gfc_offset i;
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 if (is_char4_unit(dtp)) /* kind=4 */
kono
parents:
diff changeset
398 {
kono
parents:
diff changeset
399 for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 if (dtp->internal_unit[(offset + i) * sizeof (gfc_char4_t)]
kono
parents:
diff changeset
402 != (gfc_char4_t)' ')
kono
parents:
diff changeset
403 break;
kono
parents:
diff changeset
404 }
kono
parents:
diff changeset
405 }
kono
parents:
diff changeset
406 else
kono
parents:
diff changeset
407 {
kono
parents:
diff changeset
408 for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
kono
parents:
diff changeset
409 {
kono
parents:
diff changeset
410 if (dtp->internal_unit[offset + i] != ' ')
kono
parents:
diff changeset
411 break;
kono
parents:
diff changeset
412 }
kono
parents:
diff changeset
413 }
kono
parents:
diff changeset
414
kono
parents:
diff changeset
415 if (i != 0)
kono
parents:
diff changeset
416 {
kono
parents:
diff changeset
417 sseek (dtp->u.p.current_unit->s, offset + i, SEEK_SET);
kono
parents:
diff changeset
418 dtp->u.p.current_unit->bytes_left -= i;
kono
parents:
diff changeset
419 }
kono
parents:
diff changeset
420 }
kono
parents:
diff changeset
421
kono
parents:
diff changeset
422 /* Now skip spaces, EOF and EOL are handled in next_char. */
kono
parents:
diff changeset
423 do
kono
parents:
diff changeset
424 c = next_char (dtp);
kono
parents:
diff changeset
425 while (c != EOF && (c == ' ' || c == '\r' || c == '\t'));
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 unget_char (dtp, c);
kono
parents:
diff changeset
428 return c;
kono
parents:
diff changeset
429 }
kono
parents:
diff changeset
430
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 /* This function reads characters through to the end of the current
kono
parents:
diff changeset
433 line and just ignores them. Returns 0 for success and LIBERROR_END
kono
parents:
diff changeset
434 if it hit EOF. */
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 static int
kono
parents:
diff changeset
437 eat_line (st_parameter_dt *dtp)
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 int c;
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 do
kono
parents:
diff changeset
442 c = next_char (dtp);
kono
parents:
diff changeset
443 while (c != EOF && c != '\n');
kono
parents:
diff changeset
444 if (c == EOF)
kono
parents:
diff changeset
445 return LIBERROR_END;
kono
parents:
diff changeset
446 return 0;
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 /* Skip over a separator. Technically, we don't always eat the whole
kono
parents:
diff changeset
451 separator. This is because if we've processed the last input item,
kono
parents:
diff changeset
452 then a separator is unnecessary. Plus the fact that operating
kono
parents:
diff changeset
453 systems usually deliver console input on a line basis.
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 The upshot is that if we see a newline as part of reading a
kono
parents:
diff changeset
456 separator, we stop reading. If there are more input items, we
kono
parents:
diff changeset
457 continue reading the separator with finish_separator() which takes
kono
parents:
diff changeset
458 care of the fact that we may or may not have seen a comma as part
kono
parents:
diff changeset
459 of the separator.
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 Returns 0 for success, and non-zero error code otherwise. */
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 static int
kono
parents:
diff changeset
464 eat_separator (st_parameter_dt *dtp)
kono
parents:
diff changeset
465 {
kono
parents:
diff changeset
466 int c, n;
kono
parents:
diff changeset
467 int err = 0;
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 eat_spaces (dtp);
kono
parents:
diff changeset
470 dtp->u.p.comma_flag = 0;
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
473 return LIBERROR_END;
kono
parents:
diff changeset
474 switch (c)
kono
parents:
diff changeset
475 {
kono
parents:
diff changeset
476 case ',':
kono
parents:
diff changeset
477 if (dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
478 {
kono
parents:
diff changeset
479 unget_char (dtp, c);
kono
parents:
diff changeset
480 break;
kono
parents:
diff changeset
481 }
kono
parents:
diff changeset
482 /* Fall through. */
kono
parents:
diff changeset
483 case ';':
kono
parents:
diff changeset
484 dtp->u.p.comma_flag = 1;
kono
parents:
diff changeset
485 eat_spaces (dtp);
kono
parents:
diff changeset
486 break;
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 case '/':
kono
parents:
diff changeset
489 dtp->u.p.input_complete = 1;
kono
parents:
diff changeset
490 break;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 case '\r':
kono
parents:
diff changeset
493 if ((n = next_char(dtp)) == EOF)
kono
parents:
diff changeset
494 return LIBERROR_END;
kono
parents:
diff changeset
495 if (n != '\n')
kono
parents:
diff changeset
496 {
kono
parents:
diff changeset
497 unget_char (dtp, n);
kono
parents:
diff changeset
498 break;
kono
parents:
diff changeset
499 }
kono
parents:
diff changeset
500 /* Fall through. */
kono
parents:
diff changeset
501 case '\n':
kono
parents:
diff changeset
502 dtp->u.p.at_eol = 1;
kono
parents:
diff changeset
503 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
504 {
kono
parents:
diff changeset
505 do
kono
parents:
diff changeset
506 {
kono
parents:
diff changeset
507 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
508 return LIBERROR_END;
kono
parents:
diff changeset
509 if (c == '!')
kono
parents:
diff changeset
510 {
kono
parents:
diff changeset
511 err = eat_line (dtp);
kono
parents:
diff changeset
512 if (err)
kono
parents:
diff changeset
513 return err;
kono
parents:
diff changeset
514 c = '\n';
kono
parents:
diff changeset
515 }
kono
parents:
diff changeset
516 }
kono
parents:
diff changeset
517 while (c == '\n' || c == '\r' || c == ' ' || c == '\t');
kono
parents:
diff changeset
518 unget_char (dtp, c);
kono
parents:
diff changeset
519 }
kono
parents:
diff changeset
520 break;
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 case '!':
kono
parents:
diff changeset
523 /* Eat a namelist comment. */
kono
parents:
diff changeset
524 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
525 {
kono
parents:
diff changeset
526 err = eat_line (dtp);
kono
parents:
diff changeset
527 if (err)
kono
parents:
diff changeset
528 return err;
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 break;
kono
parents:
diff changeset
531 }
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 /* Fall Through... */
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 default:
kono
parents:
diff changeset
536 unget_char (dtp, c);
kono
parents:
diff changeset
537 break;
kono
parents:
diff changeset
538 }
kono
parents:
diff changeset
539 return err;
kono
parents:
diff changeset
540 }
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 /* Finish processing a separator that was interrupted by a newline.
kono
parents:
diff changeset
544 If we're here, then another data item is present, so we finish what
kono
parents:
diff changeset
545 we started on the previous line. Return 0 on success, error code
kono
parents:
diff changeset
546 on failure. */
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 static int
kono
parents:
diff changeset
549 finish_separator (st_parameter_dt *dtp)
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 int c;
kono
parents:
diff changeset
552 int err = LIBERROR_OK;
kono
parents:
diff changeset
553
kono
parents:
diff changeset
554 restart:
kono
parents:
diff changeset
555 eat_spaces (dtp);
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
558 return LIBERROR_END;
kono
parents:
diff changeset
559 switch (c)
kono
parents:
diff changeset
560 {
kono
parents:
diff changeset
561 case ',':
kono
parents:
diff changeset
562 if (dtp->u.p.comma_flag)
kono
parents:
diff changeset
563 unget_char (dtp, c);
kono
parents:
diff changeset
564 else
kono
parents:
diff changeset
565 {
kono
parents:
diff changeset
566 if ((c = eat_spaces (dtp)) == EOF)
kono
parents:
diff changeset
567 return LIBERROR_END;
kono
parents:
diff changeset
568 if (c == '\n' || c == '\r')
kono
parents:
diff changeset
569 goto restart;
kono
parents:
diff changeset
570 }
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 break;
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 case '/':
kono
parents:
diff changeset
575 dtp->u.p.input_complete = 1;
kono
parents:
diff changeset
576 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
577 return err;
kono
parents:
diff changeset
578 break;
kono
parents:
diff changeset
579
kono
parents:
diff changeset
580 case '\n':
kono
parents:
diff changeset
581 case '\r':
kono
parents:
diff changeset
582 goto restart;
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 case '!':
kono
parents:
diff changeset
585 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
586 {
kono
parents:
diff changeset
587 err = eat_line (dtp);
kono
parents:
diff changeset
588 if (err)
kono
parents:
diff changeset
589 return err;
kono
parents:
diff changeset
590 goto restart;
kono
parents:
diff changeset
591 }
kono
parents:
diff changeset
592 /* Fall through. */
kono
parents:
diff changeset
593 default:
kono
parents:
diff changeset
594 unget_char (dtp, c);
kono
parents:
diff changeset
595 break;
kono
parents:
diff changeset
596 }
kono
parents:
diff changeset
597 return err;
kono
parents:
diff changeset
598 }
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 /* This function is needed to catch bad conversions so that namelist can
kono
parents:
diff changeset
602 attempt to see if dtp->u.p.saved_string contains a new object name rather
kono
parents:
diff changeset
603 than a bad value. */
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 static int
kono
parents:
diff changeset
606 nml_bad_return (st_parameter_dt *dtp, char c)
kono
parents:
diff changeset
607 {
kono
parents:
diff changeset
608 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
609 {
kono
parents:
diff changeset
610 dtp->u.p.nml_read_error = 1;
kono
parents:
diff changeset
611 unget_char (dtp, c);
kono
parents:
diff changeset
612 return 1;
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614 return 0;
kono
parents:
diff changeset
615 }
kono
parents:
diff changeset
616
kono
parents:
diff changeset
617 /* Convert an unsigned string to an integer. The length value is -1
kono
parents:
diff changeset
618 if we are working on a repeat count. Returns nonzero if we have a
kono
parents:
diff changeset
619 range problem. As a side effect, frees the dtp->u.p.saved_string. */
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 static int
kono
parents:
diff changeset
622 convert_integer (st_parameter_dt *dtp, int length, int negative)
kono
parents:
diff changeset
623 {
kono
parents:
diff changeset
624 char c, *buffer, message[MSGLEN];
kono
parents:
diff changeset
625 int m;
kono
parents:
diff changeset
626 GFC_UINTEGER_LARGEST v, max, max10;
kono
parents:
diff changeset
627 GFC_INTEGER_LARGEST value;
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 buffer = dtp->u.p.saved_string;
kono
parents:
diff changeset
630 v = 0;
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 if (length == -1)
kono
parents:
diff changeset
633 max = MAX_REPEAT;
kono
parents:
diff changeset
634 else
kono
parents:
diff changeset
635 {
kono
parents:
diff changeset
636 max = si_max (length);
kono
parents:
diff changeset
637 if (negative)
kono
parents:
diff changeset
638 max++;
kono
parents:
diff changeset
639 }
kono
parents:
diff changeset
640 max10 = max / 10;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 for (;;)
kono
parents:
diff changeset
643 {
kono
parents:
diff changeset
644 c = *buffer++;
kono
parents:
diff changeset
645 if (c == '\0')
kono
parents:
diff changeset
646 break;
kono
parents:
diff changeset
647 c -= '0';
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 if (v > max10)
kono
parents:
diff changeset
650 goto overflow;
kono
parents:
diff changeset
651 v = 10 * v;
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 if (v > max - c)
kono
parents:
diff changeset
654 goto overflow;
kono
parents:
diff changeset
655 v += c;
kono
parents:
diff changeset
656 }
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 m = 0;
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 if (length != -1)
kono
parents:
diff changeset
661 {
kono
parents:
diff changeset
662 if (negative)
kono
parents:
diff changeset
663 value = -v;
kono
parents:
diff changeset
664 else
kono
parents:
diff changeset
665 value = v;
kono
parents:
diff changeset
666 set_integer (dtp->u.p.value, value, length);
kono
parents:
diff changeset
667 }
kono
parents:
diff changeset
668 else
kono
parents:
diff changeset
669 {
kono
parents:
diff changeset
670 dtp->u.p.repeat_count = v;
kono
parents:
diff changeset
671
kono
parents:
diff changeset
672 if (dtp->u.p.repeat_count == 0)
kono
parents:
diff changeset
673 {
kono
parents:
diff changeset
674 snprintf (message, MSGLEN, "Zero repeat count in item %d of list input",
kono
parents:
diff changeset
675 dtp->u.p.item_count);
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
678 m = 1;
kono
parents:
diff changeset
679 }
kono
parents:
diff changeset
680 }
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 free_saved (dtp);
kono
parents:
diff changeset
683 return m;
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 overflow:
kono
parents:
diff changeset
686 if (length == -1)
kono
parents:
diff changeset
687 snprintf (message, MSGLEN, "Repeat count overflow in item %d of list input",
kono
parents:
diff changeset
688 dtp->u.p.item_count);
kono
parents:
diff changeset
689 else
kono
parents:
diff changeset
690 snprintf (message, MSGLEN, "Integer overflow while reading item %d",
kono
parents:
diff changeset
691 dtp->u.p.item_count);
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 free_saved (dtp);
kono
parents:
diff changeset
694 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
695
kono
parents:
diff changeset
696 return 1;
kono
parents:
diff changeset
697 }
kono
parents:
diff changeset
698
kono
parents:
diff changeset
699
kono
parents:
diff changeset
700 /* Parse a repeat count for logical and complex values which cannot
kono
parents:
diff changeset
701 begin with a digit. Returns nonzero if we are done, zero if we
kono
parents:
diff changeset
702 should continue on. */
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 static int
kono
parents:
diff changeset
705 parse_repeat (st_parameter_dt *dtp)
kono
parents:
diff changeset
706 {
kono
parents:
diff changeset
707 char message[MSGLEN];
kono
parents:
diff changeset
708 int c, repeat;
kono
parents:
diff changeset
709
kono
parents:
diff changeset
710 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
711 goto bad_repeat;
kono
parents:
diff changeset
712 switch (c)
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 CASE_DIGITS:
kono
parents:
diff changeset
715 repeat = c - '0';
kono
parents:
diff changeset
716 break;
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 CASE_SEPARATORS:
kono
parents:
diff changeset
719 unget_char (dtp, c);
kono
parents:
diff changeset
720 eat_separator (dtp);
kono
parents:
diff changeset
721 return 1;
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 default:
kono
parents:
diff changeset
724 unget_char (dtp, c);
kono
parents:
diff changeset
725 return 0;
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 for (;;)
kono
parents:
diff changeset
729 {
kono
parents:
diff changeset
730 c = next_char (dtp);
kono
parents:
diff changeset
731 switch (c)
kono
parents:
diff changeset
732 {
kono
parents:
diff changeset
733 CASE_DIGITS:
kono
parents:
diff changeset
734 repeat = 10 * repeat + c - '0';
kono
parents:
diff changeset
735
kono
parents:
diff changeset
736 if (repeat > MAX_REPEAT)
kono
parents:
diff changeset
737 {
kono
parents:
diff changeset
738 snprintf (message, MSGLEN,
kono
parents:
diff changeset
739 "Repeat count overflow in item %d of list input",
kono
parents:
diff changeset
740 dtp->u.p.item_count);
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
743 return 1;
kono
parents:
diff changeset
744 }
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 break;
kono
parents:
diff changeset
747
kono
parents:
diff changeset
748 case '*':
kono
parents:
diff changeset
749 if (repeat == 0)
kono
parents:
diff changeset
750 {
kono
parents:
diff changeset
751 snprintf (message, MSGLEN,
kono
parents:
diff changeset
752 "Zero repeat count in item %d of list input",
kono
parents:
diff changeset
753 dtp->u.p.item_count);
kono
parents:
diff changeset
754
kono
parents:
diff changeset
755 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
756 return 1;
kono
parents:
diff changeset
757 }
kono
parents:
diff changeset
758
kono
parents:
diff changeset
759 goto done;
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 default:
kono
parents:
diff changeset
762 goto bad_repeat;
kono
parents:
diff changeset
763 }
kono
parents:
diff changeset
764 }
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 done:
kono
parents:
diff changeset
767 dtp->u.p.repeat_count = repeat;
kono
parents:
diff changeset
768 return 0;
kono
parents:
diff changeset
769
kono
parents:
diff changeset
770 bad_repeat:
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 free_saved (dtp);
kono
parents:
diff changeset
773 if (c == EOF)
kono
parents:
diff changeset
774 {
kono
parents:
diff changeset
775 free_line (dtp);
kono
parents:
diff changeset
776 hit_eof (dtp);
kono
parents:
diff changeset
777 return 1;
kono
parents:
diff changeset
778 }
kono
parents:
diff changeset
779 else
kono
parents:
diff changeset
780 eat_line (dtp);
kono
parents:
diff changeset
781 snprintf (message, MSGLEN, "Bad repeat count in item %d of list input",
kono
parents:
diff changeset
782 dtp->u.p.item_count);
kono
parents:
diff changeset
783 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
784 return 1;
kono
parents:
diff changeset
785 }
kono
parents:
diff changeset
786
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 /* To read a logical we have to look ahead in the input stream to make sure
kono
parents:
diff changeset
789 there is not an equal sign indicating a variable name. To do this we use
kono
parents:
diff changeset
790 line_buffer to point to a temporary buffer, pushing characters there for
kono
parents:
diff changeset
791 possible later reading. */
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 static void
kono
parents:
diff changeset
794 l_push_char (st_parameter_dt *dtp, char c)
kono
parents:
diff changeset
795 {
kono
parents:
diff changeset
796 if (dtp->u.p.line_buffer == NULL)
kono
parents:
diff changeset
797 dtp->u.p.line_buffer = xcalloc (SCRATCH_SIZE, 1);
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 dtp->u.p.line_buffer[dtp->u.p.line_buffer_pos++] = c;
kono
parents:
diff changeset
800 }
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 /* Read a logical character on the input. */
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 static void
kono
parents:
diff changeset
806 read_logical (st_parameter_dt *dtp, int length)
kono
parents:
diff changeset
807 {
kono
parents:
diff changeset
808 char message[MSGLEN];
kono
parents:
diff changeset
809 int c, i, v;
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 if (parse_repeat (dtp))
kono
parents:
diff changeset
812 return;
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 c = tolower (next_char (dtp));
kono
parents:
diff changeset
815 l_push_char (dtp, c);
kono
parents:
diff changeset
816 switch (c)
kono
parents:
diff changeset
817 {
kono
parents:
diff changeset
818 case 't':
kono
parents:
diff changeset
819 v = 1;
kono
parents:
diff changeset
820 c = next_char (dtp);
kono
parents:
diff changeset
821 l_push_char (dtp, c);
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 if (!is_separator(c) && c != EOF)
kono
parents:
diff changeset
824 goto possible_name;
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 unget_char (dtp, c);
kono
parents:
diff changeset
827 break;
kono
parents:
diff changeset
828 case 'f':
kono
parents:
diff changeset
829 v = 0;
kono
parents:
diff changeset
830 c = next_char (dtp);
kono
parents:
diff changeset
831 l_push_char (dtp, c);
kono
parents:
diff changeset
832
kono
parents:
diff changeset
833 if (!is_separator(c) && c != EOF)
kono
parents:
diff changeset
834 goto possible_name;
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 unget_char (dtp, c);
kono
parents:
diff changeset
837 break;
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 case '.':
kono
parents:
diff changeset
840 c = tolower (next_char (dtp));
kono
parents:
diff changeset
841 switch (c)
kono
parents:
diff changeset
842 {
kono
parents:
diff changeset
843 case 't':
kono
parents:
diff changeset
844 v = 1;
kono
parents:
diff changeset
845 break;
kono
parents:
diff changeset
846 case 'f':
kono
parents:
diff changeset
847 v = 0;
kono
parents:
diff changeset
848 break;
kono
parents:
diff changeset
849 default:
kono
parents:
diff changeset
850 goto bad_logical;
kono
parents:
diff changeset
851 }
kono
parents:
diff changeset
852
kono
parents:
diff changeset
853 break;
kono
parents:
diff changeset
854
kono
parents:
diff changeset
855 case '!':
kono
parents:
diff changeset
856 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
857 goto bad_logical;
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 CASE_SEPARATORS:
kono
parents:
diff changeset
860 case EOF:
kono
parents:
diff changeset
861 unget_char (dtp, c);
kono
parents:
diff changeset
862 eat_separator (dtp);
kono
parents:
diff changeset
863 return; /* Null value. */
kono
parents:
diff changeset
864
kono
parents:
diff changeset
865 default:
kono
parents:
diff changeset
866 /* Save the character in case it is the beginning
kono
parents:
diff changeset
867 of the next object name. */
kono
parents:
diff changeset
868 unget_char (dtp, c);
kono
parents:
diff changeset
869 goto bad_logical;
kono
parents:
diff changeset
870 }
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 dtp->u.p.saved_type = BT_LOGICAL;
kono
parents:
diff changeset
873 dtp->u.p.saved_length = length;
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875 /* Eat trailing garbage. */
kono
parents:
diff changeset
876 do
kono
parents:
diff changeset
877 c = next_char (dtp);
kono
parents:
diff changeset
878 while (c != EOF && !is_separator (c));
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 unget_char (dtp, c);
kono
parents:
diff changeset
881 eat_separator (dtp);
kono
parents:
diff changeset
882 set_integer ((int *) dtp->u.p.value, v, length);
kono
parents:
diff changeset
883 free_line (dtp);
kono
parents:
diff changeset
884
kono
parents:
diff changeset
885 return;
kono
parents:
diff changeset
886
kono
parents:
diff changeset
887 possible_name:
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 for(i = 0; i < 63; i++)
kono
parents:
diff changeset
890 {
kono
parents:
diff changeset
891 c = next_char (dtp);
kono
parents:
diff changeset
892 if (is_separator(c))
kono
parents:
diff changeset
893 {
kono
parents:
diff changeset
894 /* All done if this is not a namelist read. */
kono
parents:
diff changeset
895 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
896 goto logical_done;
kono
parents:
diff changeset
897
kono
parents:
diff changeset
898 unget_char (dtp, c);
kono
parents:
diff changeset
899 eat_separator (dtp);
kono
parents:
diff changeset
900 c = next_char (dtp);
kono
parents:
diff changeset
901 if (c != '=')
kono
parents:
diff changeset
902 {
kono
parents:
diff changeset
903 unget_char (dtp, c);
kono
parents:
diff changeset
904 goto logical_done;
kono
parents:
diff changeset
905 }
kono
parents:
diff changeset
906 }
kono
parents:
diff changeset
907
kono
parents:
diff changeset
908 l_push_char (dtp, c);
kono
parents:
diff changeset
909 if (c == '=')
kono
parents:
diff changeset
910 {
kono
parents:
diff changeset
911 dtp->u.p.nml_read_error = 1;
kono
parents:
diff changeset
912 dtp->u.p.line_buffer_enabled = 1;
kono
parents:
diff changeset
913 dtp->u.p.line_buffer_pos = 0;
kono
parents:
diff changeset
914 return;
kono
parents:
diff changeset
915 }
kono
parents:
diff changeset
916
kono
parents:
diff changeset
917 }
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 bad_logical:
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 if (nml_bad_return (dtp, c))
kono
parents:
diff changeset
922 {
kono
parents:
diff changeset
923 free_line (dtp);
kono
parents:
diff changeset
924 return;
kono
parents:
diff changeset
925 }
kono
parents:
diff changeset
926
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 free_saved (dtp);
kono
parents:
diff changeset
929 if (c == EOF)
kono
parents:
diff changeset
930 {
kono
parents:
diff changeset
931 free_line (dtp);
kono
parents:
diff changeset
932 hit_eof (dtp);
kono
parents:
diff changeset
933 return;
kono
parents:
diff changeset
934 }
kono
parents:
diff changeset
935 else if (c != '\n')
kono
parents:
diff changeset
936 eat_line (dtp);
kono
parents:
diff changeset
937 snprintf (message, MSGLEN, "Bad logical value while reading item %d",
kono
parents:
diff changeset
938 dtp->u.p.item_count);
kono
parents:
diff changeset
939 free_line (dtp);
kono
parents:
diff changeset
940 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
941 return;
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943 logical_done:
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 dtp->u.p.saved_type = BT_LOGICAL;
kono
parents:
diff changeset
946 dtp->u.p.saved_length = length;
kono
parents:
diff changeset
947 set_integer ((int *) dtp->u.p.value, v, length);
kono
parents:
diff changeset
948 free_saved (dtp);
kono
parents:
diff changeset
949 free_line (dtp);
kono
parents:
diff changeset
950 }
kono
parents:
diff changeset
951
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 /* Reading integers is tricky because we can actually be reading a
kono
parents:
diff changeset
954 repeat count. We have to store the characters in a buffer because
kono
parents:
diff changeset
955 we could be reading an integer that is larger than the default int
kono
parents:
diff changeset
956 used for repeat counts. */
kono
parents:
diff changeset
957
kono
parents:
diff changeset
958 static void
kono
parents:
diff changeset
959 read_integer (st_parameter_dt *dtp, int length)
kono
parents:
diff changeset
960 {
kono
parents:
diff changeset
961 char message[MSGLEN];
kono
parents:
diff changeset
962 int c, negative;
kono
parents:
diff changeset
963
kono
parents:
diff changeset
964 negative = 0;
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966 c = next_char (dtp);
kono
parents:
diff changeset
967 switch (c)
kono
parents:
diff changeset
968 {
kono
parents:
diff changeset
969 case '-':
kono
parents:
diff changeset
970 negative = 1;
kono
parents:
diff changeset
971 /* Fall through... */
kono
parents:
diff changeset
972
kono
parents:
diff changeset
973 case '+':
kono
parents:
diff changeset
974 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
975 goto bad_integer;
kono
parents:
diff changeset
976 goto get_integer;
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 case '!':
kono
parents:
diff changeset
979 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
980 goto bad_integer;
kono
parents:
diff changeset
981
kono
parents:
diff changeset
982 CASE_SEPARATORS: /* Single null. */
kono
parents:
diff changeset
983 unget_char (dtp, c);
kono
parents:
diff changeset
984 eat_separator (dtp);
kono
parents:
diff changeset
985 return;
kono
parents:
diff changeset
986
kono
parents:
diff changeset
987 CASE_DIGITS:
kono
parents:
diff changeset
988 push_char (dtp, c);
kono
parents:
diff changeset
989 break;
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 default:
kono
parents:
diff changeset
992 goto bad_integer;
kono
parents:
diff changeset
993 }
kono
parents:
diff changeset
994
kono
parents:
diff changeset
995 /* Take care of what may be a repeat count. */
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 for (;;)
kono
parents:
diff changeset
998 {
kono
parents:
diff changeset
999 c = next_char (dtp);
kono
parents:
diff changeset
1000 switch (c)
kono
parents:
diff changeset
1001 {
kono
parents:
diff changeset
1002 CASE_DIGITS:
kono
parents:
diff changeset
1003 push_char (dtp, c);
kono
parents:
diff changeset
1004 break;
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 case '*':
kono
parents:
diff changeset
1007 push_char (dtp, '\0');
kono
parents:
diff changeset
1008 goto repeat;
kono
parents:
diff changeset
1009
kono
parents:
diff changeset
1010 case '!':
kono
parents:
diff changeset
1011 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1012 goto bad_integer;
kono
parents:
diff changeset
1013
kono
parents:
diff changeset
1014 CASE_SEPARATORS: /* Not a repeat count. */
kono
parents:
diff changeset
1015 case EOF:
kono
parents:
diff changeset
1016 goto done;
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 default:
kono
parents:
diff changeset
1019 goto bad_integer;
kono
parents:
diff changeset
1020 }
kono
parents:
diff changeset
1021 }
kono
parents:
diff changeset
1022
kono
parents:
diff changeset
1023 repeat:
kono
parents:
diff changeset
1024 if (convert_integer (dtp, -1, 0))
kono
parents:
diff changeset
1025 return;
kono
parents:
diff changeset
1026
kono
parents:
diff changeset
1027 /* Get the real integer. */
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1030 goto bad_integer;
kono
parents:
diff changeset
1031 switch (c)
kono
parents:
diff changeset
1032 {
kono
parents:
diff changeset
1033 CASE_DIGITS:
kono
parents:
diff changeset
1034 break;
kono
parents:
diff changeset
1035
kono
parents:
diff changeset
1036 case '!':
kono
parents:
diff changeset
1037 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1038 goto bad_integer;
kono
parents:
diff changeset
1039
kono
parents:
diff changeset
1040 CASE_SEPARATORS:
kono
parents:
diff changeset
1041 unget_char (dtp, c);
kono
parents:
diff changeset
1042 eat_separator (dtp);
kono
parents:
diff changeset
1043 return;
kono
parents:
diff changeset
1044
kono
parents:
diff changeset
1045 case '-':
kono
parents:
diff changeset
1046 negative = 1;
kono
parents:
diff changeset
1047 /* Fall through... */
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 case '+':
kono
parents:
diff changeset
1050 c = next_char (dtp);
kono
parents:
diff changeset
1051 break;
kono
parents:
diff changeset
1052 }
kono
parents:
diff changeset
1053
kono
parents:
diff changeset
1054 get_integer:
kono
parents:
diff changeset
1055 if (!isdigit (c))
kono
parents:
diff changeset
1056 goto bad_integer;
kono
parents:
diff changeset
1057 push_char (dtp, c);
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 for (;;)
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 c = next_char (dtp);
kono
parents:
diff changeset
1062 switch (c)
kono
parents:
diff changeset
1063 {
kono
parents:
diff changeset
1064 CASE_DIGITS:
kono
parents:
diff changeset
1065 push_char (dtp, c);
kono
parents:
diff changeset
1066 break;
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 case '!':
kono
parents:
diff changeset
1069 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1070 goto bad_integer;
kono
parents:
diff changeset
1071
kono
parents:
diff changeset
1072 CASE_SEPARATORS:
kono
parents:
diff changeset
1073 case EOF:
kono
parents:
diff changeset
1074 goto done;
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 default:
kono
parents:
diff changeset
1077 goto bad_integer;
kono
parents:
diff changeset
1078 }
kono
parents:
diff changeset
1079 }
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 bad_integer:
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 if (nml_bad_return (dtp, c))
kono
parents:
diff changeset
1084 return;
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 free_saved (dtp);
kono
parents:
diff changeset
1087 if (c == EOF)
kono
parents:
diff changeset
1088 {
kono
parents:
diff changeset
1089 free_line (dtp);
kono
parents:
diff changeset
1090 hit_eof (dtp);
kono
parents:
diff changeset
1091 return;
kono
parents:
diff changeset
1092 }
kono
parents:
diff changeset
1093 else if (c != '\n')
kono
parents:
diff changeset
1094 eat_line (dtp);
kono
parents:
diff changeset
1095
kono
parents:
diff changeset
1096 snprintf (message, MSGLEN, "Bad integer for item %d in list input",
kono
parents:
diff changeset
1097 dtp->u.p.item_count);
kono
parents:
diff changeset
1098 free_line (dtp);
kono
parents:
diff changeset
1099 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
1100
kono
parents:
diff changeset
1101 return;
kono
parents:
diff changeset
1102
kono
parents:
diff changeset
1103 done:
kono
parents:
diff changeset
1104 unget_char (dtp, c);
kono
parents:
diff changeset
1105 eat_separator (dtp);
kono
parents:
diff changeset
1106
kono
parents:
diff changeset
1107 push_char (dtp, '\0');
kono
parents:
diff changeset
1108 if (convert_integer (dtp, length, negative))
kono
parents:
diff changeset
1109 {
kono
parents:
diff changeset
1110 free_saved (dtp);
kono
parents:
diff changeset
1111 return;
kono
parents:
diff changeset
1112 }
kono
parents:
diff changeset
1113
kono
parents:
diff changeset
1114 free_saved (dtp);
kono
parents:
diff changeset
1115 dtp->u.p.saved_type = BT_INTEGER;
kono
parents:
diff changeset
1116 }
kono
parents:
diff changeset
1117
kono
parents:
diff changeset
1118
kono
parents:
diff changeset
1119 /* Read a character variable. */
kono
parents:
diff changeset
1120
kono
parents:
diff changeset
1121 static void
kono
parents:
diff changeset
1122 read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
kono
parents:
diff changeset
1123 {
kono
parents:
diff changeset
1124 char quote, message[MSGLEN];
kono
parents:
diff changeset
1125 int c;
kono
parents:
diff changeset
1126
kono
parents:
diff changeset
1127 quote = ' '; /* Space means no quote character. */
kono
parents:
diff changeset
1128
kono
parents:
diff changeset
1129 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1130 goto eof;
kono
parents:
diff changeset
1131 switch (c)
kono
parents:
diff changeset
1132 {
kono
parents:
diff changeset
1133 CASE_DIGITS:
kono
parents:
diff changeset
1134 push_char (dtp, c);
kono
parents:
diff changeset
1135 break;
kono
parents:
diff changeset
1136
kono
parents:
diff changeset
1137 CASE_SEPARATORS:
kono
parents:
diff changeset
1138 case EOF:
kono
parents:
diff changeset
1139 unget_char (dtp, c); /* NULL value. */
kono
parents:
diff changeset
1140 eat_separator (dtp);
kono
parents:
diff changeset
1141 return;
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 case '"':
kono
parents:
diff changeset
1144 case '\'':
kono
parents:
diff changeset
1145 quote = c;
kono
parents:
diff changeset
1146 goto get_string;
kono
parents:
diff changeset
1147
kono
parents:
diff changeset
1148 default:
kono
parents:
diff changeset
1149 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1150 {
kono
parents:
diff changeset
1151 unget_char (dtp, c);
kono
parents:
diff changeset
1152 return;
kono
parents:
diff changeset
1153 }
kono
parents:
diff changeset
1154 push_char (dtp, c);
kono
parents:
diff changeset
1155 goto get_string;
kono
parents:
diff changeset
1156 }
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 /* Deal with a possible repeat count. */
kono
parents:
diff changeset
1159
kono
parents:
diff changeset
1160 for (;;)
kono
parents:
diff changeset
1161 {
kono
parents:
diff changeset
1162 c = next_char (dtp);
kono
parents:
diff changeset
1163 switch (c)
kono
parents:
diff changeset
1164 {
kono
parents:
diff changeset
1165 CASE_DIGITS:
kono
parents:
diff changeset
1166 push_char (dtp, c);
kono
parents:
diff changeset
1167 break;
kono
parents:
diff changeset
1168
kono
parents:
diff changeset
1169 CASE_SEPARATORS:
kono
parents:
diff changeset
1170 case EOF:
kono
parents:
diff changeset
1171 unget_char (dtp, c);
kono
parents:
diff changeset
1172 goto done; /* String was only digits! */
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 case '*':
kono
parents:
diff changeset
1175 push_char (dtp, '\0');
kono
parents:
diff changeset
1176 goto got_repeat;
kono
parents:
diff changeset
1177
kono
parents:
diff changeset
1178 default:
kono
parents:
diff changeset
1179 push_char (dtp, c);
kono
parents:
diff changeset
1180 goto get_string; /* Not a repeat count after all. */
kono
parents:
diff changeset
1181 }
kono
parents:
diff changeset
1182 }
kono
parents:
diff changeset
1183
kono
parents:
diff changeset
1184 got_repeat:
kono
parents:
diff changeset
1185 if (convert_integer (dtp, -1, 0))
kono
parents:
diff changeset
1186 return;
kono
parents:
diff changeset
1187
kono
parents:
diff changeset
1188 /* Now get the real string. */
kono
parents:
diff changeset
1189
kono
parents:
diff changeset
1190 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1191 goto eof;
kono
parents:
diff changeset
1192 switch (c)
kono
parents:
diff changeset
1193 {
kono
parents:
diff changeset
1194 CASE_SEPARATORS:
kono
parents:
diff changeset
1195 unget_char (dtp, c); /* Repeated NULL values. */
kono
parents:
diff changeset
1196 eat_separator (dtp);
kono
parents:
diff changeset
1197 return;
kono
parents:
diff changeset
1198
kono
parents:
diff changeset
1199 case '"':
kono
parents:
diff changeset
1200 case '\'':
kono
parents:
diff changeset
1201 quote = c;
kono
parents:
diff changeset
1202 break;
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 default:
kono
parents:
diff changeset
1205 push_char (dtp, c);
kono
parents:
diff changeset
1206 break;
kono
parents:
diff changeset
1207 }
kono
parents:
diff changeset
1208
kono
parents:
diff changeset
1209 get_string:
kono
parents:
diff changeset
1210
kono
parents:
diff changeset
1211 for (;;)
kono
parents:
diff changeset
1212 {
kono
parents:
diff changeset
1213 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1214 goto done_eof;
kono
parents:
diff changeset
1215 switch (c)
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 case '"':
kono
parents:
diff changeset
1218 case '\'':
kono
parents:
diff changeset
1219 if (c != quote)
kono
parents:
diff changeset
1220 {
kono
parents:
diff changeset
1221 push_char (dtp, c);
kono
parents:
diff changeset
1222 break;
kono
parents:
diff changeset
1223 }
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 /* See if we have a doubled quote character or the end of
kono
parents:
diff changeset
1226 the string. */
kono
parents:
diff changeset
1227
kono
parents:
diff changeset
1228 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1229 goto done_eof;
kono
parents:
diff changeset
1230 if (c == quote)
kono
parents:
diff changeset
1231 {
kono
parents:
diff changeset
1232 push_char (dtp, quote);
kono
parents:
diff changeset
1233 break;
kono
parents:
diff changeset
1234 }
kono
parents:
diff changeset
1235
kono
parents:
diff changeset
1236 unget_char (dtp, c);
kono
parents:
diff changeset
1237 goto done;
kono
parents:
diff changeset
1238
kono
parents:
diff changeset
1239 CASE_SEPARATORS:
kono
parents:
diff changeset
1240 if (quote == ' ')
kono
parents:
diff changeset
1241 {
kono
parents:
diff changeset
1242 unget_char (dtp, c);
kono
parents:
diff changeset
1243 goto done;
kono
parents:
diff changeset
1244 }
kono
parents:
diff changeset
1245
kono
parents:
diff changeset
1246 if (c != '\n' && c != '\r')
kono
parents:
diff changeset
1247 push_char (dtp, c);
kono
parents:
diff changeset
1248 break;
kono
parents:
diff changeset
1249
kono
parents:
diff changeset
1250 default:
kono
parents:
diff changeset
1251 push_char (dtp, c);
kono
parents:
diff changeset
1252 break;
kono
parents:
diff changeset
1253 }
kono
parents:
diff changeset
1254 }
kono
parents:
diff changeset
1255
kono
parents:
diff changeset
1256 /* At this point, we have to have a separator, or else the string is
kono
parents:
diff changeset
1257 invalid. */
kono
parents:
diff changeset
1258 done:
kono
parents:
diff changeset
1259 c = next_char (dtp);
kono
parents:
diff changeset
1260 done_eof:
kono
parents:
diff changeset
1261 if (is_separator (c) || c == EOF)
kono
parents:
diff changeset
1262 {
kono
parents:
diff changeset
1263 unget_char (dtp, c);
kono
parents:
diff changeset
1264 eat_separator (dtp);
kono
parents:
diff changeset
1265 dtp->u.p.saved_type = BT_CHARACTER;
kono
parents:
diff changeset
1266 }
kono
parents:
diff changeset
1267 else
kono
parents:
diff changeset
1268 {
kono
parents:
diff changeset
1269 free_saved (dtp);
kono
parents:
diff changeset
1270 snprintf (message, MSGLEN, "Invalid string input in item %d",
kono
parents:
diff changeset
1271 dtp->u.p.item_count);
kono
parents:
diff changeset
1272 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
1273 }
kono
parents:
diff changeset
1274 free_line (dtp);
kono
parents:
diff changeset
1275 return;
kono
parents:
diff changeset
1276
kono
parents:
diff changeset
1277 eof:
kono
parents:
diff changeset
1278 free_saved (dtp);
kono
parents:
diff changeset
1279 free_line (dtp);
kono
parents:
diff changeset
1280 hit_eof (dtp);
kono
parents:
diff changeset
1281 }
kono
parents:
diff changeset
1282
kono
parents:
diff changeset
1283
kono
parents:
diff changeset
1284 /* Parse a component of a complex constant or a real number that we
kono
parents:
diff changeset
1285 are sure is already there. This is a straight real number parser. */
kono
parents:
diff changeset
1286
kono
parents:
diff changeset
1287 static int
kono
parents:
diff changeset
1288 parse_real (st_parameter_dt *dtp, void *buffer, int length)
kono
parents:
diff changeset
1289 {
kono
parents:
diff changeset
1290 char message[MSGLEN];
kono
parents:
diff changeset
1291 int c, m, seen_dp;
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1294 goto bad;
kono
parents:
diff changeset
1295
kono
parents:
diff changeset
1296 if (c == '-' || c == '+')
kono
parents:
diff changeset
1297 {
kono
parents:
diff changeset
1298 push_char (dtp, c);
kono
parents:
diff changeset
1299 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1300 goto bad;
kono
parents:
diff changeset
1301 }
kono
parents:
diff changeset
1302
kono
parents:
diff changeset
1303 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1304 c = '.';
kono
parents:
diff changeset
1305
kono
parents:
diff changeset
1306 if (!isdigit (c) && c != '.')
kono
parents:
diff changeset
1307 {
kono
parents:
diff changeset
1308 if (c == 'i' || c == 'I' || c == 'n' || c == 'N')
kono
parents:
diff changeset
1309 goto inf_nan;
kono
parents:
diff changeset
1310 else
kono
parents:
diff changeset
1311 goto bad;
kono
parents:
diff changeset
1312 }
kono
parents:
diff changeset
1313
kono
parents:
diff changeset
1314 push_char (dtp, c);
kono
parents:
diff changeset
1315
kono
parents:
diff changeset
1316 seen_dp = (c == '.') ? 1 : 0;
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 for (;;)
kono
parents:
diff changeset
1319 {
kono
parents:
diff changeset
1320 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1321 goto bad;
kono
parents:
diff changeset
1322 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1323 c = '.';
kono
parents:
diff changeset
1324 switch (c)
kono
parents:
diff changeset
1325 {
kono
parents:
diff changeset
1326 CASE_DIGITS:
kono
parents:
diff changeset
1327 push_char (dtp, c);
kono
parents:
diff changeset
1328 break;
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 case '.':
kono
parents:
diff changeset
1331 if (seen_dp)
kono
parents:
diff changeset
1332 goto bad;
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 seen_dp = 1;
kono
parents:
diff changeset
1335 push_char (dtp, c);
kono
parents:
diff changeset
1336 break;
kono
parents:
diff changeset
1337
kono
parents:
diff changeset
1338 case 'e':
kono
parents:
diff changeset
1339 case 'E':
kono
parents:
diff changeset
1340 case 'd':
kono
parents:
diff changeset
1341 case 'D':
kono
parents:
diff changeset
1342 case 'q':
kono
parents:
diff changeset
1343 case 'Q':
kono
parents:
diff changeset
1344 push_char (dtp, 'e');
kono
parents:
diff changeset
1345 goto exp1;
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 case '-':
kono
parents:
diff changeset
1348 case '+':
kono
parents:
diff changeset
1349 push_char (dtp, 'e');
kono
parents:
diff changeset
1350 push_char (dtp, c);
kono
parents:
diff changeset
1351 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1352 goto bad;
kono
parents:
diff changeset
1353 goto exp2;
kono
parents:
diff changeset
1354
kono
parents:
diff changeset
1355 case '!':
kono
parents:
diff changeset
1356 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1357 goto bad;
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 CASE_SEPARATORS:
kono
parents:
diff changeset
1360 case EOF:
kono
parents:
diff changeset
1361 goto done;
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 default:
kono
parents:
diff changeset
1364 goto done;
kono
parents:
diff changeset
1365 }
kono
parents:
diff changeset
1366 }
kono
parents:
diff changeset
1367
kono
parents:
diff changeset
1368 exp1:
kono
parents:
diff changeset
1369 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1370 goto bad;
kono
parents:
diff changeset
1371 if (c != '-' && c != '+')
kono
parents:
diff changeset
1372 push_char (dtp, '+');
kono
parents:
diff changeset
1373 else
kono
parents:
diff changeset
1374 {
kono
parents:
diff changeset
1375 push_char (dtp, c);
kono
parents:
diff changeset
1376 c = next_char (dtp);
kono
parents:
diff changeset
1377 }
kono
parents:
diff changeset
1378
kono
parents:
diff changeset
1379 exp2:
kono
parents:
diff changeset
1380 if (!isdigit (c))
kono
parents:
diff changeset
1381 {
kono
parents:
diff changeset
1382 /* Extension: allow default exponent of 0 when omitted. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1383 if (dtp->common.flags & IOPARM_DT_DEC_EXT)
111
kono
parents:
diff changeset
1384 {
kono
parents:
diff changeset
1385 push_char (dtp, '0');
kono
parents:
diff changeset
1386 goto done;
kono
parents:
diff changeset
1387 }
kono
parents:
diff changeset
1388 else
kono
parents:
diff changeset
1389 goto bad_exponent;
kono
parents:
diff changeset
1390 }
kono
parents:
diff changeset
1391
kono
parents:
diff changeset
1392 push_char (dtp, c);
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 for (;;)
kono
parents:
diff changeset
1395 {
kono
parents:
diff changeset
1396 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1397 goto bad;
kono
parents:
diff changeset
1398 switch (c)
kono
parents:
diff changeset
1399 {
kono
parents:
diff changeset
1400 CASE_DIGITS:
kono
parents:
diff changeset
1401 push_char (dtp, c);
kono
parents:
diff changeset
1402 break;
kono
parents:
diff changeset
1403
kono
parents:
diff changeset
1404 case '!':
kono
parents:
diff changeset
1405 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1406 goto bad;
kono
parents:
diff changeset
1407
kono
parents:
diff changeset
1408 CASE_SEPARATORS:
kono
parents:
diff changeset
1409 case EOF:
kono
parents:
diff changeset
1410 unget_char (dtp, c);
kono
parents:
diff changeset
1411 goto done;
kono
parents:
diff changeset
1412
kono
parents:
diff changeset
1413 default:
kono
parents:
diff changeset
1414 goto done;
kono
parents:
diff changeset
1415 }
kono
parents:
diff changeset
1416 }
kono
parents:
diff changeset
1417
kono
parents:
diff changeset
1418 done:
kono
parents:
diff changeset
1419 unget_char (dtp, c);
kono
parents:
diff changeset
1420 push_char (dtp, '\0');
kono
parents:
diff changeset
1421
kono
parents:
diff changeset
1422 m = convert_real (dtp, buffer, dtp->u.p.saved_string, length);
kono
parents:
diff changeset
1423 free_saved (dtp);
kono
parents:
diff changeset
1424
kono
parents:
diff changeset
1425 return m;
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 done_infnan:
kono
parents:
diff changeset
1428 unget_char (dtp, c);
kono
parents:
diff changeset
1429 push_char (dtp, '\0');
kono
parents:
diff changeset
1430
kono
parents:
diff changeset
1431 m = convert_infnan (dtp, buffer, dtp->u.p.saved_string, length);
kono
parents:
diff changeset
1432 free_saved (dtp);
kono
parents:
diff changeset
1433
kono
parents:
diff changeset
1434 return m;
kono
parents:
diff changeset
1435
kono
parents:
diff changeset
1436 inf_nan:
kono
parents:
diff changeset
1437 /* Match INF and Infinity. */
kono
parents:
diff changeset
1438 if ((c == 'i' || c == 'I')
kono
parents:
diff changeset
1439 && ((c = next_char (dtp)) == 'n' || c == 'N')
kono
parents:
diff changeset
1440 && ((c = next_char (dtp)) == 'f' || c == 'F'))
kono
parents:
diff changeset
1441 {
kono
parents:
diff changeset
1442 c = next_char (dtp);
kono
parents:
diff changeset
1443 if ((c != 'i' && c != 'I')
kono
parents:
diff changeset
1444 || ((c == 'i' || c == 'I')
kono
parents:
diff changeset
1445 && ((c = next_char (dtp)) == 'n' || c == 'N')
kono
parents:
diff changeset
1446 && ((c = next_char (dtp)) == 'i' || c == 'I')
kono
parents:
diff changeset
1447 && ((c = next_char (dtp)) == 't' || c == 'T')
kono
parents:
diff changeset
1448 && ((c = next_char (dtp)) == 'y' || c == 'Y')
kono
parents:
diff changeset
1449 && (c = next_char (dtp))))
kono
parents:
diff changeset
1450 {
kono
parents:
diff changeset
1451 if (is_separator (c) || (c == EOF))
kono
parents:
diff changeset
1452 unget_char (dtp, c);
kono
parents:
diff changeset
1453 push_char (dtp, 'i');
kono
parents:
diff changeset
1454 push_char (dtp, 'n');
kono
parents:
diff changeset
1455 push_char (dtp, 'f');
kono
parents:
diff changeset
1456 goto done_infnan;
kono
parents:
diff changeset
1457 }
kono
parents:
diff changeset
1458 } /* Match NaN. */
kono
parents:
diff changeset
1459 else if (((c = next_char (dtp)) == 'a' || c == 'A')
kono
parents:
diff changeset
1460 && ((c = next_char (dtp)) == 'n' || c == 'N')
kono
parents:
diff changeset
1461 && (c = next_char (dtp)))
kono
parents:
diff changeset
1462 {
kono
parents:
diff changeset
1463 if (is_separator (c) || (c == EOF))
kono
parents:
diff changeset
1464 unget_char (dtp, c);
kono
parents:
diff changeset
1465 push_char (dtp, 'n');
kono
parents:
diff changeset
1466 push_char (dtp, 'a');
kono
parents:
diff changeset
1467 push_char (dtp, 'n');
kono
parents:
diff changeset
1468
kono
parents:
diff changeset
1469 /* Match "NAN(alphanum)". */
kono
parents:
diff changeset
1470 if (c == '(')
kono
parents:
diff changeset
1471 {
kono
parents:
diff changeset
1472 for ( ; c != ')'; c = next_char (dtp))
kono
parents:
diff changeset
1473 if (is_separator (c))
kono
parents:
diff changeset
1474 goto bad;
kono
parents:
diff changeset
1475
kono
parents:
diff changeset
1476 c = next_char (dtp);
kono
parents:
diff changeset
1477 if (is_separator (c) || (c == EOF))
kono
parents:
diff changeset
1478 unget_char (dtp, c);
kono
parents:
diff changeset
1479 }
kono
parents:
diff changeset
1480 goto done_infnan;
kono
parents:
diff changeset
1481 }
kono
parents:
diff changeset
1482
kono
parents:
diff changeset
1483 bad:
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 if (nml_bad_return (dtp, c))
kono
parents:
diff changeset
1486 return 0;
kono
parents:
diff changeset
1487
kono
parents:
diff changeset
1488 bad_exponent:
kono
parents:
diff changeset
1489
kono
parents:
diff changeset
1490 free_saved (dtp);
kono
parents:
diff changeset
1491 if (c == EOF)
kono
parents:
diff changeset
1492 {
kono
parents:
diff changeset
1493 free_line (dtp);
kono
parents:
diff changeset
1494 hit_eof (dtp);
kono
parents:
diff changeset
1495 return 1;
kono
parents:
diff changeset
1496 }
kono
parents:
diff changeset
1497 else if (c != '\n')
kono
parents:
diff changeset
1498 eat_line (dtp);
kono
parents:
diff changeset
1499
kono
parents:
diff changeset
1500 snprintf (message, MSGLEN, "Bad complex floating point "
kono
parents:
diff changeset
1501 "number for item %d", dtp->u.p.item_count);
kono
parents:
diff changeset
1502 free_line (dtp);
kono
parents:
diff changeset
1503 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
1504
kono
parents:
diff changeset
1505 return 1;
kono
parents:
diff changeset
1506 }
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508
kono
parents:
diff changeset
1509 /* Reading a complex number is straightforward because we can tell
kono
parents:
diff changeset
1510 what it is right away. */
kono
parents:
diff changeset
1511
kono
parents:
diff changeset
1512 static void
kono
parents:
diff changeset
1513 read_complex (st_parameter_dt *dtp, void *dest, int kind, size_t size)
kono
parents:
diff changeset
1514 {
kono
parents:
diff changeset
1515 char message[MSGLEN];
kono
parents:
diff changeset
1516 int c;
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 if (parse_repeat (dtp))
kono
parents:
diff changeset
1519 return;
kono
parents:
diff changeset
1520
kono
parents:
diff changeset
1521 c = next_char (dtp);
kono
parents:
diff changeset
1522 switch (c)
kono
parents:
diff changeset
1523 {
kono
parents:
diff changeset
1524 case '(':
kono
parents:
diff changeset
1525 break;
kono
parents:
diff changeset
1526
kono
parents:
diff changeset
1527 case '!':
kono
parents:
diff changeset
1528 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1529 goto bad_complex;
kono
parents:
diff changeset
1530
kono
parents:
diff changeset
1531 CASE_SEPARATORS:
kono
parents:
diff changeset
1532 case EOF:
kono
parents:
diff changeset
1533 unget_char (dtp, c);
kono
parents:
diff changeset
1534 eat_separator (dtp);
kono
parents:
diff changeset
1535 return;
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 default:
kono
parents:
diff changeset
1538 goto bad_complex;
kono
parents:
diff changeset
1539 }
kono
parents:
diff changeset
1540
kono
parents:
diff changeset
1541 eol_1:
kono
parents:
diff changeset
1542 eat_spaces (dtp);
kono
parents:
diff changeset
1543 c = next_char (dtp);
kono
parents:
diff changeset
1544 if (c == '\n' || c== '\r')
kono
parents:
diff changeset
1545 goto eol_1;
kono
parents:
diff changeset
1546 else
kono
parents:
diff changeset
1547 unget_char (dtp, c);
kono
parents:
diff changeset
1548
kono
parents:
diff changeset
1549 if (parse_real (dtp, dest, kind))
kono
parents:
diff changeset
1550 return;
kono
parents:
diff changeset
1551
kono
parents:
diff changeset
1552 eol_2:
kono
parents:
diff changeset
1553 eat_spaces (dtp);
kono
parents:
diff changeset
1554 c = next_char (dtp);
kono
parents:
diff changeset
1555 if (c == '\n' || c== '\r')
kono
parents:
diff changeset
1556 goto eol_2;
kono
parents:
diff changeset
1557 else
kono
parents:
diff changeset
1558 unget_char (dtp, c);
kono
parents:
diff changeset
1559
kono
parents:
diff changeset
1560 if (next_char (dtp)
kono
parents:
diff changeset
1561 != (dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';'))
kono
parents:
diff changeset
1562 goto bad_complex;
kono
parents:
diff changeset
1563
kono
parents:
diff changeset
1564 eol_3:
kono
parents:
diff changeset
1565 eat_spaces (dtp);
kono
parents:
diff changeset
1566 c = next_char (dtp);
kono
parents:
diff changeset
1567 if (c == '\n' || c== '\r')
kono
parents:
diff changeset
1568 goto eol_3;
kono
parents:
diff changeset
1569 else
kono
parents:
diff changeset
1570 unget_char (dtp, c);
kono
parents:
diff changeset
1571
kono
parents:
diff changeset
1572 if (parse_real (dtp, dest + size / 2, kind))
kono
parents:
diff changeset
1573 return;
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 eol_4:
kono
parents:
diff changeset
1576 eat_spaces (dtp);
kono
parents:
diff changeset
1577 c = next_char (dtp);
kono
parents:
diff changeset
1578 if (c == '\n' || c== '\r')
kono
parents:
diff changeset
1579 goto eol_4;
kono
parents:
diff changeset
1580 else
kono
parents:
diff changeset
1581 unget_char (dtp, c);
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 if (next_char (dtp) != ')')
kono
parents:
diff changeset
1584 goto bad_complex;
kono
parents:
diff changeset
1585
kono
parents:
diff changeset
1586 c = next_char (dtp);
kono
parents:
diff changeset
1587 if (!is_separator (c) && (c != EOF))
kono
parents:
diff changeset
1588 goto bad_complex;
kono
parents:
diff changeset
1589
kono
parents:
diff changeset
1590 unget_char (dtp, c);
kono
parents:
diff changeset
1591 eat_separator (dtp);
kono
parents:
diff changeset
1592
kono
parents:
diff changeset
1593 free_saved (dtp);
kono
parents:
diff changeset
1594 dtp->u.p.saved_type = BT_COMPLEX;
kono
parents:
diff changeset
1595 return;
kono
parents:
diff changeset
1596
kono
parents:
diff changeset
1597 bad_complex:
kono
parents:
diff changeset
1598
kono
parents:
diff changeset
1599 if (nml_bad_return (dtp, c))
kono
parents:
diff changeset
1600 return;
kono
parents:
diff changeset
1601
kono
parents:
diff changeset
1602 free_saved (dtp);
kono
parents:
diff changeset
1603 if (c == EOF)
kono
parents:
diff changeset
1604 {
kono
parents:
diff changeset
1605 free_line (dtp);
kono
parents:
diff changeset
1606 hit_eof (dtp);
kono
parents:
diff changeset
1607 return;
kono
parents:
diff changeset
1608 }
kono
parents:
diff changeset
1609 else if (c != '\n')
kono
parents:
diff changeset
1610 eat_line (dtp);
kono
parents:
diff changeset
1611
kono
parents:
diff changeset
1612 snprintf (message, MSGLEN, "Bad complex value in item %d of list input",
kono
parents:
diff changeset
1613 dtp->u.p.item_count);
kono
parents:
diff changeset
1614 free_line (dtp);
kono
parents:
diff changeset
1615 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
1616 }
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618
kono
parents:
diff changeset
1619 /* Parse a real number with a possible repeat count. */
kono
parents:
diff changeset
1620
kono
parents:
diff changeset
1621 static void
kono
parents:
diff changeset
1622 read_real (st_parameter_dt *dtp, void *dest, int length)
kono
parents:
diff changeset
1623 {
kono
parents:
diff changeset
1624 char message[MSGLEN];
kono
parents:
diff changeset
1625 int c;
kono
parents:
diff changeset
1626 int seen_dp;
kono
parents:
diff changeset
1627 int is_inf;
kono
parents:
diff changeset
1628
kono
parents:
diff changeset
1629 seen_dp = 0;
kono
parents:
diff changeset
1630
kono
parents:
diff changeset
1631 c = next_char (dtp);
kono
parents:
diff changeset
1632 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1633 c = '.';
kono
parents:
diff changeset
1634 switch (c)
kono
parents:
diff changeset
1635 {
kono
parents:
diff changeset
1636 CASE_DIGITS:
kono
parents:
diff changeset
1637 push_char (dtp, c);
kono
parents:
diff changeset
1638 break;
kono
parents:
diff changeset
1639
kono
parents:
diff changeset
1640 case '.':
kono
parents:
diff changeset
1641 push_char (dtp, c);
kono
parents:
diff changeset
1642 seen_dp = 1;
kono
parents:
diff changeset
1643 break;
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 case '+':
kono
parents:
diff changeset
1646 case '-':
kono
parents:
diff changeset
1647 goto got_sign;
kono
parents:
diff changeset
1648
kono
parents:
diff changeset
1649 case '!':
kono
parents:
diff changeset
1650 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1651 goto bad_real;
kono
parents:
diff changeset
1652
kono
parents:
diff changeset
1653 CASE_SEPARATORS:
kono
parents:
diff changeset
1654 unget_char (dtp, c); /* Single null. */
kono
parents:
diff changeset
1655 eat_separator (dtp);
kono
parents:
diff changeset
1656 return;
kono
parents:
diff changeset
1657
kono
parents:
diff changeset
1658 case 'i':
kono
parents:
diff changeset
1659 case 'I':
kono
parents:
diff changeset
1660 case 'n':
kono
parents:
diff changeset
1661 case 'N':
kono
parents:
diff changeset
1662 goto inf_nan;
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 default:
kono
parents:
diff changeset
1665 goto bad_real;
kono
parents:
diff changeset
1666 }
kono
parents:
diff changeset
1667
kono
parents:
diff changeset
1668 /* Get the digit string that might be a repeat count. */
kono
parents:
diff changeset
1669
kono
parents:
diff changeset
1670 for (;;)
kono
parents:
diff changeset
1671 {
kono
parents:
diff changeset
1672 c = next_char (dtp);
kono
parents:
diff changeset
1673 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1674 c = '.';
kono
parents:
diff changeset
1675 switch (c)
kono
parents:
diff changeset
1676 {
kono
parents:
diff changeset
1677 CASE_DIGITS:
kono
parents:
diff changeset
1678 push_char (dtp, c);
kono
parents:
diff changeset
1679 break;
kono
parents:
diff changeset
1680
kono
parents:
diff changeset
1681 case '.':
kono
parents:
diff changeset
1682 if (seen_dp)
kono
parents:
diff changeset
1683 goto bad_real;
kono
parents:
diff changeset
1684
kono
parents:
diff changeset
1685 seen_dp = 1;
kono
parents:
diff changeset
1686 push_char (dtp, c);
kono
parents:
diff changeset
1687 goto real_loop;
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689 case 'E':
kono
parents:
diff changeset
1690 case 'e':
kono
parents:
diff changeset
1691 case 'D':
kono
parents:
diff changeset
1692 case 'd':
kono
parents:
diff changeset
1693 case 'Q':
kono
parents:
diff changeset
1694 case 'q':
kono
parents:
diff changeset
1695 goto exp1;
kono
parents:
diff changeset
1696
kono
parents:
diff changeset
1697 case '+':
kono
parents:
diff changeset
1698 case '-':
kono
parents:
diff changeset
1699 push_char (dtp, 'e');
kono
parents:
diff changeset
1700 push_char (dtp, c);
kono
parents:
diff changeset
1701 c = next_char (dtp);
kono
parents:
diff changeset
1702 goto exp2;
kono
parents:
diff changeset
1703
kono
parents:
diff changeset
1704 case '*':
kono
parents:
diff changeset
1705 push_char (dtp, '\0');
kono
parents:
diff changeset
1706 goto got_repeat;
kono
parents:
diff changeset
1707
kono
parents:
diff changeset
1708 case '!':
kono
parents:
diff changeset
1709 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1710 goto bad_real;
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 CASE_SEPARATORS:
kono
parents:
diff changeset
1713 case EOF:
kono
parents:
diff changeset
1714 if (c != '\n' && c != ',' && c != '\r' && c != ';')
kono
parents:
diff changeset
1715 unget_char (dtp, c);
kono
parents:
diff changeset
1716 goto done;
kono
parents:
diff changeset
1717
kono
parents:
diff changeset
1718 default:
kono
parents:
diff changeset
1719 goto bad_real;
kono
parents:
diff changeset
1720 }
kono
parents:
diff changeset
1721 }
kono
parents:
diff changeset
1722
kono
parents:
diff changeset
1723 got_repeat:
kono
parents:
diff changeset
1724 if (convert_integer (dtp, -1, 0))
kono
parents:
diff changeset
1725 return;
kono
parents:
diff changeset
1726
kono
parents:
diff changeset
1727 /* Now get the number itself. */
kono
parents:
diff changeset
1728
kono
parents:
diff changeset
1729 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1730 goto bad_real;
kono
parents:
diff changeset
1731 if (is_separator (c))
kono
parents:
diff changeset
1732 { /* Repeated null value. */
kono
parents:
diff changeset
1733 unget_char (dtp, c);
kono
parents:
diff changeset
1734 eat_separator (dtp);
kono
parents:
diff changeset
1735 return;
kono
parents:
diff changeset
1736 }
kono
parents:
diff changeset
1737
kono
parents:
diff changeset
1738 if (c != '-' && c != '+')
kono
parents:
diff changeset
1739 push_char (dtp, '+');
kono
parents:
diff changeset
1740 else
kono
parents:
diff changeset
1741 {
kono
parents:
diff changeset
1742 got_sign:
kono
parents:
diff changeset
1743 push_char (dtp, c);
kono
parents:
diff changeset
1744 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1745 goto bad_real;
kono
parents:
diff changeset
1746 }
kono
parents:
diff changeset
1747
kono
parents:
diff changeset
1748 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1749 c = '.';
kono
parents:
diff changeset
1750
kono
parents:
diff changeset
1751 if (!isdigit (c) && c != '.')
kono
parents:
diff changeset
1752 {
kono
parents:
diff changeset
1753 if (c == 'i' || c == 'I' || c == 'n' || c == 'N')
kono
parents:
diff changeset
1754 goto inf_nan;
kono
parents:
diff changeset
1755 else
kono
parents:
diff changeset
1756 goto bad_real;
kono
parents:
diff changeset
1757 }
kono
parents:
diff changeset
1758
kono
parents:
diff changeset
1759 if (c == '.')
kono
parents:
diff changeset
1760 {
kono
parents:
diff changeset
1761 if (seen_dp)
kono
parents:
diff changeset
1762 goto bad_real;
kono
parents:
diff changeset
1763 else
kono
parents:
diff changeset
1764 seen_dp = 1;
kono
parents:
diff changeset
1765 }
kono
parents:
diff changeset
1766
kono
parents:
diff changeset
1767 push_char (dtp, c);
kono
parents:
diff changeset
1768
kono
parents:
diff changeset
1769 real_loop:
kono
parents:
diff changeset
1770 for (;;)
kono
parents:
diff changeset
1771 {
kono
parents:
diff changeset
1772 c = next_char (dtp);
kono
parents:
diff changeset
1773 if (c == ',' && dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA)
kono
parents:
diff changeset
1774 c = '.';
kono
parents:
diff changeset
1775 switch (c)
kono
parents:
diff changeset
1776 {
kono
parents:
diff changeset
1777 CASE_DIGITS:
kono
parents:
diff changeset
1778 push_char (dtp, c);
kono
parents:
diff changeset
1779 break;
kono
parents:
diff changeset
1780
kono
parents:
diff changeset
1781 case '!':
kono
parents:
diff changeset
1782 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1783 goto bad_real;
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 CASE_SEPARATORS:
kono
parents:
diff changeset
1786 case EOF:
kono
parents:
diff changeset
1787 goto done;
kono
parents:
diff changeset
1788
kono
parents:
diff changeset
1789 case '.':
kono
parents:
diff changeset
1790 if (seen_dp)
kono
parents:
diff changeset
1791 goto bad_real;
kono
parents:
diff changeset
1792
kono
parents:
diff changeset
1793 seen_dp = 1;
kono
parents:
diff changeset
1794 push_char (dtp, c);
kono
parents:
diff changeset
1795 break;
kono
parents:
diff changeset
1796
kono
parents:
diff changeset
1797 case 'E':
kono
parents:
diff changeset
1798 case 'e':
kono
parents:
diff changeset
1799 case 'D':
kono
parents:
diff changeset
1800 case 'd':
kono
parents:
diff changeset
1801 case 'Q':
kono
parents:
diff changeset
1802 case 'q':
kono
parents:
diff changeset
1803 goto exp1;
kono
parents:
diff changeset
1804
kono
parents:
diff changeset
1805 case '+':
kono
parents:
diff changeset
1806 case '-':
kono
parents:
diff changeset
1807 push_char (dtp, 'e');
kono
parents:
diff changeset
1808 push_char (dtp, c);
kono
parents:
diff changeset
1809 c = next_char (dtp);
kono
parents:
diff changeset
1810 goto exp2;
kono
parents:
diff changeset
1811
kono
parents:
diff changeset
1812 default:
kono
parents:
diff changeset
1813 goto bad_real;
kono
parents:
diff changeset
1814 }
kono
parents:
diff changeset
1815 }
kono
parents:
diff changeset
1816
kono
parents:
diff changeset
1817 exp1:
kono
parents:
diff changeset
1818 push_char (dtp, 'e');
kono
parents:
diff changeset
1819
kono
parents:
diff changeset
1820 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1821 goto bad_real;
kono
parents:
diff changeset
1822 if (c != '+' && c != '-')
kono
parents:
diff changeset
1823 push_char (dtp, '+');
kono
parents:
diff changeset
1824 else
kono
parents:
diff changeset
1825 {
kono
parents:
diff changeset
1826 push_char (dtp, c);
kono
parents:
diff changeset
1827 c = next_char (dtp);
kono
parents:
diff changeset
1828 }
kono
parents:
diff changeset
1829
kono
parents:
diff changeset
1830 exp2:
kono
parents:
diff changeset
1831 if (!isdigit (c))
kono
parents:
diff changeset
1832 {
kono
parents:
diff changeset
1833 /* Extension: allow default exponent of 0 when omitted. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1834 if (dtp->common.flags & IOPARM_DT_DEC_EXT)
111
kono
parents:
diff changeset
1835 {
kono
parents:
diff changeset
1836 push_char (dtp, '0');
kono
parents:
diff changeset
1837 goto done;
kono
parents:
diff changeset
1838 }
kono
parents:
diff changeset
1839 else
kono
parents:
diff changeset
1840 goto bad_exponent;
kono
parents:
diff changeset
1841 }
kono
parents:
diff changeset
1842
kono
parents:
diff changeset
1843 push_char (dtp, c);
kono
parents:
diff changeset
1844
kono
parents:
diff changeset
1845 for (;;)
kono
parents:
diff changeset
1846 {
kono
parents:
diff changeset
1847 c = next_char (dtp);
kono
parents:
diff changeset
1848
kono
parents:
diff changeset
1849 switch (c)
kono
parents:
diff changeset
1850 {
kono
parents:
diff changeset
1851 CASE_DIGITS:
kono
parents:
diff changeset
1852 push_char (dtp, c);
kono
parents:
diff changeset
1853 break;
kono
parents:
diff changeset
1854
kono
parents:
diff changeset
1855 case '!':
kono
parents:
diff changeset
1856 if (!dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1857 goto bad_real;
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 CASE_SEPARATORS:
kono
parents:
diff changeset
1860 case EOF:
kono
parents:
diff changeset
1861 goto done;
kono
parents:
diff changeset
1862
kono
parents:
diff changeset
1863 default:
kono
parents:
diff changeset
1864 goto bad_real;
kono
parents:
diff changeset
1865 }
kono
parents:
diff changeset
1866 }
kono
parents:
diff changeset
1867
kono
parents:
diff changeset
1868 done:
kono
parents:
diff changeset
1869 unget_char (dtp, c);
kono
parents:
diff changeset
1870 eat_separator (dtp);
kono
parents:
diff changeset
1871 push_char (dtp, '\0');
kono
parents:
diff changeset
1872 if (convert_real (dtp, dest, dtp->u.p.saved_string, length))
kono
parents:
diff changeset
1873 {
kono
parents:
diff changeset
1874 free_saved (dtp);
kono
parents:
diff changeset
1875 return;
kono
parents:
diff changeset
1876 }
kono
parents:
diff changeset
1877
kono
parents:
diff changeset
1878 free_saved (dtp);
kono
parents:
diff changeset
1879 dtp->u.p.saved_type = BT_REAL;
kono
parents:
diff changeset
1880 return;
kono
parents:
diff changeset
1881
kono
parents:
diff changeset
1882 inf_nan:
kono
parents:
diff changeset
1883 l_push_char (dtp, c);
kono
parents:
diff changeset
1884 is_inf = 0;
kono
parents:
diff changeset
1885
kono
parents:
diff changeset
1886 /* Match INF and Infinity. */
kono
parents:
diff changeset
1887 if (c == 'i' || c == 'I')
kono
parents:
diff changeset
1888 {
kono
parents:
diff changeset
1889 c = next_char (dtp);
kono
parents:
diff changeset
1890 l_push_char (dtp, c);
kono
parents:
diff changeset
1891 if (c != 'n' && c != 'N')
kono
parents:
diff changeset
1892 goto unwind;
kono
parents:
diff changeset
1893 c = next_char (dtp);
kono
parents:
diff changeset
1894 l_push_char (dtp, c);
kono
parents:
diff changeset
1895 if (c != 'f' && c != 'F')
kono
parents:
diff changeset
1896 goto unwind;
kono
parents:
diff changeset
1897 c = next_char (dtp);
kono
parents:
diff changeset
1898 l_push_char (dtp, c);
kono
parents:
diff changeset
1899 if (!is_separator (c) && (c != EOF))
kono
parents:
diff changeset
1900 {
kono
parents:
diff changeset
1901 if (c != 'i' && c != 'I')
kono
parents:
diff changeset
1902 goto unwind;
kono
parents:
diff changeset
1903 c = next_char (dtp);
kono
parents:
diff changeset
1904 l_push_char (dtp, c);
kono
parents:
diff changeset
1905 if (c != 'n' && c != 'N')
kono
parents:
diff changeset
1906 goto unwind;
kono
parents:
diff changeset
1907 c = next_char (dtp);
kono
parents:
diff changeset
1908 l_push_char (dtp, c);
kono
parents:
diff changeset
1909 if (c != 'i' && c != 'I')
kono
parents:
diff changeset
1910 goto unwind;
kono
parents:
diff changeset
1911 c = next_char (dtp);
kono
parents:
diff changeset
1912 l_push_char (dtp, c);
kono
parents:
diff changeset
1913 if (c != 't' && c != 'T')
kono
parents:
diff changeset
1914 goto unwind;
kono
parents:
diff changeset
1915 c = next_char (dtp);
kono
parents:
diff changeset
1916 l_push_char (dtp, c);
kono
parents:
diff changeset
1917 if (c != 'y' && c != 'Y')
kono
parents:
diff changeset
1918 goto unwind;
kono
parents:
diff changeset
1919 c = next_char (dtp);
kono
parents:
diff changeset
1920 l_push_char (dtp, c);
kono
parents:
diff changeset
1921 }
kono
parents:
diff changeset
1922 is_inf = 1;
kono
parents:
diff changeset
1923 } /* Match NaN. */
kono
parents:
diff changeset
1924 else
kono
parents:
diff changeset
1925 {
kono
parents:
diff changeset
1926 c = next_char (dtp);
kono
parents:
diff changeset
1927 l_push_char (dtp, c);
kono
parents:
diff changeset
1928 if (c != 'a' && c != 'A')
kono
parents:
diff changeset
1929 goto unwind;
kono
parents:
diff changeset
1930 c = next_char (dtp);
kono
parents:
diff changeset
1931 l_push_char (dtp, c);
kono
parents:
diff changeset
1932 if (c != 'n' && c != 'N')
kono
parents:
diff changeset
1933 goto unwind;
kono
parents:
diff changeset
1934 c = next_char (dtp);
kono
parents:
diff changeset
1935 l_push_char (dtp, c);
kono
parents:
diff changeset
1936
kono
parents:
diff changeset
1937 /* Match NAN(alphanum). */
kono
parents:
diff changeset
1938 if (c == '(')
kono
parents:
diff changeset
1939 {
kono
parents:
diff changeset
1940 for (c = next_char (dtp); c != ')'; c = next_char (dtp))
kono
parents:
diff changeset
1941 if (is_separator (c))
kono
parents:
diff changeset
1942 goto unwind;
kono
parents:
diff changeset
1943 else
kono
parents:
diff changeset
1944 l_push_char (dtp, c);
kono
parents:
diff changeset
1945
kono
parents:
diff changeset
1946 l_push_char (dtp, ')');
kono
parents:
diff changeset
1947 c = next_char (dtp);
kono
parents:
diff changeset
1948 l_push_char (dtp, c);
kono
parents:
diff changeset
1949 }
kono
parents:
diff changeset
1950 }
kono
parents:
diff changeset
1951
kono
parents:
diff changeset
1952 if (!is_separator (c) && (c != EOF))
kono
parents:
diff changeset
1953 goto unwind;
kono
parents:
diff changeset
1954
kono
parents:
diff changeset
1955 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1956 {
kono
parents:
diff changeset
1957 if (c == ' ' || c =='\n' || c == '\r')
kono
parents:
diff changeset
1958 {
kono
parents:
diff changeset
1959 do
kono
parents:
diff changeset
1960 {
kono
parents:
diff changeset
1961 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
1962 goto bad_real;
kono
parents:
diff changeset
1963 }
kono
parents:
diff changeset
1964 while (c == ' ' || c =='\n' || c == '\r');
kono
parents:
diff changeset
1965
kono
parents:
diff changeset
1966 l_push_char (dtp, c);
kono
parents:
diff changeset
1967
kono
parents:
diff changeset
1968 if (c == '=')
kono
parents:
diff changeset
1969 goto unwind;
kono
parents:
diff changeset
1970 }
kono
parents:
diff changeset
1971 }
kono
parents:
diff changeset
1972
kono
parents:
diff changeset
1973 if (is_inf)
kono
parents:
diff changeset
1974 {
kono
parents:
diff changeset
1975 push_char (dtp, 'i');
kono
parents:
diff changeset
1976 push_char (dtp, 'n');
kono
parents:
diff changeset
1977 push_char (dtp, 'f');
kono
parents:
diff changeset
1978 }
kono
parents:
diff changeset
1979 else
kono
parents:
diff changeset
1980 {
kono
parents:
diff changeset
1981 push_char (dtp, 'n');
kono
parents:
diff changeset
1982 push_char (dtp, 'a');
kono
parents:
diff changeset
1983 push_char (dtp, 'n');
kono
parents:
diff changeset
1984 }
kono
parents:
diff changeset
1985
kono
parents:
diff changeset
1986 free_line (dtp);
kono
parents:
diff changeset
1987 unget_char (dtp, c);
kono
parents:
diff changeset
1988 eat_separator (dtp);
kono
parents:
diff changeset
1989 push_char (dtp, '\0');
kono
parents:
diff changeset
1990 if (convert_infnan (dtp, dest, dtp->u.p.saved_string, length))
kono
parents:
diff changeset
1991 return;
kono
parents:
diff changeset
1992
kono
parents:
diff changeset
1993 free_saved (dtp);
kono
parents:
diff changeset
1994 dtp->u.p.saved_type = BT_REAL;
kono
parents:
diff changeset
1995 return;
kono
parents:
diff changeset
1996
kono
parents:
diff changeset
1997 unwind:
kono
parents:
diff changeset
1998 if (dtp->u.p.namelist_mode)
kono
parents:
diff changeset
1999 {
kono
parents:
diff changeset
2000 dtp->u.p.nml_read_error = 1;
kono
parents:
diff changeset
2001 dtp->u.p.line_buffer_enabled = 1;
kono
parents:
diff changeset
2002 dtp->u.p.line_buffer_pos = 0;
kono
parents:
diff changeset
2003 return;
kono
parents:
diff changeset
2004 }
kono
parents:
diff changeset
2005
kono
parents:
diff changeset
2006 bad_real:
kono
parents:
diff changeset
2007
kono
parents:
diff changeset
2008 if (nml_bad_return (dtp, c))
kono
parents:
diff changeset
2009 return;
kono
parents:
diff changeset
2010
kono
parents:
diff changeset
2011 bad_exponent:
kono
parents:
diff changeset
2012
kono
parents:
diff changeset
2013 free_saved (dtp);
kono
parents:
diff changeset
2014 if (c == EOF)
kono
parents:
diff changeset
2015 {
kono
parents:
diff changeset
2016 free_line (dtp);
kono
parents:
diff changeset
2017 hit_eof (dtp);
kono
parents:
diff changeset
2018 return;
kono
parents:
diff changeset
2019 }
kono
parents:
diff changeset
2020 else if (c != '\n')
kono
parents:
diff changeset
2021 eat_line (dtp);
kono
parents:
diff changeset
2022
kono
parents:
diff changeset
2023 snprintf (message, MSGLEN, "Bad real number in item %d of list input",
kono
parents:
diff changeset
2024 dtp->u.p.item_count);
kono
parents:
diff changeset
2025 free_line (dtp);
kono
parents:
diff changeset
2026 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
2027 }
kono
parents:
diff changeset
2028
kono
parents:
diff changeset
2029
kono
parents:
diff changeset
2030 /* Check the current type against the saved type to make sure they are
kono
parents:
diff changeset
2031 compatible. Returns nonzero if incompatible. */
kono
parents:
diff changeset
2032
kono
parents:
diff changeset
2033 static int
kono
parents:
diff changeset
2034 check_type (st_parameter_dt *dtp, bt type, int kind)
kono
parents:
diff changeset
2035 {
kono
parents:
diff changeset
2036 char message[MSGLEN];
kono
parents:
diff changeset
2037
kono
parents:
diff changeset
2038 if (dtp->u.p.saved_type != BT_UNKNOWN && dtp->u.p.saved_type != type)
kono
parents:
diff changeset
2039 {
kono
parents:
diff changeset
2040 snprintf (message, MSGLEN, "Read type %s where %s was expected for item %d",
kono
parents:
diff changeset
2041 type_name (dtp->u.p.saved_type), type_name (type),
kono
parents:
diff changeset
2042 dtp->u.p.item_count);
kono
parents:
diff changeset
2043 free_line (dtp);
kono
parents:
diff changeset
2044 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
2045 return 1;
kono
parents:
diff changeset
2046 }
kono
parents:
diff changeset
2047
kono
parents:
diff changeset
2048 if (dtp->u.p.saved_type == BT_UNKNOWN || dtp->u.p.saved_type == BT_CHARACTER)
kono
parents:
diff changeset
2049 return 0;
kono
parents:
diff changeset
2050
kono
parents:
diff changeset
2051 if ((type != BT_COMPLEX && dtp->u.p.saved_length != kind)
kono
parents:
diff changeset
2052 || (type == BT_COMPLEX && dtp->u.p.saved_length != kind*2))
kono
parents:
diff changeset
2053 {
kono
parents:
diff changeset
2054 snprintf (message, MSGLEN,
kono
parents:
diff changeset
2055 "Read kind %d %s where kind %d is required for item %d",
kono
parents:
diff changeset
2056 type == BT_COMPLEX ? dtp->u.p.saved_length / 2
kono
parents:
diff changeset
2057 : dtp->u.p.saved_length,
kono
parents:
diff changeset
2058 type_name (dtp->u.p.saved_type), kind,
kono
parents:
diff changeset
2059 dtp->u.p.item_count);
kono
parents:
diff changeset
2060 free_line (dtp);
kono
parents:
diff changeset
2061 generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
kono
parents:
diff changeset
2062 return 1;
kono
parents:
diff changeset
2063 }
kono
parents:
diff changeset
2064
kono
parents:
diff changeset
2065 return 0;
kono
parents:
diff changeset
2066 }
kono
parents:
diff changeset
2067
kono
parents:
diff changeset
2068
kono
parents:
diff changeset
2069 /* Initialize the function pointers to select the correct versions of
kono
parents:
diff changeset
2070 next_char and push_char depending on what we are doing. */
kono
parents:
diff changeset
2071
kono
parents:
diff changeset
2072 static void
kono
parents:
diff changeset
2073 set_workers (st_parameter_dt *dtp)
kono
parents:
diff changeset
2074 {
kono
parents:
diff changeset
2075 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
kono
parents:
diff changeset
2076 {
kono
parents:
diff changeset
2077 dtp->u.p.current_unit->next_char_fn_ptr = &next_char_utf8;
kono
parents:
diff changeset
2078 dtp->u.p.current_unit->push_char_fn_ptr = &push_char4;
kono
parents:
diff changeset
2079 }
kono
parents:
diff changeset
2080 else if (is_internal_unit (dtp))
kono
parents:
diff changeset
2081 {
kono
parents:
diff changeset
2082 dtp->u.p.current_unit->next_char_fn_ptr = &next_char_internal;
kono
parents:
diff changeset
2083 dtp->u.p.current_unit->push_char_fn_ptr = &push_char_default;
kono
parents:
diff changeset
2084 }
kono
parents:
diff changeset
2085 else
kono
parents:
diff changeset
2086 {
kono
parents:
diff changeset
2087 dtp->u.p.current_unit->next_char_fn_ptr = &next_char_default;
kono
parents:
diff changeset
2088 dtp->u.p.current_unit->push_char_fn_ptr = &push_char_default;
kono
parents:
diff changeset
2089 }
kono
parents:
diff changeset
2090
kono
parents:
diff changeset
2091 }
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 /* Top level data transfer subroutine for list reads. Because we have
kono
parents:
diff changeset
2094 to deal with repeat counts, the data item is always saved after
kono
parents:
diff changeset
2095 reading, usually in the dtp->u.p.value[] array. If a repeat count is
kono
parents:
diff changeset
2096 greater than one, we copy the data item multiple times. */
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 static int
kono
parents:
diff changeset
2099 list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
kono
parents:
diff changeset
2100 int kind, size_t size)
kono
parents:
diff changeset
2101 {
kono
parents:
diff changeset
2102 gfc_char4_t *q, *r;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2103 size_t m;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2104 int c;
111
kono
parents:
diff changeset
2105 int err = 0;
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 /* Set the next_char and push_char worker functions. */
kono
parents:
diff changeset
2108 set_workers (dtp);
kono
parents:
diff changeset
2109
kono
parents:
diff changeset
2110 if (dtp->u.p.first_item)
kono
parents:
diff changeset
2111 {
kono
parents:
diff changeset
2112 dtp->u.p.first_item = 0;
kono
parents:
diff changeset
2113 dtp->u.p.input_complete = 0;
kono
parents:
diff changeset
2114 dtp->u.p.repeat_count = 1;
kono
parents:
diff changeset
2115 dtp->u.p.at_eol = 0;
kono
parents:
diff changeset
2116
kono
parents:
diff changeset
2117 if ((c = eat_spaces (dtp)) == EOF)
kono
parents:
diff changeset
2118 {
kono
parents:
diff changeset
2119 err = LIBERROR_END;
kono
parents:
diff changeset
2120 goto cleanup;
kono
parents:
diff changeset
2121 }
kono
parents:
diff changeset
2122 if (is_separator (c))
kono
parents:
diff changeset
2123 {
kono
parents:
diff changeset
2124 /* Found a null value. */
kono
parents:
diff changeset
2125 dtp->u.p.repeat_count = 0;
kono
parents:
diff changeset
2126 eat_separator (dtp);
kono
parents:
diff changeset
2127
kono
parents:
diff changeset
2128 /* Set end-of-line flag. */
kono
parents:
diff changeset
2129 if (c == '\n' || c == '\r')
kono
parents:
diff changeset
2130 {
kono
parents:
diff changeset
2131 dtp->u.p.at_eol = 1;
kono
parents:
diff changeset
2132 if (finish_separator (dtp) == LIBERROR_END)
kono
parents:
diff changeset
2133 {
kono
parents:
diff changeset
2134 err = LIBERROR_END;
kono
parents:
diff changeset
2135 goto cleanup;
kono
parents:
diff changeset
2136 }
kono
parents:
diff changeset
2137 }
kono
parents:
diff changeset
2138 else
kono
parents:
diff changeset
2139 goto cleanup;
kono
parents:
diff changeset
2140 }
kono
parents:
diff changeset
2141 }
kono
parents:
diff changeset
2142 else
kono
parents:
diff changeset
2143 {
kono
parents:
diff changeset
2144 if (dtp->u.p.repeat_count > 0)
kono
parents:
diff changeset
2145 {
kono
parents:
diff changeset
2146 if (check_type (dtp, type, kind))
kono
parents:
diff changeset
2147 return err;
kono
parents:
diff changeset
2148 goto set_value;
kono
parents:
diff changeset
2149 }
kono
parents:
diff changeset
2150
kono
parents:
diff changeset
2151 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
2152 goto cleanup;
kono
parents:
diff changeset
2153
kono
parents:
diff changeset
2154 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
2155 finish_separator (dtp);
kono
parents:
diff changeset
2156 else
kono
parents:
diff changeset
2157 {
kono
parents:
diff changeset
2158 eat_spaces (dtp);
kono
parents:
diff changeset
2159 /* Trailing spaces prior to end of line. */
kono
parents:
diff changeset
2160 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
2161 finish_separator (dtp);
kono
parents:
diff changeset
2162 }
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 dtp->u.p.saved_type = BT_UNKNOWN;
kono
parents:
diff changeset
2165 dtp->u.p.repeat_count = 1;
kono
parents:
diff changeset
2166 }
kono
parents:
diff changeset
2167
kono
parents:
diff changeset
2168 switch (type)
kono
parents:
diff changeset
2169 {
kono
parents:
diff changeset
2170 case BT_INTEGER:
kono
parents:
diff changeset
2171 read_integer (dtp, kind);
kono
parents:
diff changeset
2172 break;
kono
parents:
diff changeset
2173 case BT_LOGICAL:
kono
parents:
diff changeset
2174 read_logical (dtp, kind);
kono
parents:
diff changeset
2175 break;
kono
parents:
diff changeset
2176 case BT_CHARACTER:
kono
parents:
diff changeset
2177 read_character (dtp, kind);
kono
parents:
diff changeset
2178 break;
kono
parents:
diff changeset
2179 case BT_REAL:
kono
parents:
diff changeset
2180 read_real (dtp, p, kind);
kono
parents:
diff changeset
2181 /* Copy value back to temporary if needed. */
kono
parents:
diff changeset
2182 if (dtp->u.p.repeat_count > 0)
kono
parents:
diff changeset
2183 memcpy (dtp->u.p.value, p, size);
kono
parents:
diff changeset
2184 break;
kono
parents:
diff changeset
2185 case BT_COMPLEX:
kono
parents:
diff changeset
2186 read_complex (dtp, p, kind, size);
kono
parents:
diff changeset
2187 /* Copy value back to temporary if needed. */
kono
parents:
diff changeset
2188 if (dtp->u.p.repeat_count > 0)
kono
parents:
diff changeset
2189 memcpy (dtp->u.p.value, p, size);
kono
parents:
diff changeset
2190 break;
kono
parents:
diff changeset
2191 case BT_CLASS:
kono
parents:
diff changeset
2192 {
kono
parents:
diff changeset
2193 int unit = dtp->u.p.current_unit->unit_number;
kono
parents:
diff changeset
2194 char iotype[] = "LISTDIRECTED";
kono
parents:
diff changeset
2195 gfc_charlen_type iotype_len = 12;
kono
parents:
diff changeset
2196 char tmp_iomsg[IOMSG_LEN] = "";
kono
parents:
diff changeset
2197 char *child_iomsg;
kono
parents:
diff changeset
2198 gfc_charlen_type child_iomsg_len;
kono
parents:
diff changeset
2199 int noiostat;
kono
parents:
diff changeset
2200 int *child_iostat = NULL;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2201 gfc_full_array_i4 vlist;
111
kono
parents:
diff changeset
2202
kono
parents:
diff changeset
2203 GFC_DESCRIPTOR_DATA(&vlist) = NULL;
kono
parents:
diff changeset
2204 GFC_DIMENSION_SET(vlist.dim[0],1, 0, 0);
kono
parents:
diff changeset
2205
kono
parents:
diff changeset
2206 /* Set iostat, intent(out). */
kono
parents:
diff changeset
2207 noiostat = 0;
kono
parents:
diff changeset
2208 child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
kono
parents:
diff changeset
2209 dtp->common.iostat : &noiostat;
kono
parents:
diff changeset
2210
kono
parents:
diff changeset
2211 /* Set iomsge, intent(inout). */
kono
parents:
diff changeset
2212 if (dtp->common.flags & IOPARM_HAS_IOMSG)
kono
parents:
diff changeset
2213 {
kono
parents:
diff changeset
2214 child_iomsg = dtp->common.iomsg;
kono
parents:
diff changeset
2215 child_iomsg_len = dtp->common.iomsg_len;
kono
parents:
diff changeset
2216 }
kono
parents:
diff changeset
2217 else
kono
parents:
diff changeset
2218 {
kono
parents:
diff changeset
2219 child_iomsg = tmp_iomsg;
kono
parents:
diff changeset
2220 child_iomsg_len = IOMSG_LEN;
kono
parents:
diff changeset
2221 }
kono
parents:
diff changeset
2222
kono
parents:
diff changeset
2223 /* Call the user defined formatted READ procedure. */
kono
parents:
diff changeset
2224 dtp->u.p.current_unit->child_dtio++;
kono
parents:
diff changeset
2225 dtp->u.p.fdtio_ptr (p, &unit, iotype, &vlist,
kono
parents:
diff changeset
2226 child_iostat, child_iomsg,
kono
parents:
diff changeset
2227 iotype_len, child_iomsg_len);
kono
parents:
diff changeset
2228 dtp->u.p.child_saved_iostat = *child_iostat;
kono
parents:
diff changeset
2229 dtp->u.p.current_unit->child_dtio--;
kono
parents:
diff changeset
2230 }
kono
parents:
diff changeset
2231 break;
kono
parents:
diff changeset
2232 default:
kono
parents:
diff changeset
2233 internal_error (&dtp->common, "Bad type for list read");
kono
parents:
diff changeset
2234 }
kono
parents:
diff changeset
2235
kono
parents:
diff changeset
2236 if (dtp->u.p.saved_type != BT_CHARACTER && dtp->u.p.saved_type != BT_UNKNOWN)
kono
parents:
diff changeset
2237 dtp->u.p.saved_length = size;
kono
parents:
diff changeset
2238
kono
parents:
diff changeset
2239 if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
kono
parents:
diff changeset
2240 goto cleanup;
kono
parents:
diff changeset
2241
kono
parents:
diff changeset
2242 set_value:
kono
parents:
diff changeset
2243 switch (dtp->u.p.saved_type)
kono
parents:
diff changeset
2244 {
kono
parents:
diff changeset
2245 case BT_COMPLEX:
kono
parents:
diff changeset
2246 case BT_REAL:
kono
parents:
diff changeset
2247 if (dtp->u.p.repeat_count > 0)
kono
parents:
diff changeset
2248 memcpy (p, dtp->u.p.value, size);
kono
parents:
diff changeset
2249 break;
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 case BT_INTEGER:
kono
parents:
diff changeset
2252 case BT_LOGICAL:
kono
parents:
diff changeset
2253 memcpy (p, dtp->u.p.value, size);
kono
parents:
diff changeset
2254 break;
kono
parents:
diff changeset
2255
kono
parents:
diff changeset
2256 case BT_CHARACTER:
kono
parents:
diff changeset
2257 if (dtp->u.p.saved_string)
kono
parents:
diff changeset
2258 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2259 m = (size < (size_t) dtp->u.p.saved_used)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2260 ? size : (size_t) dtp->u.p.saved_used;
111
kono
parents:
diff changeset
2261
kono
parents:
diff changeset
2262 q = (gfc_char4_t *) p;
kono
parents:
diff changeset
2263 r = (gfc_char4_t *) dtp->u.p.saved_string;
kono
parents:
diff changeset
2264 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2265 for (size_t i = 0; i < m; i++)
111
kono
parents:
diff changeset
2266 *q++ = *r++;
kono
parents:
diff changeset
2267 else
kono
parents:
diff changeset
2268 {
kono
parents:
diff changeset
2269 if (kind == 1)
kono
parents:
diff changeset
2270 memcpy (p, dtp->u.p.saved_string, m);
kono
parents:
diff changeset
2271 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2272 for (size_t i = 0; i < m; i++)
111
kono
parents:
diff changeset
2273 *q++ = *r++;
kono
parents:
diff changeset
2274 }
kono
parents:
diff changeset
2275 }
kono
parents:
diff changeset
2276 else
kono
parents:
diff changeset
2277 /* Just delimiters encountered, nothing to copy but SPACE. */
kono
parents:
diff changeset
2278 m = 0;
kono
parents:
diff changeset
2279
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2280 if (m < size)
111
kono
parents:
diff changeset
2281 {
kono
parents:
diff changeset
2282 if (kind == 1)
kono
parents:
diff changeset
2283 memset (((char *) p) + m, ' ', size - m);
kono
parents:
diff changeset
2284 else
kono
parents:
diff changeset
2285 {
kono
parents:
diff changeset
2286 q = (gfc_char4_t *) p;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2287 for (size_t i = m; i < size; i++)
111
kono
parents:
diff changeset
2288 q[i] = (unsigned char) ' ';
kono
parents:
diff changeset
2289 }
kono
parents:
diff changeset
2290 }
kono
parents:
diff changeset
2291 break;
kono
parents:
diff changeset
2292
kono
parents:
diff changeset
2293 case BT_UNKNOWN:
kono
parents:
diff changeset
2294 break;
kono
parents:
diff changeset
2295
kono
parents:
diff changeset
2296 default:
kono
parents:
diff changeset
2297 internal_error (&dtp->common, "Bad type for list read");
kono
parents:
diff changeset
2298 }
kono
parents:
diff changeset
2299
kono
parents:
diff changeset
2300 if (--dtp->u.p.repeat_count <= 0)
kono
parents:
diff changeset
2301 free_saved (dtp);
kono
parents:
diff changeset
2302
kono
parents:
diff changeset
2303 cleanup:
kono
parents:
diff changeset
2304 /* err may have been set above from finish_separator, so if it is set
kono
parents:
diff changeset
2305 trigger the hit_eof. The hit_eof will set bits in common.flags. */
kono
parents:
diff changeset
2306 if (err == LIBERROR_END)
kono
parents:
diff changeset
2307 {
kono
parents:
diff changeset
2308 free_line (dtp);
kono
parents:
diff changeset
2309 hit_eof (dtp);
kono
parents:
diff changeset
2310 }
kono
parents:
diff changeset
2311 /* Now we check common.flags for any errors that could have occurred in
kono
parents:
diff changeset
2312 a READ elsewhere such as in read_integer. */
kono
parents:
diff changeset
2313 err = dtp->common.flags & IOPARM_LIBRETURN_MASK;
kono
parents:
diff changeset
2314 fbuf_flush_list (dtp->u.p.current_unit, LIST_READING);
kono
parents:
diff changeset
2315 return err;
kono
parents:
diff changeset
2316 }
kono
parents:
diff changeset
2317
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 void
kono
parents:
diff changeset
2320 list_formatted_read (st_parameter_dt *dtp, bt type, void *p, int kind,
kono
parents:
diff changeset
2321 size_t size, size_t nelems)
kono
parents:
diff changeset
2322 {
kono
parents:
diff changeset
2323 size_t elem;
kono
parents:
diff changeset
2324 char *tmp;
kono
parents:
diff changeset
2325 size_t stride = type == BT_CHARACTER ?
kono
parents:
diff changeset
2326 size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
kono
parents:
diff changeset
2327 int err;
kono
parents:
diff changeset
2328
kono
parents:
diff changeset
2329 tmp = (char *) p;
kono
parents:
diff changeset
2330
kono
parents:
diff changeset
2331 /* Big loop over all the elements. */
kono
parents:
diff changeset
2332 for (elem = 0; elem < nelems; elem++)
kono
parents:
diff changeset
2333 {
kono
parents:
diff changeset
2334 dtp->u.p.item_count++;
kono
parents:
diff changeset
2335 err = list_formatted_read_scalar (dtp, type, tmp + stride*elem,
kono
parents:
diff changeset
2336 kind, size);
kono
parents:
diff changeset
2337 if (err)
kono
parents:
diff changeset
2338 break;
kono
parents:
diff changeset
2339 }
kono
parents:
diff changeset
2340 }
kono
parents:
diff changeset
2341
kono
parents:
diff changeset
2342
kono
parents:
diff changeset
2343 /* Finish a list read. */
kono
parents:
diff changeset
2344
kono
parents:
diff changeset
2345 void
kono
parents:
diff changeset
2346 finish_list_read (st_parameter_dt *dtp)
kono
parents:
diff changeset
2347 {
kono
parents:
diff changeset
2348 free_saved (dtp);
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
kono
parents:
diff changeset
2351
kono
parents:
diff changeset
2352 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
2353 {
kono
parents:
diff changeset
2354 dtp->u.p.at_eol = 0;
kono
parents:
diff changeset
2355 return;
kono
parents:
diff changeset
2356 }
kono
parents:
diff changeset
2357
kono
parents:
diff changeset
2358 if (!is_internal_unit (dtp))
kono
parents:
diff changeset
2359 {
kono
parents:
diff changeset
2360 int c;
kono
parents:
diff changeset
2361
kono
parents:
diff changeset
2362 /* Set the next_char and push_char worker functions. */
kono
parents:
diff changeset
2363 set_workers (dtp);
kono
parents:
diff changeset
2364
kono
parents:
diff changeset
2365 if (likely (dtp->u.p.child_saved_iostat == LIBERROR_OK))
kono
parents:
diff changeset
2366 {
kono
parents:
diff changeset
2367 c = next_char (dtp);
kono
parents:
diff changeset
2368 if (c == EOF)
kono
parents:
diff changeset
2369 {
kono
parents:
diff changeset
2370 free_line (dtp);
kono
parents:
diff changeset
2371 hit_eof (dtp);
kono
parents:
diff changeset
2372 return;
kono
parents:
diff changeset
2373 }
kono
parents:
diff changeset
2374 if (c != '\n')
kono
parents:
diff changeset
2375 eat_line (dtp);
kono
parents:
diff changeset
2376 }
kono
parents:
diff changeset
2377 }
kono
parents:
diff changeset
2378
kono
parents:
diff changeset
2379 free_line (dtp);
kono
parents:
diff changeset
2380
kono
parents:
diff changeset
2381 }
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 /* NAMELIST INPUT
kono
parents:
diff changeset
2384
kono
parents:
diff changeset
2385 void namelist_read (st_parameter_dt *dtp)
kono
parents:
diff changeset
2386 calls:
kono
parents:
diff changeset
2387 static void nml_match_name (char *name, int len)
kono
parents:
diff changeset
2388 static int nml_query (st_parameter_dt *dtp)
kono
parents:
diff changeset
2389 static int nml_get_obj_data (st_parameter_dt *dtp,
kono
parents:
diff changeset
2390 namelist_info **prev_nl, char *, size_t)
kono
parents:
diff changeset
2391 calls:
kono
parents:
diff changeset
2392 static void nml_untouch_nodes (st_parameter_dt *dtp)
kono
parents:
diff changeset
2393 static namelist_info *find_nml_node (st_parameter_dt *dtp,
kono
parents:
diff changeset
2394 char *var_name)
kono
parents:
diff changeset
2395 static int nml_parse_qualifier(descriptor_dimension *ad,
kono
parents:
diff changeset
2396 array_loop_spec *ls, int rank, char *)
kono
parents:
diff changeset
2397 static void nml_touch_nodes (namelist_info *nl)
kono
parents:
diff changeset
2398 static int nml_read_obj (namelist_info *nl, index_type offset,
kono
parents:
diff changeset
2399 namelist_info **prev_nl, char *, size_t,
kono
parents:
diff changeset
2400 index_type clow, index_type chigh)
kono
parents:
diff changeset
2401 calls:
kono
parents:
diff changeset
2402 -itself- */
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 /* Inputs a rank-dimensional qualifier, which can contain
kono
parents:
diff changeset
2405 singlets, doublets, triplets or ':' with the standard meanings. */
kono
parents:
diff changeset
2406
kono
parents:
diff changeset
2407 static bool
kono
parents:
diff changeset
2408 nml_parse_qualifier (st_parameter_dt *dtp, descriptor_dimension *ad,
kono
parents:
diff changeset
2409 array_loop_spec *ls, int rank, bt nml_elem_type,
kono
parents:
diff changeset
2410 char *parse_err_msg, size_t parse_err_msg_size,
kono
parents:
diff changeset
2411 int *parsed_rank)
kono
parents:
diff changeset
2412 {
kono
parents:
diff changeset
2413 int dim;
kono
parents:
diff changeset
2414 int indx;
kono
parents:
diff changeset
2415 int neg;
kono
parents:
diff changeset
2416 int null_flag;
kono
parents:
diff changeset
2417 int is_array_section, is_char;
kono
parents:
diff changeset
2418 int c;
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 is_char = 0;
kono
parents:
diff changeset
2421 is_array_section = 0;
kono
parents:
diff changeset
2422 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 /* See if this is a character substring qualifier we are looking for. */
kono
parents:
diff changeset
2425 if (rank == -1)
kono
parents:
diff changeset
2426 {
kono
parents:
diff changeset
2427 rank = 1;
kono
parents:
diff changeset
2428 is_char = 1;
kono
parents:
diff changeset
2429 }
kono
parents:
diff changeset
2430
kono
parents:
diff changeset
2431 /* The next character in the stream should be the '('. */
kono
parents:
diff changeset
2432
kono
parents:
diff changeset
2433 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
2434 goto err_ret;
kono
parents:
diff changeset
2435
kono
parents:
diff changeset
2436 /* Process the qualifier, by dimension and triplet. */
kono
parents:
diff changeset
2437
kono
parents:
diff changeset
2438 for (dim=0; dim < rank; dim++ )
kono
parents:
diff changeset
2439 {
kono
parents:
diff changeset
2440 for (indx=0; indx<3; indx++)
kono
parents:
diff changeset
2441 {
kono
parents:
diff changeset
2442 free_saved (dtp);
kono
parents:
diff changeset
2443 eat_spaces (dtp);
kono
parents:
diff changeset
2444 neg = 0;
kono
parents:
diff changeset
2445
kono
parents:
diff changeset
2446 /* Process a potential sign. */
kono
parents:
diff changeset
2447 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
2448 goto err_ret;
kono
parents:
diff changeset
2449 switch (c)
kono
parents:
diff changeset
2450 {
kono
parents:
diff changeset
2451 case '-':
kono
parents:
diff changeset
2452 neg = 1;
kono
parents:
diff changeset
2453 break;
kono
parents:
diff changeset
2454
kono
parents:
diff changeset
2455 case '+':
kono
parents:
diff changeset
2456 break;
kono
parents:
diff changeset
2457
kono
parents:
diff changeset
2458 default:
kono
parents:
diff changeset
2459 unget_char (dtp, c);
kono
parents:
diff changeset
2460 break;
kono
parents:
diff changeset
2461 }
kono
parents:
diff changeset
2462
kono
parents:
diff changeset
2463 /* Process characters up to the next ':' , ',' or ')'. */
kono
parents:
diff changeset
2464 for (;;)
kono
parents:
diff changeset
2465 {
kono
parents:
diff changeset
2466 c = next_char (dtp);
kono
parents:
diff changeset
2467 switch (c)
kono
parents:
diff changeset
2468 {
kono
parents:
diff changeset
2469 case EOF:
kono
parents:
diff changeset
2470 goto err_ret;
kono
parents:
diff changeset
2471
kono
parents:
diff changeset
2472 case ':':
kono
parents:
diff changeset
2473 is_array_section = 1;
kono
parents:
diff changeset
2474 break;
kono
parents:
diff changeset
2475
kono
parents:
diff changeset
2476 case ',': case ')':
kono
parents:
diff changeset
2477 if ((c==',' && dim == rank -1)
kono
parents:
diff changeset
2478 || (c==')' && dim < rank -1))
kono
parents:
diff changeset
2479 {
kono
parents:
diff changeset
2480 if (is_char)
kono
parents:
diff changeset
2481 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2482 "Bad substring qualifier");
kono
parents:
diff changeset
2483 else
kono
parents:
diff changeset
2484 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2485 "Bad number of index fields");
kono
parents:
diff changeset
2486 goto err_ret;
kono
parents:
diff changeset
2487 }
kono
parents:
diff changeset
2488 break;
kono
parents:
diff changeset
2489
kono
parents:
diff changeset
2490 CASE_DIGITS:
kono
parents:
diff changeset
2491 push_char (dtp, c);
kono
parents:
diff changeset
2492 continue;
kono
parents:
diff changeset
2493
kono
parents:
diff changeset
2494 case ' ': case '\t': case '\r': case '\n':
kono
parents:
diff changeset
2495 eat_spaces (dtp);
kono
parents:
diff changeset
2496 break;
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 default:
kono
parents:
diff changeset
2499 if (is_char)
kono
parents:
diff changeset
2500 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2501 "Bad character in substring qualifier");
kono
parents:
diff changeset
2502 else
kono
parents:
diff changeset
2503 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2504 "Bad character in index");
kono
parents:
diff changeset
2505 goto err_ret;
kono
parents:
diff changeset
2506 }
kono
parents:
diff changeset
2507
kono
parents:
diff changeset
2508 if ((c == ',' || c == ')') && indx == 0
kono
parents:
diff changeset
2509 && dtp->u.p.saved_string == 0)
kono
parents:
diff changeset
2510 {
kono
parents:
diff changeset
2511 if (is_char)
kono
parents:
diff changeset
2512 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2513 "Null substring qualifier");
kono
parents:
diff changeset
2514 else
kono
parents:
diff changeset
2515 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2516 "Null index field");
kono
parents:
diff changeset
2517 goto err_ret;
kono
parents:
diff changeset
2518 }
kono
parents:
diff changeset
2519
kono
parents:
diff changeset
2520 if ((c == ':' && indx == 1 && dtp->u.p.saved_string == 0)
kono
parents:
diff changeset
2521 || (indx == 2 && dtp->u.p.saved_string == 0))
kono
parents:
diff changeset
2522 {
kono
parents:
diff changeset
2523 if (is_char)
kono
parents:
diff changeset
2524 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2525 "Bad substring qualifier");
kono
parents:
diff changeset
2526 else
kono
parents:
diff changeset
2527 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2528 "Bad index triplet");
kono
parents:
diff changeset
2529 goto err_ret;
kono
parents:
diff changeset
2530 }
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 if (is_char && !is_array_section)
kono
parents:
diff changeset
2533 {
kono
parents:
diff changeset
2534 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2535 "Missing colon in substring qualifier");
kono
parents:
diff changeset
2536 goto err_ret;
kono
parents:
diff changeset
2537 }
kono
parents:
diff changeset
2538
kono
parents:
diff changeset
2539 /* If '( : ? )' or '( ? : )' break and flag read failure. */
kono
parents:
diff changeset
2540 null_flag = 0;
kono
parents:
diff changeset
2541 if ((c == ':' && indx == 0 && dtp->u.p.saved_string == 0)
kono
parents:
diff changeset
2542 || (indx==1 && dtp->u.p.saved_string == 0))
kono
parents:
diff changeset
2543 {
kono
parents:
diff changeset
2544 null_flag = 1;
kono
parents:
diff changeset
2545 break;
kono
parents:
diff changeset
2546 }
kono
parents:
diff changeset
2547
kono
parents:
diff changeset
2548 /* Now read the index. */
kono
parents:
diff changeset
2549 if (convert_integer (dtp, sizeof(index_type), neg))
kono
parents:
diff changeset
2550 {
kono
parents:
diff changeset
2551 if (is_char)
kono
parents:
diff changeset
2552 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2553 "Bad integer substring qualifier");
kono
parents:
diff changeset
2554 else
kono
parents:
diff changeset
2555 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2556 "Bad integer in index");
kono
parents:
diff changeset
2557 goto err_ret;
kono
parents:
diff changeset
2558 }
kono
parents:
diff changeset
2559 break;
kono
parents:
diff changeset
2560 }
kono
parents:
diff changeset
2561
kono
parents:
diff changeset
2562 /* Feed the index values to the triplet arrays. */
kono
parents:
diff changeset
2563 if (!null_flag)
kono
parents:
diff changeset
2564 {
kono
parents:
diff changeset
2565 if (indx == 0)
kono
parents:
diff changeset
2566 memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
kono
parents:
diff changeset
2567 if (indx == 1)
kono
parents:
diff changeset
2568 memcpy (&ls[dim].end, dtp->u.p.value, sizeof(index_type));
kono
parents:
diff changeset
2569 if (indx == 2)
kono
parents:
diff changeset
2570 memcpy (&ls[dim].step, dtp->u.p.value, sizeof(index_type));
kono
parents:
diff changeset
2571 }
kono
parents:
diff changeset
2572
kono
parents:
diff changeset
2573 /* Singlet or doublet indices. */
kono
parents:
diff changeset
2574 if (c==',' || c==')')
kono
parents:
diff changeset
2575 {
kono
parents:
diff changeset
2576 if (indx == 0)
kono
parents:
diff changeset
2577 {
kono
parents:
diff changeset
2578 memcpy (&ls[dim].start, dtp->u.p.value, sizeof(index_type));
kono
parents:
diff changeset
2579
kono
parents:
diff changeset
2580 /* If -std=f95/2003 or an array section is specified,
kono
parents:
diff changeset
2581 do not allow excess data to be processed. */
kono
parents:
diff changeset
2582 if (is_array_section == 1
kono
parents:
diff changeset
2583 || !(compile_options.allow_std & GFC_STD_GNU)
kono
parents:
diff changeset
2584 || nml_elem_type == BT_DERIVED)
kono
parents:
diff changeset
2585 ls[dim].end = ls[dim].start;
kono
parents:
diff changeset
2586 else
kono
parents:
diff changeset
2587 dtp->u.p.expanded_read = 1;
kono
parents:
diff changeset
2588 }
kono
parents:
diff changeset
2589
kono
parents:
diff changeset
2590 /* Check for non-zero rank. */
kono
parents:
diff changeset
2591 if (is_array_section == 1 && ls[dim].start != ls[dim].end)
kono
parents:
diff changeset
2592 *parsed_rank = 1;
kono
parents:
diff changeset
2593
kono
parents:
diff changeset
2594 break;
kono
parents:
diff changeset
2595 }
kono
parents:
diff changeset
2596 }
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 if (is_array_section == 1 && dtp->u.p.expanded_read == 1)
kono
parents:
diff changeset
2599 {
kono
parents:
diff changeset
2600 int i;
kono
parents:
diff changeset
2601 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
2602 for (i = 0; i < dim; i++)
kono
parents:
diff changeset
2603 ls[i].end = ls[i].start;
kono
parents:
diff changeset
2604 }
kono
parents:
diff changeset
2605
kono
parents:
diff changeset
2606 /* Check the values of the triplet indices. */
kono
parents:
diff changeset
2607 if ((ls[dim].start > GFC_DIMENSION_UBOUND(ad[dim]))
kono
parents:
diff changeset
2608 || (ls[dim].start < GFC_DIMENSION_LBOUND(ad[dim]))
kono
parents:
diff changeset
2609 || (ls[dim].end > GFC_DIMENSION_UBOUND(ad[dim]))
kono
parents:
diff changeset
2610 || (ls[dim].end < GFC_DIMENSION_LBOUND(ad[dim])))
kono
parents:
diff changeset
2611 {
kono
parents:
diff changeset
2612 if (is_char)
kono
parents:
diff changeset
2613 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2614 "Substring out of range");
kono
parents:
diff changeset
2615 else
kono
parents:
diff changeset
2616 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2617 "Index %d out of range", dim + 1);
kono
parents:
diff changeset
2618 goto err_ret;
kono
parents:
diff changeset
2619 }
kono
parents:
diff changeset
2620
kono
parents:
diff changeset
2621 if (((ls[dim].end - ls[dim].start ) * ls[dim].step < 0)
kono
parents:
diff changeset
2622 || (ls[dim].step == 0))
kono
parents:
diff changeset
2623 {
kono
parents:
diff changeset
2624 snprintf (parse_err_msg, parse_err_msg_size,
kono
parents:
diff changeset
2625 "Bad range in index %d", dim + 1);
kono
parents:
diff changeset
2626 goto err_ret;
kono
parents:
diff changeset
2627 }
kono
parents:
diff changeset
2628
kono
parents:
diff changeset
2629 /* Initialise the loop index counter. */
kono
parents:
diff changeset
2630 ls[dim].idx = ls[dim].start;
kono
parents:
diff changeset
2631 }
kono
parents:
diff changeset
2632 eat_spaces (dtp);
kono
parents:
diff changeset
2633 return true;
kono
parents:
diff changeset
2634
kono
parents:
diff changeset
2635 err_ret:
kono
parents:
diff changeset
2636
kono
parents:
diff changeset
2637 /* The EOF error message is issued by hit_eof. Return true so that the
kono
parents:
diff changeset
2638 caller does not use parse_err_msg and parse_err_msg_size to generate
kono
parents:
diff changeset
2639 an unrelated error message. */
kono
parents:
diff changeset
2640 if (c == EOF)
kono
parents:
diff changeset
2641 {
kono
parents:
diff changeset
2642 hit_eof (dtp);
kono
parents:
diff changeset
2643 dtp->u.p.input_complete = 1;
kono
parents:
diff changeset
2644 return true;
kono
parents:
diff changeset
2645 }
kono
parents:
diff changeset
2646 return false;
kono
parents:
diff changeset
2647 }
kono
parents:
diff changeset
2648
kono
parents:
diff changeset
2649
kono
parents:
diff changeset
2650 static bool
kono
parents:
diff changeset
2651 extended_look_ahead (char *p, char *q)
kono
parents:
diff changeset
2652 {
kono
parents:
diff changeset
2653 char *r, *s;
kono
parents:
diff changeset
2654
kono
parents:
diff changeset
2655 /* Scan ahead to find a '%' in the p string. */
kono
parents:
diff changeset
2656 for(r = p, s = q; *r && *s; s++)
kono
parents:
diff changeset
2657 if ((*s == '%' || *s == '+') && strcmp (r + 1, s + 1) == 0)
kono
parents:
diff changeset
2658 return true;
kono
parents:
diff changeset
2659 return false;
kono
parents:
diff changeset
2660 }
kono
parents:
diff changeset
2661
kono
parents:
diff changeset
2662
kono
parents:
diff changeset
2663 static bool
kono
parents:
diff changeset
2664 strcmp_extended_type (char *p, char *q)
kono
parents:
diff changeset
2665 {
kono
parents:
diff changeset
2666 char *r, *s;
kono
parents:
diff changeset
2667
kono
parents:
diff changeset
2668 for (r = p, s = q; *r && *s; r++, s++)
kono
parents:
diff changeset
2669 {
kono
parents:
diff changeset
2670 if (*r != *s)
kono
parents:
diff changeset
2671 {
kono
parents:
diff changeset
2672 if (*r == '%' && *s == '+' && extended_look_ahead (r, s))
kono
parents:
diff changeset
2673 return true;
kono
parents:
diff changeset
2674 break;
kono
parents:
diff changeset
2675 }
kono
parents:
diff changeset
2676 }
kono
parents:
diff changeset
2677 return false;
kono
parents:
diff changeset
2678 }
kono
parents:
diff changeset
2679
kono
parents:
diff changeset
2680
kono
parents:
diff changeset
2681 static namelist_info *
kono
parents:
diff changeset
2682 find_nml_node (st_parameter_dt *dtp, char *var_name)
kono
parents:
diff changeset
2683 {
kono
parents:
diff changeset
2684 namelist_info *t = dtp->u.p.ionml;
kono
parents:
diff changeset
2685 while (t != NULL)
kono
parents:
diff changeset
2686 {
kono
parents:
diff changeset
2687 if (strcmp (var_name, t->var_name) == 0)
kono
parents:
diff changeset
2688 {
kono
parents:
diff changeset
2689 t->touched = 1;
kono
parents:
diff changeset
2690 return t;
kono
parents:
diff changeset
2691 }
kono
parents:
diff changeset
2692 if (strcmp_extended_type (var_name, t->var_name))
kono
parents:
diff changeset
2693 {
kono
parents:
diff changeset
2694 t->touched = 1;
kono
parents:
diff changeset
2695 return t;
kono
parents:
diff changeset
2696 }
kono
parents:
diff changeset
2697 t = t->next;
kono
parents:
diff changeset
2698 }
kono
parents:
diff changeset
2699 return NULL;
kono
parents:
diff changeset
2700 }
kono
parents:
diff changeset
2701
kono
parents:
diff changeset
2702 /* Visits all the components of a derived type that have
kono
parents:
diff changeset
2703 not explicitly been identified in the namelist input.
kono
parents:
diff changeset
2704 touched is set and the loop specification initialised
kono
parents:
diff changeset
2705 to default values */
kono
parents:
diff changeset
2706
kono
parents:
diff changeset
2707 static void
kono
parents:
diff changeset
2708 nml_touch_nodes (namelist_info *nl)
kono
parents:
diff changeset
2709 {
kono
parents:
diff changeset
2710 index_type len = strlen (nl->var_name) + 1;
kono
parents:
diff changeset
2711 int dim;
kono
parents:
diff changeset
2712 char *ext_name = xmalloc (len + 1);
kono
parents:
diff changeset
2713 memcpy (ext_name, nl->var_name, len-1);
kono
parents:
diff changeset
2714 memcpy (ext_name + len - 1, "%", 2);
kono
parents:
diff changeset
2715 for (nl = nl->next; nl; nl = nl->next)
kono
parents:
diff changeset
2716 {
kono
parents:
diff changeset
2717 if (strncmp (nl->var_name, ext_name, len) == 0)
kono
parents:
diff changeset
2718 {
kono
parents:
diff changeset
2719 nl->touched = 1;
kono
parents:
diff changeset
2720 for (dim=0; dim < nl->var_rank; dim++)
kono
parents:
diff changeset
2721 {
kono
parents:
diff changeset
2722 nl->ls[dim].step = 1;
kono
parents:
diff changeset
2723 nl->ls[dim].end = GFC_DESCRIPTOR_UBOUND(nl,dim);
kono
parents:
diff changeset
2724 nl->ls[dim].start = GFC_DESCRIPTOR_LBOUND(nl,dim);
kono
parents:
diff changeset
2725 nl->ls[dim].idx = nl->ls[dim].start;
kono
parents:
diff changeset
2726 }
kono
parents:
diff changeset
2727 }
kono
parents:
diff changeset
2728 else
kono
parents:
diff changeset
2729 break;
kono
parents:
diff changeset
2730 }
kono
parents:
diff changeset
2731 free (ext_name);
kono
parents:
diff changeset
2732 return;
kono
parents:
diff changeset
2733 }
kono
parents:
diff changeset
2734
kono
parents:
diff changeset
2735 /* Resets touched for the entire list of nml_nodes, ready for a
kono
parents:
diff changeset
2736 new object. */
kono
parents:
diff changeset
2737
kono
parents:
diff changeset
2738 static void
kono
parents:
diff changeset
2739 nml_untouch_nodes (st_parameter_dt *dtp)
kono
parents:
diff changeset
2740 {
kono
parents:
diff changeset
2741 namelist_info *t;
kono
parents:
diff changeset
2742 for (t = dtp->u.p.ionml; t; t = t->next)
kono
parents:
diff changeset
2743 t->touched = 0;
kono
parents:
diff changeset
2744 return;
kono
parents:
diff changeset
2745 }
kono
parents:
diff changeset
2746
kono
parents:
diff changeset
2747 /* Attempts to input name to namelist name. Returns
kono
parents:
diff changeset
2748 dtp->u.p.nml_read_error = 1 on no match. */
kono
parents:
diff changeset
2749
kono
parents:
diff changeset
2750 static void
kono
parents:
diff changeset
2751 nml_match_name (st_parameter_dt *dtp, const char *name, index_type len)
kono
parents:
diff changeset
2752 {
kono
parents:
diff changeset
2753 index_type i;
kono
parents:
diff changeset
2754 int c;
kono
parents:
diff changeset
2755
kono
parents:
diff changeset
2756 dtp->u.p.nml_read_error = 0;
kono
parents:
diff changeset
2757 for (i = 0; i < len; i++)
kono
parents:
diff changeset
2758 {
kono
parents:
diff changeset
2759 c = next_char (dtp);
kono
parents:
diff changeset
2760 if (c == EOF || (tolower (c) != tolower (name[i])))
kono
parents:
diff changeset
2761 {
kono
parents:
diff changeset
2762 dtp->u.p.nml_read_error = 1;
kono
parents:
diff changeset
2763 break;
kono
parents:
diff changeset
2764 }
kono
parents:
diff changeset
2765 }
kono
parents:
diff changeset
2766 }
kono
parents:
diff changeset
2767
kono
parents:
diff changeset
2768 /* If the namelist read is from stdin, output the current state of the
kono
parents:
diff changeset
2769 namelist to stdout. This is used to implement the non-standard query
kono
parents:
diff changeset
2770 features, ? and =?. If c == '=' the full namelist is printed. Otherwise
kono
parents:
diff changeset
2771 the names alone are printed. */
kono
parents:
diff changeset
2772
kono
parents:
diff changeset
2773 static void
kono
parents:
diff changeset
2774 nml_query (st_parameter_dt *dtp, char c)
kono
parents:
diff changeset
2775 {
kono
parents:
diff changeset
2776 gfc_unit *temp_unit;
kono
parents:
diff changeset
2777 namelist_info *nl;
kono
parents:
diff changeset
2778 index_type len;
kono
parents:
diff changeset
2779 char *p;
kono
parents:
diff changeset
2780 #ifdef HAVE_CRLF
kono
parents:
diff changeset
2781 static const index_type endlen = 2;
kono
parents:
diff changeset
2782 static const char endl[] = "\r\n";
kono
parents:
diff changeset
2783 static const char nmlend[] = "&end\r\n";
kono
parents:
diff changeset
2784 #else
kono
parents:
diff changeset
2785 static const index_type endlen = 1;
kono
parents:
diff changeset
2786 static const char endl[] = "\n";
kono
parents:
diff changeset
2787 static const char nmlend[] = "&end\n";
kono
parents:
diff changeset
2788 #endif
kono
parents:
diff changeset
2789
kono
parents:
diff changeset
2790 if (dtp->u.p.current_unit->unit_number != options.stdin_unit)
kono
parents:
diff changeset
2791 return;
kono
parents:
diff changeset
2792
kono
parents:
diff changeset
2793 /* Store the current unit and transfer to stdout. */
kono
parents:
diff changeset
2794
kono
parents:
diff changeset
2795 temp_unit = dtp->u.p.current_unit;
kono
parents:
diff changeset
2796 dtp->u.p.current_unit = find_unit (options.stdout_unit);
kono
parents:
diff changeset
2797
kono
parents:
diff changeset
2798 if (dtp->u.p.current_unit)
kono
parents:
diff changeset
2799 {
kono
parents:
diff changeset
2800 dtp->u.p.mode = WRITING;
kono
parents:
diff changeset
2801 next_record (dtp, 0);
kono
parents:
diff changeset
2802
kono
parents:
diff changeset
2803 /* Write the namelist in its entirety. */
kono
parents:
diff changeset
2804
kono
parents:
diff changeset
2805 if (c == '=')
kono
parents:
diff changeset
2806 namelist_write (dtp);
kono
parents:
diff changeset
2807
kono
parents:
diff changeset
2808 /* Or write the list of names. */
kono
parents:
diff changeset
2809
kono
parents:
diff changeset
2810 else
kono
parents:
diff changeset
2811 {
kono
parents:
diff changeset
2812 /* "&namelist_name\n" */
kono
parents:
diff changeset
2813
kono
parents:
diff changeset
2814 len = dtp->namelist_name_len;
kono
parents:
diff changeset
2815 p = write_block (dtp, len - 1 + endlen);
kono
parents:
diff changeset
2816 if (!p)
kono
parents:
diff changeset
2817 goto query_return;
kono
parents:
diff changeset
2818 memcpy (p, "&", 1);
kono
parents:
diff changeset
2819 memcpy ((char*)(p + 1), dtp->namelist_name, len);
kono
parents:
diff changeset
2820 memcpy ((char*)(p + len + 1), &endl, endlen);
kono
parents:
diff changeset
2821 for (nl = dtp->u.p.ionml; nl; nl = nl->next)
kono
parents:
diff changeset
2822 {
kono
parents:
diff changeset
2823 /* " var_name\n" */
kono
parents:
diff changeset
2824
kono
parents:
diff changeset
2825 len = strlen (nl->var_name);
kono
parents:
diff changeset
2826 p = write_block (dtp, len + endlen);
kono
parents:
diff changeset
2827 if (!p)
kono
parents:
diff changeset
2828 goto query_return;
kono
parents:
diff changeset
2829 memcpy (p, " ", 1);
kono
parents:
diff changeset
2830 memcpy ((char*)(p + 1), nl->var_name, len);
kono
parents:
diff changeset
2831 memcpy ((char*)(p + len + 1), &endl, endlen);
kono
parents:
diff changeset
2832 }
kono
parents:
diff changeset
2833
kono
parents:
diff changeset
2834 /* "&end\n" */
kono
parents:
diff changeset
2835
kono
parents:
diff changeset
2836 p = write_block (dtp, endlen + 4);
kono
parents:
diff changeset
2837 if (!p)
kono
parents:
diff changeset
2838 goto query_return;
kono
parents:
diff changeset
2839 memcpy (p, &nmlend, endlen + 4);
kono
parents:
diff changeset
2840 }
kono
parents:
diff changeset
2841
kono
parents:
diff changeset
2842 /* Flush the stream to force immediate output. */
kono
parents:
diff changeset
2843
kono
parents:
diff changeset
2844 fbuf_flush (dtp->u.p.current_unit, WRITING);
kono
parents:
diff changeset
2845 sflush (dtp->u.p.current_unit->s);
kono
parents:
diff changeset
2846 unlock_unit (dtp->u.p.current_unit);
kono
parents:
diff changeset
2847 }
kono
parents:
diff changeset
2848
kono
parents:
diff changeset
2849 query_return:
kono
parents:
diff changeset
2850
kono
parents:
diff changeset
2851 /* Restore the current unit. */
kono
parents:
diff changeset
2852
kono
parents:
diff changeset
2853 dtp->u.p.current_unit = temp_unit;
kono
parents:
diff changeset
2854 dtp->u.p.mode = READING;
kono
parents:
diff changeset
2855 return;
kono
parents:
diff changeset
2856 }
kono
parents:
diff changeset
2857
kono
parents:
diff changeset
2858 /* Reads and stores the input for the namelist object nl. For an array,
kono
parents:
diff changeset
2859 the function loops over the ranges defined by the loop specification.
kono
parents:
diff changeset
2860 This default to all the data or to the specification from a qualifier.
kono
parents:
diff changeset
2861 nml_read_obj recursively calls itself to read derived types. It visits
kono
parents:
diff changeset
2862 all its own components but only reads data for those that were touched
kono
parents:
diff changeset
2863 when the name was parsed. If a read error is encountered, an attempt is
kono
parents:
diff changeset
2864 made to return to read a new object name because the standard allows too
kono
parents:
diff changeset
2865 little data to be available. On the other hand, too much data is an
kono
parents:
diff changeset
2866 error. */
kono
parents:
diff changeset
2867
kono
parents:
diff changeset
2868 static bool
kono
parents:
diff changeset
2869 nml_read_obj (st_parameter_dt *dtp, namelist_info *nl, index_type offset,
kono
parents:
diff changeset
2870 namelist_info **pprev_nl, char *nml_err_msg,
kono
parents:
diff changeset
2871 size_t nml_err_msg_size, index_type clow, index_type chigh)
kono
parents:
diff changeset
2872 {
kono
parents:
diff changeset
2873 namelist_info *cmp;
kono
parents:
diff changeset
2874 char *obj_name;
kono
parents:
diff changeset
2875 int nml_carry;
kono
parents:
diff changeset
2876 int len;
kono
parents:
diff changeset
2877 int dim;
kono
parents:
diff changeset
2878 index_type dlen;
kono
parents:
diff changeset
2879 index_type m;
kono
parents:
diff changeset
2880 size_t obj_name_len;
kono
parents:
diff changeset
2881 void *pdata;
kono
parents:
diff changeset
2882 gfc_class list_obj;
kono
parents:
diff changeset
2883
kono
parents:
diff changeset
2884 /* If we have encountered a previous read error or this object has not been
kono
parents:
diff changeset
2885 touched in name parsing, just return. */
kono
parents:
diff changeset
2886 if (dtp->u.p.nml_read_error || !nl->touched)
kono
parents:
diff changeset
2887 return true;
kono
parents:
diff changeset
2888
kono
parents:
diff changeset
2889 dtp->u.p.item_count++; /* Used in error messages. */
kono
parents:
diff changeset
2890 dtp->u.p.repeat_count = 0;
kono
parents:
diff changeset
2891 eat_spaces (dtp);
kono
parents:
diff changeset
2892
kono
parents:
diff changeset
2893 len = nl->len;
kono
parents:
diff changeset
2894 switch (nl->type)
kono
parents:
diff changeset
2895 {
kono
parents:
diff changeset
2896 case BT_INTEGER:
kono
parents:
diff changeset
2897 case BT_LOGICAL:
kono
parents:
diff changeset
2898 dlen = len;
kono
parents:
diff changeset
2899 break;
kono
parents:
diff changeset
2900
kono
parents:
diff changeset
2901 case BT_REAL:
kono
parents:
diff changeset
2902 dlen = size_from_real_kind (len);
kono
parents:
diff changeset
2903 break;
kono
parents:
diff changeset
2904
kono
parents:
diff changeset
2905 case BT_COMPLEX:
kono
parents:
diff changeset
2906 dlen = size_from_complex_kind (len);
kono
parents:
diff changeset
2907 break;
kono
parents:
diff changeset
2908
kono
parents:
diff changeset
2909 case BT_CHARACTER:
kono
parents:
diff changeset
2910 dlen = chigh ? (chigh - clow + 1) : nl->string_length;
kono
parents:
diff changeset
2911 break;
kono
parents:
diff changeset
2912
kono
parents:
diff changeset
2913 default:
kono
parents:
diff changeset
2914 dlen = 0;
kono
parents:
diff changeset
2915 }
kono
parents:
diff changeset
2916
kono
parents:
diff changeset
2917 do
kono
parents:
diff changeset
2918 {
kono
parents:
diff changeset
2919 /* Update the pointer to the data, using the current index vector */
kono
parents:
diff changeset
2920
kono
parents:
diff changeset
2921 if ((nl->type == BT_DERIVED || nl->type == BT_CLASS)
kono
parents:
diff changeset
2922 && nl->dtio_sub != NULL)
kono
parents:
diff changeset
2923 {
kono
parents:
diff changeset
2924 pdata = NULL; /* Not used under these conidtions. */
kono
parents:
diff changeset
2925 if (nl->type == BT_CLASS)
kono
parents:
diff changeset
2926 list_obj.data = ((gfc_class*)nl->mem_pos)->data;
kono
parents:
diff changeset
2927 else
kono
parents:
diff changeset
2928 list_obj.data = (void *)nl->mem_pos;
kono
parents:
diff changeset
2929
kono
parents:
diff changeset
2930 for (dim = 0; dim < nl->var_rank; dim++)
kono
parents:
diff changeset
2931 list_obj.data = list_obj.data + (nl->ls[dim].idx
kono
parents:
diff changeset
2932 - GFC_DESCRIPTOR_LBOUND(nl,dim))
kono
parents:
diff changeset
2933 * GFC_DESCRIPTOR_STRIDE(nl,dim) * nl->size;
kono
parents:
diff changeset
2934 }
kono
parents:
diff changeset
2935 else
kono
parents:
diff changeset
2936 {
kono
parents:
diff changeset
2937 pdata = (void*)(nl->mem_pos + offset);
kono
parents:
diff changeset
2938 for (dim = 0; dim < nl->var_rank; dim++)
kono
parents:
diff changeset
2939 pdata = (void*)(pdata + (nl->ls[dim].idx
kono
parents:
diff changeset
2940 - GFC_DESCRIPTOR_LBOUND(nl,dim))
kono
parents:
diff changeset
2941 * GFC_DESCRIPTOR_STRIDE(nl,dim) * nl->size);
kono
parents:
diff changeset
2942 }
kono
parents:
diff changeset
2943
kono
parents:
diff changeset
2944 /* If we are finished with the repeat count, try to read next value. */
kono
parents:
diff changeset
2945
kono
parents:
diff changeset
2946 nml_carry = 0;
kono
parents:
diff changeset
2947 if (--dtp->u.p.repeat_count <= 0)
kono
parents:
diff changeset
2948 {
kono
parents:
diff changeset
2949 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
2950 return true;
kono
parents:
diff changeset
2951 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
2952 finish_separator (dtp);
kono
parents:
diff changeset
2953 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
2954 return true;
kono
parents:
diff changeset
2955
kono
parents:
diff changeset
2956 dtp->u.p.saved_type = BT_UNKNOWN;
kono
parents:
diff changeset
2957 free_saved (dtp);
kono
parents:
diff changeset
2958
kono
parents:
diff changeset
2959 switch (nl->type)
kono
parents:
diff changeset
2960 {
kono
parents:
diff changeset
2961 case BT_INTEGER:
kono
parents:
diff changeset
2962 read_integer (dtp, len);
kono
parents:
diff changeset
2963 break;
kono
parents:
diff changeset
2964
kono
parents:
diff changeset
2965 case BT_LOGICAL:
kono
parents:
diff changeset
2966 read_logical (dtp, len);
kono
parents:
diff changeset
2967 break;
kono
parents:
diff changeset
2968
kono
parents:
diff changeset
2969 case BT_CHARACTER:
kono
parents:
diff changeset
2970 read_character (dtp, len);
kono
parents:
diff changeset
2971 break;
kono
parents:
diff changeset
2972
kono
parents:
diff changeset
2973 case BT_REAL:
kono
parents:
diff changeset
2974 /* Need to copy data back from the real location to the temp in
kono
parents:
diff changeset
2975 order to handle nml reads into arrays. */
kono
parents:
diff changeset
2976 read_real (dtp, pdata, len);
kono
parents:
diff changeset
2977 memcpy (dtp->u.p.value, pdata, dlen);
kono
parents:
diff changeset
2978 break;
kono
parents:
diff changeset
2979
kono
parents:
diff changeset
2980 case BT_COMPLEX:
kono
parents:
diff changeset
2981 /* Same as for REAL, copy back to temp. */
kono
parents:
diff changeset
2982 read_complex (dtp, pdata, len, dlen);
kono
parents:
diff changeset
2983 memcpy (dtp->u.p.value, pdata, dlen);
kono
parents:
diff changeset
2984 break;
kono
parents:
diff changeset
2985
kono
parents:
diff changeset
2986 case BT_DERIVED:
kono
parents:
diff changeset
2987 case BT_CLASS:
kono
parents:
diff changeset
2988 /* If this object has a User Defined procedure, call it. */
kono
parents:
diff changeset
2989 if (nl->dtio_sub != NULL)
kono
parents:
diff changeset
2990 {
kono
parents:
diff changeset
2991 int unit = dtp->u.p.current_unit->unit_number;
kono
parents:
diff changeset
2992 char iotype[] = "NAMELIST";
kono
parents:
diff changeset
2993 gfc_charlen_type iotype_len = 8;
kono
parents:
diff changeset
2994 char tmp_iomsg[IOMSG_LEN] = "";
kono
parents:
diff changeset
2995 char *child_iomsg;
kono
parents:
diff changeset
2996 gfc_charlen_type child_iomsg_len;
kono
parents:
diff changeset
2997 int noiostat;
kono
parents:
diff changeset
2998 int *child_iostat = NULL;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2999 gfc_full_array_i4 vlist;
111
kono
parents:
diff changeset
3000 formatted_dtio dtio_ptr = (formatted_dtio)nl->dtio_sub;
kono
parents:
diff changeset
3001
kono
parents:
diff changeset
3002 GFC_DESCRIPTOR_DATA(&vlist) = NULL;
kono
parents:
diff changeset
3003 GFC_DIMENSION_SET(vlist.dim[0],1, 0, 0);
kono
parents:
diff changeset
3004
kono
parents:
diff changeset
3005 list_obj.vptr = nl->vtable;
kono
parents:
diff changeset
3006 list_obj.len = 0;
kono
parents:
diff changeset
3007
kono
parents:
diff changeset
3008 /* Set iostat, intent(out). */
kono
parents:
diff changeset
3009 noiostat = 0;
kono
parents:
diff changeset
3010 child_iostat = (dtp->common.flags & IOPARM_HAS_IOSTAT) ?
kono
parents:
diff changeset
3011 dtp->common.iostat : &noiostat;
kono
parents:
diff changeset
3012
kono
parents:
diff changeset
3013 /* Set iomsg, intent(inout). */
kono
parents:
diff changeset
3014 if (dtp->common.flags & IOPARM_HAS_IOMSG)
kono
parents:
diff changeset
3015 {
kono
parents:
diff changeset
3016 child_iomsg = dtp->common.iomsg;
kono
parents:
diff changeset
3017 child_iomsg_len = dtp->common.iomsg_len;
kono
parents:
diff changeset
3018 }
kono
parents:
diff changeset
3019 else
kono
parents:
diff changeset
3020 {
kono
parents:
diff changeset
3021 child_iomsg = tmp_iomsg;
kono
parents:
diff changeset
3022 child_iomsg_len = IOMSG_LEN;
kono
parents:
diff changeset
3023 }
kono
parents:
diff changeset
3024
kono
parents:
diff changeset
3025 /* Call the user defined formatted READ procedure. */
kono
parents:
diff changeset
3026 dtp->u.p.current_unit->child_dtio++;
kono
parents:
diff changeset
3027 dtio_ptr ((void *)&list_obj, &unit, iotype, &vlist,
kono
parents:
diff changeset
3028 child_iostat, child_iomsg,
kono
parents:
diff changeset
3029 iotype_len, child_iomsg_len);
kono
parents:
diff changeset
3030 dtp->u.p.child_saved_iostat = *child_iostat;
kono
parents:
diff changeset
3031 dtp->u.p.current_unit->child_dtio--;
kono
parents:
diff changeset
3032 goto incr_idx;
kono
parents:
diff changeset
3033 }
kono
parents:
diff changeset
3034
kono
parents:
diff changeset
3035 /* Must be default derived type namelist read. */
kono
parents:
diff changeset
3036 obj_name_len = strlen (nl->var_name) + 1;
kono
parents:
diff changeset
3037 obj_name = xmalloc (obj_name_len+1);
kono
parents:
diff changeset
3038 memcpy (obj_name, nl->var_name, obj_name_len-1);
kono
parents:
diff changeset
3039 memcpy (obj_name + obj_name_len - 1, "%", 2);
kono
parents:
diff changeset
3040
kono
parents:
diff changeset
3041 /* If reading a derived type, disable the expanded read warning
kono
parents:
diff changeset
3042 since a single object can have multiple reads. */
kono
parents:
diff changeset
3043 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
3044
kono
parents:
diff changeset
3045 /* Now loop over the components. */
kono
parents:
diff changeset
3046
kono
parents:
diff changeset
3047 for (cmp = nl->next;
kono
parents:
diff changeset
3048 cmp &&
kono
parents:
diff changeset
3049 !strncmp (cmp->var_name, obj_name, obj_name_len);
kono
parents:
diff changeset
3050 cmp = cmp->next)
kono
parents:
diff changeset
3051 {
kono
parents:
diff changeset
3052 /* Jump over nested derived type by testing if the potential
kono
parents:
diff changeset
3053 component name contains '%'. */
kono
parents:
diff changeset
3054 if (strchr (cmp->var_name + obj_name_len, '%'))
kono
parents:
diff changeset
3055 continue;
kono
parents:
diff changeset
3056
kono
parents:
diff changeset
3057 if (!nml_read_obj (dtp, cmp, (index_type)(pdata - nl->mem_pos),
kono
parents:
diff changeset
3058 pprev_nl, nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3059 clow, chigh))
kono
parents:
diff changeset
3060 {
kono
parents:
diff changeset
3061 free (obj_name);
kono
parents:
diff changeset
3062 return false;
kono
parents:
diff changeset
3063 }
kono
parents:
diff changeset
3064
kono
parents:
diff changeset
3065 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
3066 {
kono
parents:
diff changeset
3067 free (obj_name);
kono
parents:
diff changeset
3068 return true;
kono
parents:
diff changeset
3069 }
kono
parents:
diff changeset
3070 }
kono
parents:
diff changeset
3071
kono
parents:
diff changeset
3072 free (obj_name);
kono
parents:
diff changeset
3073 goto incr_idx;
kono
parents:
diff changeset
3074
kono
parents:
diff changeset
3075 default:
kono
parents:
diff changeset
3076 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3077 "Bad type for namelist object %s", nl->var_name);
kono
parents:
diff changeset
3078 internal_error (&dtp->common, nml_err_msg);
kono
parents:
diff changeset
3079 goto nml_err_ret;
kono
parents:
diff changeset
3080 }
kono
parents:
diff changeset
3081 }
kono
parents:
diff changeset
3082
kono
parents:
diff changeset
3083 /* The standard permits array data to stop short of the number of
kono
parents:
diff changeset
3084 elements specified in the loop specification. In this case, we
kono
parents:
diff changeset
3085 should be here with dtp->u.p.nml_read_error != 0. Control returns to
kono
parents:
diff changeset
3086 nml_get_obj_data and an attempt is made to read object name. */
kono
parents:
diff changeset
3087
kono
parents:
diff changeset
3088 *pprev_nl = nl;
kono
parents:
diff changeset
3089 if (dtp->u.p.nml_read_error)
kono
parents:
diff changeset
3090 {
kono
parents:
diff changeset
3091 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
3092 return true;
kono
parents:
diff changeset
3093 }
kono
parents:
diff changeset
3094
kono
parents:
diff changeset
3095 if (dtp->u.p.saved_type == BT_UNKNOWN)
kono
parents:
diff changeset
3096 {
kono
parents:
diff changeset
3097 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
3098 goto incr_idx;
kono
parents:
diff changeset
3099 }
kono
parents:
diff changeset
3100
kono
parents:
diff changeset
3101 switch (dtp->u.p.saved_type)
kono
parents:
diff changeset
3102 {
kono
parents:
diff changeset
3103
kono
parents:
diff changeset
3104 case BT_COMPLEX:
kono
parents:
diff changeset
3105 case BT_REAL:
kono
parents:
diff changeset
3106 case BT_INTEGER:
kono
parents:
diff changeset
3107 case BT_LOGICAL:
kono
parents:
diff changeset
3108 memcpy (pdata, dtp->u.p.value, dlen);
kono
parents:
diff changeset
3109 break;
kono
parents:
diff changeset
3110
kono
parents:
diff changeset
3111 case BT_CHARACTER:
kono
parents:
diff changeset
3112 if (dlen < dtp->u.p.saved_used)
kono
parents:
diff changeset
3113 {
kono
parents:
diff changeset
3114 if (compile_options.bounds_check)
kono
parents:
diff changeset
3115 {
kono
parents:
diff changeset
3116 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3117 "Namelist object '%s' truncated on read.",
kono
parents:
diff changeset
3118 nl->var_name);
kono
parents:
diff changeset
3119 generate_warning (&dtp->common, nml_err_msg);
kono
parents:
diff changeset
3120 }
kono
parents:
diff changeset
3121 m = dlen;
kono
parents:
diff changeset
3122 }
kono
parents:
diff changeset
3123 else
kono
parents:
diff changeset
3124 m = dtp->u.p.saved_used;
kono
parents:
diff changeset
3125
kono
parents:
diff changeset
3126 if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
kono
parents:
diff changeset
3127 {
kono
parents:
diff changeset
3128 gfc_char4_t *q4, *p4 = pdata;
kono
parents:
diff changeset
3129 int i;
kono
parents:
diff changeset
3130
kono
parents:
diff changeset
3131 q4 = (gfc_char4_t *) dtp->u.p.saved_string;
kono
parents:
diff changeset
3132 p4 += clow -1;
kono
parents:
diff changeset
3133 for (i = 0; i < m; i++)
kono
parents:
diff changeset
3134 *p4++ = *q4++;
kono
parents:
diff changeset
3135 if (m < dlen)
kono
parents:
diff changeset
3136 for (i = 0; i < dlen - m; i++)
kono
parents:
diff changeset
3137 *p4++ = (gfc_char4_t) ' ';
kono
parents:
diff changeset
3138 }
kono
parents:
diff changeset
3139 else
kono
parents:
diff changeset
3140 {
kono
parents:
diff changeset
3141 pdata = (void*)( pdata + clow - 1 );
kono
parents:
diff changeset
3142 memcpy (pdata, dtp->u.p.saved_string, m);
kono
parents:
diff changeset
3143 if (m < dlen)
kono
parents:
diff changeset
3144 memset ((void*)( pdata + m ), ' ', dlen - m);
kono
parents:
diff changeset
3145 }
kono
parents:
diff changeset
3146 break;
kono
parents:
diff changeset
3147
kono
parents:
diff changeset
3148 default:
kono
parents:
diff changeset
3149 break;
kono
parents:
diff changeset
3150 }
kono
parents:
diff changeset
3151
kono
parents:
diff changeset
3152 /* Warn if a non-standard expanded read occurs. A single read of a
kono
parents:
diff changeset
3153 single object is acceptable. If a second read occurs, issue a warning
kono
parents:
diff changeset
3154 and set the flag to zero to prevent further warnings. */
kono
parents:
diff changeset
3155 if (dtp->u.p.expanded_read == 2)
kono
parents:
diff changeset
3156 {
kono
parents:
diff changeset
3157 notify_std (&dtp->common, GFC_STD_GNU, "Non-standard expanded namelist read.");
kono
parents:
diff changeset
3158 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
3159 }
kono
parents:
diff changeset
3160
kono
parents:
diff changeset
3161 /* If the expanded read warning flag is set, increment it,
kono
parents:
diff changeset
3162 indicating that a single read has occurred. */
kono
parents:
diff changeset
3163 if (dtp->u.p.expanded_read >= 1)
kono
parents:
diff changeset
3164 dtp->u.p.expanded_read++;
kono
parents:
diff changeset
3165
kono
parents:
diff changeset
3166 /* Break out of loop if scalar. */
kono
parents:
diff changeset
3167 if (!nl->var_rank)
kono
parents:
diff changeset
3168 break;
kono
parents:
diff changeset
3169
kono
parents:
diff changeset
3170 /* Now increment the index vector. */
kono
parents:
diff changeset
3171
kono
parents:
diff changeset
3172 incr_idx:
kono
parents:
diff changeset
3173
kono
parents:
diff changeset
3174 nml_carry = 1;
kono
parents:
diff changeset
3175 for (dim = 0; dim < nl->var_rank; dim++)
kono
parents:
diff changeset
3176 {
kono
parents:
diff changeset
3177 nl->ls[dim].idx += nml_carry * nl->ls[dim].step;
kono
parents:
diff changeset
3178 nml_carry = 0;
kono
parents:
diff changeset
3179 if (((nl->ls[dim].step > 0) && (nl->ls[dim].idx > nl->ls[dim].end))
kono
parents:
diff changeset
3180 ||
kono
parents:
diff changeset
3181 ((nl->ls[dim].step < 0) && (nl->ls[dim].idx < nl->ls[dim].end)))
kono
parents:
diff changeset
3182 {
kono
parents:
diff changeset
3183 nl->ls[dim].idx = nl->ls[dim].start;
kono
parents:
diff changeset
3184 nml_carry = 1;
kono
parents:
diff changeset
3185 }
kono
parents:
diff changeset
3186 }
kono
parents:
diff changeset
3187 } while (!nml_carry);
kono
parents:
diff changeset
3188
kono
parents:
diff changeset
3189 if (dtp->u.p.repeat_count > 1)
kono
parents:
diff changeset
3190 {
kono
parents:
diff changeset
3191 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3192 "Repeat count too large for namelist object %s", nl->var_name);
kono
parents:
diff changeset
3193 goto nml_err_ret;
kono
parents:
diff changeset
3194 }
kono
parents:
diff changeset
3195 return true;
kono
parents:
diff changeset
3196
kono
parents:
diff changeset
3197 nml_err_ret:
kono
parents:
diff changeset
3198
kono
parents:
diff changeset
3199 return false;
kono
parents:
diff changeset
3200 }
kono
parents:
diff changeset
3201
kono
parents:
diff changeset
3202 /* Parses the object name, including array and substring qualifiers. It
kono
parents:
diff changeset
3203 iterates over derived type components, touching those components and
kono
parents:
diff changeset
3204 setting their loop specifications, if there is a qualifier. If the
kono
parents:
diff changeset
3205 object is itself a derived type, its components and subcomponents are
kono
parents:
diff changeset
3206 touched. nml_read_obj is called at the end and this reads the data in
kono
parents:
diff changeset
3207 the manner specified by the object name. */
kono
parents:
diff changeset
3208
kono
parents:
diff changeset
3209 static bool
kono
parents:
diff changeset
3210 nml_get_obj_data (st_parameter_dt *dtp, namelist_info **pprev_nl,
kono
parents:
diff changeset
3211 char *nml_err_msg, size_t nml_err_msg_size)
kono
parents:
diff changeset
3212 {
kono
parents:
diff changeset
3213 int c;
kono
parents:
diff changeset
3214 namelist_info *nl;
kono
parents:
diff changeset
3215 namelist_info *first_nl = NULL;
kono
parents:
diff changeset
3216 namelist_info *root_nl = NULL;
kono
parents:
diff changeset
3217 int dim, parsed_rank;
kono
parents:
diff changeset
3218 int component_flag, qualifier_flag;
kono
parents:
diff changeset
3219 index_type clow, chigh;
kono
parents:
diff changeset
3220 int non_zero_rank_count;
kono
parents:
diff changeset
3221
kono
parents:
diff changeset
3222 /* Look for end of input or object name. If '?' or '=?' are encountered
kono
parents:
diff changeset
3223 in stdin, print the node names or the namelist to stdout. */
kono
parents:
diff changeset
3224
kono
parents:
diff changeset
3225 eat_separator (dtp);
kono
parents:
diff changeset
3226 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
3227 return true;
kono
parents:
diff changeset
3228
kono
parents:
diff changeset
3229 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
3230 finish_separator (dtp);
kono
parents:
diff changeset
3231 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
3232 return true;
kono
parents:
diff changeset
3233
kono
parents:
diff changeset
3234 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3235 goto nml_err_ret;
kono
parents:
diff changeset
3236 switch (c)
kono
parents:
diff changeset
3237 {
kono
parents:
diff changeset
3238 case '=':
kono
parents:
diff changeset
3239 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3240 goto nml_err_ret;
kono
parents:
diff changeset
3241 if (c != '?')
kono
parents:
diff changeset
3242 {
kono
parents:
diff changeset
3243 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3244 "namelist read: misplaced = sign");
kono
parents:
diff changeset
3245 goto nml_err_ret;
kono
parents:
diff changeset
3246 }
kono
parents:
diff changeset
3247 nml_query (dtp, '=');
kono
parents:
diff changeset
3248 return true;
kono
parents:
diff changeset
3249
kono
parents:
diff changeset
3250 case '?':
kono
parents:
diff changeset
3251 nml_query (dtp, '?');
kono
parents:
diff changeset
3252 return true;
kono
parents:
diff changeset
3253
kono
parents:
diff changeset
3254 case '$':
kono
parents:
diff changeset
3255 case '&':
kono
parents:
diff changeset
3256 nml_match_name (dtp, "end", 3);
kono
parents:
diff changeset
3257 if (dtp->u.p.nml_read_error)
kono
parents:
diff changeset
3258 {
kono
parents:
diff changeset
3259 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3260 "namelist not terminated with / or &end");
kono
parents:
diff changeset
3261 goto nml_err_ret;
kono
parents:
diff changeset
3262 }
kono
parents:
diff changeset
3263 /* Fall through. */
kono
parents:
diff changeset
3264 case '/':
kono
parents:
diff changeset
3265 dtp->u.p.input_complete = 1;
kono
parents:
diff changeset
3266 return true;
kono
parents:
diff changeset
3267
kono
parents:
diff changeset
3268 default :
kono
parents:
diff changeset
3269 break;
kono
parents:
diff changeset
3270 }
kono
parents:
diff changeset
3271
kono
parents:
diff changeset
3272 /* Untouch all nodes of the namelist and reset the flags that are set for
kono
parents:
diff changeset
3273 derived type components. */
kono
parents:
diff changeset
3274
kono
parents:
diff changeset
3275 nml_untouch_nodes (dtp);
kono
parents:
diff changeset
3276 component_flag = 0;
kono
parents:
diff changeset
3277 qualifier_flag = 0;
kono
parents:
diff changeset
3278 non_zero_rank_count = 0;
kono
parents:
diff changeset
3279
kono
parents:
diff changeset
3280 /* Get the object name - should '!' and '\n' be permitted separators? */
kono
parents:
diff changeset
3281
kono
parents:
diff changeset
3282 get_name:
kono
parents:
diff changeset
3283
kono
parents:
diff changeset
3284 free_saved (dtp);
kono
parents:
diff changeset
3285
kono
parents:
diff changeset
3286 do
kono
parents:
diff changeset
3287 {
kono
parents:
diff changeset
3288 if (!is_separator (c))
kono
parents:
diff changeset
3289 push_char_default (dtp, tolower(c));
kono
parents:
diff changeset
3290 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3291 goto nml_err_ret;
kono
parents:
diff changeset
3292 }
kono
parents:
diff changeset
3293 while (!( c=='=' || c==' ' || c=='\t' || c =='(' || c =='%' ));
kono
parents:
diff changeset
3294
kono
parents:
diff changeset
3295 unget_char (dtp, c);
kono
parents:
diff changeset
3296
kono
parents:
diff changeset
3297 /* Check that the name is in the namelist and get pointer to object.
kono
parents:
diff changeset
3298 Three error conditions exist: (i) An attempt is being made to
kono
parents:
diff changeset
3299 identify a non-existent object, following a failed data read or
kono
parents:
diff changeset
3300 (ii) The object name does not exist or (iii) Too many data items
kono
parents:
diff changeset
3301 are present for an object. (iii) gives the same error message
kono
parents:
diff changeset
3302 as (i) */
kono
parents:
diff changeset
3303
kono
parents:
diff changeset
3304 push_char_default (dtp, '\0');
kono
parents:
diff changeset
3305
kono
parents:
diff changeset
3306 if (component_flag)
kono
parents:
diff changeset
3307 {
kono
parents:
diff changeset
3308 #define EXT_STACK_SZ 100
kono
parents:
diff changeset
3309 char ext_stack[EXT_STACK_SZ];
kono
parents:
diff changeset
3310 char *ext_name;
kono
parents:
diff changeset
3311 size_t var_len = strlen (root_nl->var_name);
kono
parents:
diff changeset
3312 size_t saved_len
kono
parents:
diff changeset
3313 = dtp->u.p.saved_string ? strlen (dtp->u.p.saved_string) : 0;
kono
parents:
diff changeset
3314 size_t ext_size = var_len + saved_len + 1;
kono
parents:
diff changeset
3315
kono
parents:
diff changeset
3316 if (ext_size > EXT_STACK_SZ)
kono
parents:
diff changeset
3317 ext_name = xmalloc (ext_size);
kono
parents:
diff changeset
3318 else
kono
parents:
diff changeset
3319 ext_name = ext_stack;
kono
parents:
diff changeset
3320
kono
parents:
diff changeset
3321 memcpy (ext_name, root_nl->var_name, var_len);
kono
parents:
diff changeset
3322 if (dtp->u.p.saved_string)
kono
parents:
diff changeset
3323 memcpy (ext_name + var_len, dtp->u.p.saved_string, saved_len);
kono
parents:
diff changeset
3324 ext_name[var_len + saved_len] = '\0';
kono
parents:
diff changeset
3325 nl = find_nml_node (dtp, ext_name);
kono
parents:
diff changeset
3326
kono
parents:
diff changeset
3327 if (ext_size > EXT_STACK_SZ)
kono
parents:
diff changeset
3328 free (ext_name);
kono
parents:
diff changeset
3329 }
kono
parents:
diff changeset
3330 else
kono
parents:
diff changeset
3331 nl = find_nml_node (dtp, dtp->u.p.saved_string);
kono
parents:
diff changeset
3332
kono
parents:
diff changeset
3333 if (nl == NULL)
kono
parents:
diff changeset
3334 {
kono
parents:
diff changeset
3335 if (dtp->u.p.nml_read_error && *pprev_nl)
kono
parents:
diff changeset
3336 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3337 "Bad data for namelist object %s", (*pprev_nl)->var_name);
kono
parents:
diff changeset
3338
kono
parents:
diff changeset
3339 else
kono
parents:
diff changeset
3340 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3341 "Cannot match namelist object name %s",
kono
parents:
diff changeset
3342 dtp->u.p.saved_string);
kono
parents:
diff changeset
3343
kono
parents:
diff changeset
3344 goto nml_err_ret;
kono
parents:
diff changeset
3345 }
kono
parents:
diff changeset
3346
kono
parents:
diff changeset
3347 /* Get the length, data length, base pointer and rank of the variable.
kono
parents:
diff changeset
3348 Set the default loop specification first. */
kono
parents:
diff changeset
3349
kono
parents:
diff changeset
3350 for (dim=0; dim < nl->var_rank; dim++)
kono
parents:
diff changeset
3351 {
kono
parents:
diff changeset
3352 nl->ls[dim].step = 1;
kono
parents:
diff changeset
3353 nl->ls[dim].end = GFC_DESCRIPTOR_UBOUND(nl,dim);
kono
parents:
diff changeset
3354 nl->ls[dim].start = GFC_DESCRIPTOR_LBOUND(nl,dim);
kono
parents:
diff changeset
3355 nl->ls[dim].idx = nl->ls[dim].start;
kono
parents:
diff changeset
3356 }
kono
parents:
diff changeset
3357
kono
parents:
diff changeset
3358 /* Check to see if there is a qualifier: if so, parse it.*/
kono
parents:
diff changeset
3359
kono
parents:
diff changeset
3360 if (c == '(' && nl->var_rank)
kono
parents:
diff changeset
3361 {
kono
parents:
diff changeset
3362 parsed_rank = 0;
kono
parents:
diff changeset
3363 if (!nml_parse_qualifier (dtp, nl->dim, nl->ls, nl->var_rank,
kono
parents:
diff changeset
3364 nl->type, nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3365 &parsed_rank))
kono
parents:
diff changeset
3366 {
kono
parents:
diff changeset
3367 char *nml_err_msg_end = strchr (nml_err_msg, '\0');
kono
parents:
diff changeset
3368 snprintf (nml_err_msg_end,
kono
parents:
diff changeset
3369 nml_err_msg_size - (nml_err_msg_end - nml_err_msg),
kono
parents:
diff changeset
3370 " for namelist variable %s", nl->var_name);
kono
parents:
diff changeset
3371 goto nml_err_ret;
kono
parents:
diff changeset
3372 }
kono
parents:
diff changeset
3373 if (parsed_rank > 0)
kono
parents:
diff changeset
3374 non_zero_rank_count++;
kono
parents:
diff changeset
3375
kono
parents:
diff changeset
3376 qualifier_flag = 1;
kono
parents:
diff changeset
3377
kono
parents:
diff changeset
3378 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3379 goto nml_err_ret;
kono
parents:
diff changeset
3380 unget_char (dtp, c);
kono
parents:
diff changeset
3381 }
kono
parents:
diff changeset
3382 else if (nl->var_rank > 0)
kono
parents:
diff changeset
3383 non_zero_rank_count++;
kono
parents:
diff changeset
3384
kono
parents:
diff changeset
3385 /* Now parse a derived type component. The root namelist_info address
kono
parents:
diff changeset
3386 is backed up, as is the previous component level. The component flag
kono
parents:
diff changeset
3387 is set and the iteration is made by jumping back to get_name. */
kono
parents:
diff changeset
3388
kono
parents:
diff changeset
3389 if (c == '%')
kono
parents:
diff changeset
3390 {
kono
parents:
diff changeset
3391 if (nl->type != BT_DERIVED)
kono
parents:
diff changeset
3392 {
kono
parents:
diff changeset
3393 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3394 "Attempt to get derived component for %s", nl->var_name);
kono
parents:
diff changeset
3395 goto nml_err_ret;
kono
parents:
diff changeset
3396 }
kono
parents:
diff changeset
3397
kono
parents:
diff changeset
3398 /* Don't move first_nl further in the list if a qualifier was found. */
kono
parents:
diff changeset
3399 if ((*pprev_nl == NULL && !qualifier_flag) || !component_flag)
kono
parents:
diff changeset
3400 first_nl = nl;
kono
parents:
diff changeset
3401
kono
parents:
diff changeset
3402 root_nl = nl;
kono
parents:
diff changeset
3403
kono
parents:
diff changeset
3404 component_flag = 1;
kono
parents:
diff changeset
3405 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3406 goto nml_err_ret;
kono
parents:
diff changeset
3407 goto get_name;
kono
parents:
diff changeset
3408 }
kono
parents:
diff changeset
3409
kono
parents:
diff changeset
3410 /* Parse a character qualifier, if present. chigh = 0 is a default
kono
parents:
diff changeset
3411 that signals that the string length = string_length. */
kono
parents:
diff changeset
3412
kono
parents:
diff changeset
3413 clow = 1;
kono
parents:
diff changeset
3414 chigh = 0;
kono
parents:
diff changeset
3415
kono
parents:
diff changeset
3416 if (c == '(' && nl->type == BT_CHARACTER)
kono
parents:
diff changeset
3417 {
kono
parents:
diff changeset
3418 descriptor_dimension chd[1] = { {1, clow, nl->string_length} };
kono
parents:
diff changeset
3419 array_loop_spec ind[1] = { {1, clow, nl->string_length, 1} };
kono
parents:
diff changeset
3420
kono
parents:
diff changeset
3421 if (!nml_parse_qualifier (dtp, chd, ind, -1, nl->type,
kono
parents:
diff changeset
3422 nml_err_msg, nml_err_msg_size, &parsed_rank))
kono
parents:
diff changeset
3423 {
kono
parents:
diff changeset
3424 char *nml_err_msg_end = strchr (nml_err_msg, '\0');
kono
parents:
diff changeset
3425 snprintf (nml_err_msg_end,
kono
parents:
diff changeset
3426 nml_err_msg_size - (nml_err_msg_end - nml_err_msg),
kono
parents:
diff changeset
3427 " for namelist variable %s", nl->var_name);
kono
parents:
diff changeset
3428 goto nml_err_ret;
kono
parents:
diff changeset
3429 }
kono
parents:
diff changeset
3430
kono
parents:
diff changeset
3431 clow = ind[0].start;
kono
parents:
diff changeset
3432 chigh = ind[0].end;
kono
parents:
diff changeset
3433
kono
parents:
diff changeset
3434 if (ind[0].step != 1)
kono
parents:
diff changeset
3435 {
kono
parents:
diff changeset
3436 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3437 "Step not allowed in substring qualifier"
kono
parents:
diff changeset
3438 " for namelist object %s", nl->var_name);
kono
parents:
diff changeset
3439 goto nml_err_ret;
kono
parents:
diff changeset
3440 }
kono
parents:
diff changeset
3441
kono
parents:
diff changeset
3442 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3443 goto nml_err_ret;
kono
parents:
diff changeset
3444 unget_char (dtp, c);
kono
parents:
diff changeset
3445 }
kono
parents:
diff changeset
3446
kono
parents:
diff changeset
3447 /* Make sure no extraneous qualifiers are there. */
kono
parents:
diff changeset
3448
kono
parents:
diff changeset
3449 if (c == '(')
kono
parents:
diff changeset
3450 {
kono
parents:
diff changeset
3451 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3452 "Qualifier for a scalar or non-character namelist object %s",
kono
parents:
diff changeset
3453 nl->var_name);
kono
parents:
diff changeset
3454 goto nml_err_ret;
kono
parents:
diff changeset
3455 }
kono
parents:
diff changeset
3456
kono
parents:
diff changeset
3457 /* Make sure there is no more than one non-zero rank object. */
kono
parents:
diff changeset
3458 if (non_zero_rank_count > 1)
kono
parents:
diff changeset
3459 {
kono
parents:
diff changeset
3460 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3461 "Multiple sub-objects with non-zero rank in namelist object %s",
kono
parents:
diff changeset
3462 nl->var_name);
kono
parents:
diff changeset
3463 non_zero_rank_count = 0;
kono
parents:
diff changeset
3464 goto nml_err_ret;
kono
parents:
diff changeset
3465 }
kono
parents:
diff changeset
3466
kono
parents:
diff changeset
3467 /* According to the standard, an equal sign MUST follow an object name. The
kono
parents:
diff changeset
3468 following is possibly lax - it allows comments, blank lines and so on to
kono
parents:
diff changeset
3469 intervene. eat_spaces (dtp); c = next_char (dtp); would be compliant*/
kono
parents:
diff changeset
3470
kono
parents:
diff changeset
3471 free_saved (dtp);
kono
parents:
diff changeset
3472
kono
parents:
diff changeset
3473 eat_separator (dtp);
kono
parents:
diff changeset
3474 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
3475 return true;
kono
parents:
diff changeset
3476
kono
parents:
diff changeset
3477 if (dtp->u.p.at_eol)
kono
parents:
diff changeset
3478 finish_separator (dtp);
kono
parents:
diff changeset
3479 if (dtp->u.p.input_complete)
kono
parents:
diff changeset
3480 return true;
kono
parents:
diff changeset
3481
kono
parents:
diff changeset
3482 if ((c = next_char (dtp)) == EOF)
kono
parents:
diff changeset
3483 goto nml_err_ret;
kono
parents:
diff changeset
3484
kono
parents:
diff changeset
3485 if (c != '=')
kono
parents:
diff changeset
3486 {
kono
parents:
diff changeset
3487 snprintf (nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3488 "Equal sign must follow namelist object name %s",
kono
parents:
diff changeset
3489 nl->var_name);
kono
parents:
diff changeset
3490 goto nml_err_ret;
kono
parents:
diff changeset
3491 }
kono
parents:
diff changeset
3492
kono
parents:
diff changeset
3493 /* If a derived type, touch its components and restore the root
kono
parents:
diff changeset
3494 namelist_info if we have parsed a qualified derived type
kono
parents:
diff changeset
3495 component. */
kono
parents:
diff changeset
3496
kono
parents:
diff changeset
3497 if (nl->type == BT_DERIVED && nl->dtio_sub == NULL)
kono
parents:
diff changeset
3498 nml_touch_nodes (nl);
kono
parents:
diff changeset
3499
kono
parents:
diff changeset
3500 if (first_nl)
kono
parents:
diff changeset
3501 {
kono
parents:
diff changeset
3502 if (first_nl->var_rank == 0)
kono
parents:
diff changeset
3503 {
kono
parents:
diff changeset
3504 if (component_flag && qualifier_flag)
kono
parents:
diff changeset
3505 nl = first_nl;
kono
parents:
diff changeset
3506 }
kono
parents:
diff changeset
3507 else
kono
parents:
diff changeset
3508 nl = first_nl;
kono
parents:
diff changeset
3509 }
kono
parents:
diff changeset
3510
kono
parents:
diff changeset
3511 dtp->u.p.nml_read_error = 0;
kono
parents:
diff changeset
3512 if (!nml_read_obj (dtp, nl, 0, pprev_nl, nml_err_msg, nml_err_msg_size,
kono
parents:
diff changeset
3513 clow, chigh))
kono
parents:
diff changeset
3514 goto nml_err_ret;
kono
parents:
diff changeset
3515
kono
parents:
diff changeset
3516 return true;
kono
parents:
diff changeset
3517
kono
parents:
diff changeset
3518 nml_err_ret:
kono
parents:
diff changeset
3519
kono
parents:
diff changeset
3520 /* The EOF error message is issued by hit_eof. Return true so that the
kono
parents:
diff changeset
3521 caller does not use nml_err_msg and nml_err_msg_size to generate
kono
parents:
diff changeset
3522 an unrelated error message. */
kono
parents:
diff changeset
3523 if (c == EOF)
kono
parents:
diff changeset
3524 {
kono
parents:
diff changeset
3525 dtp->u.p.input_complete = 1;
kono
parents:
diff changeset
3526 unget_char (dtp, c);
kono
parents:
diff changeset
3527 hit_eof (dtp);
kono
parents:
diff changeset
3528 return true;
kono
parents:
diff changeset
3529 }
kono
parents:
diff changeset
3530 return false;
kono
parents:
diff changeset
3531 }
kono
parents:
diff changeset
3532
kono
parents:
diff changeset
3533 /* Entry point for namelist input. Goes through input until namelist name
kono
parents:
diff changeset
3534 is matched. Then cycles through nml_get_obj_data until the input is
kono
parents:
diff changeset
3535 completed or there is an error. */
kono
parents:
diff changeset
3536
kono
parents:
diff changeset
3537 void
kono
parents:
diff changeset
3538 namelist_read (st_parameter_dt *dtp)
kono
parents:
diff changeset
3539 {
kono
parents:
diff changeset
3540 int c;
kono
parents:
diff changeset
3541 char nml_err_msg[200];
kono
parents:
diff changeset
3542
kono
parents:
diff changeset
3543 /* Initialize the error string buffer just in case we get an unexpected fail
kono
parents:
diff changeset
3544 somewhere and end up at nml_err_ret. */
kono
parents:
diff changeset
3545 strcpy (nml_err_msg, "Internal namelist read error");
kono
parents:
diff changeset
3546
kono
parents:
diff changeset
3547 /* Pointer to the previously read object, in case attempt is made to read
kono
parents:
diff changeset
3548 new object name. Should this fail, error message can give previous
kono
parents:
diff changeset
3549 name. */
kono
parents:
diff changeset
3550 namelist_info *prev_nl = NULL;
kono
parents:
diff changeset
3551
kono
parents:
diff changeset
3552 dtp->u.p.input_complete = 0;
kono
parents:
diff changeset
3553 dtp->u.p.expanded_read = 0;
kono
parents:
diff changeset
3554
kono
parents:
diff changeset
3555 /* Set the next_char and push_char worker functions. */
kono
parents:
diff changeset
3556 set_workers (dtp);
kono
parents:
diff changeset
3557
kono
parents:
diff changeset
3558 /* Look for &namelist_name . Skip all characters, testing for $nmlname.
kono
parents:
diff changeset
3559 Exit on success or EOF. If '?' or '=?' encountered in stdin, print
kono
parents:
diff changeset
3560 node names or namelist on stdout. */
kono
parents:
diff changeset
3561
kono
parents:
diff changeset
3562 find_nml_name:
kono
parents:
diff changeset
3563 c = next_char (dtp);
kono
parents:
diff changeset
3564 switch (c)
kono
parents:
diff changeset
3565 {
kono
parents:
diff changeset
3566 case '$':
kono
parents:
diff changeset
3567 case '&':
kono
parents:
diff changeset
3568 break;
kono
parents:
diff changeset
3569
kono
parents:
diff changeset
3570 case '!':
kono
parents:
diff changeset
3571 eat_line (dtp);
kono
parents:
diff changeset
3572 goto find_nml_name;
kono
parents:
diff changeset
3573
kono
parents:
diff changeset
3574 case '=':
kono
parents:
diff changeset
3575 c = next_char (dtp);
kono
parents:
diff changeset
3576 if (c == '?')
kono
parents:
diff changeset
3577 nml_query (dtp, '=');
kono
parents:
diff changeset
3578 else
kono
parents:
diff changeset
3579 unget_char (dtp, c);
kono
parents:
diff changeset
3580 goto find_nml_name;
kono
parents:
diff changeset
3581
kono
parents:
diff changeset
3582 case '?':
kono
parents:
diff changeset
3583 nml_query (dtp, '?');
kono
parents:
diff changeset
3584 goto find_nml_name;
kono
parents:
diff changeset
3585
kono
parents:
diff changeset
3586 case EOF:
kono
parents:
diff changeset
3587 return;
kono
parents:
diff changeset
3588
kono
parents:
diff changeset
3589 default:
kono
parents:
diff changeset
3590 goto find_nml_name;
kono
parents:
diff changeset
3591 }
kono
parents:
diff changeset
3592
kono
parents:
diff changeset
3593 /* Match the name of the namelist. */
kono
parents:
diff changeset
3594
kono
parents:
diff changeset
3595 nml_match_name (dtp, dtp->namelist_name, dtp->namelist_name_len);
kono
parents:
diff changeset
3596
kono
parents:
diff changeset
3597 if (dtp->u.p.nml_read_error)
kono
parents:
diff changeset
3598 goto find_nml_name;
kono
parents:
diff changeset
3599
kono
parents:
diff changeset
3600 /* A trailing space is required, we give a little latitude here, 10.9.1. */
kono
parents:
diff changeset
3601 c = next_char (dtp);
kono
parents:
diff changeset
3602 if (!is_separator(c) && c != '!')
kono
parents:
diff changeset
3603 {
kono
parents:
diff changeset
3604 unget_char (dtp, c);
kono
parents:
diff changeset
3605 goto find_nml_name;
kono
parents:
diff changeset
3606 }
kono
parents:
diff changeset
3607
kono
parents:
diff changeset
3608 unget_char (dtp, c);
kono
parents:
diff changeset
3609 eat_separator (dtp);
kono
parents:
diff changeset
3610
kono
parents:
diff changeset
3611 /* Ready to read namelist objects. If there is an error in input
kono
parents:
diff changeset
3612 from stdin, output the error message and continue. */
kono
parents:
diff changeset
3613
kono
parents:
diff changeset
3614 while (!dtp->u.p.input_complete)
kono
parents:
diff changeset
3615 {
kono
parents:
diff changeset
3616 if (!nml_get_obj_data (dtp, &prev_nl, nml_err_msg, sizeof nml_err_msg))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3617 goto nml_err_ret;
111
kono
parents:
diff changeset
3618
kono
parents:
diff changeset
3619 /* Reset the previous namelist pointer if we know we are not going
kono
parents:
diff changeset
3620 to be doing multiple reads within a single namelist object. */
kono
parents:
diff changeset
3621 if (prev_nl && prev_nl->var_rank == 0)
kono
parents:
diff changeset
3622 prev_nl = NULL;
kono
parents:
diff changeset
3623 }
kono
parents:
diff changeset
3624
kono
parents:
diff changeset
3625 free_saved (dtp);
kono
parents:
diff changeset
3626 free_line (dtp);
kono
parents:
diff changeset
3627 return;
kono
parents:
diff changeset
3628
kono
parents:
diff changeset
3629
kono
parents:
diff changeset
3630 nml_err_ret:
kono
parents:
diff changeset
3631
kono
parents:
diff changeset
3632 /* All namelist error calls return from here */
kono
parents:
diff changeset
3633 free_saved (dtp);
kono
parents:
diff changeset
3634 free_line (dtp);
kono
parents:
diff changeset
3635 generate_error (&dtp->common, LIBERROR_READ_VALUE, nml_err_msg);
kono
parents:
diff changeset
3636 return;
kono
parents:
diff changeset
3637 }