xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/io.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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