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

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