1627f7eb2Smrg /* Deal with I/O statements & related stuff.
2*4c3eb207Smrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Andy Vaught
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg #include "config.h"
22627f7eb2Smrg #include "system.h"
23627f7eb2Smrg #include "coretypes.h"
24627f7eb2Smrg #include "options.h"
25627f7eb2Smrg #include "gfortran.h"
26627f7eb2Smrg #include "match.h"
27627f7eb2Smrg #include "parse.h"
28627f7eb2Smrg #include "constructor.h"
29627f7eb2Smrg
30627f7eb2Smrg gfc_st_label
31627f7eb2Smrg format_asterisk = {0, NULL, NULL, -1, ST_LABEL_FORMAT, ST_LABEL_FORMAT, NULL,
32627f7eb2Smrg 0, {NULL, NULL}, NULL};
33627f7eb2Smrg
34627f7eb2Smrg typedef struct
35627f7eb2Smrg {
36627f7eb2Smrg const char *name, *spec, *value;
37627f7eb2Smrg bt type;
38627f7eb2Smrg }
39627f7eb2Smrg io_tag;
40627f7eb2Smrg
41627f7eb2Smrg static const io_tag
42627f7eb2Smrg tag_readonly = {"READONLY", " readonly", NULL, BT_UNKNOWN },
43627f7eb2Smrg tag_shared = {"SHARE", " shared", NULL, BT_UNKNOWN },
44627f7eb2Smrg tag_noshared = {"SHARE", " noshared", NULL, BT_UNKNOWN },
45627f7eb2Smrg tag_e_share = {"SHARE", " share =", " %e", BT_CHARACTER },
46627f7eb2Smrg tag_v_share = {"SHARE", " share =", " %v", BT_CHARACTER },
47627f7eb2Smrg tag_cc = {"CARRIAGECONTROL", " carriagecontrol =", " %e",
48627f7eb2Smrg BT_CHARACTER },
49627f7eb2Smrg tag_v_cc = {"CARRIAGECONTROL", " carriagecontrol =", " %v",
50627f7eb2Smrg BT_CHARACTER },
51627f7eb2Smrg tag_file = {"FILE", " file =", " %e", BT_CHARACTER },
52627f7eb2Smrg tag_status = {"STATUS", " status =", " %e", BT_CHARACTER},
53627f7eb2Smrg tag_e_access = {"ACCESS", " access =", " %e", BT_CHARACTER},
54627f7eb2Smrg tag_e_form = {"FORM", " form =", " %e", BT_CHARACTER},
55627f7eb2Smrg tag_e_recl = {"RECL", " recl =", " %e", BT_INTEGER},
56627f7eb2Smrg tag_e_blank = {"BLANK", " blank =", " %e", BT_CHARACTER},
57627f7eb2Smrg tag_e_position = {"POSITION", " position =", " %e", BT_CHARACTER},
58627f7eb2Smrg tag_e_action = {"ACTION", " action =", " %e", BT_CHARACTER},
59627f7eb2Smrg tag_e_delim = {"DELIM", " delim =", " %e", BT_CHARACTER},
60627f7eb2Smrg tag_e_pad = {"PAD", " pad =", " %e", BT_CHARACTER},
61627f7eb2Smrg tag_e_decimal = {"DECIMAL", " decimal =", " %e", BT_CHARACTER},
62627f7eb2Smrg tag_e_encoding = {"ENCODING", " encoding =", " %e", BT_CHARACTER},
63627f7eb2Smrg tag_e_async = {"ASYNCHRONOUS", " asynchronous =", " %e", BT_CHARACTER},
64627f7eb2Smrg tag_e_round = {"ROUND", " round =", " %e", BT_CHARACTER},
65627f7eb2Smrg tag_e_sign = {"SIGN", " sign =", " %e", BT_CHARACTER},
66627f7eb2Smrg tag_unit = {"UNIT", " unit =", " %e", BT_INTEGER},
67627f7eb2Smrg tag_advance = {"ADVANCE", " advance =", " %e", BT_CHARACTER},
68627f7eb2Smrg tag_rec = {"REC", " rec =", " %e", BT_INTEGER},
69627f7eb2Smrg tag_spos = {"POSITION", " pos =", " %e", BT_INTEGER},
70627f7eb2Smrg tag_format = {"FORMAT", NULL, NULL, BT_CHARACTER},
71627f7eb2Smrg tag_iomsg = {"IOMSG", " iomsg =", " %e", BT_CHARACTER},
72627f7eb2Smrg tag_iostat = {"IOSTAT", " iostat =", " %v", BT_INTEGER},
73627f7eb2Smrg tag_size = {"SIZE", " size =", " %v", BT_INTEGER},
74627f7eb2Smrg tag_exist = {"EXIST", " exist =", " %v", BT_LOGICAL},
75627f7eb2Smrg tag_opened = {"OPENED", " opened =", " %v", BT_LOGICAL},
76627f7eb2Smrg tag_named = {"NAMED", " named =", " %v", BT_LOGICAL},
77627f7eb2Smrg tag_name = {"NAME", " name =", " %v", BT_CHARACTER},
78627f7eb2Smrg tag_number = {"NUMBER", " number =", " %v", BT_INTEGER},
79627f7eb2Smrg tag_s_access = {"ACCESS", " access =", " %v", BT_CHARACTER},
80627f7eb2Smrg tag_sequential = {"SEQUENTIAL", " sequential =", " %v", BT_CHARACTER},
81627f7eb2Smrg tag_direct = {"DIRECT", " direct =", " %v", BT_CHARACTER},
82627f7eb2Smrg tag_s_form = {"FORM", " form =", " %v", BT_CHARACTER},
83627f7eb2Smrg tag_formatted = {"FORMATTED", " formatted =", " %v", BT_CHARACTER},
84627f7eb2Smrg tag_unformatted = {"UNFORMATTED", " unformatted =", " %v", BT_CHARACTER},
85627f7eb2Smrg tag_s_recl = {"RECL", " recl =", " %v", BT_INTEGER},
86627f7eb2Smrg tag_nextrec = {"NEXTREC", " nextrec =", " %v", BT_INTEGER},
87627f7eb2Smrg tag_s_blank = {"BLANK", " blank =", " %v", BT_CHARACTER},
88627f7eb2Smrg tag_s_position = {"POSITION", " position =", " %v", BT_CHARACTER},
89627f7eb2Smrg tag_s_action = {"ACTION", " action =", " %v", BT_CHARACTER},
90627f7eb2Smrg tag_read = {"READ", " read =", " %v", BT_CHARACTER},
91627f7eb2Smrg tag_write = {"WRITE", " write =", " %v", BT_CHARACTER},
92627f7eb2Smrg tag_readwrite = {"READWRITE", " readwrite =", " %v", BT_CHARACTER},
93627f7eb2Smrg tag_s_delim = {"DELIM", " delim =", " %v", BT_CHARACTER},
94627f7eb2Smrg tag_s_pad = {"PAD", " pad =", " %v", BT_CHARACTER},
95627f7eb2Smrg tag_s_decimal = {"DECIMAL", " decimal =", " %v", BT_CHARACTER},
96627f7eb2Smrg tag_s_encoding = {"ENCODING", " encoding =", " %v", BT_CHARACTER},
97627f7eb2Smrg tag_s_async = {"ASYNCHRONOUS", " asynchronous =", " %v", BT_CHARACTER},
98627f7eb2Smrg tag_s_round = {"ROUND", " round =", " %v", BT_CHARACTER},
99627f7eb2Smrg tag_s_sign = {"SIGN", " sign =", " %v", BT_CHARACTER},
100627f7eb2Smrg tag_iolength = {"IOLENGTH", " iolength =", " %v", BT_INTEGER},
101627f7eb2Smrg tag_convert = {"CONVERT", " convert =", " %e", BT_CHARACTER},
102627f7eb2Smrg tag_strm_out = {"POS", " pos =", " %v", BT_INTEGER},
103627f7eb2Smrg tag_err = {"ERR", " err =", " %l", BT_UNKNOWN},
104627f7eb2Smrg tag_end = {"END", " end =", " %l", BT_UNKNOWN},
105627f7eb2Smrg tag_eor = {"EOR", " eor =", " %l", BT_UNKNOWN},
106627f7eb2Smrg tag_id = {"ID", " id =", " %v", BT_INTEGER},
107627f7eb2Smrg tag_pending = {"PENDING", " pending =", " %v", BT_LOGICAL},
108627f7eb2Smrg tag_newunit = {"NEWUNIT", " newunit =", " %v", BT_INTEGER},
109627f7eb2Smrg tag_s_iqstream = {"STREAM", " stream =", " %v", BT_CHARACTER};
110627f7eb2Smrg
111627f7eb2Smrg static gfc_dt *current_dt;
112627f7eb2Smrg
113627f7eb2Smrg #define RESOLVE_TAG(x, y) if (!resolve_tag (x, y)) return false;
114627f7eb2Smrg
115627f7eb2Smrg /**************** Fortran 95 FORMAT parser *****************/
116627f7eb2Smrg
117627f7eb2Smrg /* FORMAT tokens returned by format_lex(). */
118627f7eb2Smrg enum format_token
119627f7eb2Smrg {
120627f7eb2Smrg FMT_NONE, FMT_UNKNOWN, FMT_SIGNED_INT, FMT_ZERO, FMT_POSINT, FMT_PERIOD,
121627f7eb2Smrg FMT_COMMA, FMT_COLON, FMT_SLASH, FMT_DOLLAR, FMT_LPAREN,
122627f7eb2Smrg FMT_RPAREN, FMT_X, FMT_SIGN, FMT_BLANK, FMT_CHAR, FMT_P, FMT_IBOZ, FMT_F,
123627f7eb2Smrg FMT_E, FMT_EN, FMT_ES, FMT_G, FMT_L, FMT_A, FMT_D, FMT_H, FMT_END,
124627f7eb2Smrg FMT_ERROR, FMT_DC, FMT_DP, FMT_T, FMT_TR, FMT_TL, FMT_STAR, FMT_RC,
125627f7eb2Smrg FMT_RD, FMT_RN, FMT_RP, FMT_RU, FMT_RZ, FMT_DT
126627f7eb2Smrg };
127627f7eb2Smrg
128627f7eb2Smrg /* Local variables for checking format strings. The saved_token is
129627f7eb2Smrg used to back up by a single format token during the parsing
130627f7eb2Smrg process. */
131627f7eb2Smrg static gfc_char_t *format_string;
132627f7eb2Smrg static int format_string_pos;
133627f7eb2Smrg static int format_length, use_last_char;
134627f7eb2Smrg static char error_element;
135627f7eb2Smrg static locus format_locus;
136627f7eb2Smrg
137627f7eb2Smrg static format_token saved_token;
138627f7eb2Smrg
139627f7eb2Smrg static enum
140627f7eb2Smrg { MODE_STRING, MODE_FORMAT, MODE_COPY }
141627f7eb2Smrg mode;
142627f7eb2Smrg
143627f7eb2Smrg
144627f7eb2Smrg /* Return the next character in the format string. */
145627f7eb2Smrg
146627f7eb2Smrg static char
next_char(gfc_instring in_string)147627f7eb2Smrg next_char (gfc_instring in_string)
148627f7eb2Smrg {
149627f7eb2Smrg static gfc_char_t c;
150627f7eb2Smrg
151627f7eb2Smrg if (use_last_char)
152627f7eb2Smrg {
153627f7eb2Smrg use_last_char = 0;
154627f7eb2Smrg return c;
155627f7eb2Smrg }
156627f7eb2Smrg
157627f7eb2Smrg format_length++;
158627f7eb2Smrg
159627f7eb2Smrg if (mode == MODE_STRING)
160627f7eb2Smrg c = *format_string++;
161627f7eb2Smrg else
162627f7eb2Smrg {
163627f7eb2Smrg c = gfc_next_char_literal (in_string);
164627f7eb2Smrg if (c == '\n')
165627f7eb2Smrg c = '\0';
166627f7eb2Smrg }
167627f7eb2Smrg
168627f7eb2Smrg if (flag_backslash && c == '\\')
169627f7eb2Smrg {
170627f7eb2Smrg locus old_locus = gfc_current_locus;
171627f7eb2Smrg
172627f7eb2Smrg if (gfc_match_special_char (&c) == MATCH_NO)
173627f7eb2Smrg gfc_current_locus = old_locus;
174627f7eb2Smrg
175627f7eb2Smrg if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
176627f7eb2Smrg gfc_warning (0, "Extension: backslash character at %C");
177627f7eb2Smrg }
178627f7eb2Smrg
179627f7eb2Smrg if (mode == MODE_COPY)
180627f7eb2Smrg *format_string++ = c;
181627f7eb2Smrg
182627f7eb2Smrg if (mode != MODE_STRING)
183627f7eb2Smrg format_locus = gfc_current_locus;
184627f7eb2Smrg
185627f7eb2Smrg format_string_pos++;
186627f7eb2Smrg
187627f7eb2Smrg c = gfc_wide_toupper (c);
188627f7eb2Smrg return c;
189627f7eb2Smrg }
190627f7eb2Smrg
191627f7eb2Smrg
192627f7eb2Smrg /* Back up one character position. Only works once. */
193627f7eb2Smrg
194627f7eb2Smrg static void
unget_char(void)195627f7eb2Smrg unget_char (void)
196627f7eb2Smrg {
197627f7eb2Smrg use_last_char = 1;
198627f7eb2Smrg }
199627f7eb2Smrg
200627f7eb2Smrg /* Eat up the spaces and return a character. */
201627f7eb2Smrg
202627f7eb2Smrg static char
next_char_not_space()203627f7eb2Smrg next_char_not_space ()
204627f7eb2Smrg {
205627f7eb2Smrg char c;
206627f7eb2Smrg do
207627f7eb2Smrg {
208627f7eb2Smrg error_element = c = next_char (NONSTRING);
209627f7eb2Smrg if (c == '\t')
210627f7eb2Smrg gfc_warning (OPT_Wtabs, "Nonconforming tab character in format at %C");
211627f7eb2Smrg }
212627f7eb2Smrg while (gfc_is_whitespace (c));
213627f7eb2Smrg return c;
214627f7eb2Smrg }
215627f7eb2Smrg
216627f7eb2Smrg static int value = 0;
217627f7eb2Smrg
218627f7eb2Smrg /* Simple lexical analyzer for getting the next token in a FORMAT
219627f7eb2Smrg statement. */
220627f7eb2Smrg
221627f7eb2Smrg static format_token
format_lex(void)222627f7eb2Smrg format_lex (void)
223627f7eb2Smrg {
224627f7eb2Smrg format_token token;
225627f7eb2Smrg char c, delim;
226627f7eb2Smrg int zflag;
227627f7eb2Smrg int negative_flag;
228627f7eb2Smrg
229627f7eb2Smrg if (saved_token != FMT_NONE)
230627f7eb2Smrg {
231627f7eb2Smrg token = saved_token;
232627f7eb2Smrg saved_token = FMT_NONE;
233627f7eb2Smrg return token;
234627f7eb2Smrg }
235627f7eb2Smrg
236627f7eb2Smrg c = next_char_not_space ();
237627f7eb2Smrg
238627f7eb2Smrg negative_flag = 0;
239627f7eb2Smrg switch (c)
240627f7eb2Smrg {
241627f7eb2Smrg case '-':
242627f7eb2Smrg negative_flag = 1;
243627f7eb2Smrg /* Falls through. */
244627f7eb2Smrg
245627f7eb2Smrg case '+':
246627f7eb2Smrg c = next_char_not_space ();
247627f7eb2Smrg if (!ISDIGIT (c))
248627f7eb2Smrg {
249627f7eb2Smrg token = FMT_UNKNOWN;
250627f7eb2Smrg break;
251627f7eb2Smrg }
252627f7eb2Smrg
253627f7eb2Smrg value = c - '0';
254627f7eb2Smrg
255627f7eb2Smrg do
256627f7eb2Smrg {
257627f7eb2Smrg c = next_char_not_space ();
258627f7eb2Smrg if (ISDIGIT (c))
259627f7eb2Smrg value = 10 * value + c - '0';
260627f7eb2Smrg }
261627f7eb2Smrg while (ISDIGIT (c));
262627f7eb2Smrg
263627f7eb2Smrg unget_char ();
264627f7eb2Smrg
265627f7eb2Smrg if (negative_flag)
266627f7eb2Smrg value = -value;
267627f7eb2Smrg
268627f7eb2Smrg token = FMT_SIGNED_INT;
269627f7eb2Smrg break;
270627f7eb2Smrg
271627f7eb2Smrg case '0':
272627f7eb2Smrg case '1':
273627f7eb2Smrg case '2':
274627f7eb2Smrg case '3':
275627f7eb2Smrg case '4':
276627f7eb2Smrg case '5':
277627f7eb2Smrg case '6':
278627f7eb2Smrg case '7':
279627f7eb2Smrg case '8':
280627f7eb2Smrg case '9':
281627f7eb2Smrg zflag = (c == '0');
282627f7eb2Smrg
283627f7eb2Smrg value = c - '0';
284627f7eb2Smrg
285627f7eb2Smrg do
286627f7eb2Smrg {
287627f7eb2Smrg c = next_char_not_space ();
288627f7eb2Smrg if (ISDIGIT (c))
289627f7eb2Smrg {
290627f7eb2Smrg value = 10 * value + c - '0';
291627f7eb2Smrg if (c != '0')
292627f7eb2Smrg zflag = 0;
293627f7eb2Smrg }
294627f7eb2Smrg }
295627f7eb2Smrg while (ISDIGIT (c));
296627f7eb2Smrg
297627f7eb2Smrg unget_char ();
298627f7eb2Smrg token = zflag ? FMT_ZERO : FMT_POSINT;
299627f7eb2Smrg break;
300627f7eb2Smrg
301627f7eb2Smrg case '.':
302627f7eb2Smrg token = FMT_PERIOD;
303627f7eb2Smrg break;
304627f7eb2Smrg
305627f7eb2Smrg case ',':
306627f7eb2Smrg token = FMT_COMMA;
307627f7eb2Smrg break;
308627f7eb2Smrg
309627f7eb2Smrg case ':':
310627f7eb2Smrg token = FMT_COLON;
311627f7eb2Smrg break;
312627f7eb2Smrg
313627f7eb2Smrg case '/':
314627f7eb2Smrg token = FMT_SLASH;
315627f7eb2Smrg break;
316627f7eb2Smrg
317627f7eb2Smrg case '$':
318627f7eb2Smrg token = FMT_DOLLAR;
319627f7eb2Smrg break;
320627f7eb2Smrg
321627f7eb2Smrg case 'T':
322627f7eb2Smrg c = next_char_not_space ();
323627f7eb2Smrg switch (c)
324627f7eb2Smrg {
325627f7eb2Smrg case 'L':
326627f7eb2Smrg token = FMT_TL;
327627f7eb2Smrg break;
328627f7eb2Smrg case 'R':
329627f7eb2Smrg token = FMT_TR;
330627f7eb2Smrg break;
331627f7eb2Smrg default:
332627f7eb2Smrg token = FMT_T;
333627f7eb2Smrg unget_char ();
334627f7eb2Smrg }
335627f7eb2Smrg break;
336627f7eb2Smrg
337627f7eb2Smrg case '(':
338627f7eb2Smrg token = FMT_LPAREN;
339627f7eb2Smrg break;
340627f7eb2Smrg
341627f7eb2Smrg case ')':
342627f7eb2Smrg token = FMT_RPAREN;
343627f7eb2Smrg break;
344627f7eb2Smrg
345627f7eb2Smrg case 'X':
346627f7eb2Smrg token = FMT_X;
347627f7eb2Smrg break;
348627f7eb2Smrg
349627f7eb2Smrg case 'S':
350627f7eb2Smrg c = next_char_not_space ();
351627f7eb2Smrg if (c != 'P' && c != 'S')
352627f7eb2Smrg unget_char ();
353627f7eb2Smrg
354627f7eb2Smrg token = FMT_SIGN;
355627f7eb2Smrg break;
356627f7eb2Smrg
357627f7eb2Smrg case 'B':
358627f7eb2Smrg c = next_char_not_space ();
359627f7eb2Smrg if (c == 'N' || c == 'Z')
360627f7eb2Smrg token = FMT_BLANK;
361627f7eb2Smrg else
362627f7eb2Smrg {
363627f7eb2Smrg unget_char ();
364627f7eb2Smrg token = FMT_IBOZ;
365627f7eb2Smrg }
366627f7eb2Smrg
367627f7eb2Smrg break;
368627f7eb2Smrg
369627f7eb2Smrg case '\'':
370627f7eb2Smrg case '"':
371627f7eb2Smrg delim = c;
372627f7eb2Smrg
373627f7eb2Smrg value = 0;
374627f7eb2Smrg
375627f7eb2Smrg for (;;)
376627f7eb2Smrg {
377627f7eb2Smrg c = next_char (INSTRING_WARN);
378627f7eb2Smrg if (c == '\0')
379627f7eb2Smrg {
380627f7eb2Smrg token = FMT_END;
381627f7eb2Smrg break;
382627f7eb2Smrg }
383627f7eb2Smrg
384627f7eb2Smrg if (c == delim)
385627f7eb2Smrg {
386627f7eb2Smrg c = next_char (NONSTRING);
387627f7eb2Smrg
388627f7eb2Smrg if (c == '\0')
389627f7eb2Smrg {
390627f7eb2Smrg token = FMT_END;
391627f7eb2Smrg break;
392627f7eb2Smrg }
393627f7eb2Smrg
394627f7eb2Smrg if (c != delim)
395627f7eb2Smrg {
396627f7eb2Smrg unget_char ();
397627f7eb2Smrg token = FMT_CHAR;
398627f7eb2Smrg break;
399627f7eb2Smrg }
400627f7eb2Smrg }
401627f7eb2Smrg value++;
402627f7eb2Smrg }
403627f7eb2Smrg break;
404627f7eb2Smrg
405627f7eb2Smrg case 'P':
406627f7eb2Smrg token = FMT_P;
407627f7eb2Smrg break;
408627f7eb2Smrg
409627f7eb2Smrg case 'I':
410627f7eb2Smrg case 'O':
411627f7eb2Smrg case 'Z':
412627f7eb2Smrg token = FMT_IBOZ;
413627f7eb2Smrg break;
414627f7eb2Smrg
415627f7eb2Smrg case 'F':
416627f7eb2Smrg token = FMT_F;
417627f7eb2Smrg break;
418627f7eb2Smrg
419627f7eb2Smrg case 'E':
420627f7eb2Smrg c = next_char_not_space ();
421627f7eb2Smrg if (c == 'N' )
422627f7eb2Smrg token = FMT_EN;
423627f7eb2Smrg else if (c == 'S')
424627f7eb2Smrg token = FMT_ES;
425627f7eb2Smrg else
426627f7eb2Smrg {
427627f7eb2Smrg token = FMT_E;
428627f7eb2Smrg unget_char ();
429627f7eb2Smrg }
430627f7eb2Smrg
431627f7eb2Smrg break;
432627f7eb2Smrg
433627f7eb2Smrg case 'G':
434627f7eb2Smrg token = FMT_G;
435627f7eb2Smrg break;
436627f7eb2Smrg
437627f7eb2Smrg case 'H':
438627f7eb2Smrg token = FMT_H;
439627f7eb2Smrg break;
440627f7eb2Smrg
441627f7eb2Smrg case 'L':
442627f7eb2Smrg token = FMT_L;
443627f7eb2Smrg break;
444627f7eb2Smrg
445627f7eb2Smrg case 'A':
446627f7eb2Smrg token = FMT_A;
447627f7eb2Smrg break;
448627f7eb2Smrg
449627f7eb2Smrg case 'D':
450627f7eb2Smrg c = next_char_not_space ();
451627f7eb2Smrg if (c == 'P')
452627f7eb2Smrg {
453627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "DP format "
454627f7eb2Smrg "specifier not allowed at %C"))
455627f7eb2Smrg return FMT_ERROR;
456627f7eb2Smrg token = FMT_DP;
457627f7eb2Smrg }
458627f7eb2Smrg else if (c == 'C')
459627f7eb2Smrg {
460627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "DC format "
461627f7eb2Smrg "specifier not allowed at %C"))
462627f7eb2Smrg return FMT_ERROR;
463627f7eb2Smrg token = FMT_DC;
464627f7eb2Smrg }
465627f7eb2Smrg else if (c == 'T')
466627f7eb2Smrg {
467627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Fortran 2003: DT format "
468627f7eb2Smrg "specifier not allowed at %C"))
469627f7eb2Smrg return FMT_ERROR;
470627f7eb2Smrg token = FMT_DT;
471627f7eb2Smrg c = next_char_not_space ();
472627f7eb2Smrg if (c == '\'' || c == '"')
473627f7eb2Smrg {
474627f7eb2Smrg delim = c;
475627f7eb2Smrg value = 0;
476627f7eb2Smrg
477627f7eb2Smrg for (;;)
478627f7eb2Smrg {
479627f7eb2Smrg c = next_char (INSTRING_WARN);
480627f7eb2Smrg if (c == '\0')
481627f7eb2Smrg {
482627f7eb2Smrg token = FMT_END;
483627f7eb2Smrg break;
484627f7eb2Smrg }
485627f7eb2Smrg
486627f7eb2Smrg if (c == delim)
487627f7eb2Smrg {
488627f7eb2Smrg c = next_char (NONSTRING);
489627f7eb2Smrg if (c == '\0')
490627f7eb2Smrg {
491627f7eb2Smrg token = FMT_END;
492627f7eb2Smrg break;
493627f7eb2Smrg }
494627f7eb2Smrg if (c == '/')
495627f7eb2Smrg {
496627f7eb2Smrg token = FMT_SLASH;
497627f7eb2Smrg break;
498627f7eb2Smrg }
499627f7eb2Smrg if (c == delim)
500627f7eb2Smrg continue;
501627f7eb2Smrg unget_char ();
502627f7eb2Smrg break;
503627f7eb2Smrg }
504627f7eb2Smrg }
505627f7eb2Smrg }
506627f7eb2Smrg else if (c == '/')
507627f7eb2Smrg {
508627f7eb2Smrg token = FMT_SLASH;
509627f7eb2Smrg break;
510627f7eb2Smrg }
511627f7eb2Smrg else
512627f7eb2Smrg unget_char ();
513627f7eb2Smrg }
514627f7eb2Smrg else
515627f7eb2Smrg {
516627f7eb2Smrg token = FMT_D;
517627f7eb2Smrg unget_char ();
518627f7eb2Smrg }
519627f7eb2Smrg break;
520627f7eb2Smrg
521627f7eb2Smrg case 'R':
522627f7eb2Smrg c = next_char_not_space ();
523627f7eb2Smrg switch (c)
524627f7eb2Smrg {
525627f7eb2Smrg case 'C':
526627f7eb2Smrg token = FMT_RC;
527627f7eb2Smrg break;
528627f7eb2Smrg case 'D':
529627f7eb2Smrg token = FMT_RD;
530627f7eb2Smrg break;
531627f7eb2Smrg case 'N':
532627f7eb2Smrg token = FMT_RN;
533627f7eb2Smrg break;
534627f7eb2Smrg case 'P':
535627f7eb2Smrg token = FMT_RP;
536627f7eb2Smrg break;
537627f7eb2Smrg case 'U':
538627f7eb2Smrg token = FMT_RU;
539627f7eb2Smrg break;
540627f7eb2Smrg case 'Z':
541627f7eb2Smrg token = FMT_RZ;
542627f7eb2Smrg break;
543627f7eb2Smrg default:
544627f7eb2Smrg token = FMT_UNKNOWN;
545627f7eb2Smrg unget_char ();
546627f7eb2Smrg break;
547627f7eb2Smrg }
548627f7eb2Smrg break;
549627f7eb2Smrg
550627f7eb2Smrg case '\0':
551627f7eb2Smrg token = FMT_END;
552627f7eb2Smrg break;
553627f7eb2Smrg
554627f7eb2Smrg case '*':
555627f7eb2Smrg token = FMT_STAR;
556627f7eb2Smrg break;
557627f7eb2Smrg
558627f7eb2Smrg default:
559627f7eb2Smrg token = FMT_UNKNOWN;
560627f7eb2Smrg break;
561627f7eb2Smrg }
562627f7eb2Smrg
563627f7eb2Smrg return token;
564627f7eb2Smrg }
565627f7eb2Smrg
566627f7eb2Smrg
567627f7eb2Smrg static const char *
token_to_string(format_token t)568627f7eb2Smrg token_to_string (format_token t)
569627f7eb2Smrg {
570627f7eb2Smrg switch (t)
571627f7eb2Smrg {
572627f7eb2Smrg case FMT_D:
573627f7eb2Smrg return "D";
574627f7eb2Smrg case FMT_G:
575627f7eb2Smrg return "G";
576627f7eb2Smrg case FMT_E:
577627f7eb2Smrg return "E";
578627f7eb2Smrg case FMT_EN:
579627f7eb2Smrg return "EN";
580627f7eb2Smrg case FMT_ES:
581627f7eb2Smrg return "ES";
582627f7eb2Smrg default:
583627f7eb2Smrg return "";
584627f7eb2Smrg }
585627f7eb2Smrg }
586627f7eb2Smrg
587627f7eb2Smrg /* Check a format statement. The format string, either from a FORMAT
588627f7eb2Smrg statement or a constant in an I/O statement has already been parsed
589627f7eb2Smrg by itself, and we are checking it for validity. The dual origin
590627f7eb2Smrg means that the warning message is a little less than great. */
591627f7eb2Smrg
592627f7eb2Smrg static bool
check_format(bool is_input)593627f7eb2Smrg check_format (bool is_input)
594627f7eb2Smrg {
595*4c3eb207Smrg const char *posint_required
596*4c3eb207Smrg = G_("Positive width required in format string at %L");
597*4c3eb207Smrg const char *nonneg_required
598*4c3eb207Smrg = G_("Nonnegative width required in format string at %L");
599*4c3eb207Smrg const char *unexpected_element
600*4c3eb207Smrg = G_("Unexpected element %qc in format string at %L");
601*4c3eb207Smrg const char *unexpected_end
602*4c3eb207Smrg = G_("Unexpected end of format string in format string at %L");
603*4c3eb207Smrg const char *zero_width
604*4c3eb207Smrg = G_("Zero width in format descriptor in format string at %L");
605627f7eb2Smrg
606627f7eb2Smrg const char *error = NULL;
607627f7eb2Smrg format_token t, u;
608627f7eb2Smrg int level;
609627f7eb2Smrg int repeat;
610627f7eb2Smrg bool rv;
611627f7eb2Smrg
612627f7eb2Smrg use_last_char = 0;
613627f7eb2Smrg saved_token = FMT_NONE;
614627f7eb2Smrg level = 0;
615627f7eb2Smrg repeat = 0;
616627f7eb2Smrg rv = true;
617627f7eb2Smrg format_string_pos = 0;
618627f7eb2Smrg
619627f7eb2Smrg t = format_lex ();
620627f7eb2Smrg if (t == FMT_ERROR)
621627f7eb2Smrg goto fail;
622627f7eb2Smrg if (t != FMT_LPAREN)
623627f7eb2Smrg {
624*4c3eb207Smrg error = G_("Missing leading left parenthesis in format string at %L");
625627f7eb2Smrg goto syntax;
626627f7eb2Smrg }
627627f7eb2Smrg
628627f7eb2Smrg t = format_lex ();
629627f7eb2Smrg if (t == FMT_ERROR)
630627f7eb2Smrg goto fail;
631627f7eb2Smrg if (t == FMT_RPAREN)
632627f7eb2Smrg goto finished; /* Empty format is legal */
633627f7eb2Smrg saved_token = t;
634627f7eb2Smrg
635627f7eb2Smrg format_item:
636627f7eb2Smrg /* In this state, the next thing has to be a format item. */
637627f7eb2Smrg t = format_lex ();
638627f7eb2Smrg if (t == FMT_ERROR)
639627f7eb2Smrg goto fail;
640627f7eb2Smrg format_item_1:
641627f7eb2Smrg switch (t)
642627f7eb2Smrg {
643627f7eb2Smrg case FMT_STAR:
644627f7eb2Smrg repeat = -1;
645627f7eb2Smrg t = format_lex ();
646627f7eb2Smrg if (t == FMT_ERROR)
647627f7eb2Smrg goto fail;
648627f7eb2Smrg if (t == FMT_LPAREN)
649627f7eb2Smrg {
650627f7eb2Smrg level++;
651627f7eb2Smrg goto format_item;
652627f7eb2Smrg }
653*4c3eb207Smrg error = G_("Left parenthesis required after %<*%> in format string "
654*4c3eb207Smrg "at %L");
655627f7eb2Smrg goto syntax;
656627f7eb2Smrg
657627f7eb2Smrg case FMT_POSINT:
658627f7eb2Smrg repeat = value;
659627f7eb2Smrg t = format_lex ();
660627f7eb2Smrg if (t == FMT_ERROR)
661627f7eb2Smrg goto fail;
662627f7eb2Smrg if (t == FMT_LPAREN)
663627f7eb2Smrg {
664627f7eb2Smrg level++;
665627f7eb2Smrg goto format_item;
666627f7eb2Smrg }
667627f7eb2Smrg
668627f7eb2Smrg if (t == FMT_SLASH)
669627f7eb2Smrg goto optional_comma;
670627f7eb2Smrg
671627f7eb2Smrg goto data_desc;
672627f7eb2Smrg
673627f7eb2Smrg case FMT_LPAREN:
674627f7eb2Smrg level++;
675627f7eb2Smrg goto format_item;
676627f7eb2Smrg
677627f7eb2Smrg case FMT_SIGNED_INT:
678627f7eb2Smrg case FMT_ZERO:
679627f7eb2Smrg /* Signed integer can only precede a P format. */
680627f7eb2Smrg t = format_lex ();
681627f7eb2Smrg if (t == FMT_ERROR)
682627f7eb2Smrg goto fail;
683627f7eb2Smrg if (t != FMT_P)
684627f7eb2Smrg {
685*4c3eb207Smrg error = G_("Expected P edit descriptor in format string at %L");
686627f7eb2Smrg goto syntax;
687627f7eb2Smrg }
688627f7eb2Smrg
689627f7eb2Smrg goto data_desc;
690627f7eb2Smrg
691627f7eb2Smrg case FMT_P:
692627f7eb2Smrg /* P requires a prior number. */
693*4c3eb207Smrg error = G_("P descriptor requires leading scale factor in format "
694*4c3eb207Smrg "string at %L");
695627f7eb2Smrg goto syntax;
696627f7eb2Smrg
697627f7eb2Smrg case FMT_X:
698627f7eb2Smrg /* X requires a prior number if we're being pedantic. */
699627f7eb2Smrg if (mode != MODE_FORMAT)
700627f7eb2Smrg format_locus.nextc += format_string_pos;
701627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "X descriptor requires leading "
702627f7eb2Smrg "space count at %L", &format_locus))
703627f7eb2Smrg return false;
704627f7eb2Smrg goto between_desc;
705627f7eb2Smrg
706627f7eb2Smrg case FMT_SIGN:
707627f7eb2Smrg case FMT_BLANK:
708627f7eb2Smrg case FMT_DP:
709627f7eb2Smrg case FMT_DC:
710627f7eb2Smrg case FMT_RC:
711627f7eb2Smrg case FMT_RD:
712627f7eb2Smrg case FMT_RN:
713627f7eb2Smrg case FMT_RP:
714627f7eb2Smrg case FMT_RU:
715627f7eb2Smrg case FMT_RZ:
716627f7eb2Smrg goto between_desc;
717627f7eb2Smrg
718627f7eb2Smrg case FMT_CHAR:
719627f7eb2Smrg goto extension_optional_comma;
720627f7eb2Smrg
721627f7eb2Smrg case FMT_COLON:
722627f7eb2Smrg case FMT_SLASH:
723627f7eb2Smrg goto optional_comma;
724627f7eb2Smrg
725627f7eb2Smrg case FMT_DOLLAR:
726627f7eb2Smrg t = format_lex ();
727627f7eb2Smrg if (t == FMT_ERROR)
728627f7eb2Smrg goto fail;
729627f7eb2Smrg
730627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "$ descriptor at %L", &format_locus))
731627f7eb2Smrg return false;
732627f7eb2Smrg if (t != FMT_RPAREN || level > 0)
733627f7eb2Smrg {
734627f7eb2Smrg gfc_warning (0, "$ should be the last specifier in format at %L",
735627f7eb2Smrg &format_locus);
736627f7eb2Smrg goto optional_comma_1;
737627f7eb2Smrg }
738627f7eb2Smrg
739627f7eb2Smrg goto finished;
740627f7eb2Smrg
741627f7eb2Smrg case FMT_T:
742627f7eb2Smrg case FMT_TL:
743627f7eb2Smrg case FMT_TR:
744627f7eb2Smrg case FMT_IBOZ:
745627f7eb2Smrg case FMT_F:
746627f7eb2Smrg case FMT_E:
747627f7eb2Smrg case FMT_EN:
748627f7eb2Smrg case FMT_ES:
749627f7eb2Smrg case FMT_G:
750627f7eb2Smrg case FMT_L:
751627f7eb2Smrg case FMT_A:
752627f7eb2Smrg case FMT_D:
753627f7eb2Smrg case FMT_H:
754627f7eb2Smrg case FMT_DT:
755627f7eb2Smrg goto data_desc;
756627f7eb2Smrg
757627f7eb2Smrg case FMT_END:
758627f7eb2Smrg error = unexpected_end;
759627f7eb2Smrg goto syntax;
760627f7eb2Smrg
761*4c3eb207Smrg case FMT_RPAREN:
762*4c3eb207Smrg if (flag_dec_blank_format_item)
763*4c3eb207Smrg goto finished;
764*4c3eb207Smrg else
765*4c3eb207Smrg {
766*4c3eb207Smrg error = G_("Missing item in format string at %L");
767*4c3eb207Smrg goto syntax;
768*4c3eb207Smrg }
769*4c3eb207Smrg
770627f7eb2Smrg default:
771627f7eb2Smrg error = unexpected_element;
772627f7eb2Smrg goto syntax;
773627f7eb2Smrg }
774627f7eb2Smrg
775627f7eb2Smrg data_desc:
776627f7eb2Smrg /* In this state, t must currently be a data descriptor.
777627f7eb2Smrg Deal with things that can/must follow the descriptor. */
778627f7eb2Smrg switch (t)
779627f7eb2Smrg {
780627f7eb2Smrg case FMT_SIGN:
781627f7eb2Smrg case FMT_BLANK:
782627f7eb2Smrg case FMT_DP:
783627f7eb2Smrg case FMT_DC:
784627f7eb2Smrg case FMT_X:
785627f7eb2Smrg break;
786627f7eb2Smrg
787627f7eb2Smrg case FMT_P:
788627f7eb2Smrg /* No comma after P allowed only for F, E, EN, ES, D, or G.
789627f7eb2Smrg 10.1.1 (1). */
790627f7eb2Smrg t = format_lex ();
791627f7eb2Smrg if (t == FMT_ERROR)
792627f7eb2Smrg goto fail;
793627f7eb2Smrg if (!(gfc_option.allow_std & GFC_STD_F2003) && t != FMT_COMMA
794627f7eb2Smrg && t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
795627f7eb2Smrg && t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
796627f7eb2Smrg {
797*4c3eb207Smrg error = G_("Comma required after P descriptor in format string "
798*4c3eb207Smrg "at %L");
799627f7eb2Smrg goto syntax;
800627f7eb2Smrg }
801627f7eb2Smrg if (t != FMT_COMMA)
802627f7eb2Smrg {
803627f7eb2Smrg if (t == FMT_POSINT)
804627f7eb2Smrg {
805627f7eb2Smrg t = format_lex ();
806627f7eb2Smrg if (t == FMT_ERROR)
807627f7eb2Smrg goto fail;
808627f7eb2Smrg }
809*4c3eb207Smrg if (t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
810*4c3eb207Smrg && t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
811627f7eb2Smrg {
812*4c3eb207Smrg error = G_("Comma required after P descriptor in format string "
813*4c3eb207Smrg "at %L");
814627f7eb2Smrg goto syntax;
815627f7eb2Smrg }
816627f7eb2Smrg }
817627f7eb2Smrg
818627f7eb2Smrg saved_token = t;
819627f7eb2Smrg goto optional_comma;
820627f7eb2Smrg
821627f7eb2Smrg case FMT_T:
822627f7eb2Smrg case FMT_TL:
823627f7eb2Smrg case FMT_TR:
824627f7eb2Smrg t = format_lex ();
825627f7eb2Smrg if (t != FMT_POSINT)
826627f7eb2Smrg {
827*4c3eb207Smrg error = G_("Positive width required with T descriptor in format "
828*4c3eb207Smrg "string at %L");
829627f7eb2Smrg goto syntax;
830627f7eb2Smrg }
831627f7eb2Smrg break;
832627f7eb2Smrg
833627f7eb2Smrg case FMT_L:
834627f7eb2Smrg t = format_lex ();
835627f7eb2Smrg if (t == FMT_ERROR)
836627f7eb2Smrg goto fail;
837627f7eb2Smrg if (t == FMT_POSINT)
838627f7eb2Smrg break;
839627f7eb2Smrg if (mode != MODE_FORMAT)
840627f7eb2Smrg format_locus.nextc += format_string_pos;
841627f7eb2Smrg if (t == FMT_ZERO)
842627f7eb2Smrg {
843627f7eb2Smrg switch (gfc_notification_std (GFC_STD_GNU))
844627f7eb2Smrg {
845627f7eb2Smrg case WARNING:
846627f7eb2Smrg gfc_warning (0, "Extension: Zero width after L "
847627f7eb2Smrg "descriptor at %L", &format_locus);
848627f7eb2Smrg break;
849627f7eb2Smrg case ERROR:
850627f7eb2Smrg gfc_error ("Extension: Zero width after L "
851627f7eb2Smrg "descriptor at %L", &format_locus);
852627f7eb2Smrg goto fail;
853627f7eb2Smrg case SILENT:
854627f7eb2Smrg break;
855627f7eb2Smrg default:
856627f7eb2Smrg gcc_unreachable ();
857627f7eb2Smrg }
858627f7eb2Smrg }
859627f7eb2Smrg else
860627f7eb2Smrg {
861627f7eb2Smrg saved_token = t;
862627f7eb2Smrg gfc_notify_std (GFC_STD_GNU, "Missing positive width after "
863627f7eb2Smrg "L descriptor at %L", &format_locus);
864627f7eb2Smrg }
865627f7eb2Smrg break;
866627f7eb2Smrg
867627f7eb2Smrg case FMT_A:
868627f7eb2Smrg t = format_lex ();
869627f7eb2Smrg if (t == FMT_ERROR)
870627f7eb2Smrg goto fail;
871627f7eb2Smrg if (t == FMT_ZERO)
872627f7eb2Smrg {
873627f7eb2Smrg error = zero_width;
874627f7eb2Smrg goto syntax;
875627f7eb2Smrg }
876627f7eb2Smrg if (t != FMT_POSINT)
877627f7eb2Smrg saved_token = t;
878627f7eb2Smrg break;
879627f7eb2Smrg
880627f7eb2Smrg case FMT_D:
881627f7eb2Smrg case FMT_E:
882627f7eb2Smrg case FMT_G:
883627f7eb2Smrg case FMT_EN:
884627f7eb2Smrg case FMT_ES:
885627f7eb2Smrg u = format_lex ();
886627f7eb2Smrg if (t == FMT_G && u == FMT_ZERO)
887627f7eb2Smrg {
888627f7eb2Smrg if (is_input)
889627f7eb2Smrg {
890627f7eb2Smrg error = zero_width;
891627f7eb2Smrg goto syntax;
892627f7eb2Smrg }
893627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2008, "%<G0%> in format at %L",
894627f7eb2Smrg &format_locus))
895627f7eb2Smrg return false;
896627f7eb2Smrg u = format_lex ();
897627f7eb2Smrg if (u != FMT_PERIOD)
898627f7eb2Smrg {
899627f7eb2Smrg saved_token = u;
900627f7eb2Smrg break;
901627f7eb2Smrg }
902627f7eb2Smrg u = format_lex ();
903627f7eb2Smrg if (u != FMT_POSINT)
904627f7eb2Smrg {
905627f7eb2Smrg error = posint_required;
906627f7eb2Smrg goto syntax;
907627f7eb2Smrg }
908627f7eb2Smrg u = format_lex ();
909627f7eb2Smrg if (u == FMT_E)
910627f7eb2Smrg {
911*4c3eb207Smrg error = G_("E specifier not allowed with g0 descriptor in "
912*4c3eb207Smrg "format string at %L");
913627f7eb2Smrg goto syntax;
914627f7eb2Smrg }
915627f7eb2Smrg saved_token = u;
916627f7eb2Smrg break;
917627f7eb2Smrg }
918627f7eb2Smrg
919627f7eb2Smrg if (u != FMT_POSINT)
920627f7eb2Smrg {
921*4c3eb207Smrg if (flag_dec)
922*4c3eb207Smrg {
923*4c3eb207Smrg if (flag_dec_format_defaults)
924*4c3eb207Smrg {
925*4c3eb207Smrg /* Assume a default width based on the variable size. */
926*4c3eb207Smrg saved_token = u;
927*4c3eb207Smrg break;
928*4c3eb207Smrg }
929*4c3eb207Smrg else
930*4c3eb207Smrg {
931627f7eb2Smrg gfc_error ("Positive width required in format "
932627f7eb2Smrg "specifier %s at %L", token_to_string (t),
933627f7eb2Smrg &format_locus);
934627f7eb2Smrg saved_token = u;
935627f7eb2Smrg goto fail;
936627f7eb2Smrg }
937*4c3eb207Smrg }
938*4c3eb207Smrg
939*4c3eb207Smrg format_locus.nextc += format_string_pos;
940*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2018,
941*4c3eb207Smrg "positive width required at %L",
942*4c3eb207Smrg &format_locus))
943*4c3eb207Smrg {
944*4c3eb207Smrg saved_token = u;
945*4c3eb207Smrg goto fail;
946*4c3eb207Smrg }
947*4c3eb207Smrg if (flag_dec_format_defaults)
948*4c3eb207Smrg {
949*4c3eb207Smrg /* Assume a default width based on the variable size. */
950*4c3eb207Smrg saved_token = u;
951*4c3eb207Smrg break;
952*4c3eb207Smrg }
953*4c3eb207Smrg }
954627f7eb2Smrg
955627f7eb2Smrg u = format_lex ();
956627f7eb2Smrg if (u == FMT_ERROR)
957627f7eb2Smrg goto fail;
958627f7eb2Smrg if (u != FMT_PERIOD)
959627f7eb2Smrg {
960627f7eb2Smrg /* Warn if -std=legacy, otherwise error. */
961627f7eb2Smrg format_locus.nextc += format_string_pos;
962627f7eb2Smrg if (gfc_option.warn_std != 0)
963627f7eb2Smrg {
964627f7eb2Smrg gfc_error ("Period required in format "
965627f7eb2Smrg "specifier %s at %L", token_to_string (t),
966627f7eb2Smrg &format_locus);
967627f7eb2Smrg saved_token = u;
968627f7eb2Smrg goto fail;
969627f7eb2Smrg }
970627f7eb2Smrg else
971627f7eb2Smrg gfc_warning (0, "Period required in format "
972627f7eb2Smrg "specifier %s at %L", token_to_string (t),
973627f7eb2Smrg &format_locus);
974627f7eb2Smrg /* If we go to finished, we need to unwind this
975627f7eb2Smrg before the next round. */
976627f7eb2Smrg format_locus.nextc -= format_string_pos;
977627f7eb2Smrg saved_token = u;
978627f7eb2Smrg break;
979627f7eb2Smrg }
980627f7eb2Smrg
981627f7eb2Smrg u = format_lex ();
982627f7eb2Smrg if (u == FMT_ERROR)
983627f7eb2Smrg goto fail;
984627f7eb2Smrg if (u != FMT_ZERO && u != FMT_POSINT)
985627f7eb2Smrg {
986627f7eb2Smrg error = nonneg_required;
987627f7eb2Smrg goto syntax;
988627f7eb2Smrg }
989627f7eb2Smrg
990627f7eb2Smrg if (t == FMT_D)
991627f7eb2Smrg break;
992627f7eb2Smrg
993627f7eb2Smrg /* Look for optional exponent. */
994627f7eb2Smrg u = format_lex ();
995627f7eb2Smrg if (u == FMT_ERROR)
996627f7eb2Smrg goto fail;
997627f7eb2Smrg if (u != FMT_E)
998627f7eb2Smrg saved_token = u;
999627f7eb2Smrg else
1000627f7eb2Smrg {
1001627f7eb2Smrg u = format_lex ();
1002627f7eb2Smrg if (u == FMT_ERROR)
1003627f7eb2Smrg goto fail;
1004627f7eb2Smrg if (u != FMT_POSINT)
1005627f7eb2Smrg {
1006*4c3eb207Smrg if (u == FMT_ZERO)
1007*4c3eb207Smrg {
1008*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2018,
1009*4c3eb207Smrg "Positive exponent width required in "
1010*4c3eb207Smrg "format string at %L", &format_locus))
1011*4c3eb207Smrg {
1012*4c3eb207Smrg saved_token = u;
1013*4c3eb207Smrg goto fail;
1014*4c3eb207Smrg }
1015*4c3eb207Smrg }
1016*4c3eb207Smrg else
1017*4c3eb207Smrg {
1018*4c3eb207Smrg error = G_("Positive exponent width required in format "
1019*4c3eb207Smrg "string at %L");
1020627f7eb2Smrg goto syntax;
1021627f7eb2Smrg }
1022627f7eb2Smrg }
1023*4c3eb207Smrg }
1024627f7eb2Smrg
1025627f7eb2Smrg break;
1026627f7eb2Smrg
1027627f7eb2Smrg case FMT_DT:
1028627f7eb2Smrg t = format_lex ();
1029627f7eb2Smrg if (t == FMT_ERROR)
1030627f7eb2Smrg goto fail;
1031627f7eb2Smrg switch (t)
1032627f7eb2Smrg {
1033627f7eb2Smrg case FMT_RPAREN:
1034627f7eb2Smrg level--;
1035627f7eb2Smrg if (level < 0)
1036627f7eb2Smrg goto finished;
1037627f7eb2Smrg goto between_desc;
1038627f7eb2Smrg
1039627f7eb2Smrg case FMT_COMMA:
1040627f7eb2Smrg goto format_item;
1041627f7eb2Smrg
1042627f7eb2Smrg case FMT_COLON:
1043627f7eb2Smrg goto format_item_1;
1044627f7eb2Smrg
1045627f7eb2Smrg case FMT_LPAREN:
1046627f7eb2Smrg
1047627f7eb2Smrg dtio_vlist:
1048627f7eb2Smrg t = format_lex ();
1049627f7eb2Smrg if (t == FMT_ERROR)
1050627f7eb2Smrg goto fail;
1051627f7eb2Smrg
1052627f7eb2Smrg if (t != FMT_POSINT)
1053627f7eb2Smrg {
1054627f7eb2Smrg error = posint_required;
1055627f7eb2Smrg goto syntax;
1056627f7eb2Smrg }
1057627f7eb2Smrg
1058627f7eb2Smrg t = format_lex ();
1059627f7eb2Smrg if (t == FMT_ERROR)
1060627f7eb2Smrg goto fail;
1061627f7eb2Smrg
1062627f7eb2Smrg if (t == FMT_COMMA)
1063627f7eb2Smrg goto dtio_vlist;
1064627f7eb2Smrg if (t != FMT_RPAREN)
1065627f7eb2Smrg {
1066*4c3eb207Smrg error = G_("Right parenthesis expected at %C in format string "
1067*4c3eb207Smrg "at %L");
1068627f7eb2Smrg goto syntax;
1069627f7eb2Smrg }
1070627f7eb2Smrg goto between_desc;
1071627f7eb2Smrg
1072627f7eb2Smrg default:
1073627f7eb2Smrg error = unexpected_element;
1074627f7eb2Smrg goto syntax;
1075627f7eb2Smrg }
1076627f7eb2Smrg break;
1077627f7eb2Smrg
1078627f7eb2Smrg case FMT_F:
1079627f7eb2Smrg t = format_lex ();
1080627f7eb2Smrg if (t == FMT_ERROR)
1081627f7eb2Smrg goto fail;
1082627f7eb2Smrg if (t != FMT_ZERO && t != FMT_POSINT)
1083627f7eb2Smrg {
1084*4c3eb207Smrg if (flag_dec_format_defaults)
1085*4c3eb207Smrg {
1086*4c3eb207Smrg /* Assume the default width is expected here and continue lexing. */
1087*4c3eb207Smrg value = 0; /* It doesn't matter what we set the value to here. */
1088*4c3eb207Smrg saved_token = t;
1089*4c3eb207Smrg break;
1090*4c3eb207Smrg }
1091627f7eb2Smrg error = nonneg_required;
1092627f7eb2Smrg goto syntax;
1093627f7eb2Smrg }
1094627f7eb2Smrg else if (is_input && t == FMT_ZERO)
1095627f7eb2Smrg {
1096627f7eb2Smrg error = posint_required;
1097627f7eb2Smrg goto syntax;
1098627f7eb2Smrg }
1099627f7eb2Smrg
1100627f7eb2Smrg t = format_lex ();
1101627f7eb2Smrg if (t == FMT_ERROR)
1102627f7eb2Smrg goto fail;
1103627f7eb2Smrg if (t != FMT_PERIOD)
1104627f7eb2Smrg {
1105627f7eb2Smrg /* Warn if -std=legacy, otherwise error. */
1106627f7eb2Smrg if (gfc_option.warn_std != 0)
1107627f7eb2Smrg {
1108*4c3eb207Smrg error = G_("Period required in format specifier in format "
1109*4c3eb207Smrg "string at %L");
1110627f7eb2Smrg goto syntax;
1111627f7eb2Smrg }
1112627f7eb2Smrg if (mode != MODE_FORMAT)
1113627f7eb2Smrg format_locus.nextc += format_string_pos;
1114627f7eb2Smrg gfc_warning (0, "Period required in format specifier at %L",
1115627f7eb2Smrg &format_locus);
1116627f7eb2Smrg saved_token = t;
1117627f7eb2Smrg break;
1118627f7eb2Smrg }
1119627f7eb2Smrg
1120627f7eb2Smrg t = format_lex ();
1121627f7eb2Smrg if (t == FMT_ERROR)
1122627f7eb2Smrg goto fail;
1123627f7eb2Smrg if (t != FMT_ZERO && t != FMT_POSINT)
1124627f7eb2Smrg {
1125627f7eb2Smrg error = nonneg_required;
1126627f7eb2Smrg goto syntax;
1127627f7eb2Smrg }
1128627f7eb2Smrg
1129627f7eb2Smrg break;
1130627f7eb2Smrg
1131627f7eb2Smrg case FMT_H:
1132627f7eb2Smrg if (!(gfc_option.allow_std & GFC_STD_GNU) && !inhibit_warnings)
1133627f7eb2Smrg {
1134627f7eb2Smrg if (mode != MODE_FORMAT)
1135627f7eb2Smrg format_locus.nextc += format_string_pos;
1136627f7eb2Smrg gfc_warning (0, "The H format specifier at %L is"
1137627f7eb2Smrg " a Fortran 95 deleted feature", &format_locus);
1138627f7eb2Smrg }
1139627f7eb2Smrg if (mode == MODE_STRING)
1140627f7eb2Smrg {
1141627f7eb2Smrg format_string += value;
1142627f7eb2Smrg format_length -= value;
1143627f7eb2Smrg format_string_pos += repeat;
1144627f7eb2Smrg }
1145627f7eb2Smrg else
1146627f7eb2Smrg {
1147627f7eb2Smrg while (repeat >0)
1148627f7eb2Smrg {
1149627f7eb2Smrg next_char (INSTRING_WARN);
1150627f7eb2Smrg repeat -- ;
1151627f7eb2Smrg }
1152627f7eb2Smrg }
1153627f7eb2Smrg break;
1154627f7eb2Smrg
1155627f7eb2Smrg case FMT_IBOZ:
1156627f7eb2Smrg t = format_lex ();
1157627f7eb2Smrg if (t == FMT_ERROR)
1158627f7eb2Smrg goto fail;
1159627f7eb2Smrg if (t != FMT_ZERO && t != FMT_POSINT)
1160627f7eb2Smrg {
1161*4c3eb207Smrg if (flag_dec_format_defaults)
1162*4c3eb207Smrg {
1163*4c3eb207Smrg /* Assume the default width is expected here and continue lexing. */
1164*4c3eb207Smrg value = 0; /* It doesn't matter what we set the value to here. */
1165*4c3eb207Smrg saved_token = t;
1166*4c3eb207Smrg }
1167*4c3eb207Smrg else
1168*4c3eb207Smrg {
1169627f7eb2Smrg error = nonneg_required;
1170627f7eb2Smrg goto syntax;
1171627f7eb2Smrg }
1172*4c3eb207Smrg }
1173627f7eb2Smrg else if (is_input && t == FMT_ZERO)
1174627f7eb2Smrg {
1175627f7eb2Smrg error = posint_required;
1176627f7eb2Smrg goto syntax;
1177627f7eb2Smrg }
1178627f7eb2Smrg
1179627f7eb2Smrg t = format_lex ();
1180627f7eb2Smrg if (t == FMT_ERROR)
1181627f7eb2Smrg goto fail;
1182627f7eb2Smrg if (t != FMT_PERIOD)
1183627f7eb2Smrg saved_token = t;
1184627f7eb2Smrg else
1185627f7eb2Smrg {
1186627f7eb2Smrg t = format_lex ();
1187627f7eb2Smrg if (t == FMT_ERROR)
1188627f7eb2Smrg goto fail;
1189627f7eb2Smrg if (t != FMT_ZERO && t != FMT_POSINT)
1190627f7eb2Smrg {
1191627f7eb2Smrg error = nonneg_required;
1192627f7eb2Smrg goto syntax;
1193627f7eb2Smrg }
1194627f7eb2Smrg }
1195627f7eb2Smrg
1196627f7eb2Smrg break;
1197627f7eb2Smrg
1198627f7eb2Smrg default:
1199627f7eb2Smrg error = unexpected_element;
1200627f7eb2Smrg goto syntax;
1201627f7eb2Smrg }
1202627f7eb2Smrg
1203627f7eb2Smrg between_desc:
1204627f7eb2Smrg /* Between a descriptor and what comes next. */
1205627f7eb2Smrg t = format_lex ();
1206627f7eb2Smrg if (t == FMT_ERROR)
1207627f7eb2Smrg goto fail;
1208627f7eb2Smrg switch (t)
1209627f7eb2Smrg {
1210627f7eb2Smrg
1211627f7eb2Smrg case FMT_COMMA:
1212627f7eb2Smrg goto format_item;
1213627f7eb2Smrg
1214627f7eb2Smrg case FMT_RPAREN:
1215627f7eb2Smrg level--;
1216627f7eb2Smrg if (level < 0)
1217627f7eb2Smrg goto finished;
1218627f7eb2Smrg goto between_desc;
1219627f7eb2Smrg
1220627f7eb2Smrg case FMT_COLON:
1221627f7eb2Smrg case FMT_SLASH:
1222627f7eb2Smrg goto optional_comma;
1223627f7eb2Smrg
1224627f7eb2Smrg case FMT_END:
1225627f7eb2Smrg error = unexpected_end;
1226627f7eb2Smrg goto syntax;
1227627f7eb2Smrg
1228627f7eb2Smrg default:
1229627f7eb2Smrg if (mode != MODE_FORMAT)
1230627f7eb2Smrg format_locus.nextc += format_string_pos - 1;
1231627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "Missing comma at %L", &format_locus))
1232627f7eb2Smrg return false;
1233627f7eb2Smrg /* If we do not actually return a failure, we need to unwind this
1234627f7eb2Smrg before the next round. */
1235627f7eb2Smrg if (mode != MODE_FORMAT)
1236627f7eb2Smrg format_locus.nextc -= format_string_pos;
1237627f7eb2Smrg goto format_item_1;
1238627f7eb2Smrg }
1239627f7eb2Smrg
1240627f7eb2Smrg optional_comma:
1241627f7eb2Smrg /* Optional comma is a weird between state where we've just finished
1242627f7eb2Smrg reading a colon, slash, dollar or P descriptor. */
1243627f7eb2Smrg t = format_lex ();
1244627f7eb2Smrg if (t == FMT_ERROR)
1245627f7eb2Smrg goto fail;
1246627f7eb2Smrg optional_comma_1:
1247627f7eb2Smrg switch (t)
1248627f7eb2Smrg {
1249627f7eb2Smrg case FMT_COMMA:
1250627f7eb2Smrg break;
1251627f7eb2Smrg
1252627f7eb2Smrg case FMT_RPAREN:
1253627f7eb2Smrg level--;
1254627f7eb2Smrg if (level < 0)
1255627f7eb2Smrg goto finished;
1256627f7eb2Smrg goto between_desc;
1257627f7eb2Smrg
1258627f7eb2Smrg default:
1259627f7eb2Smrg /* Assume that we have another format item. */
1260627f7eb2Smrg saved_token = t;
1261627f7eb2Smrg break;
1262627f7eb2Smrg }
1263627f7eb2Smrg
1264627f7eb2Smrg goto format_item;
1265627f7eb2Smrg
1266627f7eb2Smrg extension_optional_comma:
1267627f7eb2Smrg /* As a GNU extension, permit a missing comma after a string literal. */
1268627f7eb2Smrg t = format_lex ();
1269627f7eb2Smrg if (t == FMT_ERROR)
1270627f7eb2Smrg goto fail;
1271627f7eb2Smrg switch (t)
1272627f7eb2Smrg {
1273627f7eb2Smrg case FMT_COMMA:
1274627f7eb2Smrg break;
1275627f7eb2Smrg
1276627f7eb2Smrg case FMT_RPAREN:
1277627f7eb2Smrg level--;
1278627f7eb2Smrg if (level < 0)
1279627f7eb2Smrg goto finished;
1280627f7eb2Smrg goto between_desc;
1281627f7eb2Smrg
1282627f7eb2Smrg case FMT_COLON:
1283627f7eb2Smrg case FMT_SLASH:
1284627f7eb2Smrg goto optional_comma;
1285627f7eb2Smrg
1286627f7eb2Smrg case FMT_END:
1287627f7eb2Smrg error = unexpected_end;
1288627f7eb2Smrg goto syntax;
1289627f7eb2Smrg
1290627f7eb2Smrg default:
1291627f7eb2Smrg if (mode != MODE_FORMAT)
1292627f7eb2Smrg format_locus.nextc += format_string_pos;
1293627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "Missing comma at %L", &format_locus))
1294627f7eb2Smrg return false;
1295627f7eb2Smrg /* If we do not actually return a failure, we need to unwind this
1296627f7eb2Smrg before the next round. */
1297627f7eb2Smrg if (mode != MODE_FORMAT)
1298627f7eb2Smrg format_locus.nextc -= format_string_pos;
1299627f7eb2Smrg saved_token = t;
1300627f7eb2Smrg break;
1301627f7eb2Smrg }
1302627f7eb2Smrg
1303627f7eb2Smrg goto format_item;
1304627f7eb2Smrg
1305627f7eb2Smrg syntax:
1306627f7eb2Smrg if (mode != MODE_FORMAT)
1307627f7eb2Smrg format_locus.nextc += format_string_pos;
1308627f7eb2Smrg if (error == unexpected_element)
1309627f7eb2Smrg gfc_error (error, error_element, &format_locus);
1310627f7eb2Smrg else
1311*4c3eb207Smrg gfc_error (error, &format_locus);
1312627f7eb2Smrg fail:
1313627f7eb2Smrg rv = false;
1314627f7eb2Smrg
1315627f7eb2Smrg finished:
1316627f7eb2Smrg return rv;
1317627f7eb2Smrg }
1318627f7eb2Smrg
1319627f7eb2Smrg
1320627f7eb2Smrg /* Given an expression node that is a constant string, see if it looks
1321627f7eb2Smrg like a format string. */
1322627f7eb2Smrg
1323627f7eb2Smrg static bool
check_format_string(gfc_expr * e,bool is_input)1324627f7eb2Smrg check_format_string (gfc_expr *e, bool is_input)
1325627f7eb2Smrg {
1326627f7eb2Smrg bool rv;
1327627f7eb2Smrg int i;
1328627f7eb2Smrg if (!e || e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1329627f7eb2Smrg return true;
1330627f7eb2Smrg
1331627f7eb2Smrg mode = MODE_STRING;
1332627f7eb2Smrg format_string = e->value.character.string;
1333627f7eb2Smrg
1334627f7eb2Smrg /* More elaborate measures are needed to show where a problem is within a
1335627f7eb2Smrg format string that has been calculated, but that's probably not worth the
1336627f7eb2Smrg effort. */
1337627f7eb2Smrg format_locus = e->where;
1338627f7eb2Smrg rv = check_format (is_input);
1339627f7eb2Smrg /* check for extraneous characters at the end of an otherwise valid format
1340627f7eb2Smrg string, like '(A10,I3)F5'
1341627f7eb2Smrg start at the end and move back to the last character processed,
1342627f7eb2Smrg spaces are OK */
1343627f7eb2Smrg if (rv && e->value.character.length > format_string_pos)
1344627f7eb2Smrg for (i=e->value.character.length-1;i>format_string_pos-1;i--)
1345627f7eb2Smrg if (e->value.character.string[i] != ' ')
1346627f7eb2Smrg {
1347627f7eb2Smrg format_locus.nextc += format_length + 1;
1348627f7eb2Smrg gfc_warning (0,
1349627f7eb2Smrg "Extraneous characters in format at %L", &format_locus);
1350627f7eb2Smrg break;
1351627f7eb2Smrg }
1352627f7eb2Smrg return rv;
1353627f7eb2Smrg }
1354627f7eb2Smrg
1355627f7eb2Smrg
1356627f7eb2Smrg /************ Fortran I/O statement matchers *************/
1357627f7eb2Smrg
1358627f7eb2Smrg /* Match a FORMAT statement. This amounts to actually parsing the
1359627f7eb2Smrg format descriptors in order to correctly locate the end of the
1360627f7eb2Smrg format string. */
1361627f7eb2Smrg
1362627f7eb2Smrg match
gfc_match_format(void)1363627f7eb2Smrg gfc_match_format (void)
1364627f7eb2Smrg {
1365627f7eb2Smrg gfc_expr *e;
1366627f7eb2Smrg locus start;
1367627f7eb2Smrg
1368627f7eb2Smrg if (gfc_current_ns->proc_name
1369627f7eb2Smrg && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
1370627f7eb2Smrg {
1371627f7eb2Smrg gfc_error ("Format statement in module main block at %C");
1372627f7eb2Smrg return MATCH_ERROR;
1373627f7eb2Smrg }
1374627f7eb2Smrg
1375627f7eb2Smrg /* Before parsing the rest of a FORMAT statement, check F2008:c1206. */
1376627f7eb2Smrg if ((gfc_current_state () == COMP_FUNCTION
1377627f7eb2Smrg || gfc_current_state () == COMP_SUBROUTINE)
1378627f7eb2Smrg && gfc_state_stack->previous->state == COMP_INTERFACE)
1379627f7eb2Smrg {
1380627f7eb2Smrg gfc_error ("FORMAT statement at %C cannot appear within an INTERFACE");
1381627f7eb2Smrg return MATCH_ERROR;
1382627f7eb2Smrg }
1383627f7eb2Smrg
1384627f7eb2Smrg if (gfc_statement_label == NULL)
1385627f7eb2Smrg {
1386627f7eb2Smrg gfc_error ("Missing format label at %C");
1387627f7eb2Smrg return MATCH_ERROR;
1388627f7eb2Smrg }
1389627f7eb2Smrg gfc_gobble_whitespace ();
1390627f7eb2Smrg
1391627f7eb2Smrg mode = MODE_FORMAT;
1392627f7eb2Smrg format_length = 0;
1393627f7eb2Smrg
1394627f7eb2Smrg start = gfc_current_locus;
1395627f7eb2Smrg
1396627f7eb2Smrg if (!check_format (false))
1397627f7eb2Smrg return MATCH_ERROR;
1398627f7eb2Smrg
1399627f7eb2Smrg if (gfc_match_eos () != MATCH_YES)
1400627f7eb2Smrg {
1401627f7eb2Smrg gfc_syntax_error (ST_FORMAT);
1402627f7eb2Smrg return MATCH_ERROR;
1403627f7eb2Smrg }
1404627f7eb2Smrg
1405627f7eb2Smrg /* The label doesn't get created until after the statement is done
1406627f7eb2Smrg being matched, so we have to leave the string for later. */
1407627f7eb2Smrg
1408627f7eb2Smrg gfc_current_locus = start; /* Back to the beginning */
1409627f7eb2Smrg
1410627f7eb2Smrg new_st.loc = start;
1411627f7eb2Smrg new_st.op = EXEC_NOP;
1412627f7eb2Smrg
1413627f7eb2Smrg e = gfc_get_character_expr (gfc_default_character_kind, &start,
1414627f7eb2Smrg NULL, format_length);
1415627f7eb2Smrg format_string = e->value.character.string;
1416627f7eb2Smrg gfc_statement_label->format = e;
1417627f7eb2Smrg
1418627f7eb2Smrg mode = MODE_COPY;
1419627f7eb2Smrg check_format (false); /* Guaranteed to succeed */
1420627f7eb2Smrg gfc_match_eos (); /* Guaranteed to succeed */
1421627f7eb2Smrg
1422627f7eb2Smrg return MATCH_YES;
1423627f7eb2Smrg }
1424627f7eb2Smrg
1425627f7eb2Smrg
1426627f7eb2Smrg /* Match an expression I/O tag of some sort. */
1427627f7eb2Smrg
1428627f7eb2Smrg static match
match_etag(const io_tag * tag,gfc_expr ** v)1429627f7eb2Smrg match_etag (const io_tag *tag, gfc_expr **v)
1430627f7eb2Smrg {
1431627f7eb2Smrg gfc_expr *result;
1432627f7eb2Smrg match m;
1433627f7eb2Smrg
1434627f7eb2Smrg m = gfc_match (tag->spec);
1435627f7eb2Smrg if (m != MATCH_YES)
1436627f7eb2Smrg return m;
1437627f7eb2Smrg
1438627f7eb2Smrg m = gfc_match (tag->value, &result);
1439627f7eb2Smrg if (m != MATCH_YES)
1440627f7eb2Smrg {
1441627f7eb2Smrg gfc_error ("Invalid value for %s specification at %C", tag->name);
1442627f7eb2Smrg return MATCH_ERROR;
1443627f7eb2Smrg }
1444627f7eb2Smrg
1445627f7eb2Smrg if (*v != NULL)
1446627f7eb2Smrg {
1447627f7eb2Smrg gfc_error ("Duplicate %s specification at %C", tag->name);
1448627f7eb2Smrg gfc_free_expr (result);
1449627f7eb2Smrg return MATCH_ERROR;
1450627f7eb2Smrg }
1451627f7eb2Smrg
1452627f7eb2Smrg *v = result;
1453627f7eb2Smrg return MATCH_YES;
1454627f7eb2Smrg }
1455627f7eb2Smrg
1456627f7eb2Smrg
1457627f7eb2Smrg /* Match a variable I/O tag of some sort. */
1458627f7eb2Smrg
1459627f7eb2Smrg static match
match_vtag(const io_tag * tag,gfc_expr ** v)1460627f7eb2Smrg match_vtag (const io_tag *tag, gfc_expr **v)
1461627f7eb2Smrg {
1462627f7eb2Smrg gfc_expr *result;
1463627f7eb2Smrg match m;
1464627f7eb2Smrg
1465627f7eb2Smrg m = gfc_match (tag->spec);
1466627f7eb2Smrg if (m != MATCH_YES)
1467627f7eb2Smrg return m;
1468627f7eb2Smrg
1469627f7eb2Smrg m = gfc_match (tag->value, &result);
1470627f7eb2Smrg if (m != MATCH_YES)
1471627f7eb2Smrg {
1472627f7eb2Smrg gfc_error ("Invalid value for %s specification at %C", tag->name);
1473627f7eb2Smrg return MATCH_ERROR;
1474627f7eb2Smrg }
1475627f7eb2Smrg
1476627f7eb2Smrg if (*v != NULL)
1477627f7eb2Smrg {
1478627f7eb2Smrg gfc_error ("Duplicate %s specification at %C", tag->name);
1479627f7eb2Smrg gfc_free_expr (result);
1480627f7eb2Smrg return MATCH_ERROR;
1481627f7eb2Smrg }
1482627f7eb2Smrg
1483627f7eb2Smrg if (result->symtree)
1484627f7eb2Smrg {
1485627f7eb2Smrg bool impure;
1486627f7eb2Smrg
1487627f7eb2Smrg if (result->symtree->n.sym->attr.intent == INTENT_IN)
1488627f7eb2Smrg {
1489627f7eb2Smrg gfc_error ("Variable %s cannot be INTENT(IN) at %C", tag->name);
1490627f7eb2Smrg gfc_free_expr (result);
1491627f7eb2Smrg return MATCH_ERROR;
1492627f7eb2Smrg }
1493627f7eb2Smrg
1494627f7eb2Smrg impure = gfc_impure_variable (result->symtree->n.sym);
1495627f7eb2Smrg if (impure && gfc_pure (NULL))
1496627f7eb2Smrg {
1497627f7eb2Smrg gfc_error ("Variable %s cannot be assigned in PURE procedure at %C",
1498627f7eb2Smrg tag->name);
1499627f7eb2Smrg gfc_free_expr (result);
1500627f7eb2Smrg return MATCH_ERROR;
1501627f7eb2Smrg }
1502627f7eb2Smrg
1503627f7eb2Smrg if (impure)
1504627f7eb2Smrg gfc_unset_implicit_pure (NULL);
1505627f7eb2Smrg }
1506627f7eb2Smrg
1507627f7eb2Smrg *v = result;
1508627f7eb2Smrg return MATCH_YES;
1509627f7eb2Smrg }
1510627f7eb2Smrg
1511627f7eb2Smrg
1512627f7eb2Smrg /* Match I/O tags that cause variables to become redefined. */
1513627f7eb2Smrg
1514627f7eb2Smrg static match
match_out_tag(const io_tag * tag,gfc_expr ** result)1515627f7eb2Smrg match_out_tag (const io_tag *tag, gfc_expr **result)
1516627f7eb2Smrg {
1517627f7eb2Smrg match m;
1518627f7eb2Smrg
1519627f7eb2Smrg m = match_vtag (tag, result);
1520627f7eb2Smrg if (m == MATCH_YES)
1521627f7eb2Smrg {
1522627f7eb2Smrg if ((*result)->symtree)
1523627f7eb2Smrg gfc_check_do_variable ((*result)->symtree);
1524627f7eb2Smrg
1525627f7eb2Smrg if ((*result)->expr_type == EXPR_CONSTANT)
1526627f7eb2Smrg {
1527627f7eb2Smrg gfc_error ("Expecting a variable at %L", &(*result)->where);
1528627f7eb2Smrg return MATCH_ERROR;
1529627f7eb2Smrg }
1530627f7eb2Smrg }
1531627f7eb2Smrg
1532627f7eb2Smrg return m;
1533627f7eb2Smrg }
1534627f7eb2Smrg
1535627f7eb2Smrg
1536627f7eb2Smrg /* Match a label I/O tag. */
1537627f7eb2Smrg
1538627f7eb2Smrg static match
match_ltag(const io_tag * tag,gfc_st_label ** label)1539627f7eb2Smrg match_ltag (const io_tag *tag, gfc_st_label ** label)
1540627f7eb2Smrg {
1541627f7eb2Smrg match m;
1542627f7eb2Smrg gfc_st_label *old;
1543627f7eb2Smrg
1544627f7eb2Smrg old = *label;
1545627f7eb2Smrg m = gfc_match (tag->spec);
1546627f7eb2Smrg if (m != MATCH_YES)
1547627f7eb2Smrg return m;
1548627f7eb2Smrg
1549627f7eb2Smrg m = gfc_match (tag->value, label);
1550627f7eb2Smrg if (m != MATCH_YES)
1551627f7eb2Smrg {
1552627f7eb2Smrg gfc_error ("Invalid value for %s specification at %C", tag->name);
1553627f7eb2Smrg return MATCH_ERROR;
1554627f7eb2Smrg }
1555627f7eb2Smrg
1556627f7eb2Smrg if (old)
1557627f7eb2Smrg {
1558627f7eb2Smrg gfc_error ("Duplicate %s label specification at %C", tag->name);
1559627f7eb2Smrg return MATCH_ERROR;
1560627f7eb2Smrg }
1561627f7eb2Smrg
1562627f7eb2Smrg if (!gfc_reference_st_label (*label, ST_LABEL_TARGET))
1563627f7eb2Smrg return MATCH_ERROR;
1564627f7eb2Smrg
1565627f7eb2Smrg return m;
1566627f7eb2Smrg }
1567627f7eb2Smrg
1568627f7eb2Smrg
1569627f7eb2Smrg /* Match a tag using match_etag, but only if -fdec is enabled. */
1570627f7eb2Smrg static match
match_dec_etag(const io_tag * tag,gfc_expr ** e)1571627f7eb2Smrg match_dec_etag (const io_tag *tag, gfc_expr **e)
1572627f7eb2Smrg {
1573627f7eb2Smrg match m = match_etag (tag, e);
1574627f7eb2Smrg if (flag_dec && m != MATCH_NO)
1575627f7eb2Smrg return m;
1576627f7eb2Smrg else if (m != MATCH_NO)
1577627f7eb2Smrg {
1578627f7eb2Smrg gfc_error ("%s at %C is a DEC extension, enable with "
1579627f7eb2Smrg "%<-fdec%>", tag->name);
1580627f7eb2Smrg return MATCH_ERROR;
1581627f7eb2Smrg }
1582627f7eb2Smrg return m;
1583627f7eb2Smrg }
1584627f7eb2Smrg
1585627f7eb2Smrg
1586627f7eb2Smrg /* Match a tag using match_vtag, but only if -fdec is enabled. */
1587627f7eb2Smrg static match
match_dec_vtag(const io_tag * tag,gfc_expr ** e)1588627f7eb2Smrg match_dec_vtag (const io_tag *tag, gfc_expr **e)
1589627f7eb2Smrg {
1590627f7eb2Smrg match m = match_vtag(tag, e);
1591627f7eb2Smrg if (flag_dec && m != MATCH_NO)
1592627f7eb2Smrg return m;
1593627f7eb2Smrg else if (m != MATCH_NO)
1594627f7eb2Smrg {
1595627f7eb2Smrg gfc_error ("%s at %C is a DEC extension, enable with "
1596627f7eb2Smrg "%<-fdec%>", tag->name);
1597627f7eb2Smrg return MATCH_ERROR;
1598627f7eb2Smrg }
1599627f7eb2Smrg return m;
1600627f7eb2Smrg }
1601627f7eb2Smrg
1602627f7eb2Smrg
1603627f7eb2Smrg /* Match a DEC I/O flag tag - a tag with no expression such as READONLY. */
1604627f7eb2Smrg
1605627f7eb2Smrg static match
match_dec_ftag(const io_tag * tag,gfc_open * o)1606627f7eb2Smrg match_dec_ftag (const io_tag *tag, gfc_open *o)
1607627f7eb2Smrg {
1608627f7eb2Smrg match m;
1609627f7eb2Smrg
1610627f7eb2Smrg m = gfc_match (tag->spec);
1611627f7eb2Smrg if (m != MATCH_YES)
1612627f7eb2Smrg return m;
1613627f7eb2Smrg
1614627f7eb2Smrg if (!flag_dec)
1615627f7eb2Smrg {
1616627f7eb2Smrg gfc_error ("%s at %C is a DEC extension, enable with "
1617627f7eb2Smrg "%<-fdec%>", tag->name);
1618627f7eb2Smrg return MATCH_ERROR;
1619627f7eb2Smrg }
1620627f7eb2Smrg
1621627f7eb2Smrg /* Just set the READONLY flag, which we use at runtime to avoid delete on
1622627f7eb2Smrg close. */
1623627f7eb2Smrg if (tag == &tag_readonly)
1624627f7eb2Smrg {
1625627f7eb2Smrg o->readonly |= 1;
1626627f7eb2Smrg return MATCH_YES;
1627627f7eb2Smrg }
1628627f7eb2Smrg
1629627f7eb2Smrg /* Interpret SHARED as SHARE='DENYNONE' (read lock). */
1630627f7eb2Smrg else if (tag == &tag_shared)
1631627f7eb2Smrg {
1632627f7eb2Smrg if (o->share != NULL)
1633627f7eb2Smrg {
1634627f7eb2Smrg gfc_error ("Duplicate %s specification at %C", tag->name);
1635627f7eb2Smrg return MATCH_ERROR;
1636627f7eb2Smrg }
1637627f7eb2Smrg o->share = gfc_get_character_expr (gfc_default_character_kind,
1638627f7eb2Smrg &gfc_current_locus, "denynone", 8);
1639627f7eb2Smrg return MATCH_YES;
1640627f7eb2Smrg }
1641627f7eb2Smrg
1642627f7eb2Smrg /* Interpret NOSHARED as SHARE='DENYRW' (exclusive lock). */
1643627f7eb2Smrg else if (tag == &tag_noshared)
1644627f7eb2Smrg {
1645627f7eb2Smrg if (o->share != NULL)
1646627f7eb2Smrg {
1647627f7eb2Smrg gfc_error ("Duplicate %s specification at %C", tag->name);
1648627f7eb2Smrg return MATCH_ERROR;
1649627f7eb2Smrg }
1650627f7eb2Smrg o->share = gfc_get_character_expr (gfc_default_character_kind,
1651627f7eb2Smrg &gfc_current_locus, "denyrw", 6);
1652627f7eb2Smrg return MATCH_YES;
1653627f7eb2Smrg }
1654627f7eb2Smrg
1655627f7eb2Smrg /* We handle all DEC tags above. */
1656627f7eb2Smrg gcc_unreachable ();
1657627f7eb2Smrg }
1658627f7eb2Smrg
1659627f7eb2Smrg
1660627f7eb2Smrg /* Resolution of the FORMAT tag, to be called from resolve_tag. */
1661627f7eb2Smrg
1662627f7eb2Smrg static bool
resolve_tag_format(gfc_expr * e)1663627f7eb2Smrg resolve_tag_format (gfc_expr *e)
1664627f7eb2Smrg {
1665627f7eb2Smrg if (e->expr_type == EXPR_CONSTANT
1666627f7eb2Smrg && (e->ts.type != BT_CHARACTER
1667627f7eb2Smrg || e->ts.kind != gfc_default_character_kind))
1668627f7eb2Smrg {
1669627f7eb2Smrg gfc_error ("Constant expression in FORMAT tag at %L must be "
1670627f7eb2Smrg "of type default CHARACTER", &e->where);
1671627f7eb2Smrg return false;
1672627f7eb2Smrg }
1673627f7eb2Smrg
1674627f7eb2Smrg /* Concatenate a constant character array into a single character
1675627f7eb2Smrg expression. */
1676627f7eb2Smrg
1677627f7eb2Smrg if ((e->expr_type == EXPR_ARRAY || e->rank > 0)
1678627f7eb2Smrg && e->ts.type == BT_CHARACTER
1679627f7eb2Smrg && gfc_is_constant_expr (e))
1680627f7eb2Smrg {
1681627f7eb2Smrg if (e->expr_type == EXPR_VARIABLE
1682627f7eb2Smrg && e->symtree->n.sym->attr.flavor == FL_PARAMETER)
1683627f7eb2Smrg gfc_simplify_expr (e, 1);
1684627f7eb2Smrg
1685627f7eb2Smrg if (e->expr_type == EXPR_ARRAY)
1686627f7eb2Smrg {
1687627f7eb2Smrg gfc_constructor *c;
1688627f7eb2Smrg gfc_charlen_t n, len;
1689627f7eb2Smrg gfc_expr *r;
1690627f7eb2Smrg gfc_char_t *dest, *src;
1691627f7eb2Smrg
1692627f7eb2Smrg if (e->value.constructor == NULL)
1693627f7eb2Smrg {
1694*4c3eb207Smrg gfc_error ("FORMAT tag at %L cannot be a zero-sized array",
1695*4c3eb207Smrg &e->where);
1696627f7eb2Smrg return false;
1697627f7eb2Smrg }
1698627f7eb2Smrg
1699627f7eb2Smrg n = 0;
1700627f7eb2Smrg c = gfc_constructor_first (e->value.constructor);
1701627f7eb2Smrg len = c->expr->value.character.length;
1702627f7eb2Smrg
1703627f7eb2Smrg for ( ; c; c = gfc_constructor_next (c))
1704627f7eb2Smrg n += len;
1705627f7eb2Smrg
1706627f7eb2Smrg r = gfc_get_character_expr (e->ts.kind, &e->where, NULL, n);
1707627f7eb2Smrg dest = r->value.character.string;
1708627f7eb2Smrg
1709627f7eb2Smrg for (c = gfc_constructor_first (e->value.constructor);
1710627f7eb2Smrg c; c = gfc_constructor_next (c))
1711627f7eb2Smrg {
1712627f7eb2Smrg src = c->expr->value.character.string;
1713627f7eb2Smrg for (gfc_charlen_t i = 0 ; i < len; i++)
1714627f7eb2Smrg *dest++ = *src++;
1715627f7eb2Smrg }
1716627f7eb2Smrg
1717627f7eb2Smrg gfc_replace_expr (e, r);
1718627f7eb2Smrg return true;
1719627f7eb2Smrg }
1720627f7eb2Smrg }
1721627f7eb2Smrg
1722627f7eb2Smrg /* If e's rank is zero and e is not an element of an array, it should be
1723627f7eb2Smrg of integer or character type. The integer variable should be
1724627f7eb2Smrg ASSIGNED. */
1725627f7eb2Smrg if (e->rank == 0
1726627f7eb2Smrg && (e->expr_type != EXPR_VARIABLE
1727627f7eb2Smrg || e->symtree == NULL
1728627f7eb2Smrg || e->symtree->n.sym->as == NULL
1729627f7eb2Smrg || e->symtree->n.sym->as->rank == 0))
1730627f7eb2Smrg {
1731627f7eb2Smrg if ((e->ts.type != BT_CHARACTER
1732627f7eb2Smrg || e->ts.kind != gfc_default_character_kind)
1733627f7eb2Smrg && e->ts.type != BT_INTEGER)
1734627f7eb2Smrg {
1735627f7eb2Smrg gfc_error ("FORMAT tag at %L must be of type default-kind CHARACTER "
1736627f7eb2Smrg "or of INTEGER", &e->where);
1737627f7eb2Smrg return false;
1738627f7eb2Smrg }
1739627f7eb2Smrg else if (e->ts.type == BT_INTEGER && e->expr_type == EXPR_VARIABLE)
1740627f7eb2Smrg {
1741627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F95_DEL, "ASSIGNED variable in "
1742627f7eb2Smrg "FORMAT tag at %L", &e->where))
1743627f7eb2Smrg return false;
1744627f7eb2Smrg if (e->symtree->n.sym->attr.assign != 1)
1745627f7eb2Smrg {
1746627f7eb2Smrg gfc_error ("Variable %qs at %L has not been assigned a "
1747627f7eb2Smrg "format label", e->symtree->n.sym->name, &e->where);
1748627f7eb2Smrg return false;
1749627f7eb2Smrg }
1750627f7eb2Smrg }
1751627f7eb2Smrg else if (e->ts.type == BT_INTEGER)
1752627f7eb2Smrg {
1753627f7eb2Smrg gfc_error ("Scalar %qs in FORMAT tag at %L is not an ASSIGNED "
1754627f7eb2Smrg "variable", gfc_basic_typename (e->ts.type), &e->where);
1755627f7eb2Smrg return false;
1756627f7eb2Smrg }
1757627f7eb2Smrg
1758627f7eb2Smrg return true;
1759627f7eb2Smrg }
1760627f7eb2Smrg
1761627f7eb2Smrg /* If rank is nonzero and type is not character, we allow it under GFC_STD_LEGACY.
1762627f7eb2Smrg It may be assigned an Hollerith constant. */
1763627f7eb2Smrg if (e->ts.type != BT_CHARACTER)
1764627f7eb2Smrg {
1765*4c3eb207Smrg if (e->ts.type == BT_DERIVED || e->ts.type == BT_CLASS
1766*4c3eb207Smrg || e->ts.type == BT_VOID || e->ts.type == BT_UNKNOWN)
1767*4c3eb207Smrg {
1768*4c3eb207Smrg gfc_error ("Non-character non-Hollerith in FORMAT tag at %L",
1769*4c3eb207Smrg &e->where);
1770*4c3eb207Smrg return false;
1771*4c3eb207Smrg }
1772627f7eb2Smrg if (!gfc_notify_std (GFC_STD_LEGACY, "Non-character in FORMAT tag "
1773627f7eb2Smrg "at %L", &e->where))
1774627f7eb2Smrg return false;
1775627f7eb2Smrg
1776627f7eb2Smrg if (e->rank == 0 && e->symtree->n.sym->as->type == AS_ASSUMED_SHAPE)
1777627f7eb2Smrg {
1778627f7eb2Smrg gfc_error ("Non-character assumed shape array element in FORMAT"
1779627f7eb2Smrg " tag at %L", &e->where);
1780627f7eb2Smrg return false;
1781627f7eb2Smrg }
1782627f7eb2Smrg
1783627f7eb2Smrg if (e->rank == 0 && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
1784627f7eb2Smrg {
1785627f7eb2Smrg gfc_error ("Non-character assumed size array element in FORMAT"
1786627f7eb2Smrg " tag at %L", &e->where);
1787627f7eb2Smrg return false;
1788627f7eb2Smrg }
1789627f7eb2Smrg
1790627f7eb2Smrg if (e->rank == 0 && e->symtree->n.sym->attr.pointer)
1791627f7eb2Smrg {
1792627f7eb2Smrg gfc_error ("Non-character pointer array element in FORMAT tag at %L",
1793627f7eb2Smrg &e->where);
1794627f7eb2Smrg return false;
1795627f7eb2Smrg }
1796627f7eb2Smrg }
1797627f7eb2Smrg
1798627f7eb2Smrg return true;
1799627f7eb2Smrg }
1800627f7eb2Smrg
1801627f7eb2Smrg
1802627f7eb2Smrg /* Do expression resolution and type-checking on an expression tag. */
1803627f7eb2Smrg
1804627f7eb2Smrg static bool
resolve_tag(const io_tag * tag,gfc_expr * e)1805627f7eb2Smrg resolve_tag (const io_tag *tag, gfc_expr *e)
1806627f7eb2Smrg {
1807627f7eb2Smrg if (e == NULL)
1808627f7eb2Smrg return true;
1809627f7eb2Smrg
1810627f7eb2Smrg if (!gfc_resolve_expr (e))
1811627f7eb2Smrg return false;
1812627f7eb2Smrg
1813627f7eb2Smrg if (tag == &tag_format)
1814627f7eb2Smrg return resolve_tag_format (e);
1815627f7eb2Smrg
1816627f7eb2Smrg if (e->ts.type != tag->type)
1817627f7eb2Smrg {
1818627f7eb2Smrg gfc_error ("%s tag at %L must be of type %s", tag->name,
1819627f7eb2Smrg &e->where, gfc_basic_typename (tag->type));
1820627f7eb2Smrg return false;
1821627f7eb2Smrg }
1822627f7eb2Smrg
1823627f7eb2Smrg if (e->ts.type == BT_CHARACTER && e->ts.kind != gfc_default_character_kind)
1824627f7eb2Smrg {
1825627f7eb2Smrg gfc_error ("%s tag at %L must be a character string of default kind",
1826627f7eb2Smrg tag->name, &e->where);
1827627f7eb2Smrg return false;
1828627f7eb2Smrg }
1829627f7eb2Smrg
1830627f7eb2Smrg if (e->rank != 0)
1831627f7eb2Smrg {
1832627f7eb2Smrg gfc_error ("%s tag at %L must be scalar", tag->name, &e->where);
1833627f7eb2Smrg return false;
1834627f7eb2Smrg }
1835627f7eb2Smrg
1836627f7eb2Smrg if (tag == &tag_iomsg)
1837627f7eb2Smrg {
1838627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "IOMSG tag at %L", &e->where))
1839627f7eb2Smrg return false;
1840627f7eb2Smrg }
1841627f7eb2Smrg
1842627f7eb2Smrg if ((tag == &tag_iostat || tag == &tag_size || tag == &tag_iolength
1843627f7eb2Smrg || tag == &tag_number || tag == &tag_nextrec || tag == &tag_s_recl)
1844627f7eb2Smrg && e->ts.kind != gfc_default_integer_kind)
1845627f7eb2Smrg {
1846627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Fortran 95 requires default "
1847627f7eb2Smrg "INTEGER in %s tag at %L", tag->name, &e->where))
1848627f7eb2Smrg return false;
1849627f7eb2Smrg }
1850627f7eb2Smrg
1851627f7eb2Smrg if (e->ts.kind != gfc_default_logical_kind &&
1852627f7eb2Smrg (tag == &tag_exist || tag == &tag_named || tag == &tag_opened
1853627f7eb2Smrg || tag == &tag_pending))
1854627f7eb2Smrg {
1855627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2008, "Non-default LOGICAL kind "
1856627f7eb2Smrg "in %s tag at %L", tag->name, &e->where))
1857627f7eb2Smrg return false;
1858627f7eb2Smrg }
1859627f7eb2Smrg
1860627f7eb2Smrg if (tag == &tag_newunit)
1861627f7eb2Smrg {
1862627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2008, "NEWUNIT specifier at %L",
1863627f7eb2Smrg &e->where))
1864627f7eb2Smrg return false;
1865627f7eb2Smrg }
1866627f7eb2Smrg
1867627f7eb2Smrg /* NEWUNIT, IOSTAT, SIZE and IOMSG are variable definition contexts. */
1868627f7eb2Smrg if (tag == &tag_newunit || tag == &tag_iostat
1869627f7eb2Smrg || tag == &tag_size || tag == &tag_iomsg)
1870627f7eb2Smrg {
1871627f7eb2Smrg char context[64];
1872627f7eb2Smrg
1873627f7eb2Smrg sprintf (context, _("%s tag"), tag->name);
1874627f7eb2Smrg if (!gfc_check_vardef_context (e, false, false, false, context))
1875627f7eb2Smrg return false;
1876627f7eb2Smrg }
1877627f7eb2Smrg
1878627f7eb2Smrg if (tag == &tag_convert)
1879627f7eb2Smrg {
1880627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "CONVERT tag at %L", &e->where))
1881627f7eb2Smrg return false;
1882627f7eb2Smrg }
1883627f7eb2Smrg
1884627f7eb2Smrg return true;
1885627f7eb2Smrg }
1886627f7eb2Smrg
1887627f7eb2Smrg
1888627f7eb2Smrg /* Match a single tag of an OPEN statement. */
1889627f7eb2Smrg
1890627f7eb2Smrg static match
match_open_element(gfc_open * open)1891627f7eb2Smrg match_open_element (gfc_open *open)
1892627f7eb2Smrg {
1893627f7eb2Smrg match m;
1894627f7eb2Smrg
1895627f7eb2Smrg m = match_etag (&tag_e_async, &open->asynchronous);
1896627f7eb2Smrg if (m != MATCH_NO)
1897627f7eb2Smrg return m;
1898627f7eb2Smrg m = match_etag (&tag_unit, &open->unit);
1899627f7eb2Smrg if (m != MATCH_NO)
1900627f7eb2Smrg return m;
1901627f7eb2Smrg m = match_etag (&tag_iomsg, &open->iomsg);
1902627f7eb2Smrg if (m != MATCH_NO)
1903627f7eb2Smrg return m;
1904627f7eb2Smrg m = match_out_tag (&tag_iostat, &open->iostat);
1905627f7eb2Smrg if (m != MATCH_NO)
1906627f7eb2Smrg return m;
1907627f7eb2Smrg m = match_etag (&tag_file, &open->file);
1908627f7eb2Smrg if (m != MATCH_NO)
1909627f7eb2Smrg return m;
1910627f7eb2Smrg m = match_etag (&tag_status, &open->status);
1911627f7eb2Smrg if (m != MATCH_NO)
1912627f7eb2Smrg return m;
1913627f7eb2Smrg m = match_etag (&tag_e_access, &open->access);
1914627f7eb2Smrg if (m != MATCH_NO)
1915627f7eb2Smrg return m;
1916627f7eb2Smrg m = match_etag (&tag_e_form, &open->form);
1917627f7eb2Smrg if (m != MATCH_NO)
1918627f7eb2Smrg return m;
1919627f7eb2Smrg m = match_etag (&tag_e_recl, &open->recl);
1920627f7eb2Smrg if (m != MATCH_NO)
1921627f7eb2Smrg return m;
1922627f7eb2Smrg m = match_etag (&tag_e_blank, &open->blank);
1923627f7eb2Smrg if (m != MATCH_NO)
1924627f7eb2Smrg return m;
1925627f7eb2Smrg m = match_etag (&tag_e_position, &open->position);
1926627f7eb2Smrg if (m != MATCH_NO)
1927627f7eb2Smrg return m;
1928627f7eb2Smrg m = match_etag (&tag_e_action, &open->action);
1929627f7eb2Smrg if (m != MATCH_NO)
1930627f7eb2Smrg return m;
1931627f7eb2Smrg m = match_etag (&tag_e_delim, &open->delim);
1932627f7eb2Smrg if (m != MATCH_NO)
1933627f7eb2Smrg return m;
1934627f7eb2Smrg m = match_etag (&tag_e_pad, &open->pad);
1935627f7eb2Smrg if (m != MATCH_NO)
1936627f7eb2Smrg return m;
1937627f7eb2Smrg m = match_etag (&tag_e_decimal, &open->decimal);
1938627f7eb2Smrg if (m != MATCH_NO)
1939627f7eb2Smrg return m;
1940627f7eb2Smrg m = match_etag (&tag_e_encoding, &open->encoding);
1941627f7eb2Smrg if (m != MATCH_NO)
1942627f7eb2Smrg return m;
1943627f7eb2Smrg m = match_etag (&tag_e_round, &open->round);
1944627f7eb2Smrg if (m != MATCH_NO)
1945627f7eb2Smrg return m;
1946627f7eb2Smrg m = match_etag (&tag_e_sign, &open->sign);
1947627f7eb2Smrg if (m != MATCH_NO)
1948627f7eb2Smrg return m;
1949627f7eb2Smrg m = match_ltag (&tag_err, &open->err);
1950627f7eb2Smrg if (m != MATCH_NO)
1951627f7eb2Smrg return m;
1952627f7eb2Smrg m = match_etag (&tag_convert, &open->convert);
1953627f7eb2Smrg if (m != MATCH_NO)
1954627f7eb2Smrg return m;
1955627f7eb2Smrg m = match_out_tag (&tag_newunit, &open->newunit);
1956627f7eb2Smrg if (m != MATCH_NO)
1957627f7eb2Smrg return m;
1958627f7eb2Smrg
1959627f7eb2Smrg /* The following are extensions enabled with -fdec. */
1960627f7eb2Smrg m = match_dec_etag (&tag_e_share, &open->share);
1961627f7eb2Smrg if (m != MATCH_NO)
1962627f7eb2Smrg return m;
1963627f7eb2Smrg m = match_dec_etag (&tag_cc, &open->cc);
1964627f7eb2Smrg if (m != MATCH_NO)
1965627f7eb2Smrg return m;
1966627f7eb2Smrg m = match_dec_ftag (&tag_readonly, open);
1967627f7eb2Smrg if (m != MATCH_NO)
1968627f7eb2Smrg return m;
1969627f7eb2Smrg m = match_dec_ftag (&tag_shared, open);
1970627f7eb2Smrg if (m != MATCH_NO)
1971627f7eb2Smrg return m;
1972627f7eb2Smrg m = match_dec_ftag (&tag_noshared, open);
1973627f7eb2Smrg if (m != MATCH_NO)
1974627f7eb2Smrg return m;
1975627f7eb2Smrg
1976627f7eb2Smrg return MATCH_NO;
1977627f7eb2Smrg }
1978627f7eb2Smrg
1979627f7eb2Smrg
1980627f7eb2Smrg /* Free the gfc_open structure and all the expressions it contains. */
1981627f7eb2Smrg
1982627f7eb2Smrg void
gfc_free_open(gfc_open * open)1983627f7eb2Smrg gfc_free_open (gfc_open *open)
1984627f7eb2Smrg {
1985627f7eb2Smrg if (open == NULL)
1986627f7eb2Smrg return;
1987627f7eb2Smrg
1988627f7eb2Smrg gfc_free_expr (open->unit);
1989627f7eb2Smrg gfc_free_expr (open->iomsg);
1990627f7eb2Smrg gfc_free_expr (open->iostat);
1991627f7eb2Smrg gfc_free_expr (open->file);
1992627f7eb2Smrg gfc_free_expr (open->status);
1993627f7eb2Smrg gfc_free_expr (open->access);
1994627f7eb2Smrg gfc_free_expr (open->form);
1995627f7eb2Smrg gfc_free_expr (open->recl);
1996627f7eb2Smrg gfc_free_expr (open->blank);
1997627f7eb2Smrg gfc_free_expr (open->position);
1998627f7eb2Smrg gfc_free_expr (open->action);
1999627f7eb2Smrg gfc_free_expr (open->delim);
2000627f7eb2Smrg gfc_free_expr (open->pad);
2001627f7eb2Smrg gfc_free_expr (open->decimal);
2002627f7eb2Smrg gfc_free_expr (open->encoding);
2003627f7eb2Smrg gfc_free_expr (open->round);
2004627f7eb2Smrg gfc_free_expr (open->sign);
2005627f7eb2Smrg gfc_free_expr (open->convert);
2006627f7eb2Smrg gfc_free_expr (open->asynchronous);
2007627f7eb2Smrg gfc_free_expr (open->newunit);
2008627f7eb2Smrg gfc_free_expr (open->share);
2009627f7eb2Smrg gfc_free_expr (open->cc);
2010627f7eb2Smrg free (open);
2011627f7eb2Smrg }
2012627f7eb2Smrg
2013627f7eb2Smrg
2014*4c3eb207Smrg static int
2015*4c3eb207Smrg compare_to_allowed_values (const char *specifier, const char *allowed[],
2016*4c3eb207Smrg const char *allowed_f2003[],
2017*4c3eb207Smrg const char *allowed_gnu[], gfc_char_t *value,
2018*4c3eb207Smrg const char *statement, bool warn, locus *where,
2019*4c3eb207Smrg int *num = NULL);
2020*4c3eb207Smrg
2021*4c3eb207Smrg
2022*4c3eb207Smrg static bool
2023*4c3eb207Smrg check_open_constraints (gfc_open *open, locus *where);
2024*4c3eb207Smrg
2025627f7eb2Smrg /* Resolve everything in a gfc_open structure. */
2026627f7eb2Smrg
2027627f7eb2Smrg bool
gfc_resolve_open(gfc_open * open,locus * where)2028*4c3eb207Smrg gfc_resolve_open (gfc_open *open, locus *where)
2029627f7eb2Smrg {
2030627f7eb2Smrg RESOLVE_TAG (&tag_unit, open->unit);
2031627f7eb2Smrg RESOLVE_TAG (&tag_iomsg, open->iomsg);
2032627f7eb2Smrg RESOLVE_TAG (&tag_iostat, open->iostat);
2033627f7eb2Smrg RESOLVE_TAG (&tag_file, open->file);
2034627f7eb2Smrg RESOLVE_TAG (&tag_status, open->status);
2035627f7eb2Smrg RESOLVE_TAG (&tag_e_access, open->access);
2036627f7eb2Smrg RESOLVE_TAG (&tag_e_form, open->form);
2037627f7eb2Smrg RESOLVE_TAG (&tag_e_recl, open->recl);
2038627f7eb2Smrg RESOLVE_TAG (&tag_e_blank, open->blank);
2039627f7eb2Smrg RESOLVE_TAG (&tag_e_position, open->position);
2040627f7eb2Smrg RESOLVE_TAG (&tag_e_action, open->action);
2041627f7eb2Smrg RESOLVE_TAG (&tag_e_delim, open->delim);
2042627f7eb2Smrg RESOLVE_TAG (&tag_e_pad, open->pad);
2043627f7eb2Smrg RESOLVE_TAG (&tag_e_decimal, open->decimal);
2044627f7eb2Smrg RESOLVE_TAG (&tag_e_encoding, open->encoding);
2045627f7eb2Smrg RESOLVE_TAG (&tag_e_async, open->asynchronous);
2046627f7eb2Smrg RESOLVE_TAG (&tag_e_round, open->round);
2047627f7eb2Smrg RESOLVE_TAG (&tag_e_sign, open->sign);
2048627f7eb2Smrg RESOLVE_TAG (&tag_convert, open->convert);
2049627f7eb2Smrg RESOLVE_TAG (&tag_newunit, open->newunit);
2050627f7eb2Smrg RESOLVE_TAG (&tag_e_share, open->share);
2051627f7eb2Smrg RESOLVE_TAG (&tag_cc, open->cc);
2052627f7eb2Smrg
2053627f7eb2Smrg if (!gfc_reference_st_label (open->err, ST_LABEL_TARGET))
2054627f7eb2Smrg return false;
2055627f7eb2Smrg
2056*4c3eb207Smrg return check_open_constraints (open, where);
2057627f7eb2Smrg }
2058627f7eb2Smrg
2059627f7eb2Smrg
2060627f7eb2Smrg /* Check if a given value for a SPECIFIER is either in the list of values
2061627f7eb2Smrg allowed in F95 or F2003, issuing an error message and returning a zero
2062627f7eb2Smrg value if it is not allowed. */
2063627f7eb2Smrg
2064627f7eb2Smrg
2065627f7eb2Smrg static int
compare_to_allowed_values(const char * specifier,const char * allowed[],const char * allowed_f2003[],const char * allowed_gnu[],gfc_char_t * value,const char * statement,bool warn,locus * where,int * num)2066627f7eb2Smrg compare_to_allowed_values (const char *specifier, const char *allowed[],
2067627f7eb2Smrg const char *allowed_f2003[],
2068627f7eb2Smrg const char *allowed_gnu[], gfc_char_t *value,
2069*4c3eb207Smrg const char *statement, bool warn, locus *where,
2070*4c3eb207Smrg int *num)
2071627f7eb2Smrg {
2072627f7eb2Smrg int i;
2073627f7eb2Smrg unsigned int len;
2074627f7eb2Smrg
2075627f7eb2Smrg len = gfc_wide_strlen (value);
2076627f7eb2Smrg if (len > 0)
2077627f7eb2Smrg {
2078627f7eb2Smrg for (len--; len > 0; len--)
2079627f7eb2Smrg if (value[len] != ' ')
2080627f7eb2Smrg break;
2081627f7eb2Smrg len++;
2082627f7eb2Smrg }
2083627f7eb2Smrg
2084627f7eb2Smrg for (i = 0; allowed[i]; i++)
2085627f7eb2Smrg if (len == strlen (allowed[i])
2086627f7eb2Smrg && gfc_wide_strncasecmp (value, allowed[i], strlen (allowed[i])) == 0)
2087627f7eb2Smrg {
2088627f7eb2Smrg if (num)
2089627f7eb2Smrg *num = i;
2090627f7eb2Smrg return 1;
2091627f7eb2Smrg }
2092627f7eb2Smrg
2093*4c3eb207Smrg if (!where)
2094*4c3eb207Smrg where = &gfc_current_locus;
2095*4c3eb207Smrg
2096627f7eb2Smrg for (i = 0; allowed_f2003 && allowed_f2003[i]; i++)
2097627f7eb2Smrg if (len == strlen (allowed_f2003[i])
2098627f7eb2Smrg && gfc_wide_strncasecmp (value, allowed_f2003[i],
2099627f7eb2Smrg strlen (allowed_f2003[i])) == 0)
2100627f7eb2Smrg {
2101627f7eb2Smrg notification n = gfc_notification_std (GFC_STD_F2003);
2102627f7eb2Smrg
2103627f7eb2Smrg if (n == WARNING || (warn && n == ERROR))
2104627f7eb2Smrg {
2105*4c3eb207Smrg gfc_warning (0, "Fortran 2003: %s specifier in %s statement at %L "
2106*4c3eb207Smrg "has value %qs", specifier, statement, where,
2107627f7eb2Smrg allowed_f2003[i]);
2108627f7eb2Smrg return 1;
2109627f7eb2Smrg }
2110627f7eb2Smrg else
2111627f7eb2Smrg if (n == ERROR)
2112627f7eb2Smrg {
2113627f7eb2Smrg gfc_notify_std (GFC_STD_F2003, "%s specifier in "
2114*4c3eb207Smrg "%s statement at %L has value %qs", specifier,
2115*4c3eb207Smrg statement, where, allowed_f2003[i]);
2116627f7eb2Smrg return 0;
2117627f7eb2Smrg }
2118627f7eb2Smrg
2119627f7eb2Smrg /* n == SILENT */
2120627f7eb2Smrg return 1;
2121627f7eb2Smrg }
2122627f7eb2Smrg
2123627f7eb2Smrg for (i = 0; allowed_gnu && allowed_gnu[i]; i++)
2124627f7eb2Smrg if (len == strlen (allowed_gnu[i])
2125627f7eb2Smrg && gfc_wide_strncasecmp (value, allowed_gnu[i],
2126627f7eb2Smrg strlen (allowed_gnu[i])) == 0)
2127627f7eb2Smrg {
2128627f7eb2Smrg notification n = gfc_notification_std (GFC_STD_GNU);
2129627f7eb2Smrg
2130627f7eb2Smrg if (n == WARNING || (warn && n == ERROR))
2131627f7eb2Smrg {
2132*4c3eb207Smrg gfc_warning (0, "Extension: %s specifier in %s statement at %L "
2133*4c3eb207Smrg "has value %qs", specifier, statement, where,
2134627f7eb2Smrg allowed_gnu[i]);
2135627f7eb2Smrg return 1;
2136627f7eb2Smrg }
2137627f7eb2Smrg else
2138627f7eb2Smrg if (n == ERROR)
2139627f7eb2Smrg {
2140627f7eb2Smrg gfc_notify_std (GFC_STD_GNU, "%s specifier in "
2141*4c3eb207Smrg "%s statement at %L has value %qs", specifier,
2142*4c3eb207Smrg statement, where, allowed_gnu[i]);
2143627f7eb2Smrg return 0;
2144627f7eb2Smrg }
2145627f7eb2Smrg
2146627f7eb2Smrg /* n == SILENT */
2147627f7eb2Smrg return 1;
2148627f7eb2Smrg }
2149627f7eb2Smrg
2150627f7eb2Smrg if (warn)
2151627f7eb2Smrg {
2152627f7eb2Smrg char *s = gfc_widechar_to_char (value, -1);
2153627f7eb2Smrg gfc_warning (0,
2154*4c3eb207Smrg "%s specifier in %s statement at %L has invalid value %qs",
2155*4c3eb207Smrg specifier, statement, where, s);
2156627f7eb2Smrg free (s);
2157627f7eb2Smrg return 1;
2158627f7eb2Smrg }
2159627f7eb2Smrg else
2160627f7eb2Smrg {
2161627f7eb2Smrg char *s = gfc_widechar_to_char (value, -1);
2162*4c3eb207Smrg gfc_error ("%s specifier in %s statement at %L has invalid value %qs",
2163*4c3eb207Smrg specifier, statement, where, s);
2164627f7eb2Smrg free (s);
2165627f7eb2Smrg return 0;
2166627f7eb2Smrg }
2167627f7eb2Smrg }
2168627f7eb2Smrg
2169627f7eb2Smrg
2170*4c3eb207Smrg /* Check constraints on the OPEN statement.
2171*4c3eb207Smrg Similar to check_io_constraints for data transfer statements.
2172*4c3eb207Smrg At this point all tags have already been resolved via resolve_tag, which,
2173*4c3eb207Smrg among other things, verifies that BT_CHARACTER tags are of default kind. */
2174*4c3eb207Smrg
2175*4c3eb207Smrg static bool
check_open_constraints(gfc_open * open,locus * where)2176*4c3eb207Smrg check_open_constraints (gfc_open *open, locus *where)
2177*4c3eb207Smrg {
2178*4c3eb207Smrg #define warn_or_error(...) \
2179*4c3eb207Smrg { \
2180*4c3eb207Smrg if (warn) \
2181*4c3eb207Smrg gfc_warning (0, __VA_ARGS__); \
2182*4c3eb207Smrg else \
2183*4c3eb207Smrg { \
2184*4c3eb207Smrg gfc_error (__VA_ARGS__); \
2185*4c3eb207Smrg return false; \
2186*4c3eb207Smrg } \
2187*4c3eb207Smrg }
2188*4c3eb207Smrg
2189*4c3eb207Smrg bool warn = (open->err || open->iostat) ? true : false;
2190*4c3eb207Smrg
2191*4c3eb207Smrg /* Checks on the ACCESS specifier. */
2192*4c3eb207Smrg if (open->access && open->access->expr_type == EXPR_CONSTANT)
2193*4c3eb207Smrg {
2194*4c3eb207Smrg static const char *access_f95[] = { "SEQUENTIAL", "DIRECT", NULL };
2195*4c3eb207Smrg static const char *access_f2003[] = { "STREAM", NULL };
2196*4c3eb207Smrg static const char *access_gnu[] = { "APPEND", NULL };
2197*4c3eb207Smrg
2198*4c3eb207Smrg if (!compare_to_allowed_values ("ACCESS", access_f95, access_f2003,
2199*4c3eb207Smrg access_gnu,
2200*4c3eb207Smrg open->access->value.character.string,
2201*4c3eb207Smrg "OPEN", warn, &open->access->where))
2202*4c3eb207Smrg return false;
2203*4c3eb207Smrg }
2204*4c3eb207Smrg
2205*4c3eb207Smrg /* Checks on the ACTION specifier. */
2206*4c3eb207Smrg if (open->action && open->action->expr_type == EXPR_CONSTANT)
2207*4c3eb207Smrg {
2208*4c3eb207Smrg gfc_char_t *str = open->action->value.character.string;
2209*4c3eb207Smrg static const char *action[] = { "READ", "WRITE", "READWRITE", NULL };
2210*4c3eb207Smrg
2211*4c3eb207Smrg if (!compare_to_allowed_values ("ACTION", action, NULL, NULL,
2212*4c3eb207Smrg str, "OPEN", warn, &open->action->where))
2213*4c3eb207Smrg return false;
2214*4c3eb207Smrg
2215*4c3eb207Smrg /* With READONLY, only allow ACTION='READ'. */
2216*4c3eb207Smrg if (open->readonly && (gfc_wide_strlen (str) != 4
2217*4c3eb207Smrg || gfc_wide_strncasecmp (str, "READ", 4) != 0))
2218*4c3eb207Smrg {
2219*4c3eb207Smrg gfc_error ("ACTION type conflicts with READONLY specifier at %L",
2220*4c3eb207Smrg &open->action->where);
2221*4c3eb207Smrg return false;
2222*4c3eb207Smrg }
2223*4c3eb207Smrg }
2224*4c3eb207Smrg
2225*4c3eb207Smrg /* If we see READONLY and no ACTION, set ACTION='READ'. */
2226*4c3eb207Smrg else if (open->readonly && open->action == NULL)
2227*4c3eb207Smrg {
2228*4c3eb207Smrg open->action = gfc_get_character_expr (gfc_default_character_kind,
2229*4c3eb207Smrg &gfc_current_locus, "read", 4);
2230*4c3eb207Smrg }
2231*4c3eb207Smrg
2232*4c3eb207Smrg /* Checks on the ASYNCHRONOUS specifier. */
2233*4c3eb207Smrg if (open->asynchronous)
2234*4c3eb207Smrg {
2235*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "ASYNCHRONOUS= at %L "
2236*4c3eb207Smrg "not allowed in Fortran 95",
2237*4c3eb207Smrg &open->asynchronous->where))
2238*4c3eb207Smrg return false;
2239*4c3eb207Smrg
2240*4c3eb207Smrg if (open->asynchronous->expr_type == EXPR_CONSTANT)
2241*4c3eb207Smrg {
2242*4c3eb207Smrg static const char * asynchronous[] = { "YES", "NO", NULL };
2243*4c3eb207Smrg
2244*4c3eb207Smrg if (!compare_to_allowed_values ("ASYNCHRONOUS", asynchronous,
2245*4c3eb207Smrg NULL, NULL, open->asynchronous->value.character.string,
2246*4c3eb207Smrg "OPEN", warn, &open->asynchronous->where))
2247*4c3eb207Smrg return false;
2248*4c3eb207Smrg }
2249*4c3eb207Smrg }
2250*4c3eb207Smrg
2251*4c3eb207Smrg /* Checks on the BLANK specifier. */
2252*4c3eb207Smrg if (open->blank)
2253*4c3eb207Smrg {
2254*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %L "
2255*4c3eb207Smrg "not allowed in Fortran 95", &open->blank->where))
2256*4c3eb207Smrg return false;
2257*4c3eb207Smrg
2258*4c3eb207Smrg if (open->blank->expr_type == EXPR_CONSTANT)
2259*4c3eb207Smrg {
2260*4c3eb207Smrg static const char *blank[] = { "ZERO", "NULL", NULL };
2261*4c3eb207Smrg
2262*4c3eb207Smrg if (!compare_to_allowed_values ("BLANK", blank, NULL, NULL,
2263*4c3eb207Smrg open->blank->value.character.string,
2264*4c3eb207Smrg "OPEN", warn, &open->blank->where))
2265*4c3eb207Smrg return false;
2266*4c3eb207Smrg }
2267*4c3eb207Smrg }
2268*4c3eb207Smrg
2269*4c3eb207Smrg /* Checks on the CARRIAGECONTROL specifier. */
2270*4c3eb207Smrg if (open->cc && open->cc->expr_type == EXPR_CONSTANT)
2271*4c3eb207Smrg {
2272*4c3eb207Smrg static const char *cc[] = { "LIST", "FORTRAN", "NONE", NULL };
2273*4c3eb207Smrg if (!compare_to_allowed_values ("CARRIAGECONTROL", cc, NULL, NULL,
2274*4c3eb207Smrg open->cc->value.character.string,
2275*4c3eb207Smrg "OPEN", warn, &open->cc->where))
2276*4c3eb207Smrg return false;
2277*4c3eb207Smrg }
2278*4c3eb207Smrg
2279*4c3eb207Smrg /* Checks on the DECIMAL specifier. */
2280*4c3eb207Smrg if (open->decimal)
2281*4c3eb207Smrg {
2282*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %L "
2283*4c3eb207Smrg "not allowed in Fortran 95", &open->decimal->where))
2284*4c3eb207Smrg return false;
2285*4c3eb207Smrg
2286*4c3eb207Smrg if (open->decimal->expr_type == EXPR_CONSTANT)
2287*4c3eb207Smrg {
2288*4c3eb207Smrg static const char * decimal[] = { "COMMA", "POINT", NULL };
2289*4c3eb207Smrg
2290*4c3eb207Smrg if (!compare_to_allowed_values ("DECIMAL", decimal, NULL, NULL,
2291*4c3eb207Smrg open->decimal->value.character.string,
2292*4c3eb207Smrg "OPEN", warn, &open->decimal->where))
2293*4c3eb207Smrg return false;
2294*4c3eb207Smrg }
2295*4c3eb207Smrg }
2296*4c3eb207Smrg
2297*4c3eb207Smrg /* Checks on the DELIM specifier. */
2298*4c3eb207Smrg if (open->delim)
2299*4c3eb207Smrg {
2300*4c3eb207Smrg if (open->delim->expr_type == EXPR_CONSTANT)
2301*4c3eb207Smrg {
2302*4c3eb207Smrg static const char *delim[] = { "APOSTROPHE", "QUOTE", "NONE", NULL };
2303*4c3eb207Smrg
2304*4c3eb207Smrg if (!compare_to_allowed_values ("DELIM", delim, NULL, NULL,
2305*4c3eb207Smrg open->delim->value.character.string,
2306*4c3eb207Smrg "OPEN", warn, &open->delim->where))
2307*4c3eb207Smrg return false;
2308*4c3eb207Smrg }
2309*4c3eb207Smrg }
2310*4c3eb207Smrg
2311*4c3eb207Smrg /* Checks on the ENCODING specifier. */
2312*4c3eb207Smrg if (open->encoding)
2313*4c3eb207Smrg {
2314*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "ENCODING= at %L "
2315*4c3eb207Smrg "not allowed in Fortran 95", &open->encoding->where))
2316*4c3eb207Smrg return false;
2317*4c3eb207Smrg
2318*4c3eb207Smrg if (open->encoding->expr_type == EXPR_CONSTANT)
2319*4c3eb207Smrg {
2320*4c3eb207Smrg static const char * encoding[] = { "DEFAULT", "UTF-8", NULL };
2321*4c3eb207Smrg
2322*4c3eb207Smrg if (!compare_to_allowed_values ("ENCODING", encoding, NULL, NULL,
2323*4c3eb207Smrg open->encoding->value.character.string,
2324*4c3eb207Smrg "OPEN", warn, &open->encoding->where))
2325*4c3eb207Smrg return false;
2326*4c3eb207Smrg }
2327*4c3eb207Smrg }
2328*4c3eb207Smrg
2329*4c3eb207Smrg /* Checks on the FORM specifier. */
2330*4c3eb207Smrg if (open->form && open->form->expr_type == EXPR_CONSTANT)
2331*4c3eb207Smrg {
2332*4c3eb207Smrg static const char *form[] = { "FORMATTED", "UNFORMATTED", NULL };
2333*4c3eb207Smrg
2334*4c3eb207Smrg if (!compare_to_allowed_values ("FORM", form, NULL, NULL,
2335*4c3eb207Smrg open->form->value.character.string,
2336*4c3eb207Smrg "OPEN", warn, &open->form->where))
2337*4c3eb207Smrg return false;
2338*4c3eb207Smrg }
2339*4c3eb207Smrg
2340*4c3eb207Smrg /* Checks on the PAD specifier. */
2341*4c3eb207Smrg if (open->pad && open->pad->expr_type == EXPR_CONSTANT)
2342*4c3eb207Smrg {
2343*4c3eb207Smrg static const char *pad[] = { "YES", "NO", NULL };
2344*4c3eb207Smrg
2345*4c3eb207Smrg if (!compare_to_allowed_values ("PAD", pad, NULL, NULL,
2346*4c3eb207Smrg open->pad->value.character.string,
2347*4c3eb207Smrg "OPEN", warn, &open->pad->where))
2348*4c3eb207Smrg return false;
2349*4c3eb207Smrg }
2350*4c3eb207Smrg
2351*4c3eb207Smrg /* Checks on the POSITION specifier. */
2352*4c3eb207Smrg if (open->position && open->position->expr_type == EXPR_CONSTANT)
2353*4c3eb207Smrg {
2354*4c3eb207Smrg static const char *position[] = { "ASIS", "REWIND", "APPEND", NULL };
2355*4c3eb207Smrg
2356*4c3eb207Smrg if (!compare_to_allowed_values ("POSITION", position, NULL, NULL,
2357*4c3eb207Smrg open->position->value.character.string,
2358*4c3eb207Smrg "OPEN", warn, &open->position->where))
2359*4c3eb207Smrg return false;
2360*4c3eb207Smrg }
2361*4c3eb207Smrg
2362*4c3eb207Smrg /* Checks on the ROUND specifier. */
2363*4c3eb207Smrg if (open->round)
2364*4c3eb207Smrg {
2365*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %L "
2366*4c3eb207Smrg "not allowed in Fortran 95", &open->round->where))
2367*4c3eb207Smrg return false;
2368*4c3eb207Smrg
2369*4c3eb207Smrg if (open->round->expr_type == EXPR_CONSTANT)
2370*4c3eb207Smrg {
2371*4c3eb207Smrg static const char * round[] = { "UP", "DOWN", "ZERO", "NEAREST",
2372*4c3eb207Smrg "COMPATIBLE", "PROCESSOR_DEFINED",
2373*4c3eb207Smrg NULL };
2374*4c3eb207Smrg
2375*4c3eb207Smrg if (!compare_to_allowed_values ("ROUND", round, NULL, NULL,
2376*4c3eb207Smrg open->round->value.character.string,
2377*4c3eb207Smrg "OPEN", warn, &open->round->where))
2378*4c3eb207Smrg return false;
2379*4c3eb207Smrg }
2380*4c3eb207Smrg }
2381*4c3eb207Smrg
2382*4c3eb207Smrg /* Checks on the SHARE specifier. */
2383*4c3eb207Smrg if (open->share && open->share->expr_type == EXPR_CONSTANT)
2384*4c3eb207Smrg {
2385*4c3eb207Smrg static const char *share[] = { "DENYNONE", "DENYRW", NULL };
2386*4c3eb207Smrg if (!compare_to_allowed_values ("SHARE", share, NULL, NULL,
2387*4c3eb207Smrg open->share->value.character.string,
2388*4c3eb207Smrg "OPEN", warn, &open->share->where))
2389*4c3eb207Smrg return false;
2390*4c3eb207Smrg }
2391*4c3eb207Smrg
2392*4c3eb207Smrg /* Checks on the SIGN specifier. */
2393*4c3eb207Smrg if (open->sign)
2394*4c3eb207Smrg {
2395*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "SIGN= at %L "
2396*4c3eb207Smrg "not allowed in Fortran 95", &open->sign->where))
2397*4c3eb207Smrg return false;
2398*4c3eb207Smrg
2399*4c3eb207Smrg if (open->sign->expr_type == EXPR_CONSTANT)
2400*4c3eb207Smrg {
2401*4c3eb207Smrg static const char * sign[] = { "PLUS", "SUPPRESS", "PROCESSOR_DEFINED",
2402*4c3eb207Smrg NULL };
2403*4c3eb207Smrg
2404*4c3eb207Smrg if (!compare_to_allowed_values ("SIGN", sign, NULL, NULL,
2405*4c3eb207Smrg open->sign->value.character.string,
2406*4c3eb207Smrg "OPEN", warn, &open->sign->where))
2407*4c3eb207Smrg return false;
2408*4c3eb207Smrg }
2409*4c3eb207Smrg }
2410*4c3eb207Smrg
2411*4c3eb207Smrg /* Checks on the RECL specifier. */
2412*4c3eb207Smrg if (open->recl && open->recl->expr_type == EXPR_CONSTANT
2413*4c3eb207Smrg && open->recl->ts.type == BT_INTEGER
2414*4c3eb207Smrg && mpz_sgn (open->recl->value.integer) != 1)
2415*4c3eb207Smrg {
2416*4c3eb207Smrg warn_or_error ("RECL in OPEN statement at %L must be positive",
2417*4c3eb207Smrg &open->recl->where);
2418*4c3eb207Smrg }
2419*4c3eb207Smrg
2420*4c3eb207Smrg /* Checks on the STATUS specifier. */
2421*4c3eb207Smrg if (open->status && open->status->expr_type == EXPR_CONSTANT)
2422*4c3eb207Smrg {
2423*4c3eb207Smrg static const char *status[] = { "OLD", "NEW", "SCRATCH",
2424*4c3eb207Smrg "REPLACE", "UNKNOWN", NULL };
2425*4c3eb207Smrg
2426*4c3eb207Smrg if (!compare_to_allowed_values ("STATUS", status, NULL, NULL,
2427*4c3eb207Smrg open->status->value.character.string,
2428*4c3eb207Smrg "OPEN", warn, &open->status->where))
2429*4c3eb207Smrg return false;
2430*4c3eb207Smrg
2431*4c3eb207Smrg /* F2003, 9.4.5: If the STATUS= specifier has the value NEW or REPLACE,
2432*4c3eb207Smrg the FILE= specifier shall appear. */
2433*4c3eb207Smrg if (open->file == NULL
2434*4c3eb207Smrg && (gfc_wide_strncasecmp (open->status->value.character.string,
2435*4c3eb207Smrg "replace", 7) == 0
2436*4c3eb207Smrg || gfc_wide_strncasecmp (open->status->value.character.string,
2437*4c3eb207Smrg "new", 3) == 0))
2438*4c3eb207Smrg {
2439*4c3eb207Smrg char *s = gfc_widechar_to_char (open->status->value.character.string,
2440*4c3eb207Smrg -1);
2441*4c3eb207Smrg warn_or_error ("The STATUS specified in OPEN statement at %L is "
2442*4c3eb207Smrg "%qs and no FILE specifier is present",
2443*4c3eb207Smrg &open->status->where, s);
2444*4c3eb207Smrg free (s);
2445*4c3eb207Smrg }
2446*4c3eb207Smrg
2447*4c3eb207Smrg /* F2003, 9.4.5: If the STATUS= specifier has the value SCRATCH,
2448*4c3eb207Smrg the FILE= specifier shall not appear. */
2449*4c3eb207Smrg if (gfc_wide_strncasecmp (open->status->value.character.string,
2450*4c3eb207Smrg "scratch", 7) == 0 && open->file)
2451*4c3eb207Smrg {
2452*4c3eb207Smrg warn_or_error ("The STATUS specified in OPEN statement at %L "
2453*4c3eb207Smrg "cannot have the value SCRATCH if a FILE specifier "
2454*4c3eb207Smrg "is present", &open->status->where);
2455*4c3eb207Smrg }
2456*4c3eb207Smrg }
2457*4c3eb207Smrg
2458*4c3eb207Smrg /* Checks on NEWUNIT specifier. */
2459*4c3eb207Smrg if (open->newunit)
2460*4c3eb207Smrg {
2461*4c3eb207Smrg if (open->unit)
2462*4c3eb207Smrg {
2463*4c3eb207Smrg gfc_error ("UNIT specifier not allowed with NEWUNIT at %L",
2464*4c3eb207Smrg &open->newunit->where);
2465*4c3eb207Smrg return false;
2466*4c3eb207Smrg }
2467*4c3eb207Smrg
2468*4c3eb207Smrg if (!open->file &&
2469*4c3eb207Smrg (!open->status ||
2470*4c3eb207Smrg (open->status->expr_type == EXPR_CONSTANT
2471*4c3eb207Smrg && gfc_wide_strncasecmp (open->status->value.character.string,
2472*4c3eb207Smrg "scratch", 7) != 0)))
2473*4c3eb207Smrg {
2474*4c3eb207Smrg gfc_error ("NEWUNIT specifier must have FILE= "
2475*4c3eb207Smrg "or STATUS='scratch' at %L", &open->newunit->where);
2476*4c3eb207Smrg return false;
2477*4c3eb207Smrg }
2478*4c3eb207Smrg }
2479*4c3eb207Smrg else if (!open->unit)
2480*4c3eb207Smrg {
2481*4c3eb207Smrg gfc_error ("OPEN statement at %L must have UNIT or NEWUNIT specified",
2482*4c3eb207Smrg where);
2483*4c3eb207Smrg return false;
2484*4c3eb207Smrg }
2485*4c3eb207Smrg
2486*4c3eb207Smrg /* Things that are not allowed for unformatted I/O. */
2487*4c3eb207Smrg if (open->form && open->form->expr_type == EXPR_CONSTANT
2488*4c3eb207Smrg && (open->delim || open->decimal || open->encoding || open->round
2489*4c3eb207Smrg || open->sign || open->pad || open->blank)
2490*4c3eb207Smrg && gfc_wide_strncasecmp (open->form->value.character.string,
2491*4c3eb207Smrg "unformatted", 11) == 0)
2492*4c3eb207Smrg {
2493*4c3eb207Smrg locus *loc;
2494*4c3eb207Smrg const char *spec;
2495*4c3eb207Smrg if (open->delim)
2496*4c3eb207Smrg {
2497*4c3eb207Smrg loc = &open->delim->where;
2498*4c3eb207Smrg spec = "DELIM ";
2499*4c3eb207Smrg }
2500*4c3eb207Smrg else if (open->pad)
2501*4c3eb207Smrg {
2502*4c3eb207Smrg loc = &open->pad->where;
2503*4c3eb207Smrg spec = "PAD ";
2504*4c3eb207Smrg }
2505*4c3eb207Smrg else if (open->blank)
2506*4c3eb207Smrg {
2507*4c3eb207Smrg loc = &open->blank->where;
2508*4c3eb207Smrg spec = "BLANK ";
2509*4c3eb207Smrg }
2510*4c3eb207Smrg else
2511*4c3eb207Smrg {
2512*4c3eb207Smrg loc = where;
2513*4c3eb207Smrg spec = "";
2514*4c3eb207Smrg }
2515*4c3eb207Smrg
2516*4c3eb207Smrg warn_or_error ("%s specifier at %L not allowed in OPEN statement for "
2517*4c3eb207Smrg "unformatted I/O", spec, loc);
2518*4c3eb207Smrg }
2519*4c3eb207Smrg
2520*4c3eb207Smrg if (open->recl && open->access && open->access->expr_type == EXPR_CONSTANT
2521*4c3eb207Smrg && gfc_wide_strncasecmp (open->access->value.character.string,
2522*4c3eb207Smrg "stream", 6) == 0)
2523*4c3eb207Smrg {
2524*4c3eb207Smrg warn_or_error ("RECL specifier not allowed in OPEN statement at %L for "
2525*4c3eb207Smrg "stream I/O", &open->recl->where);
2526*4c3eb207Smrg }
2527*4c3eb207Smrg
2528*4c3eb207Smrg if (open->position
2529*4c3eb207Smrg && open->access && open->access->expr_type == EXPR_CONSTANT
2530*4c3eb207Smrg && !(gfc_wide_strncasecmp (open->access->value.character.string,
2531*4c3eb207Smrg "sequential", 10) == 0
2532*4c3eb207Smrg || gfc_wide_strncasecmp (open->access->value.character.string,
2533*4c3eb207Smrg "stream", 6) == 0
2534*4c3eb207Smrg || gfc_wide_strncasecmp (open->access->value.character.string,
2535*4c3eb207Smrg "append", 6) == 0))
2536*4c3eb207Smrg {
2537*4c3eb207Smrg warn_or_error ("POSITION specifier in OPEN statement at %L only allowed "
2538*4c3eb207Smrg "for stream or sequential ACCESS", &open->position->where);
2539*4c3eb207Smrg }
2540*4c3eb207Smrg
2541*4c3eb207Smrg return true;
2542*4c3eb207Smrg #undef warn_or_error
2543*4c3eb207Smrg }
2544*4c3eb207Smrg
2545*4c3eb207Smrg
2546627f7eb2Smrg /* Match an OPEN statement. */
2547627f7eb2Smrg
2548627f7eb2Smrg match
gfc_match_open(void)2549627f7eb2Smrg gfc_match_open (void)
2550627f7eb2Smrg {
2551627f7eb2Smrg gfc_open *open;
2552627f7eb2Smrg match m;
2553627f7eb2Smrg
2554627f7eb2Smrg m = gfc_match_char ('(');
2555627f7eb2Smrg if (m == MATCH_NO)
2556627f7eb2Smrg return m;
2557627f7eb2Smrg
2558627f7eb2Smrg open = XCNEW (gfc_open);
2559627f7eb2Smrg
2560627f7eb2Smrg m = match_open_element (open);
2561627f7eb2Smrg
2562627f7eb2Smrg if (m == MATCH_ERROR)
2563627f7eb2Smrg goto cleanup;
2564627f7eb2Smrg if (m == MATCH_NO)
2565627f7eb2Smrg {
2566627f7eb2Smrg m = gfc_match_expr (&open->unit);
2567627f7eb2Smrg if (m == MATCH_ERROR)
2568627f7eb2Smrg goto cleanup;
2569627f7eb2Smrg }
2570627f7eb2Smrg
2571627f7eb2Smrg for (;;)
2572627f7eb2Smrg {
2573627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
2574627f7eb2Smrg break;
2575627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
2576627f7eb2Smrg goto syntax;
2577627f7eb2Smrg
2578627f7eb2Smrg m = match_open_element (open);
2579627f7eb2Smrg if (m == MATCH_ERROR)
2580627f7eb2Smrg goto cleanup;
2581627f7eb2Smrg if (m == MATCH_NO)
2582627f7eb2Smrg goto syntax;
2583627f7eb2Smrg }
2584627f7eb2Smrg
2585627f7eb2Smrg if (gfc_match_eos () == MATCH_NO)
2586627f7eb2Smrg goto syntax;
2587627f7eb2Smrg
2588627f7eb2Smrg if (gfc_pure (NULL))
2589627f7eb2Smrg {
2590627f7eb2Smrg gfc_error ("OPEN statement not allowed in PURE procedure at %C");
2591627f7eb2Smrg goto cleanup;
2592627f7eb2Smrg }
2593627f7eb2Smrg
2594627f7eb2Smrg gfc_unset_implicit_pure (NULL);
2595627f7eb2Smrg
2596627f7eb2Smrg new_st.op = EXEC_OPEN;
2597627f7eb2Smrg new_st.ext.open = open;
2598627f7eb2Smrg return MATCH_YES;
2599627f7eb2Smrg
2600627f7eb2Smrg syntax:
2601627f7eb2Smrg gfc_syntax_error (ST_OPEN);
2602627f7eb2Smrg
2603627f7eb2Smrg cleanup:
2604627f7eb2Smrg gfc_free_open (open);
2605627f7eb2Smrg return MATCH_ERROR;
2606627f7eb2Smrg }
2607627f7eb2Smrg
2608627f7eb2Smrg
2609627f7eb2Smrg /* Free a gfc_close structure an all its expressions. */
2610627f7eb2Smrg
2611627f7eb2Smrg void
gfc_free_close(gfc_close * close)2612627f7eb2Smrg gfc_free_close (gfc_close *close)
2613627f7eb2Smrg {
2614627f7eb2Smrg if (close == NULL)
2615627f7eb2Smrg return;
2616627f7eb2Smrg
2617627f7eb2Smrg gfc_free_expr (close->unit);
2618627f7eb2Smrg gfc_free_expr (close->iomsg);
2619627f7eb2Smrg gfc_free_expr (close->iostat);
2620627f7eb2Smrg gfc_free_expr (close->status);
2621627f7eb2Smrg free (close);
2622627f7eb2Smrg }
2623627f7eb2Smrg
2624627f7eb2Smrg
2625627f7eb2Smrg /* Match elements of a CLOSE statement. */
2626627f7eb2Smrg
2627627f7eb2Smrg static match
match_close_element(gfc_close * close)2628627f7eb2Smrg match_close_element (gfc_close *close)
2629627f7eb2Smrg {
2630627f7eb2Smrg match m;
2631627f7eb2Smrg
2632627f7eb2Smrg m = match_etag (&tag_unit, &close->unit);
2633627f7eb2Smrg if (m != MATCH_NO)
2634627f7eb2Smrg return m;
2635627f7eb2Smrg m = match_etag (&tag_status, &close->status);
2636627f7eb2Smrg if (m != MATCH_NO)
2637627f7eb2Smrg return m;
2638627f7eb2Smrg m = match_etag (&tag_iomsg, &close->iomsg);
2639627f7eb2Smrg if (m != MATCH_NO)
2640627f7eb2Smrg return m;
2641627f7eb2Smrg m = match_out_tag (&tag_iostat, &close->iostat);
2642627f7eb2Smrg if (m != MATCH_NO)
2643627f7eb2Smrg return m;
2644627f7eb2Smrg m = match_ltag (&tag_err, &close->err);
2645627f7eb2Smrg if (m != MATCH_NO)
2646627f7eb2Smrg return m;
2647627f7eb2Smrg
2648627f7eb2Smrg return MATCH_NO;
2649627f7eb2Smrg }
2650627f7eb2Smrg
2651627f7eb2Smrg
2652627f7eb2Smrg /* Match a CLOSE statement. */
2653627f7eb2Smrg
2654627f7eb2Smrg match
gfc_match_close(void)2655627f7eb2Smrg gfc_match_close (void)
2656627f7eb2Smrg {
2657627f7eb2Smrg gfc_close *close;
2658627f7eb2Smrg match m;
2659627f7eb2Smrg
2660627f7eb2Smrg m = gfc_match_char ('(');
2661627f7eb2Smrg if (m == MATCH_NO)
2662627f7eb2Smrg return m;
2663627f7eb2Smrg
2664627f7eb2Smrg close = XCNEW (gfc_close);
2665627f7eb2Smrg
2666627f7eb2Smrg m = match_close_element (close);
2667627f7eb2Smrg
2668627f7eb2Smrg if (m == MATCH_ERROR)
2669627f7eb2Smrg goto cleanup;
2670627f7eb2Smrg if (m == MATCH_NO)
2671627f7eb2Smrg {
2672627f7eb2Smrg m = gfc_match_expr (&close->unit);
2673627f7eb2Smrg if (m == MATCH_NO)
2674627f7eb2Smrg goto syntax;
2675627f7eb2Smrg if (m == MATCH_ERROR)
2676627f7eb2Smrg goto cleanup;
2677627f7eb2Smrg }
2678627f7eb2Smrg
2679627f7eb2Smrg for (;;)
2680627f7eb2Smrg {
2681627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
2682627f7eb2Smrg break;
2683627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
2684627f7eb2Smrg goto syntax;
2685627f7eb2Smrg
2686627f7eb2Smrg m = match_close_element (close);
2687627f7eb2Smrg if (m == MATCH_ERROR)
2688627f7eb2Smrg goto cleanup;
2689627f7eb2Smrg if (m == MATCH_NO)
2690627f7eb2Smrg goto syntax;
2691627f7eb2Smrg }
2692627f7eb2Smrg
2693627f7eb2Smrg if (gfc_match_eos () == MATCH_NO)
2694627f7eb2Smrg goto syntax;
2695627f7eb2Smrg
2696627f7eb2Smrg if (gfc_pure (NULL))
2697627f7eb2Smrg {
2698627f7eb2Smrg gfc_error ("CLOSE statement not allowed in PURE procedure at %C");
2699627f7eb2Smrg goto cleanup;
2700627f7eb2Smrg }
2701627f7eb2Smrg
2702627f7eb2Smrg gfc_unset_implicit_pure (NULL);
2703627f7eb2Smrg
2704627f7eb2Smrg new_st.op = EXEC_CLOSE;
2705627f7eb2Smrg new_st.ext.close = close;
2706627f7eb2Smrg return MATCH_YES;
2707627f7eb2Smrg
2708627f7eb2Smrg syntax:
2709627f7eb2Smrg gfc_syntax_error (ST_CLOSE);
2710627f7eb2Smrg
2711627f7eb2Smrg cleanup:
2712627f7eb2Smrg gfc_free_close (close);
2713627f7eb2Smrg return MATCH_ERROR;
2714627f7eb2Smrg }
2715627f7eb2Smrg
2716627f7eb2Smrg
2717*4c3eb207Smrg static bool
check_close_constraints(gfc_close * close,locus * where)2718*4c3eb207Smrg check_close_constraints (gfc_close *close, locus *where)
2719627f7eb2Smrg {
2720*4c3eb207Smrg bool warn = (close->iostat || close->err) ? true : false;
2721627f7eb2Smrg
2722627f7eb2Smrg if (close->unit == NULL)
2723627f7eb2Smrg {
2724*4c3eb207Smrg gfc_error ("CLOSE statement at %L requires a UNIT number", where);
2725627f7eb2Smrg return false;
2726627f7eb2Smrg }
2727627f7eb2Smrg
2728627f7eb2Smrg if (close->unit->expr_type == EXPR_CONSTANT
2729627f7eb2Smrg && close->unit->ts.type == BT_INTEGER
2730627f7eb2Smrg && mpz_sgn (close->unit->value.integer) < 0)
2731627f7eb2Smrg {
2732627f7eb2Smrg gfc_error ("UNIT number in CLOSE statement at %L must be non-negative",
2733627f7eb2Smrg &close->unit->where);
2734627f7eb2Smrg }
2735627f7eb2Smrg
2736*4c3eb207Smrg /* Checks on the STATUS specifier. */
2737*4c3eb207Smrg if (close->status && close->status->expr_type == EXPR_CONSTANT)
2738*4c3eb207Smrg {
2739*4c3eb207Smrg static const char *status[] = { "KEEP", "DELETE", NULL };
2740*4c3eb207Smrg
2741*4c3eb207Smrg if (!compare_to_allowed_values ("STATUS", status, NULL, NULL,
2742*4c3eb207Smrg close->status->value.character.string,
2743*4c3eb207Smrg "CLOSE", warn, &close->status->where))
2744*4c3eb207Smrg return false;
2745*4c3eb207Smrg }
2746*4c3eb207Smrg
2747627f7eb2Smrg return true;
2748627f7eb2Smrg }
2749627f7eb2Smrg
2750*4c3eb207Smrg /* Resolve everything in a gfc_close structure. */
2751*4c3eb207Smrg
2752*4c3eb207Smrg bool
gfc_resolve_close(gfc_close * close,locus * where)2753*4c3eb207Smrg gfc_resolve_close (gfc_close *close, locus *where)
2754*4c3eb207Smrg {
2755*4c3eb207Smrg RESOLVE_TAG (&tag_unit, close->unit);
2756*4c3eb207Smrg RESOLVE_TAG (&tag_iomsg, close->iomsg);
2757*4c3eb207Smrg RESOLVE_TAG (&tag_iostat, close->iostat);
2758*4c3eb207Smrg RESOLVE_TAG (&tag_status, close->status);
2759*4c3eb207Smrg
2760*4c3eb207Smrg if (!gfc_reference_st_label (close->err, ST_LABEL_TARGET))
2761*4c3eb207Smrg return false;
2762*4c3eb207Smrg
2763*4c3eb207Smrg return check_close_constraints (close, where);
2764*4c3eb207Smrg }
2765*4c3eb207Smrg
2766627f7eb2Smrg
2767627f7eb2Smrg /* Free a gfc_filepos structure. */
2768627f7eb2Smrg
2769627f7eb2Smrg void
gfc_free_filepos(gfc_filepos * fp)2770627f7eb2Smrg gfc_free_filepos (gfc_filepos *fp)
2771627f7eb2Smrg {
2772627f7eb2Smrg gfc_free_expr (fp->unit);
2773627f7eb2Smrg gfc_free_expr (fp->iomsg);
2774627f7eb2Smrg gfc_free_expr (fp->iostat);
2775627f7eb2Smrg free (fp);
2776627f7eb2Smrg }
2777627f7eb2Smrg
2778627f7eb2Smrg
2779627f7eb2Smrg /* Match elements of a REWIND, BACKSPACE, ENDFILE, or FLUSH statement. */
2780627f7eb2Smrg
2781627f7eb2Smrg static match
match_file_element(gfc_filepos * fp)2782627f7eb2Smrg match_file_element (gfc_filepos *fp)
2783627f7eb2Smrg {
2784627f7eb2Smrg match m;
2785627f7eb2Smrg
2786627f7eb2Smrg m = match_etag (&tag_unit, &fp->unit);
2787627f7eb2Smrg if (m != MATCH_NO)
2788627f7eb2Smrg return m;
2789627f7eb2Smrg m = match_etag (&tag_iomsg, &fp->iomsg);
2790627f7eb2Smrg if (m != MATCH_NO)
2791627f7eb2Smrg return m;
2792627f7eb2Smrg m = match_out_tag (&tag_iostat, &fp->iostat);
2793627f7eb2Smrg if (m != MATCH_NO)
2794627f7eb2Smrg return m;
2795627f7eb2Smrg m = match_ltag (&tag_err, &fp->err);
2796627f7eb2Smrg if (m != MATCH_NO)
2797627f7eb2Smrg return m;
2798627f7eb2Smrg
2799627f7eb2Smrg return MATCH_NO;
2800627f7eb2Smrg }
2801627f7eb2Smrg
2802627f7eb2Smrg
2803627f7eb2Smrg /* Match the second half of the file-positioning statements, REWIND,
2804627f7eb2Smrg BACKSPACE, ENDFILE, or the FLUSH statement. */
2805627f7eb2Smrg
2806627f7eb2Smrg static match
match_filepos(gfc_statement st,gfc_exec_op op)2807627f7eb2Smrg match_filepos (gfc_statement st, gfc_exec_op op)
2808627f7eb2Smrg {
2809627f7eb2Smrg gfc_filepos *fp;
2810627f7eb2Smrg match m;
2811627f7eb2Smrg
2812627f7eb2Smrg fp = XCNEW (gfc_filepos);
2813627f7eb2Smrg
2814627f7eb2Smrg if (gfc_match_char ('(') == MATCH_NO)
2815627f7eb2Smrg {
2816627f7eb2Smrg m = gfc_match_expr (&fp->unit);
2817627f7eb2Smrg if (m == MATCH_ERROR)
2818627f7eb2Smrg goto cleanup;
2819627f7eb2Smrg if (m == MATCH_NO)
2820627f7eb2Smrg goto syntax;
2821627f7eb2Smrg
2822627f7eb2Smrg goto done;
2823627f7eb2Smrg }
2824627f7eb2Smrg
2825627f7eb2Smrg m = match_file_element (fp);
2826627f7eb2Smrg if (m == MATCH_ERROR)
2827627f7eb2Smrg goto cleanup;
2828627f7eb2Smrg if (m == MATCH_NO)
2829627f7eb2Smrg {
2830627f7eb2Smrg m = gfc_match_expr (&fp->unit);
2831627f7eb2Smrg if (m == MATCH_ERROR || m == MATCH_NO)
2832627f7eb2Smrg goto syntax;
2833627f7eb2Smrg }
2834627f7eb2Smrg
2835627f7eb2Smrg for (;;)
2836627f7eb2Smrg {
2837627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
2838627f7eb2Smrg break;
2839627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
2840627f7eb2Smrg goto syntax;
2841627f7eb2Smrg
2842627f7eb2Smrg m = match_file_element (fp);
2843627f7eb2Smrg if (m == MATCH_ERROR)
2844627f7eb2Smrg goto cleanup;
2845627f7eb2Smrg if (m == MATCH_NO)
2846627f7eb2Smrg goto syntax;
2847627f7eb2Smrg }
2848627f7eb2Smrg
2849627f7eb2Smrg done:
2850627f7eb2Smrg if (gfc_match_eos () != MATCH_YES)
2851627f7eb2Smrg goto syntax;
2852627f7eb2Smrg
2853627f7eb2Smrg if (gfc_pure (NULL))
2854627f7eb2Smrg {
2855627f7eb2Smrg gfc_error ("%s statement not allowed in PURE procedure at %C",
2856627f7eb2Smrg gfc_ascii_statement (st));
2857627f7eb2Smrg
2858627f7eb2Smrg goto cleanup;
2859627f7eb2Smrg }
2860627f7eb2Smrg
2861627f7eb2Smrg gfc_unset_implicit_pure (NULL);
2862627f7eb2Smrg
2863627f7eb2Smrg new_st.op = op;
2864627f7eb2Smrg new_st.ext.filepos = fp;
2865627f7eb2Smrg return MATCH_YES;
2866627f7eb2Smrg
2867627f7eb2Smrg syntax:
2868627f7eb2Smrg gfc_syntax_error (st);
2869627f7eb2Smrg
2870627f7eb2Smrg cleanup:
2871627f7eb2Smrg gfc_free_filepos (fp);
2872627f7eb2Smrg return MATCH_ERROR;
2873627f7eb2Smrg }
2874627f7eb2Smrg
2875627f7eb2Smrg
2876627f7eb2Smrg bool
gfc_resolve_filepos(gfc_filepos * fp,locus * where)2877627f7eb2Smrg gfc_resolve_filepos (gfc_filepos *fp, locus *where)
2878627f7eb2Smrg {
2879627f7eb2Smrg RESOLVE_TAG (&tag_unit, fp->unit);
2880627f7eb2Smrg RESOLVE_TAG (&tag_iostat, fp->iostat);
2881627f7eb2Smrg RESOLVE_TAG (&tag_iomsg, fp->iomsg);
2882627f7eb2Smrg
2883627f7eb2Smrg if (!fp->unit && (fp->iostat || fp->iomsg || fp->err))
2884627f7eb2Smrg {
2885627f7eb2Smrg gfc_error ("UNIT number missing in statement at %L", where);
2886627f7eb2Smrg return false;
2887627f7eb2Smrg }
2888627f7eb2Smrg
2889627f7eb2Smrg if (!gfc_reference_st_label (fp->err, ST_LABEL_TARGET))
2890627f7eb2Smrg return false;
2891627f7eb2Smrg
2892627f7eb2Smrg if (fp->unit->expr_type == EXPR_CONSTANT
2893627f7eb2Smrg && fp->unit->ts.type == BT_INTEGER
2894627f7eb2Smrg && mpz_sgn (fp->unit->value.integer) < 0)
2895627f7eb2Smrg {
2896627f7eb2Smrg gfc_error ("UNIT number in statement at %L must be non-negative",
2897627f7eb2Smrg &fp->unit->where);
2898627f7eb2Smrg return false;
2899627f7eb2Smrg }
2900627f7eb2Smrg
2901627f7eb2Smrg return true;
2902627f7eb2Smrg }
2903627f7eb2Smrg
2904627f7eb2Smrg
2905627f7eb2Smrg /* Match the file positioning statements: ENDFILE, BACKSPACE, REWIND,
2906627f7eb2Smrg and the FLUSH statement. */
2907627f7eb2Smrg
2908627f7eb2Smrg match
gfc_match_endfile(void)2909627f7eb2Smrg gfc_match_endfile (void)
2910627f7eb2Smrg {
2911627f7eb2Smrg return match_filepos (ST_END_FILE, EXEC_ENDFILE);
2912627f7eb2Smrg }
2913627f7eb2Smrg
2914627f7eb2Smrg match
gfc_match_backspace(void)2915627f7eb2Smrg gfc_match_backspace (void)
2916627f7eb2Smrg {
2917627f7eb2Smrg return match_filepos (ST_BACKSPACE, EXEC_BACKSPACE);
2918627f7eb2Smrg }
2919627f7eb2Smrg
2920627f7eb2Smrg match
gfc_match_rewind(void)2921627f7eb2Smrg gfc_match_rewind (void)
2922627f7eb2Smrg {
2923627f7eb2Smrg return match_filepos (ST_REWIND, EXEC_REWIND);
2924627f7eb2Smrg }
2925627f7eb2Smrg
2926627f7eb2Smrg match
gfc_match_flush(void)2927627f7eb2Smrg gfc_match_flush (void)
2928627f7eb2Smrg {
2929627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "FLUSH statement at %C"))
2930627f7eb2Smrg return MATCH_ERROR;
2931627f7eb2Smrg
2932627f7eb2Smrg return match_filepos (ST_FLUSH, EXEC_FLUSH);
2933627f7eb2Smrg }
2934627f7eb2Smrg
2935627f7eb2Smrg /******************** Data Transfer Statements *********************/
2936627f7eb2Smrg
2937627f7eb2Smrg /* Return a default unit number. */
2938627f7eb2Smrg
2939627f7eb2Smrg static gfc_expr *
default_unit(io_kind k)2940627f7eb2Smrg default_unit (io_kind k)
2941627f7eb2Smrg {
2942627f7eb2Smrg int unit;
2943627f7eb2Smrg
2944627f7eb2Smrg if (k == M_READ)
2945627f7eb2Smrg unit = 5;
2946627f7eb2Smrg else
2947627f7eb2Smrg unit = 6;
2948627f7eb2Smrg
2949627f7eb2Smrg return gfc_get_int_expr (gfc_default_integer_kind, NULL, unit);
2950627f7eb2Smrg }
2951627f7eb2Smrg
2952627f7eb2Smrg
2953627f7eb2Smrg /* Match a unit specification for a data transfer statement. */
2954627f7eb2Smrg
2955627f7eb2Smrg static match
match_dt_unit(io_kind k,gfc_dt * dt)2956627f7eb2Smrg match_dt_unit (io_kind k, gfc_dt *dt)
2957627f7eb2Smrg {
2958627f7eb2Smrg gfc_expr *e;
2959627f7eb2Smrg char c;
2960627f7eb2Smrg
2961627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES)
2962627f7eb2Smrg {
2963627f7eb2Smrg if (dt->io_unit != NULL)
2964627f7eb2Smrg goto conflict;
2965627f7eb2Smrg
2966627f7eb2Smrg dt->io_unit = default_unit (k);
2967627f7eb2Smrg
2968627f7eb2Smrg c = gfc_peek_ascii_char ();
2969627f7eb2Smrg if (c == ')')
2970627f7eb2Smrg gfc_error_now ("Missing format with default unit at %C");
2971627f7eb2Smrg
2972627f7eb2Smrg return MATCH_YES;
2973627f7eb2Smrg }
2974627f7eb2Smrg
2975627f7eb2Smrg if (gfc_match_expr (&e) == MATCH_YES)
2976627f7eb2Smrg {
2977627f7eb2Smrg if (dt->io_unit != NULL)
2978627f7eb2Smrg {
2979627f7eb2Smrg gfc_free_expr (e);
2980627f7eb2Smrg goto conflict;
2981627f7eb2Smrg }
2982627f7eb2Smrg
2983627f7eb2Smrg dt->io_unit = e;
2984627f7eb2Smrg return MATCH_YES;
2985627f7eb2Smrg }
2986627f7eb2Smrg
2987627f7eb2Smrg return MATCH_NO;
2988627f7eb2Smrg
2989627f7eb2Smrg conflict:
2990627f7eb2Smrg gfc_error ("Duplicate UNIT specification at %C");
2991627f7eb2Smrg return MATCH_ERROR;
2992627f7eb2Smrg }
2993627f7eb2Smrg
2994627f7eb2Smrg
2995627f7eb2Smrg /* Match a format specification. */
2996627f7eb2Smrg
2997627f7eb2Smrg static match
match_dt_format(gfc_dt * dt)2998627f7eb2Smrg match_dt_format (gfc_dt *dt)
2999627f7eb2Smrg {
3000627f7eb2Smrg locus where;
3001627f7eb2Smrg gfc_expr *e;
3002627f7eb2Smrg gfc_st_label *label;
3003627f7eb2Smrg match m;
3004627f7eb2Smrg
3005627f7eb2Smrg where = gfc_current_locus;
3006627f7eb2Smrg
3007627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES)
3008627f7eb2Smrg {
3009627f7eb2Smrg if (dt->format_expr != NULL || dt->format_label != NULL)
3010627f7eb2Smrg goto conflict;
3011627f7eb2Smrg
3012627f7eb2Smrg dt->format_label = &format_asterisk;
3013627f7eb2Smrg return MATCH_YES;
3014627f7eb2Smrg }
3015627f7eb2Smrg
3016627f7eb2Smrg if ((m = gfc_match_st_label (&label)) == MATCH_YES)
3017627f7eb2Smrg {
3018627f7eb2Smrg char c;
3019627f7eb2Smrg
3020627f7eb2Smrg /* Need to check if the format label is actually either an operand
3021627f7eb2Smrg to a user-defined operator or is a kind type parameter. That is,
3022627f7eb2Smrg print 2.ip.8 ! .ip. is a user-defined operator return CHARACTER.
3023627f7eb2Smrg print 1_'(I0)', i ! 1_'(I0)' is a default character string. */
3024627f7eb2Smrg
3025627f7eb2Smrg gfc_gobble_whitespace ();
3026627f7eb2Smrg c = gfc_peek_ascii_char ();
3027627f7eb2Smrg if (c == '.' || c == '_')
3028627f7eb2Smrg gfc_current_locus = where;
3029627f7eb2Smrg else
3030627f7eb2Smrg {
3031627f7eb2Smrg if (dt->format_expr != NULL || dt->format_label != NULL)
3032627f7eb2Smrg {
3033627f7eb2Smrg gfc_free_st_label (label);
3034627f7eb2Smrg goto conflict;
3035627f7eb2Smrg }
3036627f7eb2Smrg
3037627f7eb2Smrg if (!gfc_reference_st_label (label, ST_LABEL_FORMAT))
3038627f7eb2Smrg return MATCH_ERROR;
3039627f7eb2Smrg
3040627f7eb2Smrg dt->format_label = label;
3041627f7eb2Smrg return MATCH_YES;
3042627f7eb2Smrg }
3043627f7eb2Smrg }
3044627f7eb2Smrg else if (m == MATCH_ERROR)
3045627f7eb2Smrg /* The label was zero or too large. Emit the correct diagnosis. */
3046627f7eb2Smrg return MATCH_ERROR;
3047627f7eb2Smrg
3048627f7eb2Smrg if (gfc_match_expr (&e) == MATCH_YES)
3049627f7eb2Smrg {
3050627f7eb2Smrg if (dt->format_expr != NULL || dt->format_label != NULL)
3051627f7eb2Smrg {
3052627f7eb2Smrg gfc_free_expr (e);
3053627f7eb2Smrg goto conflict;
3054627f7eb2Smrg }
3055627f7eb2Smrg dt->format_expr = e;
3056627f7eb2Smrg return MATCH_YES;
3057627f7eb2Smrg }
3058627f7eb2Smrg
3059627f7eb2Smrg gfc_current_locus = where; /* The only case where we have to restore */
3060627f7eb2Smrg
3061627f7eb2Smrg return MATCH_NO;
3062627f7eb2Smrg
3063627f7eb2Smrg conflict:
3064627f7eb2Smrg gfc_error ("Duplicate format specification at %C");
3065627f7eb2Smrg return MATCH_ERROR;
3066627f7eb2Smrg }
3067627f7eb2Smrg
3068627f7eb2Smrg /* Check for formatted read and write DTIO procedures. */
3069627f7eb2Smrg
3070627f7eb2Smrg static bool
dtio_procs_present(gfc_symbol * sym,io_kind k)3071627f7eb2Smrg dtio_procs_present (gfc_symbol *sym, io_kind k)
3072627f7eb2Smrg {
3073627f7eb2Smrg gfc_symbol *derived;
3074627f7eb2Smrg
3075627f7eb2Smrg if (sym && sym->ts.u.derived)
3076627f7eb2Smrg {
3077627f7eb2Smrg if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
3078627f7eb2Smrg derived = CLASS_DATA (sym)->ts.u.derived;
3079627f7eb2Smrg else if (sym->ts.type == BT_DERIVED)
3080627f7eb2Smrg derived = sym->ts.u.derived;
3081627f7eb2Smrg else
3082627f7eb2Smrg return false;
3083627f7eb2Smrg if ((k == M_WRITE || k == M_PRINT) &&
3084627f7eb2Smrg (gfc_find_specific_dtio_proc (derived, true, true) != NULL))
3085627f7eb2Smrg return true;
3086627f7eb2Smrg if ((k == M_READ) &&
3087627f7eb2Smrg (gfc_find_specific_dtio_proc (derived, false, true) != NULL))
3088627f7eb2Smrg return true;
3089627f7eb2Smrg }
3090627f7eb2Smrg return false;
3091627f7eb2Smrg }
3092627f7eb2Smrg
3093627f7eb2Smrg /* Traverse a namelist that is part of a READ statement to make sure
3094627f7eb2Smrg that none of the variables in the namelist are INTENT(IN). Returns
3095627f7eb2Smrg nonzero if we find such a variable. */
3096627f7eb2Smrg
3097627f7eb2Smrg static int
check_namelist(gfc_symbol * sym)3098627f7eb2Smrg check_namelist (gfc_symbol *sym)
3099627f7eb2Smrg {
3100627f7eb2Smrg gfc_namelist *p;
3101627f7eb2Smrg
3102627f7eb2Smrg for (p = sym->namelist; p; p = p->next)
3103627f7eb2Smrg if (p->sym->attr.intent == INTENT_IN)
3104627f7eb2Smrg {
3105627f7eb2Smrg gfc_error ("Symbol %qs in namelist %qs is INTENT(IN) at %C",
3106627f7eb2Smrg p->sym->name, sym->name);
3107627f7eb2Smrg return 1;
3108627f7eb2Smrg }
3109627f7eb2Smrg
3110627f7eb2Smrg return 0;
3111627f7eb2Smrg }
3112627f7eb2Smrg
3113627f7eb2Smrg
3114627f7eb2Smrg /* Match a single data transfer element. */
3115627f7eb2Smrg
3116627f7eb2Smrg static match
match_dt_element(io_kind k,gfc_dt * dt)3117627f7eb2Smrg match_dt_element (io_kind k, gfc_dt *dt)
3118627f7eb2Smrg {
3119627f7eb2Smrg char name[GFC_MAX_SYMBOL_LEN + 1];
3120627f7eb2Smrg gfc_symbol *sym;
3121627f7eb2Smrg match m;
3122627f7eb2Smrg
3123627f7eb2Smrg if (gfc_match (" unit =") == MATCH_YES)
3124627f7eb2Smrg {
3125627f7eb2Smrg m = match_dt_unit (k, dt);
3126627f7eb2Smrg if (m != MATCH_NO)
3127627f7eb2Smrg return m;
3128627f7eb2Smrg }
3129627f7eb2Smrg
3130627f7eb2Smrg if (gfc_match (" fmt =") == MATCH_YES)
3131627f7eb2Smrg {
3132627f7eb2Smrg m = match_dt_format (dt);
3133627f7eb2Smrg if (m != MATCH_NO)
3134627f7eb2Smrg return m;
3135627f7eb2Smrg }
3136627f7eb2Smrg
3137627f7eb2Smrg if (gfc_match (" nml = %n", name) == MATCH_YES)
3138627f7eb2Smrg {
3139627f7eb2Smrg if (dt->namelist != NULL)
3140627f7eb2Smrg {
3141627f7eb2Smrg gfc_error ("Duplicate NML specification at %C");
3142627f7eb2Smrg return MATCH_ERROR;
3143627f7eb2Smrg }
3144627f7eb2Smrg
3145627f7eb2Smrg if (gfc_find_symbol (name, NULL, 1, &sym))
3146627f7eb2Smrg return MATCH_ERROR;
3147627f7eb2Smrg
3148627f7eb2Smrg if (sym == NULL || sym->attr.flavor != FL_NAMELIST)
3149627f7eb2Smrg {
3150627f7eb2Smrg gfc_error ("Symbol %qs at %C must be a NAMELIST group name",
3151627f7eb2Smrg sym != NULL ? sym->name : name);
3152627f7eb2Smrg return MATCH_ERROR;
3153627f7eb2Smrg }
3154627f7eb2Smrg
3155627f7eb2Smrg dt->namelist = sym;
3156627f7eb2Smrg if (k == M_READ && check_namelist (sym))
3157627f7eb2Smrg return MATCH_ERROR;
3158627f7eb2Smrg
3159627f7eb2Smrg return MATCH_YES;
3160627f7eb2Smrg }
3161627f7eb2Smrg
3162627f7eb2Smrg m = match_etag (&tag_e_async, &dt->asynchronous);
3163627f7eb2Smrg if (m != MATCH_NO)
3164627f7eb2Smrg return m;
3165627f7eb2Smrg m = match_etag (&tag_e_blank, &dt->blank);
3166627f7eb2Smrg if (m != MATCH_NO)
3167627f7eb2Smrg return m;
3168627f7eb2Smrg m = match_etag (&tag_e_delim, &dt->delim);
3169627f7eb2Smrg if (m != MATCH_NO)
3170627f7eb2Smrg return m;
3171627f7eb2Smrg m = match_etag (&tag_e_pad, &dt->pad);
3172627f7eb2Smrg if (m != MATCH_NO)
3173627f7eb2Smrg return m;
3174627f7eb2Smrg m = match_etag (&tag_e_sign, &dt->sign);
3175627f7eb2Smrg if (m != MATCH_NO)
3176627f7eb2Smrg return m;
3177627f7eb2Smrg m = match_etag (&tag_e_round, &dt->round);
3178627f7eb2Smrg if (m != MATCH_NO)
3179627f7eb2Smrg return m;
3180627f7eb2Smrg m = match_out_tag (&tag_id, &dt->id);
3181627f7eb2Smrg if (m != MATCH_NO)
3182627f7eb2Smrg return m;
3183627f7eb2Smrg m = match_etag (&tag_e_decimal, &dt->decimal);
3184627f7eb2Smrg if (m != MATCH_NO)
3185627f7eb2Smrg return m;
3186627f7eb2Smrg m = match_etag (&tag_rec, &dt->rec);
3187627f7eb2Smrg if (m != MATCH_NO)
3188627f7eb2Smrg return m;
3189627f7eb2Smrg m = match_etag (&tag_spos, &dt->pos);
3190627f7eb2Smrg if (m != MATCH_NO)
3191627f7eb2Smrg return m;
3192627f7eb2Smrg m = match_etag (&tag_iomsg, &dt->iomsg);
3193627f7eb2Smrg if (m != MATCH_NO)
3194627f7eb2Smrg return m;
3195627f7eb2Smrg
3196627f7eb2Smrg m = match_out_tag (&tag_iostat, &dt->iostat);
3197627f7eb2Smrg if (m != MATCH_NO)
3198627f7eb2Smrg return m;
3199627f7eb2Smrg m = match_ltag (&tag_err, &dt->err);
3200627f7eb2Smrg if (m == MATCH_YES)
3201627f7eb2Smrg dt->err_where = gfc_current_locus;
3202627f7eb2Smrg if (m != MATCH_NO)
3203627f7eb2Smrg return m;
3204627f7eb2Smrg m = match_etag (&tag_advance, &dt->advance);
3205627f7eb2Smrg if (m != MATCH_NO)
3206627f7eb2Smrg return m;
3207627f7eb2Smrg m = match_out_tag (&tag_size, &dt->size);
3208627f7eb2Smrg if (m != MATCH_NO)
3209627f7eb2Smrg return m;
3210627f7eb2Smrg
3211627f7eb2Smrg m = match_ltag (&tag_end, &dt->end);
3212627f7eb2Smrg if (m == MATCH_YES)
3213627f7eb2Smrg {
3214627f7eb2Smrg if (k == M_WRITE)
3215627f7eb2Smrg {
3216627f7eb2Smrg gfc_error ("END tag at %C not allowed in output statement");
3217627f7eb2Smrg return MATCH_ERROR;
3218627f7eb2Smrg }
3219627f7eb2Smrg dt->end_where = gfc_current_locus;
3220627f7eb2Smrg }
3221627f7eb2Smrg if (m != MATCH_NO)
3222627f7eb2Smrg return m;
3223627f7eb2Smrg
3224627f7eb2Smrg m = match_ltag (&tag_eor, &dt->eor);
3225627f7eb2Smrg if (m == MATCH_YES)
3226627f7eb2Smrg dt->eor_where = gfc_current_locus;
3227627f7eb2Smrg if (m != MATCH_NO)
3228627f7eb2Smrg return m;
3229627f7eb2Smrg
3230627f7eb2Smrg return MATCH_NO;
3231627f7eb2Smrg }
3232627f7eb2Smrg
3233627f7eb2Smrg
3234627f7eb2Smrg /* Free a data transfer structure and everything below it. */
3235627f7eb2Smrg
3236627f7eb2Smrg void
gfc_free_dt(gfc_dt * dt)3237627f7eb2Smrg gfc_free_dt (gfc_dt *dt)
3238627f7eb2Smrg {
3239627f7eb2Smrg if (dt == NULL)
3240627f7eb2Smrg return;
3241627f7eb2Smrg
3242627f7eb2Smrg gfc_free_expr (dt->io_unit);
3243627f7eb2Smrg gfc_free_expr (dt->format_expr);
3244627f7eb2Smrg gfc_free_expr (dt->rec);
3245627f7eb2Smrg gfc_free_expr (dt->advance);
3246627f7eb2Smrg gfc_free_expr (dt->iomsg);
3247627f7eb2Smrg gfc_free_expr (dt->iostat);
3248627f7eb2Smrg gfc_free_expr (dt->size);
3249627f7eb2Smrg gfc_free_expr (dt->pad);
3250627f7eb2Smrg gfc_free_expr (dt->delim);
3251627f7eb2Smrg gfc_free_expr (dt->sign);
3252627f7eb2Smrg gfc_free_expr (dt->round);
3253627f7eb2Smrg gfc_free_expr (dt->blank);
3254627f7eb2Smrg gfc_free_expr (dt->decimal);
3255627f7eb2Smrg gfc_free_expr (dt->pos);
3256627f7eb2Smrg gfc_free_expr (dt->dt_io_kind);
3257627f7eb2Smrg /* dt->extra_comma is a link to dt_io_kind if it is set. */
3258627f7eb2Smrg free (dt);
3259627f7eb2Smrg }
3260627f7eb2Smrg
3261627f7eb2Smrg
3262*4c3eb207Smrg static const char *
3263*4c3eb207Smrg io_kind_name (io_kind k);
3264*4c3eb207Smrg
3265*4c3eb207Smrg static bool
3266*4c3eb207Smrg check_io_constraints (io_kind k, gfc_dt *dt, gfc_code *io_code,
3267*4c3eb207Smrg locus *spec_end);
3268*4c3eb207Smrg
3269627f7eb2Smrg /* Resolve everything in a gfc_dt structure. */
3270627f7eb2Smrg
3271627f7eb2Smrg bool
gfc_resolve_dt(gfc_code * dt_code,gfc_dt * dt,locus * loc)3272*4c3eb207Smrg gfc_resolve_dt (gfc_code *dt_code, gfc_dt *dt, locus *loc)
3273627f7eb2Smrg {
3274627f7eb2Smrg gfc_expr *e;
3275627f7eb2Smrg io_kind k;
3276627f7eb2Smrg
3277627f7eb2Smrg /* This is set in any case. */
3278627f7eb2Smrg gcc_assert (dt->dt_io_kind);
3279627f7eb2Smrg k = dt->dt_io_kind->value.iokind;
3280627f7eb2Smrg
3281*4c3eb207Smrg RESOLVE_TAG (&tag_format, dt->format_expr);
3282627f7eb2Smrg RESOLVE_TAG (&tag_rec, dt->rec);
3283627f7eb2Smrg RESOLVE_TAG (&tag_spos, dt->pos);
3284627f7eb2Smrg RESOLVE_TAG (&tag_advance, dt->advance);
3285627f7eb2Smrg RESOLVE_TAG (&tag_id, dt->id);
3286627f7eb2Smrg RESOLVE_TAG (&tag_iomsg, dt->iomsg);
3287627f7eb2Smrg RESOLVE_TAG (&tag_iostat, dt->iostat);
3288627f7eb2Smrg RESOLVE_TAG (&tag_size, dt->size);
3289627f7eb2Smrg RESOLVE_TAG (&tag_e_pad, dt->pad);
3290627f7eb2Smrg RESOLVE_TAG (&tag_e_delim, dt->delim);
3291627f7eb2Smrg RESOLVE_TAG (&tag_e_sign, dt->sign);
3292627f7eb2Smrg RESOLVE_TAG (&tag_e_round, dt->round);
3293627f7eb2Smrg RESOLVE_TAG (&tag_e_blank, dt->blank);
3294627f7eb2Smrg RESOLVE_TAG (&tag_e_decimal, dt->decimal);
3295627f7eb2Smrg RESOLVE_TAG (&tag_e_async, dt->asynchronous);
3296627f7eb2Smrg
3297*4c3eb207Smrg /* Check I/O constraints.
3298*4c3eb207Smrg To validate NAMELIST we need to check if we were also given an I/O list,
3299*4c3eb207Smrg which is stored in code->block->next with op EXEC_TRANSFER.
3300*4c3eb207Smrg Note that the I/O list was already resolved from resolve_transfer. */
3301*4c3eb207Smrg gfc_code *io_code = NULL;
3302*4c3eb207Smrg if (dt_code && dt_code->block && dt_code->block->next
3303*4c3eb207Smrg && dt_code->block->next->op == EXEC_TRANSFER)
3304*4c3eb207Smrg io_code = dt_code->block->next;
3305*4c3eb207Smrg
3306*4c3eb207Smrg if (!check_io_constraints (k, dt, io_code, loc))
3307*4c3eb207Smrg return false;
3308*4c3eb207Smrg
3309627f7eb2Smrg e = dt->io_unit;
3310627f7eb2Smrg if (e == NULL)
3311627f7eb2Smrg {
3312627f7eb2Smrg gfc_error ("UNIT not specified at %L", loc);
3313627f7eb2Smrg return false;
3314627f7eb2Smrg }
3315627f7eb2Smrg
3316*4c3eb207Smrg if (e->symtree && e->symtree->n.sym->attr.flavor == FL_PARAMETER
3317*4c3eb207Smrg && e->ts.type == BT_CHARACTER)
3318*4c3eb207Smrg {
3319*4c3eb207Smrg gfc_error ("UNIT specification at %L must "
3320*4c3eb207Smrg "not be a character PARAMETER", &e->where);
3321*4c3eb207Smrg return false;
3322*4c3eb207Smrg }
3323*4c3eb207Smrg
3324627f7eb2Smrg if (gfc_resolve_expr (e)
3325627f7eb2Smrg && (e->ts.type != BT_INTEGER
3326627f7eb2Smrg && (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_VARIABLE)))
3327627f7eb2Smrg {
3328627f7eb2Smrg /* If there is no extra comma signifying the "format" form of the IO
3329627f7eb2Smrg statement, then this must be an error. */
3330627f7eb2Smrg if (!dt->extra_comma)
3331627f7eb2Smrg {
3332627f7eb2Smrg gfc_error ("UNIT specification at %L must be an INTEGER expression "
3333627f7eb2Smrg "or a CHARACTER variable", &e->where);
3334627f7eb2Smrg return false;
3335627f7eb2Smrg }
3336627f7eb2Smrg else
3337627f7eb2Smrg {
3338627f7eb2Smrg /* At this point, we have an extra comma. If io_unit has arrived as
3339627f7eb2Smrg type character, we assume its really the "format" form of the I/O
3340627f7eb2Smrg statement. We set the io_unit to the default unit and format to
3341627f7eb2Smrg the character expression. See F95 Standard section 9.4. */
3342627f7eb2Smrg if (e->ts.type == BT_CHARACTER && (k == M_READ || k == M_PRINT))
3343627f7eb2Smrg {
3344627f7eb2Smrg dt->format_expr = dt->io_unit;
3345627f7eb2Smrg dt->io_unit = default_unit (k);
3346627f7eb2Smrg
3347627f7eb2Smrg /* Nullify this pointer now so that a warning/error is not
3348627f7eb2Smrg triggered below for the "Extension". */
3349627f7eb2Smrg dt->extra_comma = NULL;
3350627f7eb2Smrg }
3351627f7eb2Smrg
3352627f7eb2Smrg if (k == M_WRITE)
3353627f7eb2Smrg {
3354627f7eb2Smrg gfc_error ("Invalid form of WRITE statement at %L, UNIT required",
3355627f7eb2Smrg &dt->extra_comma->where);
3356627f7eb2Smrg return false;
3357627f7eb2Smrg }
3358627f7eb2Smrg }
3359627f7eb2Smrg }
3360627f7eb2Smrg
3361627f7eb2Smrg if (e->ts.type == BT_CHARACTER)
3362627f7eb2Smrg {
3363627f7eb2Smrg if (gfc_has_vector_index (e))
3364627f7eb2Smrg {
3365627f7eb2Smrg gfc_error ("Internal unit with vector subscript at %L", &e->where);
3366627f7eb2Smrg return false;
3367627f7eb2Smrg }
3368627f7eb2Smrg
3369627f7eb2Smrg /* If we are writing, make sure the internal unit can be changed. */
3370627f7eb2Smrg gcc_assert (k != M_PRINT);
3371627f7eb2Smrg if (k == M_WRITE
3372627f7eb2Smrg && !gfc_check_vardef_context (e, false, false, false,
3373627f7eb2Smrg _("internal unit in WRITE")))
3374627f7eb2Smrg return false;
3375627f7eb2Smrg }
3376627f7eb2Smrg
3377627f7eb2Smrg if (e->rank && e->ts.type != BT_CHARACTER)
3378627f7eb2Smrg {
3379627f7eb2Smrg gfc_error ("External IO UNIT cannot be an array at %L", &e->where);
3380627f7eb2Smrg return false;
3381627f7eb2Smrg }
3382627f7eb2Smrg
3383627f7eb2Smrg if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_INTEGER
3384627f7eb2Smrg && mpz_sgn (e->value.integer) < 0)
3385627f7eb2Smrg {
3386627f7eb2Smrg gfc_error ("UNIT number in statement at %L must be non-negative",
3387627f7eb2Smrg &e->where);
3388627f7eb2Smrg return false;
3389627f7eb2Smrg }
3390627f7eb2Smrg
3391627f7eb2Smrg /* If we are reading and have a namelist, check that all namelist symbols
3392627f7eb2Smrg can appear in a variable definition context. */
3393627f7eb2Smrg if (dt->namelist)
3394627f7eb2Smrg {
3395627f7eb2Smrg gfc_namelist* n;
3396627f7eb2Smrg for (n = dt->namelist->namelist; n; n = n->next)
3397627f7eb2Smrg {
3398627f7eb2Smrg gfc_expr* e;
3399627f7eb2Smrg bool t;
3400627f7eb2Smrg
3401627f7eb2Smrg if (k == M_READ)
3402627f7eb2Smrg {
3403627f7eb2Smrg e = gfc_get_variable_expr (gfc_find_sym_in_symtree (n->sym));
3404627f7eb2Smrg t = gfc_check_vardef_context (e, false, false, false, NULL);
3405627f7eb2Smrg gfc_free_expr (e);
3406627f7eb2Smrg
3407627f7eb2Smrg if (!t)
3408627f7eb2Smrg {
3409627f7eb2Smrg gfc_error ("NAMELIST %qs in READ statement at %L contains"
3410627f7eb2Smrg " the symbol %qs which may not appear in a"
3411627f7eb2Smrg " variable definition context",
3412627f7eb2Smrg dt->namelist->name, loc, n->sym->name);
3413627f7eb2Smrg return false;
3414627f7eb2Smrg }
3415627f7eb2Smrg }
3416627f7eb2Smrg
3417627f7eb2Smrg t = dtio_procs_present (n->sym, k);
3418627f7eb2Smrg
3419627f7eb2Smrg if (n->sym->ts.type == BT_CLASS && !t)
3420627f7eb2Smrg {
3421627f7eb2Smrg gfc_error ("NAMELIST object %qs in namelist %qs at %L is "
3422627f7eb2Smrg "polymorphic and requires a defined input/output "
3423627f7eb2Smrg "procedure", n->sym->name, dt->namelist->name, loc);
3424627f7eb2Smrg return false;
3425627f7eb2Smrg }
3426627f7eb2Smrg
3427627f7eb2Smrg if ((n->sym->ts.type == BT_DERIVED)
3428627f7eb2Smrg && (n->sym->ts.u.derived->attr.alloc_comp
3429627f7eb2Smrg || n->sym->ts.u.derived->attr.pointer_comp))
3430627f7eb2Smrg {
3431627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "NAMELIST object %qs in "
3432627f7eb2Smrg "namelist %qs at %L with ALLOCATABLE "
3433627f7eb2Smrg "or POINTER components", n->sym->name,
3434627f7eb2Smrg dt->namelist->name, loc))
3435627f7eb2Smrg return false;
3436627f7eb2Smrg
3437627f7eb2Smrg if (!t)
3438627f7eb2Smrg {
3439627f7eb2Smrg gfc_error ("NAMELIST object %qs in namelist %qs at %L has "
3440627f7eb2Smrg "ALLOCATABLE or POINTER components and thus requires "
3441627f7eb2Smrg "a defined input/output procedure", n->sym->name,
3442627f7eb2Smrg dt->namelist->name, loc);
3443627f7eb2Smrg return false;
3444627f7eb2Smrg }
3445627f7eb2Smrg }
3446627f7eb2Smrg }
3447627f7eb2Smrg }
3448627f7eb2Smrg
3449627f7eb2Smrg if (dt->extra_comma
3450627f7eb2Smrg && !gfc_notify_std (GFC_STD_LEGACY, "Comma before i/o item list at %L",
3451627f7eb2Smrg &dt->extra_comma->where))
3452627f7eb2Smrg return false;
3453627f7eb2Smrg
3454627f7eb2Smrg if (dt->err)
3455627f7eb2Smrg {
3456627f7eb2Smrg if (!gfc_reference_st_label (dt->err, ST_LABEL_TARGET))
3457627f7eb2Smrg return false;
3458627f7eb2Smrg if (dt->err->defined == ST_LABEL_UNKNOWN)
3459627f7eb2Smrg {
3460627f7eb2Smrg gfc_error ("ERR tag label %d at %L not defined",
3461627f7eb2Smrg dt->err->value, &dt->err_where);
3462627f7eb2Smrg return false;
3463627f7eb2Smrg }
3464627f7eb2Smrg }
3465627f7eb2Smrg
3466627f7eb2Smrg if (dt->end)
3467627f7eb2Smrg {
3468627f7eb2Smrg if (!gfc_reference_st_label (dt->end, ST_LABEL_TARGET))
3469627f7eb2Smrg return false;
3470627f7eb2Smrg if (dt->end->defined == ST_LABEL_UNKNOWN)
3471627f7eb2Smrg {
3472627f7eb2Smrg gfc_error ("END tag label %d at %L not defined",
3473627f7eb2Smrg dt->end->value, &dt->end_where);
3474627f7eb2Smrg return false;
3475627f7eb2Smrg }
3476627f7eb2Smrg }
3477627f7eb2Smrg
3478627f7eb2Smrg if (dt->eor)
3479627f7eb2Smrg {
3480627f7eb2Smrg if (!gfc_reference_st_label (dt->eor, ST_LABEL_TARGET))
3481627f7eb2Smrg return false;
3482627f7eb2Smrg if (dt->eor->defined == ST_LABEL_UNKNOWN)
3483627f7eb2Smrg {
3484627f7eb2Smrg gfc_error ("EOR tag label %d at %L not defined",
3485627f7eb2Smrg dt->eor->value, &dt->eor_where);
3486627f7eb2Smrg return false;
3487627f7eb2Smrg }
3488627f7eb2Smrg }
3489627f7eb2Smrg
3490627f7eb2Smrg /* Check the format label actually exists. */
3491627f7eb2Smrg if (dt->format_label && dt->format_label != &format_asterisk
3492627f7eb2Smrg && dt->format_label->defined == ST_LABEL_UNKNOWN)
3493627f7eb2Smrg {
3494627f7eb2Smrg gfc_error ("FORMAT label %d at %L not defined", dt->format_label->value,
3495627f7eb2Smrg loc);
3496627f7eb2Smrg return false;
3497627f7eb2Smrg }
3498627f7eb2Smrg
3499627f7eb2Smrg return true;
3500627f7eb2Smrg }
3501627f7eb2Smrg
3502627f7eb2Smrg
3503627f7eb2Smrg /* Given an io_kind, return its name. */
3504627f7eb2Smrg
3505627f7eb2Smrg static const char *
io_kind_name(io_kind k)3506627f7eb2Smrg io_kind_name (io_kind k)
3507627f7eb2Smrg {
3508627f7eb2Smrg const char *name;
3509627f7eb2Smrg
3510627f7eb2Smrg switch (k)
3511627f7eb2Smrg {
3512627f7eb2Smrg case M_READ:
3513627f7eb2Smrg name = "READ";
3514627f7eb2Smrg break;
3515627f7eb2Smrg case M_WRITE:
3516627f7eb2Smrg name = "WRITE";
3517627f7eb2Smrg break;
3518627f7eb2Smrg case M_PRINT:
3519627f7eb2Smrg name = "PRINT";
3520627f7eb2Smrg break;
3521627f7eb2Smrg case M_INQUIRE:
3522627f7eb2Smrg name = "INQUIRE";
3523627f7eb2Smrg break;
3524627f7eb2Smrg default:
3525627f7eb2Smrg gfc_internal_error ("io_kind_name(): bad I/O-kind");
3526627f7eb2Smrg }
3527627f7eb2Smrg
3528627f7eb2Smrg return name;
3529627f7eb2Smrg }
3530627f7eb2Smrg
3531627f7eb2Smrg
3532627f7eb2Smrg /* Match an IO iteration statement of the form:
3533627f7eb2Smrg
3534627f7eb2Smrg ( [<IO element> ,] <IO element>, I = <expr>, <expr> [, <expr> ] )
3535627f7eb2Smrg
3536627f7eb2Smrg which is equivalent to a single IO element. This function is
3537627f7eb2Smrg mutually recursive with match_io_element(). */
3538627f7eb2Smrg
3539627f7eb2Smrg static match match_io_element (io_kind, gfc_code **);
3540627f7eb2Smrg
3541627f7eb2Smrg static match
match_io_iterator(io_kind k,gfc_code ** result)3542627f7eb2Smrg match_io_iterator (io_kind k, gfc_code **result)
3543627f7eb2Smrg {
3544627f7eb2Smrg gfc_code *head, *tail, *new_code;
3545627f7eb2Smrg gfc_iterator *iter;
3546627f7eb2Smrg locus old_loc;
3547627f7eb2Smrg match m;
3548627f7eb2Smrg int n;
3549627f7eb2Smrg
3550627f7eb2Smrg iter = NULL;
3551627f7eb2Smrg head = NULL;
3552627f7eb2Smrg old_loc = gfc_current_locus;
3553627f7eb2Smrg
3554627f7eb2Smrg if (gfc_match_char ('(') != MATCH_YES)
3555627f7eb2Smrg return MATCH_NO;
3556627f7eb2Smrg
3557627f7eb2Smrg m = match_io_element (k, &head);
3558627f7eb2Smrg tail = head;
3559627f7eb2Smrg
3560627f7eb2Smrg if (m != MATCH_YES || gfc_match_char (',') != MATCH_YES)
3561627f7eb2Smrg {
3562627f7eb2Smrg m = MATCH_NO;
3563627f7eb2Smrg goto cleanup;
3564627f7eb2Smrg }
3565627f7eb2Smrg
3566627f7eb2Smrg /* Can't be anything but an IO iterator. Build a list. */
3567627f7eb2Smrg iter = gfc_get_iterator ();
3568627f7eb2Smrg
3569627f7eb2Smrg for (n = 1;; n++)
3570627f7eb2Smrg {
3571627f7eb2Smrg m = gfc_match_iterator (iter, 0);
3572627f7eb2Smrg if (m == MATCH_ERROR)
3573627f7eb2Smrg goto cleanup;
3574627f7eb2Smrg if (m == MATCH_YES)
3575627f7eb2Smrg {
3576627f7eb2Smrg gfc_check_do_variable (iter->var->symtree);
3577627f7eb2Smrg break;
3578627f7eb2Smrg }
3579627f7eb2Smrg
3580627f7eb2Smrg m = match_io_element (k, &new_code);
3581627f7eb2Smrg if (m == MATCH_ERROR)
3582627f7eb2Smrg goto cleanup;
3583627f7eb2Smrg if (m == MATCH_NO)
3584627f7eb2Smrg {
3585627f7eb2Smrg if (n > 2)
3586627f7eb2Smrg goto syntax;
3587627f7eb2Smrg goto cleanup;
3588627f7eb2Smrg }
3589627f7eb2Smrg
3590627f7eb2Smrg tail = gfc_append_code (tail, new_code);
3591627f7eb2Smrg
3592627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
3593627f7eb2Smrg {
3594627f7eb2Smrg if (n > 2)
3595627f7eb2Smrg goto syntax;
3596627f7eb2Smrg m = MATCH_NO;
3597627f7eb2Smrg goto cleanup;
3598627f7eb2Smrg }
3599627f7eb2Smrg }
3600627f7eb2Smrg
3601627f7eb2Smrg if (gfc_match_char (')') != MATCH_YES)
3602627f7eb2Smrg goto syntax;
3603627f7eb2Smrg
3604627f7eb2Smrg new_code = gfc_get_code (EXEC_DO);
3605627f7eb2Smrg new_code->ext.iterator = iter;
3606627f7eb2Smrg
3607627f7eb2Smrg new_code->block = gfc_get_code (EXEC_DO);
3608627f7eb2Smrg new_code->block->next = head;
3609627f7eb2Smrg
3610627f7eb2Smrg *result = new_code;
3611627f7eb2Smrg return MATCH_YES;
3612627f7eb2Smrg
3613627f7eb2Smrg syntax:
3614627f7eb2Smrg gfc_error ("Syntax error in I/O iterator at %C");
3615627f7eb2Smrg m = MATCH_ERROR;
3616627f7eb2Smrg
3617627f7eb2Smrg cleanup:
3618627f7eb2Smrg gfc_free_iterator (iter, 1);
3619627f7eb2Smrg gfc_free_statements (head);
3620627f7eb2Smrg gfc_current_locus = old_loc;
3621627f7eb2Smrg return m;
3622627f7eb2Smrg }
3623627f7eb2Smrg
3624627f7eb2Smrg
3625627f7eb2Smrg /* Match a single element of an IO list, which is either a single
3626627f7eb2Smrg expression or an IO Iterator. */
3627627f7eb2Smrg
3628627f7eb2Smrg static match
match_io_element(io_kind k,gfc_code ** cpp)3629627f7eb2Smrg match_io_element (io_kind k, gfc_code **cpp)
3630627f7eb2Smrg {
3631627f7eb2Smrg gfc_expr *expr;
3632627f7eb2Smrg gfc_code *cp;
3633627f7eb2Smrg match m;
3634627f7eb2Smrg
3635627f7eb2Smrg expr = NULL;
3636627f7eb2Smrg
3637627f7eb2Smrg m = match_io_iterator (k, cpp);
3638627f7eb2Smrg if (m == MATCH_YES)
3639627f7eb2Smrg return MATCH_YES;
3640627f7eb2Smrg
3641627f7eb2Smrg if (k == M_READ)
3642627f7eb2Smrg {
3643627f7eb2Smrg m = gfc_match_variable (&expr, 0);
3644627f7eb2Smrg if (m == MATCH_NO)
3645627f7eb2Smrg {
3646627f7eb2Smrg gfc_error ("Expecting variable in READ statement at %C");
3647627f7eb2Smrg m = MATCH_ERROR;
3648627f7eb2Smrg }
3649627f7eb2Smrg
3650627f7eb2Smrg if (m == MATCH_YES && expr->expr_type == EXPR_CONSTANT)
3651627f7eb2Smrg {
3652627f7eb2Smrg gfc_error ("Expecting variable or io-implied-do in READ statement "
3653627f7eb2Smrg "at %L", &expr->where);
3654627f7eb2Smrg m = MATCH_ERROR;
3655627f7eb2Smrg }
3656627f7eb2Smrg
3657627f7eb2Smrg if (m == MATCH_YES
3658627f7eb2Smrg && expr->expr_type == EXPR_VARIABLE
3659627f7eb2Smrg && expr->symtree->n.sym->attr.external)
3660627f7eb2Smrg {
3661627f7eb2Smrg gfc_error ("Expecting variable or io-implied-do at %L",
3662627f7eb2Smrg &expr->where);
3663627f7eb2Smrg m = MATCH_ERROR;
3664627f7eb2Smrg }
3665627f7eb2Smrg }
3666627f7eb2Smrg else
3667627f7eb2Smrg {
3668627f7eb2Smrg m = gfc_match_expr (&expr);
3669627f7eb2Smrg if (m == MATCH_NO)
3670627f7eb2Smrg gfc_error ("Expected expression in %s statement at %C",
3671627f7eb2Smrg io_kind_name (k));
3672*4c3eb207Smrg
3673*4c3eb207Smrg if (m == MATCH_YES && expr->ts.type == BT_BOZ)
3674*4c3eb207Smrg {
3675*4c3eb207Smrg if (gfc_invalid_boz ("BOZ literal constant at %L cannot appear in "
3676*4c3eb207Smrg "an output IO list", &gfc_current_locus))
3677*4c3eb207Smrg return MATCH_ERROR;
3678*4c3eb207Smrg if (!gfc_boz2int (expr, gfc_max_integer_kind))
3679*4c3eb207Smrg return MATCH_ERROR;
3680*4c3eb207Smrg };
3681627f7eb2Smrg }
3682627f7eb2Smrg
3683627f7eb2Smrg if (m == MATCH_YES && k == M_READ && gfc_check_do_variable (expr->symtree))
3684627f7eb2Smrg m = MATCH_ERROR;
3685627f7eb2Smrg
3686627f7eb2Smrg if (m != MATCH_YES)
3687627f7eb2Smrg {
3688627f7eb2Smrg gfc_free_expr (expr);
3689627f7eb2Smrg return MATCH_ERROR;
3690627f7eb2Smrg }
3691627f7eb2Smrg
3692627f7eb2Smrg cp = gfc_get_code (EXEC_TRANSFER);
3693627f7eb2Smrg cp->expr1 = expr;
3694627f7eb2Smrg if (k != M_INQUIRE)
3695627f7eb2Smrg cp->ext.dt = current_dt;
3696627f7eb2Smrg
3697627f7eb2Smrg *cpp = cp;
3698627f7eb2Smrg return MATCH_YES;
3699627f7eb2Smrg }
3700627f7eb2Smrg
3701627f7eb2Smrg
3702627f7eb2Smrg /* Match an I/O list, building gfc_code structures as we go. */
3703627f7eb2Smrg
3704627f7eb2Smrg static match
match_io_list(io_kind k,gfc_code ** head_p)3705627f7eb2Smrg match_io_list (io_kind k, gfc_code **head_p)
3706627f7eb2Smrg {
3707627f7eb2Smrg gfc_code *head, *tail, *new_code;
3708627f7eb2Smrg match m;
3709627f7eb2Smrg
3710627f7eb2Smrg *head_p = head = tail = NULL;
3711627f7eb2Smrg if (gfc_match_eos () == MATCH_YES)
3712627f7eb2Smrg return MATCH_YES;
3713627f7eb2Smrg
3714627f7eb2Smrg for (;;)
3715627f7eb2Smrg {
3716627f7eb2Smrg m = match_io_element (k, &new_code);
3717627f7eb2Smrg if (m == MATCH_ERROR)
3718627f7eb2Smrg goto cleanup;
3719627f7eb2Smrg if (m == MATCH_NO)
3720627f7eb2Smrg goto syntax;
3721627f7eb2Smrg
3722627f7eb2Smrg tail = gfc_append_code (tail, new_code);
3723627f7eb2Smrg if (head == NULL)
3724627f7eb2Smrg head = new_code;
3725627f7eb2Smrg
3726627f7eb2Smrg if (gfc_match_eos () == MATCH_YES)
3727627f7eb2Smrg break;
3728627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
3729627f7eb2Smrg goto syntax;
3730627f7eb2Smrg }
3731627f7eb2Smrg
3732627f7eb2Smrg *head_p = head;
3733627f7eb2Smrg return MATCH_YES;
3734627f7eb2Smrg
3735627f7eb2Smrg syntax:
3736627f7eb2Smrg gfc_error ("Syntax error in %s statement at %C", io_kind_name (k));
3737627f7eb2Smrg
3738627f7eb2Smrg cleanup:
3739627f7eb2Smrg gfc_free_statements (head);
3740627f7eb2Smrg return MATCH_ERROR;
3741627f7eb2Smrg }
3742627f7eb2Smrg
3743627f7eb2Smrg
3744627f7eb2Smrg /* Attach the data transfer end node. */
3745627f7eb2Smrg
3746627f7eb2Smrg static void
terminate_io(gfc_code * io_code)3747627f7eb2Smrg terminate_io (gfc_code *io_code)
3748627f7eb2Smrg {
3749627f7eb2Smrg gfc_code *c;
3750627f7eb2Smrg
3751627f7eb2Smrg if (io_code == NULL)
3752627f7eb2Smrg io_code = new_st.block;
3753627f7eb2Smrg
3754627f7eb2Smrg c = gfc_get_code (EXEC_DT_END);
3755627f7eb2Smrg
3756627f7eb2Smrg /* Point to structure that is already there */
3757627f7eb2Smrg c->ext.dt = new_st.ext.dt;
3758627f7eb2Smrg gfc_append_code (io_code, c);
3759627f7eb2Smrg }
3760627f7eb2Smrg
3761627f7eb2Smrg
3762627f7eb2Smrg /* Check the constraints for a data transfer statement. The majority of the
3763*4c3eb207Smrg constraints appearing in 9.4 of the standard appear here.
3764627f7eb2Smrg
3765*4c3eb207Smrg Tag expressions are already resolved by resolve_tag, which includes
3766*4c3eb207Smrg verifying the type, that they are scalar, and verifying that BT_CHARACTER
3767*4c3eb207Smrg tags are of default kind. */
3768*4c3eb207Smrg
3769*4c3eb207Smrg static bool
check_io_constraints(io_kind k,gfc_dt * dt,gfc_code * io_code,locus * spec_end)3770627f7eb2Smrg check_io_constraints (io_kind k, gfc_dt *dt, gfc_code *io_code,
3771627f7eb2Smrg locus *spec_end)
3772627f7eb2Smrg {
3773627f7eb2Smrg #define io_constraint(condition, msg, arg)\
3774627f7eb2Smrg if (condition) \
3775627f7eb2Smrg {\
3776627f7eb2Smrg if ((arg)->lb != NULL)\
3777627f7eb2Smrg gfc_error ((msg), (arg));\
3778627f7eb2Smrg else\
3779*4c3eb207Smrg gfc_error ((msg), spec_end);\
3780*4c3eb207Smrg return false;\
3781627f7eb2Smrg }
3782627f7eb2Smrg
3783627f7eb2Smrg gfc_expr *expr;
3784627f7eb2Smrg gfc_symbol *sym = NULL;
3785627f7eb2Smrg bool warn, unformatted;
3786627f7eb2Smrg
3787627f7eb2Smrg warn = (dt->err || dt->iostat) ? true : false;
3788627f7eb2Smrg unformatted = dt->format_expr == NULL && dt->format_label == NULL
3789627f7eb2Smrg && dt->namelist == NULL;
3790627f7eb2Smrg
3791627f7eb2Smrg expr = dt->io_unit;
3792627f7eb2Smrg if (expr && expr->expr_type == EXPR_VARIABLE
3793627f7eb2Smrg && expr->ts.type == BT_CHARACTER)
3794627f7eb2Smrg {
3795627f7eb2Smrg sym = expr->symtree->n.sym;
3796627f7eb2Smrg
3797627f7eb2Smrg io_constraint (k == M_WRITE && sym->attr.intent == INTENT_IN,
3798627f7eb2Smrg "Internal file at %L must not be INTENT(IN)",
3799627f7eb2Smrg &expr->where);
3800627f7eb2Smrg
3801627f7eb2Smrg io_constraint (gfc_has_vector_index (dt->io_unit),
3802627f7eb2Smrg "Internal file incompatible with vector subscript at %L",
3803627f7eb2Smrg &expr->where);
3804627f7eb2Smrg
3805627f7eb2Smrg io_constraint (dt->rec != NULL,
3806627f7eb2Smrg "REC tag at %L is incompatible with internal file",
3807627f7eb2Smrg &dt->rec->where);
3808627f7eb2Smrg
3809627f7eb2Smrg io_constraint (dt->pos != NULL,
3810627f7eb2Smrg "POS tag at %L is incompatible with internal file",
3811627f7eb2Smrg &dt->pos->where);
3812627f7eb2Smrg
3813627f7eb2Smrg io_constraint (unformatted,
3814627f7eb2Smrg "Unformatted I/O not allowed with internal unit at %L",
3815627f7eb2Smrg &dt->io_unit->where);
3816627f7eb2Smrg
3817627f7eb2Smrg io_constraint (dt->asynchronous != NULL,
3818627f7eb2Smrg "ASYNCHRONOUS tag at %L not allowed with internal file",
3819627f7eb2Smrg &dt->asynchronous->where);
3820627f7eb2Smrg
3821627f7eb2Smrg if (dt->namelist != NULL)
3822627f7eb2Smrg {
3823627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "Internal file at %L with "
3824627f7eb2Smrg "namelist", &expr->where))
3825*4c3eb207Smrg return false;
3826627f7eb2Smrg }
3827627f7eb2Smrg
3828627f7eb2Smrg io_constraint (dt->advance != NULL,
3829627f7eb2Smrg "ADVANCE tag at %L is incompatible with internal file",
3830627f7eb2Smrg &dt->advance->where);
3831627f7eb2Smrg }
3832627f7eb2Smrg
3833627f7eb2Smrg if (expr && expr->ts.type != BT_CHARACTER)
3834627f7eb2Smrg {
3835627f7eb2Smrg
3836627f7eb2Smrg if (gfc_pure (NULL) && (k == M_READ || k == M_WRITE))
3837627f7eb2Smrg {
3838*4c3eb207Smrg gfc_error ("IO UNIT in %s statement at %L must be "
3839627f7eb2Smrg "an internal file in a PURE procedure",
3840*4c3eb207Smrg io_kind_name (k), &expr->where);
3841*4c3eb207Smrg return false;
3842627f7eb2Smrg }
3843627f7eb2Smrg
3844627f7eb2Smrg if (k == M_READ || k == M_WRITE)
3845627f7eb2Smrg gfc_unset_implicit_pure (NULL);
3846627f7eb2Smrg }
3847627f7eb2Smrg
3848627f7eb2Smrg if (dt->asynchronous)
3849627f7eb2Smrg {
3850*4c3eb207Smrg int num = -1;
3851627f7eb2Smrg static const char * asynchronous[] = { "YES", "NO", NULL };
3852627f7eb2Smrg
3853*4c3eb207Smrg /* Note: gfc_reduce_init_expr reports an error if not init-expr. */
3854627f7eb2Smrg if (!gfc_reduce_init_expr (dt->asynchronous))
3855*4c3eb207Smrg return false;
3856627f7eb2Smrg
3857627f7eb2Smrg if (!compare_to_allowed_values
3858627f7eb2Smrg ("ASYNCHRONOUS", asynchronous, NULL, NULL,
3859627f7eb2Smrg dt->asynchronous->value.character.string,
3860*4c3eb207Smrg io_kind_name (k), warn, &dt->asynchronous->where, &num))
3861*4c3eb207Smrg return false;
3862627f7eb2Smrg
3863*4c3eb207Smrg gcc_checking_assert (num != -1);
3864*4c3eb207Smrg
3865*4c3eb207Smrg /* For "YES", mark related symbols as asynchronous. */
3866*4c3eb207Smrg if (num == 0)
3867*4c3eb207Smrg {
3868*4c3eb207Smrg /* SIZE variable. */
3869*4c3eb207Smrg if (dt->size)
3870627f7eb2Smrg dt->size->symtree->n.sym->attr.asynchronous = 1;
3871*4c3eb207Smrg
3872*4c3eb207Smrg /* Variables in a NAMELIST. */
3873*4c3eb207Smrg if (dt->namelist)
3874*4c3eb207Smrg for (gfc_namelist *nl = dt->namelist->namelist; nl; nl = nl->next)
3875*4c3eb207Smrg nl->sym->attr.asynchronous = 1;
3876*4c3eb207Smrg
3877*4c3eb207Smrg /* Variables in an I/O list. */
3878*4c3eb207Smrg for (gfc_code *xfer = io_code; xfer && xfer->op == EXEC_TRANSFER;
3879*4c3eb207Smrg xfer = xfer->next)
3880*4c3eb207Smrg {
3881*4c3eb207Smrg gfc_expr *expr = xfer->expr1;
3882*4c3eb207Smrg while (expr != NULL && expr->expr_type == EXPR_OP
3883*4c3eb207Smrg && expr->value.op.op == INTRINSIC_PARENTHESES)
3884*4c3eb207Smrg expr = expr->value.op.op1;
3885*4c3eb207Smrg
3886*4c3eb207Smrg if (expr && expr->expr_type == EXPR_VARIABLE)
3887*4c3eb207Smrg expr->symtree->n.sym->attr.asynchronous = 1;
3888627f7eb2Smrg }
3889*4c3eb207Smrg }
3890*4c3eb207Smrg }
3891627f7eb2Smrg
3892627f7eb2Smrg if (dt->id)
3893627f7eb2Smrg {
3894627f7eb2Smrg bool not_yes
3895627f7eb2Smrg = !dt->asynchronous
3896627f7eb2Smrg || gfc_wide_strlen (dt->asynchronous->value.character.string) != 3
3897627f7eb2Smrg || gfc_wide_strncasecmp (dt->asynchronous->value.character.string,
3898627f7eb2Smrg "yes", 3) != 0;
3899627f7eb2Smrg io_constraint (not_yes,
3900627f7eb2Smrg "ID= specifier at %L must be with ASYNCHRONOUS='yes' "
3901627f7eb2Smrg "specifier", &dt->id->where);
3902627f7eb2Smrg }
3903627f7eb2Smrg
3904627f7eb2Smrg if (dt->decimal)
3905627f7eb2Smrg {
3906*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "DECIMAL= at %L "
3907*4c3eb207Smrg "not allowed in Fortran 95", &dt->decimal->where))
3908*4c3eb207Smrg return false;
3909627f7eb2Smrg
3910627f7eb2Smrg if (dt->decimal->expr_type == EXPR_CONSTANT)
3911627f7eb2Smrg {
3912627f7eb2Smrg static const char * decimal[] = { "COMMA", "POINT", NULL };
3913627f7eb2Smrg
3914627f7eb2Smrg if (!compare_to_allowed_values ("DECIMAL", decimal, NULL, NULL,
3915627f7eb2Smrg dt->decimal->value.character.string,
3916*4c3eb207Smrg io_kind_name (k), warn,
3917*4c3eb207Smrg &dt->decimal->where))
3918*4c3eb207Smrg return false;
3919627f7eb2Smrg
3920627f7eb2Smrg io_constraint (unformatted,
3921627f7eb2Smrg "the DECIMAL= specifier at %L must be with an "
3922627f7eb2Smrg "explicit format expression", &dt->decimal->where);
3923627f7eb2Smrg }
3924627f7eb2Smrg }
3925627f7eb2Smrg
3926627f7eb2Smrg if (dt->blank)
3927627f7eb2Smrg {
3928*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "BLANK= at %L "
3929*4c3eb207Smrg "not allowed in Fortran 95", &dt->blank->where))
3930*4c3eb207Smrg return false;
3931627f7eb2Smrg
3932627f7eb2Smrg if (dt->blank->expr_type == EXPR_CONSTANT)
3933627f7eb2Smrg {
3934627f7eb2Smrg static const char * blank[] = { "NULL", "ZERO", NULL };
3935627f7eb2Smrg
3936627f7eb2Smrg
3937627f7eb2Smrg if (!compare_to_allowed_values ("BLANK", blank, NULL, NULL,
3938627f7eb2Smrg dt->blank->value.character.string,
3939*4c3eb207Smrg io_kind_name (k), warn,
3940*4c3eb207Smrg &dt->blank->where))
3941*4c3eb207Smrg return false;
3942627f7eb2Smrg
3943627f7eb2Smrg io_constraint (unformatted,
3944627f7eb2Smrg "the BLANK= specifier at %L must be with an "
3945627f7eb2Smrg "explicit format expression", &dt->blank->where);
3946627f7eb2Smrg }
3947627f7eb2Smrg }
3948627f7eb2Smrg
3949627f7eb2Smrg if (dt->pad)
3950627f7eb2Smrg {
3951*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "PAD= at %L "
3952*4c3eb207Smrg "not allowed in Fortran 95", &dt->pad->where))
3953*4c3eb207Smrg return false;
3954627f7eb2Smrg
3955627f7eb2Smrg if (dt->pad->expr_type == EXPR_CONSTANT)
3956627f7eb2Smrg {
3957627f7eb2Smrg static const char * pad[] = { "YES", "NO", NULL };
3958627f7eb2Smrg
3959627f7eb2Smrg if (!compare_to_allowed_values ("PAD", pad, NULL, NULL,
3960627f7eb2Smrg dt->pad->value.character.string,
3961*4c3eb207Smrg io_kind_name (k), warn,
3962*4c3eb207Smrg &dt->pad->where))
3963*4c3eb207Smrg return false;
3964627f7eb2Smrg
3965627f7eb2Smrg io_constraint (unformatted,
3966627f7eb2Smrg "the PAD= specifier at %L must be with an "
3967627f7eb2Smrg "explicit format expression", &dt->pad->where);
3968627f7eb2Smrg }
3969627f7eb2Smrg }
3970627f7eb2Smrg
3971627f7eb2Smrg if (dt->round)
3972627f7eb2Smrg {
3973*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "ROUND= at %L "
3974*4c3eb207Smrg "not allowed in Fortran 95", &dt->round->where))
3975*4c3eb207Smrg return false;
3976627f7eb2Smrg
3977627f7eb2Smrg if (dt->round->expr_type == EXPR_CONSTANT)
3978627f7eb2Smrg {
3979627f7eb2Smrg static const char * round[] = { "UP", "DOWN", "ZERO", "NEAREST",
3980627f7eb2Smrg "COMPATIBLE", "PROCESSOR_DEFINED",
3981627f7eb2Smrg NULL };
3982627f7eb2Smrg
3983627f7eb2Smrg if (!compare_to_allowed_values ("ROUND", round, NULL, NULL,
3984627f7eb2Smrg dt->round->value.character.string,
3985*4c3eb207Smrg io_kind_name (k), warn,
3986*4c3eb207Smrg &dt->round->where))
3987*4c3eb207Smrg return false;
3988627f7eb2Smrg }
3989627f7eb2Smrg }
3990627f7eb2Smrg
3991627f7eb2Smrg if (dt->sign)
3992627f7eb2Smrg {
3993627f7eb2Smrg /* When implemented, change the following to use gfc_notify_std F2003.
3994*4c3eb207Smrg if (gfc_notify_std (GFC_STD_F2003, "SIGN= at %L "
3995*4c3eb207Smrg "not allowed in Fortran 95", &dt->sign->where) == false)
3996*4c3eb207Smrg return false; */
3997627f7eb2Smrg
3998627f7eb2Smrg if (dt->sign->expr_type == EXPR_CONSTANT)
3999627f7eb2Smrg {
4000627f7eb2Smrg static const char * sign[] = { "PLUS", "SUPPRESS", "PROCESSOR_DEFINED",
4001627f7eb2Smrg NULL };
4002627f7eb2Smrg
4003627f7eb2Smrg if (!compare_to_allowed_values ("SIGN", sign, NULL, NULL,
4004627f7eb2Smrg dt->sign->value.character.string,
4005*4c3eb207Smrg io_kind_name (k), warn, &dt->sign->where))
4006*4c3eb207Smrg return false;
4007627f7eb2Smrg
4008627f7eb2Smrg io_constraint (unformatted,
4009627f7eb2Smrg "SIGN= specifier at %L must be with an "
4010627f7eb2Smrg "explicit format expression", &dt->sign->where);
4011627f7eb2Smrg
4012627f7eb2Smrg io_constraint (k == M_READ,
4013627f7eb2Smrg "SIGN= specifier at %L not allowed in a "
4014627f7eb2Smrg "READ statement", &dt->sign->where);
4015627f7eb2Smrg }
4016627f7eb2Smrg }
4017627f7eb2Smrg
4018627f7eb2Smrg if (dt->delim)
4019627f7eb2Smrg {
4020*4c3eb207Smrg if (!gfc_notify_std (GFC_STD_F2003, "DELIM= at %L "
4021*4c3eb207Smrg "not allowed in Fortran 95", &dt->delim->where))
4022*4c3eb207Smrg return false;
4023627f7eb2Smrg
4024627f7eb2Smrg if (dt->delim->expr_type == EXPR_CONSTANT)
4025627f7eb2Smrg {
4026627f7eb2Smrg static const char *delim[] = { "APOSTROPHE", "QUOTE", "NONE", NULL };
4027627f7eb2Smrg
4028627f7eb2Smrg if (!compare_to_allowed_values ("DELIM", delim, NULL, NULL,
4029627f7eb2Smrg dt->delim->value.character.string,
4030*4c3eb207Smrg io_kind_name (k), warn,
4031*4c3eb207Smrg &dt->delim->where))
4032*4c3eb207Smrg return false;
4033627f7eb2Smrg
4034627f7eb2Smrg io_constraint (k == M_READ,
4035627f7eb2Smrg "DELIM= specifier at %L not allowed in a "
4036627f7eb2Smrg "READ statement", &dt->delim->where);
4037627f7eb2Smrg
4038627f7eb2Smrg io_constraint (dt->format_label != &format_asterisk
4039627f7eb2Smrg && dt->namelist == NULL,
4040627f7eb2Smrg "DELIM= specifier at %L must have FMT=*",
4041627f7eb2Smrg &dt->delim->where);
4042627f7eb2Smrg
4043627f7eb2Smrg io_constraint (unformatted && dt->namelist == NULL,
4044627f7eb2Smrg "DELIM= specifier at %L must be with FMT=* or "
4045627f7eb2Smrg "NML= specifier", &dt->delim->where);
4046627f7eb2Smrg }
4047627f7eb2Smrg }
4048627f7eb2Smrg
4049627f7eb2Smrg if (dt->namelist)
4050627f7eb2Smrg {
4051627f7eb2Smrg io_constraint (io_code && dt->namelist,
4052627f7eb2Smrg "NAMELIST cannot be followed by IO-list at %L",
4053627f7eb2Smrg &io_code->loc);
4054627f7eb2Smrg
4055627f7eb2Smrg io_constraint (dt->format_expr,
4056627f7eb2Smrg "IO spec-list cannot contain both NAMELIST group name "
4057627f7eb2Smrg "and format specification at %L",
4058627f7eb2Smrg &dt->format_expr->where);
4059627f7eb2Smrg
4060627f7eb2Smrg io_constraint (dt->format_label,
4061627f7eb2Smrg "IO spec-list cannot contain both NAMELIST group name "
4062627f7eb2Smrg "and format label at %L", spec_end);
4063627f7eb2Smrg
4064627f7eb2Smrg io_constraint (dt->rec,
4065627f7eb2Smrg "NAMELIST IO is not allowed with a REC= specifier "
4066627f7eb2Smrg "at %L", &dt->rec->where);
4067627f7eb2Smrg
4068627f7eb2Smrg io_constraint (dt->advance,
4069627f7eb2Smrg "NAMELIST IO is not allowed with a ADVANCE= specifier "
4070627f7eb2Smrg "at %L", &dt->advance->where);
4071627f7eb2Smrg }
4072627f7eb2Smrg
4073627f7eb2Smrg if (dt->rec)
4074627f7eb2Smrg {
4075627f7eb2Smrg io_constraint (dt->end,
4076627f7eb2Smrg "An END tag is not allowed with a "
4077627f7eb2Smrg "REC= specifier at %L", &dt->end_where);
4078627f7eb2Smrg
4079627f7eb2Smrg io_constraint (dt->format_label == &format_asterisk,
4080627f7eb2Smrg "FMT=* is not allowed with a REC= specifier "
4081627f7eb2Smrg "at %L", spec_end);
4082627f7eb2Smrg
4083627f7eb2Smrg io_constraint (dt->pos,
4084627f7eb2Smrg "POS= is not allowed with REC= specifier "
4085627f7eb2Smrg "at %L", &dt->pos->where);
4086627f7eb2Smrg }
4087627f7eb2Smrg
4088627f7eb2Smrg if (dt->advance)
4089627f7eb2Smrg {
4090627f7eb2Smrg int not_yes, not_no;
4091627f7eb2Smrg expr = dt->advance;
4092627f7eb2Smrg
4093627f7eb2Smrg io_constraint (dt->format_label == &format_asterisk,
4094627f7eb2Smrg "List directed format(*) is not allowed with a "
4095627f7eb2Smrg "ADVANCE= specifier at %L.", &expr->where);
4096627f7eb2Smrg
4097627f7eb2Smrg io_constraint (unformatted,
4098627f7eb2Smrg "the ADVANCE= specifier at %L must appear with an "
4099627f7eb2Smrg "explicit format expression", &expr->where);
4100627f7eb2Smrg
4101627f7eb2Smrg if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_CHARACTER)
4102627f7eb2Smrg {
4103627f7eb2Smrg const gfc_char_t *advance = expr->value.character.string;
4104627f7eb2Smrg not_no = gfc_wide_strlen (advance) != 2
4105627f7eb2Smrg || gfc_wide_strncasecmp (advance, "no", 2) != 0;
4106627f7eb2Smrg not_yes = gfc_wide_strlen (advance) != 3
4107627f7eb2Smrg || gfc_wide_strncasecmp (advance, "yes", 3) != 0;
4108627f7eb2Smrg }
4109627f7eb2Smrg else
4110627f7eb2Smrg {
4111627f7eb2Smrg not_no = 0;
4112627f7eb2Smrg not_yes = 0;
4113627f7eb2Smrg }
4114627f7eb2Smrg
4115627f7eb2Smrg io_constraint (not_no && not_yes,
4116627f7eb2Smrg "ADVANCE= specifier at %L must have value = "
4117627f7eb2Smrg "YES or NO.", &expr->where);
4118627f7eb2Smrg
4119627f7eb2Smrg io_constraint (dt->size && not_no && k == M_READ,
4120627f7eb2Smrg "SIZE tag at %L requires an ADVANCE = %<NO%>",
4121627f7eb2Smrg &dt->size->where);
4122627f7eb2Smrg
4123627f7eb2Smrg io_constraint (dt->eor && not_no && k == M_READ,
4124627f7eb2Smrg "EOR tag at %L requires an ADVANCE = %<NO%>",
4125627f7eb2Smrg &dt->eor_where);
4126627f7eb2Smrg }
4127627f7eb2Smrg
4128*4c3eb207Smrg if (k != M_READ)
4129*4c3eb207Smrg {
4130*4c3eb207Smrg io_constraint (dt->end, "END tag not allowed with output at %L",
4131*4c3eb207Smrg &dt->end_where);
4132627f7eb2Smrg
4133*4c3eb207Smrg io_constraint (dt->eor, "EOR tag not allowed with output at %L",
4134*4c3eb207Smrg &dt->eor_where);
4135*4c3eb207Smrg
4136*4c3eb207Smrg io_constraint (dt->blank,
4137*4c3eb207Smrg "BLANK= specifier not allowed with output at %L",
4138*4c3eb207Smrg &dt->blank->where);
4139*4c3eb207Smrg
4140*4c3eb207Smrg io_constraint (dt->pad, "PAD= specifier not allowed with output at %L",
4141*4c3eb207Smrg &dt->pad->where);
4142*4c3eb207Smrg
4143*4c3eb207Smrg io_constraint (dt->size, "SIZE= specifier not allowed with output at %L",
4144*4c3eb207Smrg &dt->size->where);
4145627f7eb2Smrg }
4146*4c3eb207Smrg else
4147*4c3eb207Smrg {
4148*4c3eb207Smrg io_constraint (dt->size && dt->advance == NULL,
4149*4c3eb207Smrg "SIZE tag at %L requires an ADVANCE tag",
4150*4c3eb207Smrg &dt->size->where);
4151*4c3eb207Smrg
4152*4c3eb207Smrg io_constraint (dt->eor && dt->advance == NULL,
4153*4c3eb207Smrg "EOR tag at %L requires an ADVANCE tag",
4154*4c3eb207Smrg &dt->eor_where);
4155*4c3eb207Smrg }
4156*4c3eb207Smrg
4157*4c3eb207Smrg return true;
4158627f7eb2Smrg #undef io_constraint
4159*4c3eb207Smrg }
4160627f7eb2Smrg
4161627f7eb2Smrg
4162627f7eb2Smrg /* Match a READ, WRITE or PRINT statement. */
4163627f7eb2Smrg
4164627f7eb2Smrg static match
match_io(io_kind k)4165627f7eb2Smrg match_io (io_kind k)
4166627f7eb2Smrg {
4167627f7eb2Smrg char name[GFC_MAX_SYMBOL_LEN + 1];
4168627f7eb2Smrg gfc_code *io_code;
4169627f7eb2Smrg gfc_symbol *sym;
4170627f7eb2Smrg int comma_flag;
4171627f7eb2Smrg locus where;
4172*4c3eb207Smrg locus control;
4173627f7eb2Smrg gfc_dt *dt;
4174627f7eb2Smrg match m;
4175627f7eb2Smrg
4176627f7eb2Smrg where = gfc_current_locus;
4177627f7eb2Smrg comma_flag = 0;
4178627f7eb2Smrg current_dt = dt = XCNEW (gfc_dt);
4179627f7eb2Smrg m = gfc_match_char ('(');
4180627f7eb2Smrg if (m == MATCH_NO)
4181627f7eb2Smrg {
4182627f7eb2Smrg where = gfc_current_locus;
4183627f7eb2Smrg if (k == M_WRITE)
4184627f7eb2Smrg goto syntax;
4185627f7eb2Smrg else if (k == M_PRINT)
4186627f7eb2Smrg {
4187627f7eb2Smrg /* Treat the non-standard case of PRINT namelist. */
4188627f7eb2Smrg if ((gfc_current_form == FORM_FIXED || gfc_peek_ascii_char () == ' ')
4189627f7eb2Smrg && gfc_match_name (name) == MATCH_YES)
4190627f7eb2Smrg {
4191627f7eb2Smrg gfc_find_symbol (name, NULL, 1, &sym);
4192627f7eb2Smrg if (sym && sym->attr.flavor == FL_NAMELIST)
4193627f7eb2Smrg {
4194627f7eb2Smrg if (!gfc_notify_std (GFC_STD_GNU, "PRINT namelist at "
4195627f7eb2Smrg "%C is an extension"))
4196627f7eb2Smrg {
4197627f7eb2Smrg m = MATCH_ERROR;
4198627f7eb2Smrg goto cleanup;
4199627f7eb2Smrg }
4200627f7eb2Smrg
4201627f7eb2Smrg dt->io_unit = default_unit (k);
4202627f7eb2Smrg dt->namelist = sym;
4203627f7eb2Smrg goto get_io_list;
4204627f7eb2Smrg }
4205627f7eb2Smrg else
4206627f7eb2Smrg gfc_current_locus = where;
4207627f7eb2Smrg }
4208627f7eb2Smrg
4209627f7eb2Smrg if (gfc_match_char ('*') == MATCH_YES
4210627f7eb2Smrg && gfc_match_char(',') == MATCH_YES)
4211627f7eb2Smrg {
4212627f7eb2Smrg locus where2 = gfc_current_locus;
4213627f7eb2Smrg if (gfc_match_eos () == MATCH_YES)
4214627f7eb2Smrg {
4215627f7eb2Smrg gfc_current_locus = where2;
4216627f7eb2Smrg gfc_error ("Comma after * at %C not allowed without I/O list");
4217627f7eb2Smrg m = MATCH_ERROR;
4218627f7eb2Smrg goto cleanup;
4219627f7eb2Smrg }
4220627f7eb2Smrg else
4221627f7eb2Smrg gfc_current_locus = where;
4222627f7eb2Smrg }
4223627f7eb2Smrg else
4224627f7eb2Smrg gfc_current_locus = where;
4225627f7eb2Smrg }
4226627f7eb2Smrg
4227627f7eb2Smrg if (gfc_current_form == FORM_FREE)
4228627f7eb2Smrg {
4229627f7eb2Smrg char c = gfc_peek_ascii_char ();
4230627f7eb2Smrg if (c != ' ' && c != '*' && c != '\'' && c != '"')
4231627f7eb2Smrg {
4232627f7eb2Smrg m = MATCH_NO;
4233627f7eb2Smrg goto cleanup;
4234627f7eb2Smrg }
4235627f7eb2Smrg }
4236627f7eb2Smrg
4237627f7eb2Smrg m = match_dt_format (dt);
4238627f7eb2Smrg if (m == MATCH_ERROR)
4239627f7eb2Smrg goto cleanup;
4240627f7eb2Smrg if (m == MATCH_NO)
4241627f7eb2Smrg goto syntax;
4242627f7eb2Smrg
4243627f7eb2Smrg comma_flag = 1;
4244627f7eb2Smrg dt->io_unit = default_unit (k);
4245627f7eb2Smrg goto get_io_list;
4246627f7eb2Smrg }
4247627f7eb2Smrg else
4248627f7eb2Smrg {
4249627f7eb2Smrg /* Before issuing an error for a malformed 'print (1,*)' type of
4250627f7eb2Smrg error, check for a default-char-expr of the form ('(I0)'). */
4251627f7eb2Smrg if (m == MATCH_YES)
4252627f7eb2Smrg {
4253627f7eb2Smrg control = gfc_current_locus;
4254627f7eb2Smrg if (k == M_PRINT)
4255627f7eb2Smrg {
4256627f7eb2Smrg /* Reset current locus to get the initial '(' in an expression. */
4257627f7eb2Smrg gfc_current_locus = where;
4258627f7eb2Smrg dt->format_expr = NULL;
4259627f7eb2Smrg m = match_dt_format (dt);
4260627f7eb2Smrg
4261627f7eb2Smrg if (m == MATCH_ERROR)
4262627f7eb2Smrg goto cleanup;
4263627f7eb2Smrg if (m == MATCH_NO || dt->format_expr == NULL)
4264627f7eb2Smrg goto syntax;
4265627f7eb2Smrg
4266627f7eb2Smrg comma_flag = 1;
4267627f7eb2Smrg dt->io_unit = default_unit (k);
4268627f7eb2Smrg goto get_io_list;
4269627f7eb2Smrg }
4270627f7eb2Smrg if (k == M_READ)
4271627f7eb2Smrg {
4272627f7eb2Smrg /* Commit any pending symbols now so that when we undo
4273627f7eb2Smrg symbols later we wont lose them. */
4274627f7eb2Smrg gfc_commit_symbols ();
4275627f7eb2Smrg /* Reset current locus to get the initial '(' in an expression. */
4276627f7eb2Smrg gfc_current_locus = where;
4277627f7eb2Smrg dt->format_expr = NULL;
4278627f7eb2Smrg m = gfc_match_expr (&dt->format_expr);
4279627f7eb2Smrg if (m == MATCH_YES)
4280627f7eb2Smrg {
4281627f7eb2Smrg if (dt->format_expr
4282627f7eb2Smrg && dt->format_expr->ts.type == BT_CHARACTER)
4283627f7eb2Smrg {
4284627f7eb2Smrg comma_flag = 1;
4285627f7eb2Smrg dt->io_unit = default_unit (k);
4286627f7eb2Smrg goto get_io_list;
4287627f7eb2Smrg }
4288627f7eb2Smrg else
4289627f7eb2Smrg {
4290627f7eb2Smrg gfc_free_expr (dt->format_expr);
4291627f7eb2Smrg dt->format_expr = NULL;
4292627f7eb2Smrg gfc_current_locus = control;
4293627f7eb2Smrg }
4294627f7eb2Smrg }
4295627f7eb2Smrg else
4296627f7eb2Smrg {
4297627f7eb2Smrg gfc_clear_error ();
4298627f7eb2Smrg gfc_undo_symbols ();
4299627f7eb2Smrg gfc_free_expr (dt->format_expr);
4300627f7eb2Smrg dt->format_expr = NULL;
4301627f7eb2Smrg gfc_current_locus = control;
4302627f7eb2Smrg }
4303627f7eb2Smrg }
4304627f7eb2Smrg }
4305627f7eb2Smrg }
4306627f7eb2Smrg
4307627f7eb2Smrg /* Match a control list */
4308627f7eb2Smrg if (match_dt_element (k, dt) == MATCH_YES)
4309627f7eb2Smrg goto next;
4310627f7eb2Smrg if (match_dt_unit (k, dt) != MATCH_YES)
4311627f7eb2Smrg goto loop;
4312627f7eb2Smrg
4313627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
4314627f7eb2Smrg goto get_io_list;
4315627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
4316627f7eb2Smrg goto syntax;
4317627f7eb2Smrg
4318627f7eb2Smrg m = match_dt_element (k, dt);
4319627f7eb2Smrg if (m == MATCH_YES)
4320627f7eb2Smrg goto next;
4321627f7eb2Smrg if (m == MATCH_ERROR)
4322627f7eb2Smrg goto cleanup;
4323627f7eb2Smrg
4324627f7eb2Smrg m = match_dt_format (dt);
4325627f7eb2Smrg if (m == MATCH_YES)
4326627f7eb2Smrg goto next;
4327627f7eb2Smrg if (m == MATCH_ERROR)
4328627f7eb2Smrg goto cleanup;
4329627f7eb2Smrg
4330627f7eb2Smrg where = gfc_current_locus;
4331627f7eb2Smrg
4332627f7eb2Smrg m = gfc_match_name (name);
4333627f7eb2Smrg if (m == MATCH_YES)
4334627f7eb2Smrg {
4335627f7eb2Smrg gfc_find_symbol (name, NULL, 1, &sym);
4336627f7eb2Smrg if (sym && sym->attr.flavor == FL_NAMELIST)
4337627f7eb2Smrg {
4338627f7eb2Smrg dt->namelist = sym;
4339627f7eb2Smrg if (k == M_READ && check_namelist (sym))
4340627f7eb2Smrg {
4341627f7eb2Smrg m = MATCH_ERROR;
4342627f7eb2Smrg goto cleanup;
4343627f7eb2Smrg }
4344627f7eb2Smrg goto next;
4345627f7eb2Smrg }
4346627f7eb2Smrg }
4347627f7eb2Smrg
4348627f7eb2Smrg gfc_current_locus = where;
4349627f7eb2Smrg
4350627f7eb2Smrg goto loop; /* No matches, try regular elements */
4351627f7eb2Smrg
4352627f7eb2Smrg next:
4353627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
4354627f7eb2Smrg goto get_io_list;
4355627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
4356627f7eb2Smrg goto syntax;
4357627f7eb2Smrg
4358627f7eb2Smrg loop:
4359627f7eb2Smrg for (;;)
4360627f7eb2Smrg {
4361627f7eb2Smrg m = match_dt_element (k, dt);
4362627f7eb2Smrg if (m == MATCH_NO)
4363627f7eb2Smrg goto syntax;
4364627f7eb2Smrg if (m == MATCH_ERROR)
4365627f7eb2Smrg goto cleanup;
4366627f7eb2Smrg
4367627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
4368627f7eb2Smrg break;
4369627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
4370627f7eb2Smrg goto syntax;
4371627f7eb2Smrg }
4372627f7eb2Smrg
4373627f7eb2Smrg get_io_list:
4374627f7eb2Smrg
4375627f7eb2Smrg /* Save the IO kind for later use. */
4376627f7eb2Smrg dt->dt_io_kind = gfc_get_iokind_expr (&gfc_current_locus, k);
4377627f7eb2Smrg
4378627f7eb2Smrg /* Optional leading comma (non-standard). We use a gfc_expr structure here
4379627f7eb2Smrg to save the locus. This is used later when resolving transfer statements
4380627f7eb2Smrg that might have a format expression without unit number. */
4381627f7eb2Smrg if (!comma_flag && gfc_match_char (',') == MATCH_YES)
4382627f7eb2Smrg dt->extra_comma = dt->dt_io_kind;
4383627f7eb2Smrg
4384627f7eb2Smrg io_code = NULL;
4385627f7eb2Smrg if (gfc_match_eos () != MATCH_YES)
4386627f7eb2Smrg {
4387627f7eb2Smrg if (comma_flag && gfc_match_char (',') != MATCH_YES)
4388627f7eb2Smrg {
4389627f7eb2Smrg gfc_error ("Expected comma in I/O list at %C");
4390627f7eb2Smrg m = MATCH_ERROR;
4391627f7eb2Smrg goto cleanup;
4392627f7eb2Smrg }
4393627f7eb2Smrg
4394627f7eb2Smrg m = match_io_list (k, &io_code);
4395627f7eb2Smrg if (m == MATCH_ERROR)
4396627f7eb2Smrg goto cleanup;
4397627f7eb2Smrg if (m == MATCH_NO)
4398627f7eb2Smrg goto syntax;
4399627f7eb2Smrg }
4400627f7eb2Smrg
4401627f7eb2Smrg /* See if we want to use defaults for missing exponents in real transfers
4402627f7eb2Smrg and other DEC runtime extensions. */
4403*4c3eb207Smrg if (flag_dec_format_defaults)
4404627f7eb2Smrg dt->dec_ext = 1;
4405627f7eb2Smrg
4406*4c3eb207Smrg /* Check the format string now. */
4407*4c3eb207Smrg if (dt->format_expr
4408*4c3eb207Smrg && (!gfc_simplify_expr (dt->format_expr, 0)
4409*4c3eb207Smrg || !check_format_string (dt->format_expr, k == M_READ)))
4410*4c3eb207Smrg return MATCH_ERROR;
4411627f7eb2Smrg
4412627f7eb2Smrg new_st.op = (k == M_READ) ? EXEC_READ : EXEC_WRITE;
4413627f7eb2Smrg new_st.ext.dt = dt;
4414627f7eb2Smrg new_st.block = gfc_get_code (new_st.op);
4415627f7eb2Smrg new_st.block->next = io_code;
4416627f7eb2Smrg
4417627f7eb2Smrg terminate_io (io_code);
4418627f7eb2Smrg
4419627f7eb2Smrg return MATCH_YES;
4420627f7eb2Smrg
4421627f7eb2Smrg syntax:
4422627f7eb2Smrg gfc_error ("Syntax error in %s statement at %C", io_kind_name (k));
4423627f7eb2Smrg m = MATCH_ERROR;
4424627f7eb2Smrg
4425627f7eb2Smrg cleanup:
4426627f7eb2Smrg gfc_free_dt (dt);
4427627f7eb2Smrg return m;
4428627f7eb2Smrg }
4429627f7eb2Smrg
4430627f7eb2Smrg
4431627f7eb2Smrg match
gfc_match_read(void)4432627f7eb2Smrg gfc_match_read (void)
4433627f7eb2Smrg {
4434627f7eb2Smrg return match_io (M_READ);
4435627f7eb2Smrg }
4436627f7eb2Smrg
4437627f7eb2Smrg
4438627f7eb2Smrg match
gfc_match_write(void)4439627f7eb2Smrg gfc_match_write (void)
4440627f7eb2Smrg {
4441627f7eb2Smrg return match_io (M_WRITE);
4442627f7eb2Smrg }
4443627f7eb2Smrg
4444627f7eb2Smrg
4445627f7eb2Smrg match
gfc_match_print(void)4446627f7eb2Smrg gfc_match_print (void)
4447627f7eb2Smrg {
4448627f7eb2Smrg match m;
4449627f7eb2Smrg
4450627f7eb2Smrg m = match_io (M_PRINT);
4451627f7eb2Smrg if (m != MATCH_YES)
4452627f7eb2Smrg return m;
4453627f7eb2Smrg
4454627f7eb2Smrg if (gfc_pure (NULL))
4455627f7eb2Smrg {
4456627f7eb2Smrg gfc_error ("PRINT statement at %C not allowed within PURE procedure");
4457627f7eb2Smrg return MATCH_ERROR;
4458627f7eb2Smrg }
4459627f7eb2Smrg
4460627f7eb2Smrg gfc_unset_implicit_pure (NULL);
4461627f7eb2Smrg
4462627f7eb2Smrg return MATCH_YES;
4463627f7eb2Smrg }
4464627f7eb2Smrg
4465627f7eb2Smrg
4466627f7eb2Smrg /* Free a gfc_inquire structure. */
4467627f7eb2Smrg
4468627f7eb2Smrg void
gfc_free_inquire(gfc_inquire * inquire)4469627f7eb2Smrg gfc_free_inquire (gfc_inquire *inquire)
4470627f7eb2Smrg {
4471627f7eb2Smrg
4472627f7eb2Smrg if (inquire == NULL)
4473627f7eb2Smrg return;
4474627f7eb2Smrg
4475627f7eb2Smrg gfc_free_expr (inquire->unit);
4476627f7eb2Smrg gfc_free_expr (inquire->file);
4477627f7eb2Smrg gfc_free_expr (inquire->iomsg);
4478627f7eb2Smrg gfc_free_expr (inquire->iostat);
4479627f7eb2Smrg gfc_free_expr (inquire->exist);
4480627f7eb2Smrg gfc_free_expr (inquire->opened);
4481627f7eb2Smrg gfc_free_expr (inquire->number);
4482627f7eb2Smrg gfc_free_expr (inquire->named);
4483627f7eb2Smrg gfc_free_expr (inquire->name);
4484627f7eb2Smrg gfc_free_expr (inquire->access);
4485627f7eb2Smrg gfc_free_expr (inquire->sequential);
4486627f7eb2Smrg gfc_free_expr (inquire->direct);
4487627f7eb2Smrg gfc_free_expr (inquire->form);
4488627f7eb2Smrg gfc_free_expr (inquire->formatted);
4489627f7eb2Smrg gfc_free_expr (inquire->unformatted);
4490627f7eb2Smrg gfc_free_expr (inquire->recl);
4491627f7eb2Smrg gfc_free_expr (inquire->nextrec);
4492627f7eb2Smrg gfc_free_expr (inquire->blank);
4493627f7eb2Smrg gfc_free_expr (inquire->position);
4494627f7eb2Smrg gfc_free_expr (inquire->action);
4495627f7eb2Smrg gfc_free_expr (inquire->read);
4496627f7eb2Smrg gfc_free_expr (inquire->write);
4497627f7eb2Smrg gfc_free_expr (inquire->readwrite);
4498627f7eb2Smrg gfc_free_expr (inquire->delim);
4499627f7eb2Smrg gfc_free_expr (inquire->encoding);
4500627f7eb2Smrg gfc_free_expr (inquire->pad);
4501627f7eb2Smrg gfc_free_expr (inquire->iolength);
4502627f7eb2Smrg gfc_free_expr (inquire->convert);
4503627f7eb2Smrg gfc_free_expr (inquire->strm_pos);
4504627f7eb2Smrg gfc_free_expr (inquire->asynchronous);
4505627f7eb2Smrg gfc_free_expr (inquire->decimal);
4506627f7eb2Smrg gfc_free_expr (inquire->pending);
4507627f7eb2Smrg gfc_free_expr (inquire->id);
4508627f7eb2Smrg gfc_free_expr (inquire->sign);
4509627f7eb2Smrg gfc_free_expr (inquire->size);
4510627f7eb2Smrg gfc_free_expr (inquire->round);
4511627f7eb2Smrg gfc_free_expr (inquire->share);
4512627f7eb2Smrg gfc_free_expr (inquire->cc);
4513627f7eb2Smrg free (inquire);
4514627f7eb2Smrg }
4515627f7eb2Smrg
4516627f7eb2Smrg
4517627f7eb2Smrg /* Match an element of an INQUIRE statement. */
4518627f7eb2Smrg
4519627f7eb2Smrg #define RETM if (m != MATCH_NO) return m;
4520627f7eb2Smrg
4521627f7eb2Smrg static match
match_inquire_element(gfc_inquire * inquire)4522627f7eb2Smrg match_inquire_element (gfc_inquire *inquire)
4523627f7eb2Smrg {
4524627f7eb2Smrg match m;
4525627f7eb2Smrg
4526627f7eb2Smrg m = match_etag (&tag_unit, &inquire->unit);
4527627f7eb2Smrg RETM m = match_etag (&tag_file, &inquire->file);
4528627f7eb2Smrg RETM m = match_ltag (&tag_err, &inquire->err);
4529627f7eb2Smrg RETM m = match_etag (&tag_iomsg, &inquire->iomsg);
4530627f7eb2Smrg RETM m = match_out_tag (&tag_iostat, &inquire->iostat);
4531627f7eb2Smrg RETM m = match_vtag (&tag_exist, &inquire->exist);
4532627f7eb2Smrg RETM m = match_vtag (&tag_opened, &inquire->opened);
4533627f7eb2Smrg RETM m = match_vtag (&tag_named, &inquire->named);
4534627f7eb2Smrg RETM m = match_vtag (&tag_name, &inquire->name);
4535627f7eb2Smrg RETM m = match_out_tag (&tag_number, &inquire->number);
4536627f7eb2Smrg RETM m = match_vtag (&tag_s_access, &inquire->access);
4537627f7eb2Smrg RETM m = match_vtag (&tag_sequential, &inquire->sequential);
4538627f7eb2Smrg RETM m = match_vtag (&tag_direct, &inquire->direct);
4539627f7eb2Smrg RETM m = match_vtag (&tag_s_form, &inquire->form);
4540627f7eb2Smrg RETM m = match_vtag (&tag_formatted, &inquire->formatted);
4541627f7eb2Smrg RETM m = match_vtag (&tag_unformatted, &inquire->unformatted);
4542627f7eb2Smrg RETM m = match_out_tag (&tag_s_recl, &inquire->recl);
4543627f7eb2Smrg RETM m = match_out_tag (&tag_nextrec, &inquire->nextrec);
4544627f7eb2Smrg RETM m = match_vtag (&tag_s_blank, &inquire->blank);
4545627f7eb2Smrg RETM m = match_vtag (&tag_s_position, &inquire->position);
4546627f7eb2Smrg RETM m = match_vtag (&tag_s_action, &inquire->action);
4547627f7eb2Smrg RETM m = match_vtag (&tag_read, &inquire->read);
4548627f7eb2Smrg RETM m = match_vtag (&tag_write, &inquire->write);
4549627f7eb2Smrg RETM m = match_vtag (&tag_readwrite, &inquire->readwrite);
4550627f7eb2Smrg RETM m = match_vtag (&tag_s_async, &inquire->asynchronous);
4551627f7eb2Smrg RETM m = match_vtag (&tag_s_delim, &inquire->delim);
4552627f7eb2Smrg RETM m = match_vtag (&tag_s_decimal, &inquire->decimal);
4553627f7eb2Smrg RETM m = match_out_tag (&tag_size, &inquire->size);
4554627f7eb2Smrg RETM m = match_vtag (&tag_s_encoding, &inquire->encoding);
4555627f7eb2Smrg RETM m = match_vtag (&tag_s_round, &inquire->round);
4556627f7eb2Smrg RETM m = match_vtag (&tag_s_sign, &inquire->sign);
4557627f7eb2Smrg RETM m = match_vtag (&tag_s_pad, &inquire->pad);
4558627f7eb2Smrg RETM m = match_out_tag (&tag_iolength, &inquire->iolength);
4559627f7eb2Smrg RETM m = match_vtag (&tag_convert, &inquire->convert);
4560627f7eb2Smrg RETM m = match_out_tag (&tag_strm_out, &inquire->strm_pos);
4561627f7eb2Smrg RETM m = match_vtag (&tag_pending, &inquire->pending);
4562627f7eb2Smrg RETM m = match_vtag (&tag_id, &inquire->id);
4563627f7eb2Smrg RETM m = match_vtag (&tag_s_iqstream, &inquire->iqstream);
4564627f7eb2Smrg RETM m = match_dec_vtag (&tag_v_share, &inquire->share);
4565627f7eb2Smrg RETM m = match_dec_vtag (&tag_v_cc, &inquire->cc);
4566627f7eb2Smrg RETM return MATCH_NO;
4567627f7eb2Smrg }
4568627f7eb2Smrg
4569627f7eb2Smrg #undef RETM
4570627f7eb2Smrg
4571627f7eb2Smrg
4572627f7eb2Smrg match
gfc_match_inquire(void)4573627f7eb2Smrg gfc_match_inquire (void)
4574627f7eb2Smrg {
4575627f7eb2Smrg gfc_inquire *inquire;
4576627f7eb2Smrg gfc_code *code;
4577627f7eb2Smrg match m;
4578627f7eb2Smrg locus loc;
4579627f7eb2Smrg
4580627f7eb2Smrg m = gfc_match_char ('(');
4581627f7eb2Smrg if (m == MATCH_NO)
4582627f7eb2Smrg return m;
4583627f7eb2Smrg
4584627f7eb2Smrg inquire = XCNEW (gfc_inquire);
4585627f7eb2Smrg
4586627f7eb2Smrg loc = gfc_current_locus;
4587627f7eb2Smrg
4588627f7eb2Smrg m = match_inquire_element (inquire);
4589627f7eb2Smrg if (m == MATCH_ERROR)
4590627f7eb2Smrg goto cleanup;
4591627f7eb2Smrg if (m == MATCH_NO)
4592627f7eb2Smrg {
4593627f7eb2Smrg m = gfc_match_expr (&inquire->unit);
4594627f7eb2Smrg if (m == MATCH_ERROR)
4595627f7eb2Smrg goto cleanup;
4596627f7eb2Smrg if (m == MATCH_NO)
4597627f7eb2Smrg goto syntax;
4598627f7eb2Smrg }
4599627f7eb2Smrg
4600627f7eb2Smrg /* See if we have the IOLENGTH form of the inquire statement. */
4601627f7eb2Smrg if (inquire->iolength != NULL)
4602627f7eb2Smrg {
4603627f7eb2Smrg if (gfc_match_char (')') != MATCH_YES)
4604627f7eb2Smrg goto syntax;
4605627f7eb2Smrg
4606627f7eb2Smrg m = match_io_list (M_INQUIRE, &code);
4607627f7eb2Smrg if (m == MATCH_ERROR)
4608627f7eb2Smrg goto cleanup;
4609627f7eb2Smrg if (m == MATCH_NO)
4610627f7eb2Smrg goto syntax;
4611627f7eb2Smrg
4612627f7eb2Smrg for (gfc_code *c = code; c; c = c->next)
4613627f7eb2Smrg if (c->expr1 && c->expr1->expr_type == EXPR_FUNCTION
4614627f7eb2Smrg && c->expr1->symtree && c->expr1->symtree->n.sym->attr.function
4615627f7eb2Smrg && !c->expr1->symtree->n.sym->attr.external
4616627f7eb2Smrg && strcmp (c->expr1->symtree->name, "null") == 0)
4617627f7eb2Smrg {
4618627f7eb2Smrg gfc_error ("NULL() near %L cannot appear in INQUIRE statement",
4619627f7eb2Smrg &c->expr1->where);
4620627f7eb2Smrg goto cleanup;
4621627f7eb2Smrg }
4622627f7eb2Smrg
4623627f7eb2Smrg new_st.op = EXEC_IOLENGTH;
4624627f7eb2Smrg new_st.expr1 = inquire->iolength;
4625627f7eb2Smrg new_st.ext.inquire = inquire;
4626627f7eb2Smrg
4627627f7eb2Smrg if (gfc_pure (NULL))
4628627f7eb2Smrg {
4629627f7eb2Smrg gfc_free_statements (code);
4630627f7eb2Smrg gfc_error ("INQUIRE statement not allowed in PURE procedure at %C");
4631627f7eb2Smrg return MATCH_ERROR;
4632627f7eb2Smrg }
4633627f7eb2Smrg
4634627f7eb2Smrg gfc_unset_implicit_pure (NULL);
4635627f7eb2Smrg
4636627f7eb2Smrg new_st.block = gfc_get_code (EXEC_IOLENGTH);
4637627f7eb2Smrg terminate_io (code);
4638627f7eb2Smrg new_st.block->next = code;
4639627f7eb2Smrg return MATCH_YES;
4640627f7eb2Smrg }
4641627f7eb2Smrg
4642627f7eb2Smrg /* At this point, we have the non-IOLENGTH inquire statement. */
4643627f7eb2Smrg for (;;)
4644627f7eb2Smrg {
4645627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
4646627f7eb2Smrg break;
4647627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
4648627f7eb2Smrg goto syntax;
4649627f7eb2Smrg
4650627f7eb2Smrg m = match_inquire_element (inquire);
4651627f7eb2Smrg if (m == MATCH_ERROR)
4652627f7eb2Smrg goto cleanup;
4653627f7eb2Smrg if (m == MATCH_NO)
4654627f7eb2Smrg goto syntax;
4655627f7eb2Smrg
4656627f7eb2Smrg if (inquire->iolength != NULL)
4657627f7eb2Smrg {
4658627f7eb2Smrg gfc_error ("IOLENGTH tag invalid in INQUIRE statement at %C");
4659627f7eb2Smrg goto cleanup;
4660627f7eb2Smrg }
4661627f7eb2Smrg }
4662627f7eb2Smrg
4663627f7eb2Smrg if (gfc_match_eos () != MATCH_YES)
4664627f7eb2Smrg goto syntax;
4665627f7eb2Smrg
4666627f7eb2Smrg if (inquire->unit != NULL && inquire->file != NULL)
4667627f7eb2Smrg {
4668627f7eb2Smrg gfc_error ("INQUIRE statement at %L cannot contain both FILE and "
4669627f7eb2Smrg "UNIT specifiers", &loc);
4670627f7eb2Smrg goto cleanup;
4671627f7eb2Smrg }
4672627f7eb2Smrg
4673627f7eb2Smrg if (inquire->unit == NULL && inquire->file == NULL)
4674627f7eb2Smrg {
4675627f7eb2Smrg gfc_error ("INQUIRE statement at %L requires either FILE or "
4676627f7eb2Smrg "UNIT specifier", &loc);
4677627f7eb2Smrg goto cleanup;
4678627f7eb2Smrg }
4679627f7eb2Smrg
4680627f7eb2Smrg if (inquire->unit != NULL && inquire->unit->expr_type == EXPR_CONSTANT
4681627f7eb2Smrg && inquire->unit->ts.type == BT_INTEGER
4682627f7eb2Smrg && ((mpz_get_si (inquire->unit->value.integer) == GFC_INTERNAL_UNIT4)
4683627f7eb2Smrg || (mpz_get_si (inquire->unit->value.integer) == GFC_INTERNAL_UNIT)))
4684627f7eb2Smrg {
4685627f7eb2Smrg gfc_error ("UNIT number in INQUIRE statement at %L cannot "
4686627f7eb2Smrg "be %d", &loc, (int) mpz_get_si (inquire->unit->value.integer));
4687627f7eb2Smrg goto cleanup;
4688627f7eb2Smrg }
4689627f7eb2Smrg
4690627f7eb2Smrg if (gfc_pure (NULL))
4691627f7eb2Smrg {
4692627f7eb2Smrg gfc_error ("INQUIRE statement not allowed in PURE procedure at %C");
4693627f7eb2Smrg goto cleanup;
4694627f7eb2Smrg }
4695627f7eb2Smrg
4696627f7eb2Smrg gfc_unset_implicit_pure (NULL);
4697627f7eb2Smrg
4698627f7eb2Smrg if (inquire->id != NULL && inquire->pending == NULL)
4699627f7eb2Smrg {
4700627f7eb2Smrg gfc_error ("INQUIRE statement at %L requires a PENDING= specifier with "
4701627f7eb2Smrg "the ID= specifier", &loc);
4702627f7eb2Smrg goto cleanup;
4703627f7eb2Smrg }
4704627f7eb2Smrg
4705627f7eb2Smrg new_st.op = EXEC_INQUIRE;
4706627f7eb2Smrg new_st.ext.inquire = inquire;
4707627f7eb2Smrg return MATCH_YES;
4708627f7eb2Smrg
4709627f7eb2Smrg syntax:
4710627f7eb2Smrg gfc_syntax_error (ST_INQUIRE);
4711627f7eb2Smrg
4712627f7eb2Smrg cleanup:
4713627f7eb2Smrg gfc_free_inquire (inquire);
4714627f7eb2Smrg return MATCH_ERROR;
4715627f7eb2Smrg }
4716627f7eb2Smrg
4717627f7eb2Smrg
4718627f7eb2Smrg /* Resolve everything in a gfc_inquire structure. */
4719627f7eb2Smrg
4720627f7eb2Smrg bool
gfc_resolve_inquire(gfc_inquire * inquire)4721627f7eb2Smrg gfc_resolve_inquire (gfc_inquire *inquire)
4722627f7eb2Smrg {
4723627f7eb2Smrg RESOLVE_TAG (&tag_unit, inquire->unit);
4724627f7eb2Smrg RESOLVE_TAG (&tag_file, inquire->file);
4725627f7eb2Smrg RESOLVE_TAG (&tag_id, inquire->id);
4726627f7eb2Smrg
4727627f7eb2Smrg /* For INQUIRE, all tags except FILE, ID and UNIT are variable definition
4728627f7eb2Smrg contexts. Thus, use an extended RESOLVE_TAG macro for that. */
4729627f7eb2Smrg #define INQUIRE_RESOLVE_TAG(tag, expr) \
4730627f7eb2Smrg RESOLVE_TAG (tag, expr); \
4731627f7eb2Smrg if (expr) \
4732627f7eb2Smrg { \
4733627f7eb2Smrg char context[64]; \
4734627f7eb2Smrg sprintf (context, _("%s tag with INQUIRE"), (tag)->name); \
4735627f7eb2Smrg if (gfc_check_vardef_context ((expr), false, false, false, \
4736627f7eb2Smrg context) == false) \
4737627f7eb2Smrg return false; \
4738627f7eb2Smrg }
4739627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_iomsg, inquire->iomsg);
4740627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_iostat, inquire->iostat);
4741627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_exist, inquire->exist);
4742627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_opened, inquire->opened);
4743627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_number, inquire->number);
4744627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_named, inquire->named);
4745627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_name, inquire->name);
4746627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_access, inquire->access);
4747627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_sequential, inquire->sequential);
4748627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_direct, inquire->direct);
4749627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_form, inquire->form);
4750627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_formatted, inquire->formatted);
4751627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_unformatted, inquire->unformatted);
4752627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_recl, inquire->recl);
4753627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_nextrec, inquire->nextrec);
4754627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_blank, inquire->blank);
4755627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_position, inquire->position);
4756627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_action, inquire->action);
4757627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_read, inquire->read);
4758627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_write, inquire->write);
4759627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_readwrite, inquire->readwrite);
4760627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_delim, inquire->delim);
4761627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_pad, inquire->pad);
4762627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_encoding, inquire->encoding);
4763627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_round, inquire->round);
4764627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_iolength, inquire->iolength);
4765627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_convert, inquire->convert);
4766627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_strm_out, inquire->strm_pos);
4767627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_async, inquire->asynchronous);
4768627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_sign, inquire->sign);
4769627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_round, inquire->round);
4770627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_pending, inquire->pending);
4771627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_size, inquire->size);
4772627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_decimal, inquire->decimal);
4773627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_s_iqstream, inquire->iqstream);
4774627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_v_share, inquire->share);
4775627f7eb2Smrg INQUIRE_RESOLVE_TAG (&tag_v_cc, inquire->cc);
4776627f7eb2Smrg #undef INQUIRE_RESOLVE_TAG
4777627f7eb2Smrg
4778627f7eb2Smrg if (!gfc_reference_st_label (inquire->err, ST_LABEL_TARGET))
4779627f7eb2Smrg return false;
4780627f7eb2Smrg
4781627f7eb2Smrg return true;
4782627f7eb2Smrg }
4783627f7eb2Smrg
4784627f7eb2Smrg
4785627f7eb2Smrg void
gfc_free_wait(gfc_wait * wait)4786627f7eb2Smrg gfc_free_wait (gfc_wait *wait)
4787627f7eb2Smrg {
4788627f7eb2Smrg if (wait == NULL)
4789627f7eb2Smrg return;
4790627f7eb2Smrg
4791627f7eb2Smrg gfc_free_expr (wait->unit);
4792627f7eb2Smrg gfc_free_expr (wait->iostat);
4793627f7eb2Smrg gfc_free_expr (wait->iomsg);
4794627f7eb2Smrg gfc_free_expr (wait->id);
4795627f7eb2Smrg free (wait);
4796627f7eb2Smrg }
4797627f7eb2Smrg
4798627f7eb2Smrg
4799627f7eb2Smrg bool
gfc_resolve_wait(gfc_wait * wait)4800627f7eb2Smrg gfc_resolve_wait (gfc_wait *wait)
4801627f7eb2Smrg {
4802627f7eb2Smrg RESOLVE_TAG (&tag_unit, wait->unit);
4803627f7eb2Smrg RESOLVE_TAG (&tag_iomsg, wait->iomsg);
4804627f7eb2Smrg RESOLVE_TAG (&tag_iostat, wait->iostat);
4805627f7eb2Smrg RESOLVE_TAG (&tag_id, wait->id);
4806627f7eb2Smrg
4807627f7eb2Smrg if (!gfc_reference_st_label (wait->err, ST_LABEL_TARGET))
4808627f7eb2Smrg return false;
4809627f7eb2Smrg
4810627f7eb2Smrg if (!gfc_reference_st_label (wait->end, ST_LABEL_TARGET))
4811627f7eb2Smrg return false;
4812627f7eb2Smrg
4813627f7eb2Smrg return true;
4814627f7eb2Smrg }
4815627f7eb2Smrg
4816627f7eb2Smrg /* Match an element of a WAIT statement. */
4817627f7eb2Smrg
4818627f7eb2Smrg #define RETM if (m != MATCH_NO) return m;
4819627f7eb2Smrg
4820627f7eb2Smrg static match
match_wait_element(gfc_wait * wait)4821627f7eb2Smrg match_wait_element (gfc_wait *wait)
4822627f7eb2Smrg {
4823627f7eb2Smrg match m;
4824627f7eb2Smrg
4825627f7eb2Smrg m = match_etag (&tag_unit, &wait->unit);
4826627f7eb2Smrg RETM m = match_ltag (&tag_err, &wait->err);
4827627f7eb2Smrg RETM m = match_ltag (&tag_end, &wait->end);
4828627f7eb2Smrg RETM m = match_ltag (&tag_eor, &wait->eor);
4829627f7eb2Smrg RETM m = match_etag (&tag_iomsg, &wait->iomsg);
4830627f7eb2Smrg RETM m = match_out_tag (&tag_iostat, &wait->iostat);
4831627f7eb2Smrg RETM m = match_etag (&tag_id, &wait->id);
4832627f7eb2Smrg RETM return MATCH_NO;
4833627f7eb2Smrg }
4834627f7eb2Smrg
4835627f7eb2Smrg #undef RETM
4836627f7eb2Smrg
4837627f7eb2Smrg
4838627f7eb2Smrg match
gfc_match_wait(void)4839627f7eb2Smrg gfc_match_wait (void)
4840627f7eb2Smrg {
4841627f7eb2Smrg gfc_wait *wait;
4842627f7eb2Smrg match m;
4843627f7eb2Smrg
4844627f7eb2Smrg m = gfc_match_char ('(');
4845627f7eb2Smrg if (m == MATCH_NO)
4846627f7eb2Smrg return m;
4847627f7eb2Smrg
4848627f7eb2Smrg wait = XCNEW (gfc_wait);
4849627f7eb2Smrg
4850627f7eb2Smrg m = match_wait_element (wait);
4851627f7eb2Smrg if (m == MATCH_ERROR)
4852627f7eb2Smrg goto cleanup;
4853627f7eb2Smrg if (m == MATCH_NO)
4854627f7eb2Smrg {
4855627f7eb2Smrg m = gfc_match_expr (&wait->unit);
4856627f7eb2Smrg if (m == MATCH_ERROR)
4857627f7eb2Smrg goto cleanup;
4858627f7eb2Smrg if (m == MATCH_NO)
4859627f7eb2Smrg goto syntax;
4860627f7eb2Smrg }
4861627f7eb2Smrg
4862627f7eb2Smrg for (;;)
4863627f7eb2Smrg {
4864627f7eb2Smrg if (gfc_match_char (')') == MATCH_YES)
4865627f7eb2Smrg break;
4866627f7eb2Smrg if (gfc_match_char (',') != MATCH_YES)
4867627f7eb2Smrg goto syntax;
4868627f7eb2Smrg
4869627f7eb2Smrg m = match_wait_element (wait);
4870627f7eb2Smrg if (m == MATCH_ERROR)
4871627f7eb2Smrg goto cleanup;
4872627f7eb2Smrg if (m == MATCH_NO)
4873627f7eb2Smrg goto syntax;
4874627f7eb2Smrg }
4875627f7eb2Smrg
4876627f7eb2Smrg if (!gfc_notify_std (GFC_STD_F2003, "WAIT at %C "
4877627f7eb2Smrg "not allowed in Fortran 95"))
4878627f7eb2Smrg goto cleanup;
4879627f7eb2Smrg
4880627f7eb2Smrg if (gfc_pure (NULL))
4881627f7eb2Smrg {
4882627f7eb2Smrg gfc_error ("WAIT statement not allowed in PURE procedure at %C");
4883627f7eb2Smrg goto cleanup;
4884627f7eb2Smrg }
4885627f7eb2Smrg
4886627f7eb2Smrg gfc_unset_implicit_pure (NULL);
4887627f7eb2Smrg
4888627f7eb2Smrg new_st.op = EXEC_WAIT;
4889627f7eb2Smrg new_st.ext.wait = wait;
4890627f7eb2Smrg
4891627f7eb2Smrg return MATCH_YES;
4892627f7eb2Smrg
4893627f7eb2Smrg syntax:
4894627f7eb2Smrg gfc_syntax_error (ST_WAIT);
4895627f7eb2Smrg
4896627f7eb2Smrg cleanup:
4897627f7eb2Smrg gfc_free_wait (wait);
4898627f7eb2Smrg return MATCH_ERROR;
4899627f7eb2Smrg }
4900