xref: /openbsd/gnu/usr.bin/gcc/gcc/f/ste.c (revision c87b03e5)
1 /* ste.c -- Implementation File (module.c template V1.0)
2    Copyright (C) 1995, 1996, 2000, 2002, 2003 Free Software Foundation, Inc.
3    Contributed by James Craig Burley.
4 
5 This file is part of GNU Fortran.
6 
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 
22    Related Modules:
23       ste.c
24 
25    Description:
26       Implements the various statements and such like.
27 
28    Modifications:
29 */
30 
31 /* Include files. */
32 
33 #include "proj.h"
34 #include "rtl.h"
35 #include "toplev.h"
36 #include "ggc.h"
37 #include "ste.h"
38 #include "bld.h"
39 #include "com.h"
40 #include "expr.h"
41 #include "lab.h"
42 #include "lex.h"
43 #include "sta.h"
44 #include "stp.h"
45 #include "str.h"
46 #include "sts.h"
47 #include "stt.h"
48 #include "stv.h"
49 #include "stw.h"
50 #include "symbol.h"
51 
52 /* Externals defined here. */
53 
54 
55 /* Simple definitions and enumerations. */
56 
57 typedef enum
58   {
59     FFESTE_stateletSIMPLE_,	/* Expecting simple/start. */
60     FFESTE_stateletATTRIB_,	/* Expecting attrib/item/itemstart. */
61     FFESTE_stateletITEM_,	/* Expecting item/itemstart/finish. */
62     FFESTE_stateletITEMVALS_,	/* Expecting itemvalue/itemendvals. */
63     FFESTE_
64   } ffesteStatelet_;
65 
66 /* Internal typedefs. */
67 
68 
69 /* Private include files. */
70 
71 
72 /* Internal structure definitions. */
73 
74 
75 /* Static objects accessed by functions in this module. */
76 
77 static ffesteStatelet_ ffeste_statelet_ = FFESTE_stateletSIMPLE_;
78 static ffelab ffeste_label_formatdef_ = NULL;
79 static tree (*ffeste_io_driver_) (ffebld expr);	/* do?io. */
80 static ffecomGfrt ffeste_io_endgfrt_;	/* end function to call. */
81 static tree ffeste_io_abort_;	/* abort-io label or NULL_TREE. */
82 static bool ffeste_io_abort_is_temp_;	/* abort-io label is a temp. */
83 static tree ffeste_io_end_;	/* END= label or NULL_TREE. */
84 static tree ffeste_io_err_;	/* ERR= label or NULL_TREE. */
85 static tree ffeste_io_iostat_;	/* IOSTAT= var or NULL_TREE. */
86 static bool ffeste_io_iostat_is_temp_;	/* IOSTAT= var is a temp. */
87 
88 /* Static functions (internal). */
89 
90 static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
91 				  tree *xitersvar, ffebld var,
92 				  ffebld start, ffelexToken start_token,
93 				  ffebld end, ffelexToken end_token,
94 				  ffebld incr, ffelexToken incr_token,
95 				  const char *msg);
96 static void ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr,
97 				tree itersvar);
98 static void ffeste_io_call_ (tree call, bool do_check);
99 static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
100 static tree ffeste_io_dofio_ (ffebld expr);
101 static tree ffeste_io_dolio_ (ffebld expr);
102 static tree ffeste_io_douio_ (ffebld expr);
103 static tree ffeste_io_ialist_ (bool have_err, ffestvUnit unit,
104 			       ffebld unit_expr, int unit_dflt);
105 static tree ffeste_io_cilist_ (bool have_err, ffestvUnit unit,
106 			       ffebld unit_expr, int unit_dflt,
107 			       bool have_end, ffestvFormat format,
108 			       ffestpFile *format_spec, bool rec,
109 			       ffebld rec_expr);
110 static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
111 			       ffestpFile *stat_spec);
112 static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
113 				bool have_end, ffestvFormat format,
114 				ffestpFile *format_spec);
115 static tree ffeste_io_inlist_ (bool have_err,
116 			       ffestpFile *unit_spec,
117 			       ffestpFile *file_spec,
118 			       ffestpFile *exist_spec,
119 			       ffestpFile *open_spec,
120 			       ffestpFile *number_spec,
121 			       ffestpFile *named_spec,
122 			       ffestpFile *name_spec,
123 			       ffestpFile *access_spec,
124 			       ffestpFile *sequential_spec,
125 			       ffestpFile *direct_spec,
126 			       ffestpFile *form_spec,
127 			       ffestpFile *formatted_spec,
128 			       ffestpFile *unformatted_spec,
129 			       ffestpFile *recl_spec,
130 			       ffestpFile *nextrec_spec,
131 			       ffestpFile *blank_spec);
132 static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
133 			      ffestpFile *file_spec,
134 			      ffestpFile *stat_spec,
135 			      ffestpFile *access_spec,
136 			      ffestpFile *form_spec,
137 			      ffestpFile *recl_spec,
138 			      ffestpFile *blank_spec);
139 static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
140 
141 /* Internal macros. */
142 
143 #define ffeste_emit_line_note_() \
144   emit_line_note (input_filename, lineno)
145 #define ffeste_check_simple_() \
146   assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_)
147 #define ffeste_check_start_() \
148   assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_); \
149   ffeste_statelet_ = FFESTE_stateletATTRIB_
150 #define ffeste_check_attrib_() \
151   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_)
152 #define ffeste_check_item_() \
153   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_	 \
154 	 || ffeste_statelet_ == FFESTE_stateletITEM_); \
155   ffeste_statelet_ = FFESTE_stateletITEM_
156 #define ffeste_check_item_startvals_() \
157   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_	 \
158 	 || ffeste_statelet_ == FFESTE_stateletITEM_); \
159   ffeste_statelet_ = FFESTE_stateletITEMVALS_
160 #define ffeste_check_item_value_() \
161   assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_)
162 #define ffeste_check_item_endvals_() \
163   assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_); \
164   ffeste_statelet_ = FFESTE_stateletITEM_
165 #define ffeste_check_finish_() \
166   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_	 \
167 	 || ffeste_statelet_ == FFESTE_stateletITEM_); \
168   ffeste_statelet_ = FFESTE_stateletSIMPLE_
169 
170 #define ffeste_f2c_init_charnolen_(Exp,Init,Spec)			      \
171   do									      \
172     {									      \
173       if ((Spec)->kw_or_val_present)					      \
174 	Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &ignore);	      \
175       else								      \
176 	Exp = null_pointer_node;					      \
177       if (Exp)								      \
178 	Init = Exp;							      \
179       else								      \
180 	{								      \
181 	  Init = null_pointer_node;					      \
182 	  constantp = FALSE;						      \
183 	}								      \
184     } while(0)
185 
186 #define ffeste_f2c_init_char_(Exp,Init,Lenexp,Leninit,Spec)		      \
187   do									      \
188     {									      \
189       if ((Spec)->kw_or_val_present)					      \
190 	Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &Lenexp);	      \
191       else								      \
192 	{								      \
193 	  Exp = null_pointer_node;					      \
194 	  Lenexp = ffecom_f2c_ftnlen_zero_node;				      \
195 	}								      \
196       if (Exp)								      \
197 	Init = Exp;							      \
198       else								      \
199 	{								      \
200 	  Init = null_pointer_node;					      \
201 	  constantp = FALSE;						      \
202 	}								      \
203       if (Lenexp)							      \
204 	Leninit = Lenexp;						      \
205       else								      \
206 	{								      \
207 	  Leninit = ffecom_f2c_ftnlen_zero_node;			      \
208 	  constantp = FALSE;						      \
209 	}								      \
210     } while(0)
211 
212 #define ffeste_f2c_init_flag_(Flag,Init)				      \
213   do									      \
214     {									      \
215       Init = convert (ffecom_f2c_flag_type_node,			      \
216 		      (Flag) ? integer_one_node : integer_zero_node);	      \
217     } while(0)
218 
219 #define ffeste_f2c_init_format_(Exp,Init,Spec)				      \
220   do									      \
221     {									      \
222       Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, NULL);	      \
223       if (Exp)								      \
224 	Init = Exp;							      \
225       else								      \
226 	{								      \
227 	  Init = null_pointer_node;					      \
228 	  constantp = FALSE;						      \
229 	}								      \
230     } while(0)
231 
232 #define ffeste_f2c_init_int_(Exp,Init,Spec)				      \
233   do									      \
234     {									      \
235       if ((Spec)->kw_or_val_present)					      \
236 	Exp = ffecom_const_expr ((Spec)->u.expr);			      \
237       else								      \
238 	Exp = ffecom_integer_zero_node;					      \
239       if (Exp)								      \
240 	Init = Exp;							      \
241       else								      \
242 	{								      \
243 	  Init = ffecom_integer_zero_node;				      \
244 	  constantp = FALSE;						      \
245 	}								      \
246     } while(0)
247 
248 #define ffeste_f2c_init_ptrtoint_(Exp,Init,Spec)			      \
249   do									      \
250     {									      \
251       if ((Spec)->kw_or_val_present)					      \
252 	Exp = ffecom_ptr_to_const_expr ((Spec)->u.expr);		      \
253       else								      \
254 	Exp = null_pointer_node;					      \
255       if (Exp)								      \
256 	Init = Exp;							      \
257       else								      \
258 	{								      \
259 	  Init = null_pointer_node;					      \
260 	  constantp = FALSE;						      \
261 	}								      \
262     } while(0)
263 
264 #define ffeste_f2c_init_next_(Init)					      \
265   do									      \
266     {									      \
267       TREE_CHAIN (initn) = build_tree_list ((field = TREE_CHAIN (field)),     \
268 					    (Init));			      \
269       initn = TREE_CHAIN(initn);					      \
270     } while(0)
271 
272 #define ffeste_f2c_prepare_charnolen_(Spec,Exp)				      \
273   do									      \
274     {									      \
275       if (! (Exp))							      \
276         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);		      \
277     } while(0)
278 
279 #define ffeste_f2c_prepare_char_(Spec,Exp)				      \
280   do									      \
281     {									      \
282       if (! (Exp))							      \
283         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);		      \
284     } while(0)
285 
286 #define ffeste_f2c_prepare_format_(Spec,Exp)				      \
287   do									      \
288     {									      \
289       if (! (Exp))							      \
290         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);		      \
291     } while(0)
292 
293 #define ffeste_f2c_prepare_int_(Spec,Exp)				      \
294   do									      \
295     {									      \
296       if (! (Exp))							      \
297         ffecom_prepare_expr ((Spec)->u.expr);				      \
298     } while(0)
299 
300 #define ffeste_f2c_prepare_ptrtoint_(Spec,Exp)				      \
301   do									      \
302     {									      \
303       if (! (Exp))							      \
304         ffecom_prepare_ptr_to_expr ((Spec)->u.expr);			      \
305     } while(0)
306 
307 #define ffeste_f2c_compile_(Field,Exp)					      \
308   do									      \
309     {									      \
310       tree exz;								      \
311       if ((Exp))							      \
312 	{								      \
313 	  exz = ffecom_modify (void_type_node,				      \
314 			       ffecom_2 (COMPONENT_REF, TREE_TYPE (Field),    \
315 					 t, (Field)),			      \
316 			       (Exp));					      \
317 	  expand_expr_stmt (exz);					      \
318 	}								      \
319     } while(0)
320 
321 #define ffeste_f2c_compile_charnolen_(Field,Spec,Exp)			      \
322   do									      \
323     {									      \
324       tree exq;								      \
325       if (! (Exp))							      \
326 	{								      \
327 	  exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &ignore);	      \
328 	  ffeste_f2c_compile_ ((Field), exq);				      \
329 	}								      \
330     } while(0)
331 
332 #define ffeste_f2c_compile_char_(Field,Lenfield,Spec,Exp,Lenexp)	      \
333   do									      \
334     {									      \
335       tree exq = (Exp);							      \
336       tree lenexq = (Lenexp);						      \
337       int need_exq = (! exq);						      \
338       int need_lenexq = (! lenexq); 					      \
339       if (need_exq || need_lenexq)					      \
340 	{								      \
341 	  exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &lenexq);	      \
342 	  if (need_exq)							      \
343 	    ffeste_f2c_compile_ ((Field), exq);				      \
344 	  if (need_lenexq)						      \
345 	    ffeste_f2c_compile_ ((Lenfield), lenexq);			      \
346 	}								      \
347     } while(0)
348 
349 #define ffeste_f2c_compile_format_(Field,Spec,Exp)			      \
350   do									      \
351     {									      \
352       tree exq;								      \
353       if (! (Exp))							      \
354 	{								      \
355 	  exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, NULL);		      \
356 	  ffeste_f2c_compile_ ((Field), exq);				      \
357 	}								      \
358     } while(0)
359 
360 #define ffeste_f2c_compile_int_(Field,Spec,Exp)				      \
361   do									      \
362     {									      \
363       tree exq;								      \
364       if (! (Exp))							      \
365 	{								      \
366 	  exq = ffecom_expr ((Spec)->u.expr);				      \
367 	  ffeste_f2c_compile_ ((Field), exq);				      \
368 	}								      \
369     } while(0)
370 
371 #define ffeste_f2c_compile_ptrtoint_(Field,Spec,Exp)			      \
372   do									      \
373     {									      \
374       tree exq;								      \
375       if (! (Exp))							      \
376 	{								      \
377 	  exq = ffecom_ptr_to_expr ((Spec)->u.expr);			      \
378 	  ffeste_f2c_compile_ ((Field), exq);				      \
379 	}								      \
380     } while(0)
381 
382 /* Start a Fortran block.  */
383 
384 #ifdef ENABLE_CHECKING
385 
386 typedef struct gbe_block
387 {
388   struct gbe_block *outer;
389   ffestw block;
390   int lineno;
391   const char *input_filename;
392   bool is_stmt;
393 } *gbe_block;
394 
395 gbe_block ffeste_top_block_ = NULL;
396 
397 static void
ffeste_start_block_(ffestw block)398 ffeste_start_block_ (ffestw block)
399 {
400   gbe_block b = xmalloc (sizeof (*b));
401 
402   b->outer = ffeste_top_block_;
403   b->block = block;
404   b->lineno = lineno;
405   b->input_filename = input_filename;
406   b->is_stmt = FALSE;
407 
408   ffeste_top_block_ = b;
409 
410   ffecom_start_compstmt ();
411 }
412 
413 /* End a Fortran block.  */
414 
415 static void
ffeste_end_block_(ffestw block)416 ffeste_end_block_ (ffestw block)
417 {
418   gbe_block b = ffeste_top_block_;
419 
420   assert (b);
421   assert (! b->is_stmt);
422   assert (b->block == block);
423   assert (! b->is_stmt);
424 
425   ffeste_top_block_ = b->outer;
426 
427   free (b);
428 
429   ffecom_end_compstmt ();
430 }
431 
432 /* Start a Fortran statement.
433 
434    Starts a back-end block, so temporaries can be managed, clean-ups
435    properly handled, etc.  Nesting of statements *is* allowed -- the
436    handling of I/O items, even implied-DO I/O lists, within a READ,
437    PRINT, or WRITE statement is one example.  */
438 
439 static void
ffeste_start_stmt_(void)440 ffeste_start_stmt_(void)
441 {
442   gbe_block b = xmalloc (sizeof (*b));
443 
444   b->outer = ffeste_top_block_;
445   b->block = NULL;
446   b->lineno = lineno;
447   b->input_filename = input_filename;
448   b->is_stmt = TRUE;
449 
450   ffeste_top_block_ = b;
451 
452   ffecom_start_compstmt ();
453 }
454 
455 /* End a Fortran statement.  */
456 
457 static void
ffeste_end_stmt_(void)458 ffeste_end_stmt_(void)
459 {
460   gbe_block b = ffeste_top_block_;
461 
462   assert (b);
463   assert (b->is_stmt);
464 
465   ffeste_top_block_ = b->outer;
466 
467   free (b);
468 
469   ffecom_end_compstmt ();
470 }
471 
472 #else  /* ! defined (ENABLE_CHECKING) */
473 
474 #define ffeste_start_block_(b) ffecom_start_compstmt ()
475 #define ffeste_end_block_(b)	\
476   do				\
477     {				\
478       ffecom_end_compstmt ();	\
479     } while(0)
480 #define ffeste_start_stmt_() ffeste_start_block_(NULL)
481 #define ffeste_end_stmt_() ffeste_end_block_(NULL)
482 
483 #endif  /* ! defined (ENABLE_CHECKING) */
484 
485 /* Begin an iterative DO loop.  Pass the block to start if
486    applicable.  */
487 
488 static void
ffeste_begin_iterdo_(ffestw block,tree * xtvar,tree * xtincr,tree * xitersvar,ffebld var,ffebld start,ffelexToken start_token,ffebld end,ffelexToken end_token,ffebld incr,ffelexToken incr_token,const char * msg)489 ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
490 		      tree *xitersvar, ffebld var,
491 		      ffebld start, ffelexToken start_token,
492 		      ffebld end, ffelexToken end_token,
493 		      ffebld incr, ffelexToken incr_token,
494 		      const char *msg)
495 {
496   tree tvar;
497   tree expr;
498   tree tstart;
499   tree tend;
500   tree tincr;
501   tree tincr_saved;
502   tree niters;
503   struct nesting *expanded_loop;
504 
505   /* Want to have tvar, tincr, and niters for the whole loop body. */
506 
507   if (block)
508     ffeste_start_block_ (block);
509   else
510     ffeste_start_stmt_ ();
511 
512   niters = ffecom_make_tempvar (block ? "do" : "impdo",
513 				ffecom_integer_type_node,
514 				FFETARGET_charactersizeNONE, -1);
515 
516   ffecom_prepare_expr (incr);
517   ffecom_prepare_expr_rw (NULL_TREE, var);
518 
519   ffecom_prepare_end ();
520 
521   tvar = ffecom_expr_rw (NULL_TREE, var);
522   tincr = ffecom_expr (incr);
523 
524   if (TREE_CODE (tvar) == ERROR_MARK
525       || TREE_CODE (tincr) == ERROR_MARK)
526     {
527       if (block)
528 	{
529 	  ffeste_end_block_ (block);
530 	  ffestw_set_do_tvar (block, error_mark_node);
531 	}
532       else
533 	{
534 	  ffeste_end_stmt_ ();
535 	  *xtvar = error_mark_node;
536 	}
537       return;
538     }
539 
540   /* Check whether incr is known to be zero, complain and fix.  */
541 
542   if (integer_zerop (tincr) || real_zerop (tincr))
543     {
544       ffebad_start (FFEBAD_DO_STEP_ZERO);
545       ffebad_here (0, ffelex_token_where_line (incr_token),
546 		   ffelex_token_where_column (incr_token));
547       ffebad_string (msg);
548       ffebad_finish ();
549       tincr = convert (TREE_TYPE (tvar), integer_one_node);
550     }
551 
552   tincr_saved = ffecom_save_tree (tincr);
553 
554   /* Want to have tstart, tend for just this statement. */
555 
556   ffeste_start_stmt_ ();
557 
558   ffecom_prepare_expr (start);
559   ffecom_prepare_expr (end);
560 
561   ffecom_prepare_end ();
562 
563   tstart = ffecom_expr (start);
564   tend = ffecom_expr (end);
565 
566   if (TREE_CODE (tstart) == ERROR_MARK
567       || TREE_CODE (tend) == ERROR_MARK)
568     {
569       ffeste_end_stmt_ ();
570 
571       if (block)
572 	{
573 	  ffeste_end_block_ (block);
574 	  ffestw_set_do_tvar (block, error_mark_node);
575 	}
576       else
577 	{
578 	  ffeste_end_stmt_ ();
579 	  *xtvar = error_mark_node;
580 	}
581       return;
582     }
583 
584   /* For warnings only, nothing else happens here.  */
585   {
586     tree try;
587 
588     if (! ffe_is_onetrip ())
589       {
590 	try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
591 			tend,
592 			tstart);
593 
594 	try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
595 			try,
596 			tincr);
597 
598 	if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
599 	  try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
600 			  tincr);
601 	else
602 	  try = convert (integer_type_node,
603 			 ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
604 				   try,
605 				   tincr));
606 
607 	/* Warn if loop never executed, since we've done the evaluation
608 	   of the unofficial iteration count already.  */
609 
610 	try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
611 					    try,
612 					    convert (TREE_TYPE (tvar),
613 						     integer_zero_node)));
614 
615 	if (integer_onep (try))
616 	  {
617 	    ffebad_start (FFEBAD_DO_NULL);
618 	    ffebad_here (0, ffelex_token_where_line (start_token),
619 			 ffelex_token_where_column (start_token));
620 	    ffebad_string (msg);
621 	    ffebad_finish ();
622 	  }
623       }
624 
625     /* Warn if end plus incr would overflow.  */
626 
627     try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
628 		    tend,
629 		    tincr);
630 
631     if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
632 	&& TREE_CONSTANT_OVERFLOW (try))
633       {
634 	ffebad_start (FFEBAD_DO_END_OVERFLOW);
635 	ffebad_here (0, ffelex_token_where_line (end_token),
636 		     ffelex_token_where_column (end_token));
637 	ffebad_string (msg);
638 	ffebad_finish ();
639       }
640   }
641 
642   /* Do the initial assignment into the DO var.  */
643 
644   tstart = ffecom_save_tree (tstart);
645 
646   expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
647 		   tend,
648 		   tstart);
649 
650   if (! ffe_is_onetrip ())
651     {
652       expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
653 		       expr,
654 		       convert (TREE_TYPE (expr), tincr_saved));
655     }
656 
657   if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
658     expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
659 		     expr,
660 		     tincr_saved);
661   else
662     expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
663 		     expr,
664 		     tincr_saved);
665 
666 #if 1	/* New, F90-approved approach: convert to default INTEGER. */
667   if (TREE_TYPE (tvar) != error_mark_node)
668     expr = convert (ffecom_integer_type_node, expr);
669 #else	/* Old approach; convert to INTEGER unless that's a narrowing. */
670   if ((TREE_TYPE (tvar) != error_mark_node)
671       && ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
672 	  || ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
673 	      && ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
674 		   != INTEGER_CST)
675 		  || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
676 		      <= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
677     /* Convert unless promoting INTEGER type of any kind downward to
678        default INTEGER; else leave as, say, INTEGER*8 (long long int).  */
679     expr = convert (ffecom_integer_type_node, expr);
680 #endif
681 
682   assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
683 	  == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
684 
685   expr = ffecom_modify (void_type_node, niters, expr);
686   expand_expr_stmt (expr);
687 
688   expr = ffecom_modify (void_type_node, tvar, tstart);
689   expand_expr_stmt (expr);
690 
691   ffeste_end_stmt_ ();
692 
693   expanded_loop = expand_start_loop_continue_elsewhere (!! block);
694   if (block)
695     ffestw_set_do_hook (block, expanded_loop);
696 
697   if (! ffe_is_onetrip ())
698     {
699       expr = ffecom_truth_value
700 	(ffecom_2 (GE_EXPR, integer_type_node,
701 		   ffecom_2 (PREDECREMENT_EXPR,
702 			     TREE_TYPE (niters),
703 			     niters,
704 			     convert (TREE_TYPE (niters),
705 				      ffecom_integer_one_node)),
706 		   convert (TREE_TYPE (niters),
707 			    ffecom_integer_zero_node)));
708 
709       expand_exit_loop_top_cond (0, expr);
710     }
711 
712   if (block)
713     {
714       ffestw_set_do_tvar (block, tvar);
715       ffestw_set_do_incr_saved (block, tincr_saved);
716       ffestw_set_do_count_var (block, niters);
717     }
718   else
719     {
720       *xtvar = tvar;
721       *xtincr = tincr_saved;
722       *xitersvar = niters;
723     }
724 }
725 
726 /* End an iterative DO loop.  Pass the same iteration variable and increment
727    value trees that were generated in the paired _begin_ call.  */
728 
729 static void
ffeste_end_iterdo_(ffestw block,tree tvar,tree tincr,tree itersvar)730 ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
731 {
732   tree expr;
733   tree niters = itersvar;
734 
735   if (tvar == error_mark_node)
736     return;
737 
738   expand_loop_continue_here ();
739 
740   ffeste_start_stmt_ ();
741 
742   if (ffe_is_onetrip ())
743     {
744       expr = ffecom_truth_value
745 	(ffecom_2 (GE_EXPR, integer_type_node,
746 		   ffecom_2 (PREDECREMENT_EXPR,
747 			     TREE_TYPE (niters),
748 			     niters,
749 			     convert (TREE_TYPE (niters),
750 				      ffecom_integer_one_node)),
751 		   convert (TREE_TYPE (niters),
752 			    ffecom_integer_zero_node)));
753 
754       expand_exit_loop_if_false (0, expr);
755     }
756 
757   expr = ffecom_modify (void_type_node, tvar,
758 			ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
759 				  tvar,
760 				  tincr));
761   expand_expr_stmt (expr);
762 
763   /* Lose the stuff we just built. */
764   ffeste_end_stmt_ ();
765 
766   expand_end_loop ();
767 
768   /* Lose the tvar and incr_saved trees. */
769   if (block)
770     ffeste_end_block_ (block);
771   else
772     ffeste_end_stmt_ ();
773 }
774 
775 /* Generate call to run-time I/O routine.  */
776 
777 static void
ffeste_io_call_(tree call,bool do_check)778 ffeste_io_call_ (tree call, bool do_check)
779 {
780   /* Generate the call and optional assignment into iostat var. */
781 
782   TREE_SIDE_EFFECTS (call) = 1;
783   if (ffeste_io_iostat_ != NULL_TREE)
784     call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
785 			  ffeste_io_iostat_, call);
786   expand_expr_stmt (call);
787 
788   if (! do_check
789       || ffeste_io_abort_ == NULL_TREE
790       || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
791     return;
792 
793   /* Generate optional test. */
794 
795   expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
796   expand_goto (ffeste_io_abort_);
797   expand_end_cond ();
798 }
799 
800 /* Handle implied-DO in I/O list.
801 
802    Expands code to start up the DO loop.  Then for each item in the
803    DO loop, handles appropriately (possibly including recursively calling
804    itself).  Then expands code to end the DO loop.  */
805 
806 static void
ffeste_io_impdo_(ffebld impdo,ffelexToken impdo_token)807 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
808 {
809   ffebld var = ffebld_head (ffebld_right (impdo));
810   ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
811   ffebld end = ffebld_head (ffebld_trail (ffebld_trail
812 					  (ffebld_right (impdo))));
813   ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
814 				    (ffebld_trail (ffebld_right (impdo)))));
815   ffebld list;
816   ffebld item;
817   tree tvar;
818   tree tincr;
819   tree titervar;
820 
821   if (incr == NULL)
822     {
823       incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
824       ffebld_set_info (incr, ffeinfo_new
825 		       (FFEINFO_basictypeINTEGER,
826 			FFEINFO_kindtypeINTEGERDEFAULT,
827 			0,
828 			FFEINFO_kindENTITY,
829 			FFEINFO_whereCONSTANT,
830 			FFETARGET_charactersizeNONE));
831     }
832 
833   /* Start the DO loop.  */
834 
835   start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
836 				FFEEXPR_contextLET);
837   end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
838 			      FFEEXPR_contextLET);
839   incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
840 			       FFEEXPR_contextLET);
841 
842   ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
843 			start, impdo_token,
844 			end, impdo_token,
845 			incr, impdo_token,
846 			"Implied DO loop");
847 
848   /* Handle the list of items.  */
849 
850   for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
851     {
852       item = ffebld_head (list);
853       if (item == NULL)
854 	continue;
855 
856       /* Strip parens off items such as in "READ *,(A)".  This is really a bug
857 	 in the user's code, but I've been told lots of code does this.  */
858       while (ffebld_op (item) == FFEBLD_opPAREN)
859 	item = ffebld_left (item);
860 
861       if (ffebld_op (item) == FFEBLD_opANY)
862 	continue;
863 
864       if (ffebld_op (item) == FFEBLD_opIMPDO)
865 	ffeste_io_impdo_ (item, impdo_token);
866       else
867 	{
868 	  ffeste_start_stmt_ ();
869 
870 	  ffecom_prepare_arg_ptr_to_expr (item);
871 
872 	  ffecom_prepare_end ();
873 
874 	  ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
875 
876 	  ffeste_end_stmt_ ();
877 	}
878     }
879 
880   /* Generate end of implied-do construct. */
881 
882   ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
883 }
884 
885 /* I/O driver for formatted I/O item (do_fio)
886 
887    Returns a tree for a CALL_EXPR to the do_fio function, which handles
888    a formatted I/O list item, along with the appropriate arguments for
889    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
890    for the CALL_EXPR, expand (emit) the expression, emit any assignment
891    of the result to an IOSTAT= variable, and emit any checking of the
892    result for errors.  */
893 
894 static tree
ffeste_io_dofio_(ffebld expr)895 ffeste_io_dofio_ (ffebld expr)
896 {
897   tree num_elements;
898   tree variable;
899   tree size;
900   tree arglist;
901   ffeinfoBasictype bt;
902   ffeinfoKindtype kt;
903   bool is_complex;
904 
905   bt = ffeinfo_basictype (ffebld_info (expr));
906   kt = ffeinfo_kindtype (ffebld_info (expr));
907 
908   if ((bt == FFEINFO_basictypeANY)
909       || (kt == FFEINFO_kindtypeANY))
910     return error_mark_node;
911 
912   if (bt == FFEINFO_basictypeCOMPLEX)
913     {
914       is_complex = TRUE;
915       bt = FFEINFO_basictypeREAL;
916     }
917   else
918     is_complex = FALSE;
919 
920   variable = ffecom_arg_ptr_to_expr (expr, &size);
921 
922   if ((variable == error_mark_node)
923       || (size == error_mark_node))
924     return error_mark_node;
925 
926   if (size == NULL_TREE)	/* Already filled in for CHARACTER type. */
927     {				/* "(ftnlen) sizeof(type)" */
928       size = size_binop (CEIL_DIV_EXPR,
929 			 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
930 			 size_int (TYPE_PRECISION (char_type_node)
931 				   / BITS_PER_UNIT));
932 #if 0	/* Assume that while it is possible that char * is wider than
933 	   ftnlen, no object in Fortran space can get big enough for its
934 	   size to be wider than ftnlen.  I really hope nobody wastes
935 	   time debugging a case where it can!  */
936       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
937 	      >= TYPE_PRECISION (TREE_TYPE (size)));
938 #endif
939       size = convert (ffecom_f2c_ftnlen_type_node, size);
940     }
941 
942   if (ffeinfo_rank (ffebld_info (expr)) == 0
943       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
944     num_elements
945       = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
946   else
947     {
948       num_elements
949 	= size_binop (CEIL_DIV_EXPR,
950 		      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
951 		      convert (sizetype, size));
952       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
953 				 size_int (TYPE_PRECISION (char_type_node)
954 					   / BITS_PER_UNIT));
955       num_elements = convert (ffecom_f2c_ftnlen_type_node,
956 			      num_elements);
957     }
958 
959   num_elements
960     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
961 		num_elements);
962 
963   variable = convert (string_type_node, variable);
964 
965   arglist = build_tree_list (NULL_TREE, num_elements);
966   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
967   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
968 
969   return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
970 }
971 
972 /* I/O driver for list-directed I/O item (do_lio)
973 
974    Returns a tree for a CALL_EXPR to the do_lio function, which handles
975    a list-directed I/O list item, along with the appropriate arguments for
976    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
977    for the CALL_EXPR, expand (emit) the expression, emit any assignment
978    of the result to an IOSTAT= variable, and emit any checking of the
979    result for errors.  */
980 
981 static tree
ffeste_io_dolio_(ffebld expr)982 ffeste_io_dolio_ (ffebld expr)
983 {
984   tree type_id;
985   tree num_elements;
986   tree variable;
987   tree size;
988   tree arglist;
989   ffeinfoBasictype bt;
990   ffeinfoKindtype kt;
991   int tc;
992 
993   bt = ffeinfo_basictype (ffebld_info (expr));
994   kt = ffeinfo_kindtype (ffebld_info (expr));
995 
996   if ((bt == FFEINFO_basictypeANY)
997       || (kt == FFEINFO_kindtypeANY))
998     return error_mark_node;
999 
1000   tc = ffecom_f2c_typecode (bt, kt);
1001   assert (tc != -1);
1002   type_id = build_int_2 (tc, 0);
1003 
1004   type_id
1005     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
1006 		convert (ffecom_f2c_ftnint_type_node,
1007 			 type_id));
1008 
1009   variable = ffecom_arg_ptr_to_expr (expr, &size);
1010 
1011   if ((type_id == error_mark_node)
1012       || (variable == error_mark_node)
1013       || (size == error_mark_node))
1014     return error_mark_node;
1015 
1016   if (size == NULL_TREE)	/* Already filled in for CHARACTER type. */
1017     {				/* "(ftnlen) sizeof(type)" */
1018       size = size_binop (CEIL_DIV_EXPR,
1019 			 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1020 			 size_int (TYPE_PRECISION (char_type_node)
1021 				   / BITS_PER_UNIT));
1022 #if 0	/* Assume that while it is possible that char * is wider than
1023 	   ftnlen, no object in Fortran space can get big enough for its
1024 	   size to be wider than ftnlen.  I really hope nobody wastes
1025 	   time debugging a case where it can!  */
1026       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1027 	      >= TYPE_PRECISION (TREE_TYPE (size)));
1028 #endif
1029       size = convert (ffecom_f2c_ftnlen_type_node, size);
1030     }
1031 
1032   if (ffeinfo_rank (ffebld_info (expr)) == 0
1033       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1034     num_elements = ffecom_integer_one_node;
1035   else
1036     {
1037       num_elements
1038 	= size_binop (CEIL_DIV_EXPR,
1039 		      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1040 		      convert (sizetype, size));
1041       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1042 				 size_int (TYPE_PRECISION (char_type_node)
1043 					   / BITS_PER_UNIT));
1044       num_elements = convert (ffecom_f2c_ftnlen_type_node,
1045 			      num_elements);
1046     }
1047 
1048   num_elements
1049     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1050 		num_elements);
1051 
1052   variable = convert (string_type_node, variable);
1053 
1054   arglist = build_tree_list (NULL_TREE, type_id);
1055   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
1056   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
1057   TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
1058     = build_tree_list (NULL_TREE, size);
1059 
1060   return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
1061 }
1062 
1063 /* I/O driver for unformatted I/O item (do_uio)
1064 
1065    Returns a tree for a CALL_EXPR to the do_uio function, which handles
1066    an unformatted I/O list item, along with the appropriate arguments for
1067    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
1068    for the CALL_EXPR, expand (emit) the expression, emit any assignment
1069    of the result to an IOSTAT= variable, and emit any checking of the
1070    result for errors.  */
1071 
1072 static tree
ffeste_io_douio_(ffebld expr)1073 ffeste_io_douio_ (ffebld expr)
1074 {
1075   tree num_elements;
1076   tree variable;
1077   tree size;
1078   tree arglist;
1079   ffeinfoBasictype bt;
1080   ffeinfoKindtype kt;
1081   bool is_complex;
1082 
1083   bt = ffeinfo_basictype (ffebld_info (expr));
1084   kt = ffeinfo_kindtype (ffebld_info (expr));
1085 
1086   if ((bt == FFEINFO_basictypeANY)
1087       || (kt == FFEINFO_kindtypeANY))
1088     return error_mark_node;
1089 
1090   if (bt == FFEINFO_basictypeCOMPLEX)
1091     {
1092       is_complex = TRUE;
1093       bt = FFEINFO_basictypeREAL;
1094     }
1095   else
1096     is_complex = FALSE;
1097 
1098   variable = ffecom_arg_ptr_to_expr (expr, &size);
1099 
1100   if ((variable == error_mark_node)
1101       || (size == error_mark_node))
1102     return error_mark_node;
1103 
1104   if (size == NULL_TREE)	/* Already filled in for CHARACTER type. */
1105     {				/* "(ftnlen) sizeof(type)" */
1106       size = size_binop (CEIL_DIV_EXPR,
1107 			 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1108 			 size_int (TYPE_PRECISION (char_type_node)
1109 				   / BITS_PER_UNIT));
1110 #if 0	/* Assume that while it is possible that char * is wider than
1111 	   ftnlen, no object in Fortran space can get big enough for its
1112 	   size to be wider than ftnlen.  I really hope nobody wastes
1113 	   time debugging a case where it can!  */
1114       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1115 	      >= TYPE_PRECISION (TREE_TYPE (size)));
1116 #endif
1117       size = convert (ffecom_f2c_ftnlen_type_node, size);
1118     }
1119 
1120   if (ffeinfo_rank (ffebld_info (expr)) == 0
1121       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1122     num_elements
1123       = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
1124   else
1125     {
1126       num_elements
1127 	= size_binop (CEIL_DIV_EXPR,
1128 		      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1129 		      convert (sizetype, size));
1130       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1131 				 size_int (TYPE_PRECISION (char_type_node)
1132 					   / BITS_PER_UNIT));
1133       num_elements = convert (ffecom_f2c_ftnlen_type_node,
1134 			      num_elements);
1135     }
1136 
1137   num_elements
1138     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1139 		num_elements);
1140 
1141   variable = convert (string_type_node, variable);
1142 
1143   arglist = build_tree_list (NULL_TREE, num_elements);
1144   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
1145   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
1146 
1147   return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
1148 }
1149 
1150 /* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
1151 
1152    Returns a tree suitable as an argument list containing a pointer to
1153    a BACKSPACE/ENDFILE/REWIND control list.  First, generates that control
1154    list, if necessary, along with any static and run-time initializations
1155    that are needed as specified by the arguments to this function.
1156 
1157    Must ensure that all expressions are prepared before being evaluated,
1158    for any whose evaluation might result in the generation of temporaries.
1159 
1160    Note that this means this function causes a transition, within the
1161    current block being code-generated via the back end, from the
1162    declaration of variables (temporaries) to the expanding of expressions,
1163    statements, etc.  */
1164 
1165 static GTY(()) tree f2c_alist_struct;
1166 static tree
ffeste_io_ialist_(bool have_err,ffestvUnit unit,ffebld unit_expr,int unit_dflt)1167 ffeste_io_ialist_ (bool have_err,
1168 		   ffestvUnit unit,
1169 		   ffebld unit_expr,
1170 		   int unit_dflt)
1171 {
1172   tree t;
1173   tree ttype;
1174   tree field;
1175   tree inits, initn;
1176   bool constantp = TRUE;
1177   static tree errfield, unitfield;
1178   tree errinit, unitinit;
1179   tree unitexp;
1180   static int mynumber = 0;
1181 
1182   if (f2c_alist_struct == NULL_TREE)
1183     {
1184       tree ref;
1185 
1186       ref = make_node (RECORD_TYPE);
1187 
1188       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1189 				    ffecom_f2c_flag_type_node);
1190       unitfield = ffecom_decl_field (ref, errfield, "unit",
1191 				     ffecom_f2c_ftnint_type_node);
1192 
1193       TYPE_FIELDS (ref) = errfield;
1194       layout_type (ref);
1195 
1196       f2c_alist_struct = ref;
1197     }
1198 
1199   /* Try to do as much compile-time initialization of the structure
1200      as possible, to save run time.  */
1201 
1202   ffeste_f2c_init_flag_ (have_err, errinit);
1203 
1204   switch (unit)
1205     {
1206     case FFESTV_unitNONE:
1207     case FFESTV_unitASTERISK:
1208       unitinit = build_int_2 (unit_dflt, 0);
1209       unitexp = unitinit;
1210       break;
1211 
1212     case FFESTV_unitINTEXPR:
1213       unitexp = ffecom_const_expr (unit_expr);
1214       if (unitexp)
1215 	unitinit = unitexp;
1216       else
1217 	{
1218 	  unitinit = ffecom_integer_zero_node;
1219 	  constantp = FALSE;
1220 	}
1221       break;
1222 
1223     default:
1224       assert ("bad unit spec" == NULL);
1225       unitinit = ffecom_integer_zero_node;
1226       unitexp = unitinit;
1227       break;
1228     }
1229 
1230   inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
1231   initn = inits;
1232   ffeste_f2c_init_next_ (unitinit);
1233 
1234   inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
1235   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1236   TREE_STATIC (inits) = 1;
1237 
1238   t = build_decl (VAR_DECL,
1239 		  ffecom_get_invented_identifier ("__g77_alist_%d",
1240 						  mynumber++),
1241 		  f2c_alist_struct);
1242   TREE_STATIC (t) = 1;
1243   t = ffecom_start_decl (t, 1);
1244   ffecom_finish_decl (t, inits, 0);
1245 
1246   /* Prepare run-time expressions.  */
1247 
1248   if (! unitexp)
1249     ffecom_prepare_expr (unit_expr);
1250 
1251   ffecom_prepare_end ();
1252 
1253   /* Now evaluate run-time expressions as needed.  */
1254 
1255   if (! unitexp)
1256     {
1257       unitexp = ffecom_expr (unit_expr);
1258       ffeste_f2c_compile_ (unitfield, unitexp);
1259     }
1260 
1261   ttype = build_pointer_type (TREE_TYPE (t));
1262   t = ffecom_1 (ADDR_EXPR, ttype, t);
1263 
1264   t = build_tree_list (NULL_TREE, t);
1265 
1266   return t;
1267 }
1268 
1269 /* Make arglist with ptr to external-I/O control list.
1270 
1271    Returns a tree suitable as an argument list containing a pointer to
1272    an external-I/O control list.  First, generates that control
1273    list, if necessary, along with any static and run-time initializations
1274    that are needed as specified by the arguments to this function.
1275 
1276    Must ensure that all expressions are prepared before being evaluated,
1277    for any whose evaluation might result in the generation of temporaries.
1278 
1279    Note that this means this function causes a transition, within the
1280    current block being code-generated via the back end, from the
1281    declaration of variables (temporaries) to the expanding of expressions,
1282    statements, etc.  */
1283 
1284 static GTY(()) tree f2c_cilist_struct;
1285 static tree
ffeste_io_cilist_(bool have_err,ffestvUnit unit,ffebld unit_expr,int unit_dflt,bool have_end,ffestvFormat format,ffestpFile * format_spec,bool rec,ffebld rec_expr)1286 ffeste_io_cilist_ (bool have_err,
1287 		   ffestvUnit unit,
1288 		   ffebld unit_expr,
1289 		   int unit_dflt,
1290 		   bool have_end,
1291 		   ffestvFormat format,
1292 		   ffestpFile *format_spec,
1293 		   bool rec,
1294 		   ffebld rec_expr)
1295 {
1296   tree t;
1297   tree ttype;
1298   tree field;
1299   tree inits, initn;
1300   bool constantp = TRUE;
1301   static tree errfield, unitfield, endfield, formatfield, recfield;
1302   tree errinit, unitinit, endinit, formatinit, recinit;
1303   tree unitexp, formatexp, recexp;
1304   static int mynumber = 0;
1305 
1306   if (f2c_cilist_struct == NULL_TREE)
1307     {
1308       tree ref;
1309 
1310       ref = make_node (RECORD_TYPE);
1311 
1312       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1313 				    ffecom_f2c_flag_type_node);
1314       unitfield = ffecom_decl_field (ref, errfield, "unit",
1315 				     ffecom_f2c_ftnint_type_node);
1316       endfield = ffecom_decl_field (ref, unitfield, "end",
1317 				    ffecom_f2c_flag_type_node);
1318       formatfield = ffecom_decl_field (ref, endfield, "format",
1319 				       string_type_node);
1320       recfield = ffecom_decl_field (ref, formatfield, "rec",
1321 				    ffecom_f2c_ftnint_type_node);
1322 
1323       TYPE_FIELDS (ref) = errfield;
1324       layout_type (ref);
1325 
1326       f2c_cilist_struct = ref;
1327     }
1328 
1329   /* Try to do as much compile-time initialization of the structure
1330      as possible, to save run time.  */
1331 
1332   ffeste_f2c_init_flag_ (have_err, errinit);
1333 
1334   switch (unit)
1335     {
1336     case FFESTV_unitNONE:
1337     case FFESTV_unitASTERISK:
1338       unitinit = build_int_2 (unit_dflt, 0);
1339       unitexp = unitinit;
1340       break;
1341 
1342     case FFESTV_unitINTEXPR:
1343       unitexp = ffecom_const_expr (unit_expr);
1344       if (unitexp)
1345 	unitinit = unitexp;
1346       else
1347 	{
1348 	  unitinit = ffecom_integer_zero_node;
1349 	  constantp = FALSE;
1350 	}
1351       break;
1352 
1353     default:
1354       assert ("bad unit spec" == NULL);
1355       unitinit = ffecom_integer_zero_node;
1356       unitexp = unitinit;
1357       break;
1358     }
1359 
1360   switch (format)
1361     {
1362     case FFESTV_formatNONE:
1363       formatinit = null_pointer_node;
1364       formatexp = formatinit;
1365       break;
1366 
1367     case FFESTV_formatLABEL:
1368       formatexp = error_mark_node;
1369       formatinit = ffecom_lookup_label (format_spec->u.label);
1370       if ((formatinit == NULL_TREE)
1371 	  || (TREE_CODE (formatinit) == ERROR_MARK))
1372 	break;
1373       formatinit = ffecom_1 (ADDR_EXPR,
1374 			     build_pointer_type (void_type_node),
1375 			     formatinit);
1376       TREE_CONSTANT (formatinit) = 1;
1377       break;
1378 
1379     case FFESTV_formatCHAREXPR:
1380       formatexp = ffecom_arg_ptr_to_const_expr (format_spec->u.expr, NULL);
1381       if (formatexp)
1382 	formatinit = formatexp;
1383       else
1384 	{
1385 	  formatinit = null_pointer_node;
1386 	  constantp = FALSE;
1387 	}
1388       break;
1389 
1390     case FFESTV_formatASTERISK:
1391       formatinit = null_pointer_node;
1392       formatexp = formatinit;
1393       break;
1394 
1395     case FFESTV_formatINTEXPR:
1396       formatinit = null_pointer_node;
1397       formatexp = ffecom_expr_assign (format_spec->u.expr);
1398       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1399 	  < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1400 	error ("ASSIGNed FORMAT specifier is too small");
1401       formatexp = convert (string_type_node, formatexp);
1402       break;
1403 
1404     case FFESTV_formatNAMELIST:
1405       formatinit = ffecom_expr (format_spec->u.expr);
1406       formatexp = formatinit;
1407       break;
1408 
1409     default:
1410       assert ("bad format spec" == NULL);
1411       formatinit = integer_zero_node;
1412       formatexp = formatinit;
1413       break;
1414     }
1415 
1416   ffeste_f2c_init_flag_ (have_end, endinit);
1417 
1418   if (rec)
1419     recexp = ffecom_const_expr (rec_expr);
1420   else
1421     recexp = ffecom_integer_zero_node;
1422   if (recexp)
1423     recinit = recexp;
1424   else
1425     {
1426       recinit = ffecom_integer_zero_node;
1427       constantp = FALSE;
1428     }
1429 
1430   inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
1431   initn = inits;
1432   ffeste_f2c_init_next_ (unitinit);
1433   ffeste_f2c_init_next_ (endinit);
1434   ffeste_f2c_init_next_ (formatinit);
1435   ffeste_f2c_init_next_ (recinit);
1436 
1437   inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1438   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1439   TREE_STATIC (inits) = 1;
1440 
1441   t = build_decl (VAR_DECL,
1442 		  ffecom_get_invented_identifier ("__g77_cilist_%d",
1443 						  mynumber++),
1444 		  f2c_cilist_struct);
1445   TREE_STATIC (t) = 1;
1446   t = ffecom_start_decl (t, 1);
1447   ffecom_finish_decl (t, inits, 0);
1448 
1449   /* Prepare run-time expressions.  */
1450 
1451   if (! unitexp)
1452     ffecom_prepare_expr (unit_expr);
1453 
1454   if (! formatexp)
1455     ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
1456 
1457   if (! recexp)
1458     ffecom_prepare_expr (rec_expr);
1459 
1460   ffecom_prepare_end ();
1461 
1462   /* Now evaluate run-time expressions as needed.  */
1463 
1464   if (! unitexp)
1465     {
1466       unitexp = ffecom_expr (unit_expr);
1467       ffeste_f2c_compile_ (unitfield, unitexp);
1468     }
1469 
1470   if (! formatexp)
1471     {
1472       formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1473       ffeste_f2c_compile_ (formatfield, formatexp);
1474     }
1475   else if (format == FFESTV_formatINTEXPR)
1476     ffeste_f2c_compile_ (formatfield, formatexp);
1477 
1478   if (! recexp)
1479     {
1480       recexp = ffecom_expr (rec_expr);
1481       ffeste_f2c_compile_ (recfield, recexp);
1482     }
1483 
1484   ttype = build_pointer_type (TREE_TYPE (t));
1485   t = ffecom_1 (ADDR_EXPR, ttype, t);
1486 
1487   t = build_tree_list (NULL_TREE, t);
1488 
1489   return t;
1490 }
1491 
1492 /* Make arglist with ptr to CLOSE control list.
1493 
1494    Returns a tree suitable as an argument list containing a pointer to
1495    a CLOSE-statement control list.  First, generates that control
1496    list, if necessary, along with any static and run-time initializations
1497    that are needed as specified by the arguments to this function.
1498 
1499    Must ensure that all expressions are prepared before being evaluated,
1500    for any whose evaluation might result in the generation of temporaries.
1501 
1502    Note that this means this function causes a transition, within the
1503    current block being code-generated via the back end, from the
1504    declaration of variables (temporaries) to the expanding of expressions,
1505    statements, etc.  */
1506 
1507 static GTY(()) tree f2c_close_struct;
1508 static tree
ffeste_io_cllist_(bool have_err,ffebld unit_expr,ffestpFile * stat_spec)1509 ffeste_io_cllist_ (bool have_err,
1510 		   ffebld unit_expr,
1511 		   ffestpFile *stat_spec)
1512 {
1513   tree t;
1514   tree ttype;
1515   tree field;
1516   tree inits, initn;
1517   tree ignore;			/* Ignore length info for certain fields. */
1518   bool constantp = TRUE;
1519   static tree errfield, unitfield, statfield;
1520   tree errinit, unitinit, statinit;
1521   tree unitexp, statexp;
1522   static int mynumber = 0;
1523 
1524   if (f2c_close_struct == NULL_TREE)
1525     {
1526       tree ref;
1527 
1528       ref = make_node (RECORD_TYPE);
1529 
1530       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1531 				    ffecom_f2c_flag_type_node);
1532       unitfield = ffecom_decl_field (ref, errfield, "unit",
1533 				     ffecom_f2c_ftnint_type_node);
1534       statfield = ffecom_decl_field (ref, unitfield, "stat",
1535 				     string_type_node);
1536 
1537       TYPE_FIELDS (ref) = errfield;
1538       layout_type (ref);
1539 
1540       f2c_close_struct = ref;
1541     }
1542 
1543   /* Try to do as much compile-time initialization of the structure
1544      as possible, to save run time.  */
1545 
1546   ffeste_f2c_init_flag_ (have_err, errinit);
1547 
1548   unitexp = ffecom_const_expr (unit_expr);
1549   if (unitexp)
1550     unitinit = unitexp;
1551   else
1552     {
1553       unitinit = ffecom_integer_zero_node;
1554       constantp = FALSE;
1555     }
1556 
1557   ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
1558 
1559   inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
1560   initn = inits;
1561   ffeste_f2c_init_next_ (unitinit);
1562   ffeste_f2c_init_next_ (statinit);
1563 
1564   inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1565   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1566   TREE_STATIC (inits) = 1;
1567 
1568   t = build_decl (VAR_DECL,
1569 		  ffecom_get_invented_identifier ("__g77_cllist_%d",
1570 						  mynumber++),
1571 		  f2c_close_struct);
1572   TREE_STATIC (t) = 1;
1573   t = ffecom_start_decl (t, 1);
1574   ffecom_finish_decl (t, inits, 0);
1575 
1576   /* Prepare run-time expressions.  */
1577 
1578   if (! unitexp)
1579     ffecom_prepare_expr (unit_expr);
1580 
1581   if (! statexp)
1582     ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
1583 
1584   ffecom_prepare_end ();
1585 
1586   /* Now evaluate run-time expressions as needed.  */
1587 
1588   if (! unitexp)
1589     {
1590       unitexp = ffecom_expr (unit_expr);
1591       ffeste_f2c_compile_ (unitfield, unitexp);
1592     }
1593 
1594   ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
1595 
1596   ttype = build_pointer_type (TREE_TYPE (t));
1597   t = ffecom_1 (ADDR_EXPR, ttype, t);
1598 
1599   t = build_tree_list (NULL_TREE, t);
1600 
1601   return t;
1602 }
1603 
1604 /* Make arglist with ptr to internal-I/O control list.
1605 
1606    Returns a tree suitable as an argument list containing a pointer to
1607    an internal-I/O control list.  First, generates that control
1608    list, if necessary, along with any static and run-time initializations
1609    that are needed as specified by the arguments to this function.
1610 
1611    Must ensure that all expressions are prepared before being evaluated,
1612    for any whose evaluation might result in the generation of temporaries.
1613 
1614    Note that this means this function causes a transition, within the
1615    current block being code-generated via the back end, from the
1616    declaration of variables (temporaries) to the expanding of expressions,
1617    statements, etc.  */
1618 
1619 static GTY(()) tree f2c_icilist_struct;
1620 static tree
ffeste_io_icilist_(bool have_err,ffebld unit_expr,bool have_end,ffestvFormat format,ffestpFile * format_spec)1621 ffeste_io_icilist_ (bool have_err,
1622 		    ffebld unit_expr,
1623 		    bool have_end,
1624 		    ffestvFormat format,
1625 		    ffestpFile *format_spec)
1626 {
1627   tree t;
1628   tree ttype;
1629   tree field;
1630   tree inits, initn;
1631   bool constantp = TRUE;
1632   static tree errfield, unitfield, endfield, formatfield, unitlenfield,
1633     unitnumfield;
1634   tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
1635   tree unitexp, formatexp, unitlenexp, unitnumexp;
1636   static int mynumber = 0;
1637 
1638   if (f2c_icilist_struct == NULL_TREE)
1639     {
1640       tree ref;
1641 
1642       ref = make_node (RECORD_TYPE);
1643 
1644       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1645 				    ffecom_f2c_flag_type_node);
1646       unitfield = ffecom_decl_field (ref, errfield, "unit",
1647 				     string_type_node);
1648       endfield = ffecom_decl_field (ref, unitfield, "end",
1649 				    ffecom_f2c_flag_type_node);
1650       formatfield = ffecom_decl_field (ref, endfield, "format",
1651 				       string_type_node);
1652       unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
1653 					ffecom_f2c_ftnint_type_node);
1654       unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
1655 					ffecom_f2c_ftnint_type_node);
1656 
1657       TYPE_FIELDS (ref) = errfield;
1658       layout_type (ref);
1659 
1660       f2c_icilist_struct = ref;
1661     }
1662 
1663   /* Try to do as much compile-time initialization of the structure
1664      as possible, to save run time.  */
1665 
1666   ffeste_f2c_init_flag_ (have_err, errinit);
1667 
1668   unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
1669   if (unitexp)
1670     unitinit = unitexp;
1671   else
1672     {
1673       unitinit = null_pointer_node;
1674       constantp = FALSE;
1675     }
1676   if (unitlenexp)
1677     unitleninit = unitlenexp;
1678   else
1679     {
1680       unitleninit = ffecom_integer_zero_node;
1681       constantp = FALSE;
1682     }
1683 
1684   /* Now see if we can fully initialize the number of elements, or
1685      if we have to compute that at run time.  */
1686   if (ffeinfo_rank (ffebld_info (unit_expr)) == 0
1687       || (unitexp
1688 	  && TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
1689     {
1690       /* Not an array, so just one element.  */
1691       unitnuminit = ffecom_integer_one_node;
1692       unitnumexp = unitnuminit;
1693     }
1694   else if (unitexp && unitlenexp)
1695     {
1696       /* An array, but all the info is constant, so compute now.  */
1697       unitnuminit
1698 	= size_binop (CEIL_DIV_EXPR,
1699 		      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1700 		      convert (sizetype, unitlenexp));
1701       unitnuminit = size_binop (CEIL_DIV_EXPR, unitnuminit,
1702 				size_int (TYPE_PRECISION (char_type_node)
1703 					  / BITS_PER_UNIT));
1704       unitnumexp = unitnuminit;
1705     }
1706   else
1707     {
1708       /* Put off computing until run time.  */
1709       unitnuminit = ffecom_integer_zero_node;
1710       unitnumexp = NULL_TREE;
1711       constantp = FALSE;
1712     }
1713 
1714   switch (format)
1715     {
1716     case FFESTV_formatNONE:
1717       formatinit = null_pointer_node;
1718       formatexp = formatinit;
1719       break;
1720 
1721     case FFESTV_formatLABEL:
1722       formatexp = error_mark_node;
1723       formatinit = ffecom_lookup_label (format_spec->u.label);
1724       if ((formatinit == NULL_TREE)
1725 	  || (TREE_CODE (formatinit) == ERROR_MARK))
1726 	break;
1727       formatinit = ffecom_1 (ADDR_EXPR,
1728 			     build_pointer_type (void_type_node),
1729 			     formatinit);
1730       TREE_CONSTANT (formatinit) = 1;
1731       break;
1732 
1733     case FFESTV_formatCHAREXPR:
1734       ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
1735       break;
1736 
1737     case FFESTV_formatASTERISK:
1738       formatinit = null_pointer_node;
1739       formatexp = formatinit;
1740       break;
1741 
1742     case FFESTV_formatINTEXPR:
1743       formatinit = null_pointer_node;
1744       formatexp = ffecom_expr_assign (format_spec->u.expr);
1745       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1746 	  < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1747 	error ("ASSIGNed FORMAT specifier is too small");
1748       formatexp = convert (string_type_node, formatexp);
1749       break;
1750 
1751     default:
1752       assert ("bad format spec" == NULL);
1753       formatinit = ffecom_integer_zero_node;
1754       formatexp = formatinit;
1755       break;
1756     }
1757 
1758   ffeste_f2c_init_flag_ (have_end, endinit);
1759 
1760   inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
1761 			   errinit);
1762   initn = inits;
1763   ffeste_f2c_init_next_ (unitinit);
1764   ffeste_f2c_init_next_ (endinit);
1765   ffeste_f2c_init_next_ (formatinit);
1766   ffeste_f2c_init_next_ (unitleninit);
1767   ffeste_f2c_init_next_ (unitnuminit);
1768 
1769   inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1770   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1771   TREE_STATIC (inits) = 1;
1772 
1773   t = build_decl (VAR_DECL,
1774 		  ffecom_get_invented_identifier ("__g77_icilist_%d",
1775 						  mynumber++),
1776 		  f2c_icilist_struct);
1777   TREE_STATIC (t) = 1;
1778   t = ffecom_start_decl (t, 1);
1779   ffecom_finish_decl (t, inits, 0);
1780 
1781   /* Prepare run-time expressions.  */
1782 
1783   if (! unitexp)
1784     ffecom_prepare_arg_ptr_to_expr (unit_expr);
1785 
1786   ffeste_f2c_prepare_format_ (format_spec, formatexp);
1787 
1788   ffecom_prepare_end ();
1789 
1790   /* Now evaluate run-time expressions as needed.  */
1791 
1792   if (! unitexp || ! unitlenexp)
1793     {
1794       int need_unitexp = (! unitexp);
1795       int need_unitlenexp = (! unitlenexp);
1796 
1797       unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
1798       if (need_unitexp)
1799 	ffeste_f2c_compile_ (unitfield, unitexp);
1800       if (need_unitlenexp)
1801 	ffeste_f2c_compile_ (unitlenfield, unitlenexp);
1802     }
1803 
1804   if (! unitnumexp
1805       && unitexp != error_mark_node
1806       && unitlenexp != error_mark_node)
1807     {
1808       unitnumexp
1809 	= size_binop (CEIL_DIV_EXPR,
1810 		      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1811 		      convert (sizetype, unitlenexp));
1812       unitnumexp = size_binop (CEIL_DIV_EXPR, unitnumexp,
1813 			       size_int (TYPE_PRECISION (char_type_node)
1814 					 / BITS_PER_UNIT));
1815       ffeste_f2c_compile_ (unitnumfield, unitnumexp);
1816     }
1817 
1818   if (format == FFESTV_formatINTEXPR)
1819     ffeste_f2c_compile_ (formatfield, formatexp);
1820   else
1821     ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
1822 
1823   ttype = build_pointer_type (TREE_TYPE (t));
1824   t = ffecom_1 (ADDR_EXPR, ttype, t);
1825 
1826   t = build_tree_list (NULL_TREE, t);
1827 
1828   return t;
1829 }
1830 
1831 /* Make arglist with ptr to INQUIRE control list
1832 
1833    Returns a tree suitable as an argument list containing a pointer to
1834    an INQUIRE-statement control list.  First, generates that control
1835    list, if necessary, along with any static and run-time initializations
1836    that are needed as specified by the arguments to this function.
1837 
1838    Must ensure that all expressions are prepared before being evaluated,
1839    for any whose evaluation might result in the generation of temporaries.
1840 
1841    Note that this means this function causes a transition, within the
1842    current block being code-generated via the back end, from the
1843    declaration of variables (temporaries) to the expanding of expressions,
1844    statements, etc.  */
1845 
1846 static GTY(()) tree f2c_inquire_struct;
1847 static tree
ffeste_io_inlist_(bool have_err,ffestpFile * unit_spec,ffestpFile * file_spec,ffestpFile * exist_spec,ffestpFile * open_spec,ffestpFile * number_spec,ffestpFile * named_spec,ffestpFile * name_spec,ffestpFile * access_spec,ffestpFile * sequential_spec,ffestpFile * direct_spec,ffestpFile * form_spec,ffestpFile * formatted_spec,ffestpFile * unformatted_spec,ffestpFile * recl_spec,ffestpFile * nextrec_spec,ffestpFile * blank_spec)1848 ffeste_io_inlist_ (bool have_err,
1849 		   ffestpFile *unit_spec,
1850 		   ffestpFile *file_spec,
1851 		   ffestpFile *exist_spec,
1852 		   ffestpFile *open_spec,
1853 		   ffestpFile *number_spec,
1854 		   ffestpFile *named_spec,
1855 		   ffestpFile *name_spec,
1856 		   ffestpFile *access_spec,
1857 		   ffestpFile *sequential_spec,
1858 		   ffestpFile *direct_spec,
1859 		   ffestpFile *form_spec,
1860 		   ffestpFile *formatted_spec,
1861 		   ffestpFile *unformatted_spec,
1862 		   ffestpFile *recl_spec,
1863 		   ffestpFile *nextrec_spec,
1864 		   ffestpFile *blank_spec)
1865 {
1866   tree t;
1867   tree ttype;
1868   tree field;
1869   tree inits, initn;
1870   bool constantp = TRUE;
1871   static tree errfield, unitfield, filefield, filelenfield, existfield,
1872     openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
1873     accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
1874     formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
1875     unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
1876   tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
1877     namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
1878     sequentialleninit, directinit, directleninit, forminit, formleninit,
1879     formattedinit, formattedleninit, unformattedinit, unformattedleninit,
1880     reclinit, nextrecinit, blankinit, blankleninit;
1881   tree
1882     unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
1883     nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
1884     directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
1885     unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
1886   static int mynumber = 0;
1887 
1888   if (f2c_inquire_struct == NULL_TREE)
1889     {
1890       tree ref;
1891 
1892       ref = make_node (RECORD_TYPE);
1893 
1894       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1895 				    ffecom_f2c_flag_type_node);
1896       unitfield = ffecom_decl_field (ref, errfield, "unit",
1897 				     ffecom_f2c_ftnint_type_node);
1898       filefield = ffecom_decl_field (ref, unitfield, "file",
1899 				     string_type_node);
1900       filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1901 					ffecom_f2c_ftnlen_type_node);
1902       existfield = ffecom_decl_field (ref, filelenfield, "exist",
1903 				      ffecom_f2c_ptr_to_ftnint_type_node);
1904       openfield = ffecom_decl_field (ref, existfield, "open",
1905 				     ffecom_f2c_ptr_to_ftnint_type_node);
1906       numberfield = ffecom_decl_field (ref, openfield, "number",
1907 				       ffecom_f2c_ptr_to_ftnint_type_node);
1908       namedfield = ffecom_decl_field (ref, numberfield, "named",
1909 				      ffecom_f2c_ptr_to_ftnint_type_node);
1910       namefield = ffecom_decl_field (ref, namedfield, "name",
1911 				     string_type_node);
1912       namelenfield = ffecom_decl_field (ref, namefield, "namelen",
1913 					ffecom_f2c_ftnlen_type_node);
1914       accessfield = ffecom_decl_field (ref, namelenfield, "access",
1915 				       string_type_node);
1916       accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
1917 					  ffecom_f2c_ftnlen_type_node);
1918       sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
1919 					   string_type_node);
1920       sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
1921 					      "sequentiallen",
1922 					      ffecom_f2c_ftnlen_type_node);
1923       directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
1924 				       string_type_node);
1925       directlenfield = ffecom_decl_field (ref, directfield, "directlen",
1926 					  ffecom_f2c_ftnlen_type_node);
1927       formfield = ffecom_decl_field (ref, directlenfield, "form",
1928 				     string_type_node);
1929       formlenfield = ffecom_decl_field (ref, formfield, "formlen",
1930 					ffecom_f2c_ftnlen_type_node);
1931       formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
1932 					  string_type_node);
1933       formattedlenfield = ffecom_decl_field (ref, formattedfield,
1934 					     "formattedlen",
1935 					     ffecom_f2c_ftnlen_type_node);
1936       unformattedfield = ffecom_decl_field (ref, formattedlenfield,
1937 					    "unformatted",
1938 					    string_type_node);
1939       unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
1940 					       "unformattedlen",
1941 					       ffecom_f2c_ftnlen_type_node);
1942       reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
1943 				     ffecom_f2c_ptr_to_ftnint_type_node);
1944       nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
1945 					ffecom_f2c_ptr_to_ftnint_type_node);
1946       blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
1947 				      string_type_node);
1948       blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
1949 					 ffecom_f2c_ftnlen_type_node);
1950 
1951       TYPE_FIELDS (ref) = errfield;
1952       layout_type (ref);
1953 
1954       f2c_inquire_struct = ref;
1955     }
1956 
1957   /* Try to do as much compile-time initialization of the structure
1958      as possible, to save run time.  */
1959 
1960   ffeste_f2c_init_flag_ (have_err, errinit);
1961   ffeste_f2c_init_int_ (unitexp, unitinit, unit_spec);
1962   ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
1963 			 file_spec);
1964   ffeste_f2c_init_ptrtoint_ (existexp, existinit, exist_spec);
1965   ffeste_f2c_init_ptrtoint_ (openexp, openinit, open_spec);
1966   ffeste_f2c_init_ptrtoint_ (numberexp, numberinit, number_spec);
1967   ffeste_f2c_init_ptrtoint_ (namedexp, namedinit, named_spec);
1968   ffeste_f2c_init_char_ (nameexp, nameinit, namelenexp, nameleninit,
1969 			 name_spec);
1970   ffeste_f2c_init_char_ (accessexp, accessinit, accesslenexp,
1971 			 accessleninit, access_spec);
1972   ffeste_f2c_init_char_ (sequentialexp, sequentialinit, sequentiallenexp,
1973 			 sequentialleninit, sequential_spec);
1974   ffeste_f2c_init_char_ (directexp, directinit, directlenexp,
1975 			 directleninit, direct_spec);
1976   ffeste_f2c_init_char_ (formexp, forminit, formlenexp, formleninit,
1977 			 form_spec);
1978   ffeste_f2c_init_char_ (formattedexp, formattedinit,
1979 			 formattedlenexp, formattedleninit, formatted_spec);
1980   ffeste_f2c_init_char_ (unformattedexp, unformattedinit, unformattedlenexp,
1981 			 unformattedleninit, unformatted_spec);
1982   ffeste_f2c_init_ptrtoint_ (reclexp, reclinit, recl_spec);
1983   ffeste_f2c_init_ptrtoint_ (nextrecexp, nextrecinit, nextrec_spec);
1984   ffeste_f2c_init_char_ (blankexp, blankinit, blanklenexp,
1985 			 blankleninit, blank_spec);
1986 
1987   inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
1988 			   errinit);
1989   initn = inits;
1990   ffeste_f2c_init_next_ (unitinit);
1991   ffeste_f2c_init_next_ (fileinit);
1992   ffeste_f2c_init_next_ (fileleninit);
1993   ffeste_f2c_init_next_ (existinit);
1994   ffeste_f2c_init_next_ (openinit);
1995   ffeste_f2c_init_next_ (numberinit);
1996   ffeste_f2c_init_next_ (namedinit);
1997   ffeste_f2c_init_next_ (nameinit);
1998   ffeste_f2c_init_next_ (nameleninit);
1999   ffeste_f2c_init_next_ (accessinit);
2000   ffeste_f2c_init_next_ (accessleninit);
2001   ffeste_f2c_init_next_ (sequentialinit);
2002   ffeste_f2c_init_next_ (sequentialleninit);
2003   ffeste_f2c_init_next_ (directinit);
2004   ffeste_f2c_init_next_ (directleninit);
2005   ffeste_f2c_init_next_ (forminit);
2006   ffeste_f2c_init_next_ (formleninit);
2007   ffeste_f2c_init_next_ (formattedinit);
2008   ffeste_f2c_init_next_ (formattedleninit);
2009   ffeste_f2c_init_next_ (unformattedinit);
2010   ffeste_f2c_init_next_ (unformattedleninit);
2011   ffeste_f2c_init_next_ (reclinit);
2012   ffeste_f2c_init_next_ (nextrecinit);
2013   ffeste_f2c_init_next_ (blankinit);
2014   ffeste_f2c_init_next_ (blankleninit);
2015 
2016   inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
2017   TREE_CONSTANT (inits) = constantp ? 1 : 0;
2018   TREE_STATIC (inits) = 1;
2019 
2020   t = build_decl (VAR_DECL,
2021 		  ffecom_get_invented_identifier ("__g77_inlist_%d",
2022 						  mynumber++),
2023 		  f2c_inquire_struct);
2024   TREE_STATIC (t) = 1;
2025   t = ffecom_start_decl (t, 1);
2026   ffecom_finish_decl (t, inits, 0);
2027 
2028   /* Prepare run-time expressions.  */
2029 
2030   ffeste_f2c_prepare_int_ (unit_spec, unitexp);
2031   ffeste_f2c_prepare_char_ (file_spec, fileexp);
2032   ffeste_f2c_prepare_ptrtoint_ (exist_spec, existexp);
2033   ffeste_f2c_prepare_ptrtoint_ (open_spec, openexp);
2034   ffeste_f2c_prepare_ptrtoint_ (number_spec, numberexp);
2035   ffeste_f2c_prepare_ptrtoint_ (named_spec, namedexp);
2036   ffeste_f2c_prepare_char_ (name_spec, nameexp);
2037   ffeste_f2c_prepare_char_ (access_spec, accessexp);
2038   ffeste_f2c_prepare_char_ (sequential_spec, sequentialexp);
2039   ffeste_f2c_prepare_char_ (direct_spec, directexp);
2040   ffeste_f2c_prepare_char_ (form_spec, formexp);
2041   ffeste_f2c_prepare_char_ (formatted_spec, formattedexp);
2042   ffeste_f2c_prepare_char_ (unformatted_spec, unformattedexp);
2043   ffeste_f2c_prepare_ptrtoint_ (recl_spec, reclexp);
2044   ffeste_f2c_prepare_ptrtoint_ (nextrec_spec, nextrecexp);
2045   ffeste_f2c_prepare_char_ (blank_spec, blankexp);
2046 
2047   ffecom_prepare_end ();
2048 
2049   /* Now evaluate run-time expressions as needed.  */
2050 
2051   ffeste_f2c_compile_int_ (unitfield, unit_spec, unitexp);
2052   ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec,
2053 			    fileexp, filelenexp);
2054   ffeste_f2c_compile_ptrtoint_ (existfield, exist_spec, existexp);
2055   ffeste_f2c_compile_ptrtoint_ (openfield, open_spec, openexp);
2056   ffeste_f2c_compile_ptrtoint_ (numberfield, number_spec, numberexp);
2057   ffeste_f2c_compile_ptrtoint_ (namedfield, named_spec, namedexp);
2058   ffeste_f2c_compile_char_ (namefield, namelenfield, name_spec, nameexp,
2059 			    namelenexp);
2060   ffeste_f2c_compile_char_ (accessfield, accesslenfield, access_spec,
2061 			    accessexp, accesslenexp);
2062   ffeste_f2c_compile_char_ (sequentialfield, sequentiallenfield,
2063 			    sequential_spec, sequentialexp,
2064 			    sequentiallenexp);
2065   ffeste_f2c_compile_char_ (directfield, directlenfield, direct_spec,
2066 			    directexp, directlenexp);
2067   ffeste_f2c_compile_char_ (formfield, formlenfield, form_spec, formexp,
2068 			    formlenexp);
2069   ffeste_f2c_compile_char_ (formattedfield, formattedlenfield, formatted_spec,
2070 			    formattedexp, formattedlenexp);
2071   ffeste_f2c_compile_char_ (unformattedfield, unformattedlenfield,
2072 			    unformatted_spec, unformattedexp,
2073 			    unformattedlenexp);
2074   ffeste_f2c_compile_ptrtoint_ (reclfield, recl_spec, reclexp);
2075   ffeste_f2c_compile_ptrtoint_ (nextrecfield, nextrec_spec, nextrecexp);
2076   ffeste_f2c_compile_char_ (blankfield, blanklenfield, blank_spec, blankexp,
2077 			    blanklenexp);
2078 
2079   ttype = build_pointer_type (TREE_TYPE (t));
2080   t = ffecom_1 (ADDR_EXPR, ttype, t);
2081 
2082   t = build_tree_list (NULL_TREE, t);
2083 
2084   return t;
2085 }
2086 
2087 /* Make arglist with ptr to OPEN control list
2088 
2089    Returns a tree suitable as an argument list containing a pointer to
2090    an OPEN-statement control list.  First, generates that control
2091    list, if necessary, along with any static and run-time initializations
2092    that are needed as specified by the arguments to this function.
2093 
2094    Must ensure that all expressions are prepared before being evaluated,
2095    for any whose evaluation might result in the generation of temporaries.
2096 
2097    Note that this means this function causes a transition, within the
2098    current block being code-generated via the back end, from the
2099    declaration of variables (temporaries) to the expanding of expressions,
2100    statements, etc.  */
2101 
2102 static GTY(()) tree f2c_open_struct;
2103 static tree
ffeste_io_olist_(bool have_err,ffebld unit_expr,ffestpFile * file_spec,ffestpFile * stat_spec,ffestpFile * access_spec,ffestpFile * form_spec,ffestpFile * recl_spec,ffestpFile * blank_spec)2104 ffeste_io_olist_ (bool have_err,
2105 		  ffebld unit_expr,
2106 		  ffestpFile *file_spec,
2107 		  ffestpFile *stat_spec,
2108 		  ffestpFile *access_spec,
2109 		  ffestpFile *form_spec,
2110 		  ffestpFile *recl_spec,
2111 		  ffestpFile *blank_spec)
2112 {
2113   tree t;
2114   tree ttype;
2115   tree field;
2116   tree inits, initn;
2117   tree ignore;			/* Ignore length info for certain fields. */
2118   bool constantp = TRUE;
2119   static tree errfield, unitfield, filefield, filelenfield, statfield,
2120     accessfield, formfield, reclfield, blankfield;
2121   tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
2122     forminit, reclinit, blankinit;
2123   tree
2124     unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
2125     blankexp;
2126   static int mynumber = 0;
2127 
2128   if (f2c_open_struct == NULL_TREE)
2129     {
2130       tree ref;
2131 
2132       ref = make_node (RECORD_TYPE);
2133 
2134       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
2135 				    ffecom_f2c_flag_type_node);
2136       unitfield = ffecom_decl_field (ref, errfield, "unit",
2137 				     ffecom_f2c_ftnint_type_node);
2138       filefield = ffecom_decl_field (ref, unitfield, "file",
2139 				     string_type_node);
2140       filelenfield = ffecom_decl_field (ref, filefield, "filelen",
2141 					ffecom_f2c_ftnlen_type_node);
2142       statfield = ffecom_decl_field (ref, filelenfield, "stat",
2143 				     string_type_node);
2144       accessfield = ffecom_decl_field (ref, statfield, "access",
2145 				       string_type_node);
2146       formfield = ffecom_decl_field (ref, accessfield, "form",
2147 				     string_type_node);
2148       reclfield = ffecom_decl_field (ref, formfield, "recl",
2149 				     ffecom_f2c_ftnint_type_node);
2150       blankfield = ffecom_decl_field (ref, reclfield, "blank",
2151 				      string_type_node);
2152 
2153       TYPE_FIELDS (ref) = errfield;
2154       layout_type (ref);
2155 
2156       f2c_open_struct = ref;
2157     }
2158 
2159   /* Try to do as much compile-time initialization of the structure
2160      as possible, to save run time.  */
2161 
2162   ffeste_f2c_init_flag_ (have_err, errinit);
2163 
2164   unitexp = ffecom_const_expr (unit_expr);
2165   if (unitexp)
2166     unitinit = unitexp;
2167   else
2168     {
2169       unitinit = ffecom_integer_zero_node;
2170       constantp = FALSE;
2171     }
2172 
2173   ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2174 			 file_spec);
2175   ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
2176   ffeste_f2c_init_charnolen_ (accessexp, accessinit, access_spec);
2177   ffeste_f2c_init_charnolen_ (formexp, forminit, form_spec);
2178   ffeste_f2c_init_int_ (reclexp, reclinit, recl_spec);
2179   ffeste_f2c_init_charnolen_ (blankexp, blankinit, blank_spec);
2180 
2181   inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
2182   initn = inits;
2183   ffeste_f2c_init_next_ (unitinit);
2184   ffeste_f2c_init_next_ (fileinit);
2185   ffeste_f2c_init_next_ (fileleninit);
2186   ffeste_f2c_init_next_ (statinit);
2187   ffeste_f2c_init_next_ (accessinit);
2188   ffeste_f2c_init_next_ (forminit);
2189   ffeste_f2c_init_next_ (reclinit);
2190   ffeste_f2c_init_next_ (blankinit);
2191 
2192   inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
2193   TREE_CONSTANT (inits) = constantp ? 1 : 0;
2194   TREE_STATIC (inits) = 1;
2195 
2196   t = build_decl (VAR_DECL,
2197 		  ffecom_get_invented_identifier ("__g77_olist_%d",
2198 						  mynumber++),
2199 		  f2c_open_struct);
2200   TREE_STATIC (t) = 1;
2201   t = ffecom_start_decl (t, 1);
2202   ffecom_finish_decl (t, inits, 0);
2203 
2204   /* Prepare run-time expressions.  */
2205 
2206   if (! unitexp)
2207     ffecom_prepare_expr (unit_expr);
2208 
2209   ffeste_f2c_prepare_char_ (file_spec, fileexp);
2210   ffeste_f2c_prepare_charnolen_ (stat_spec, statexp);
2211   ffeste_f2c_prepare_charnolen_ (access_spec, accessexp);
2212   ffeste_f2c_prepare_charnolen_ (form_spec, formexp);
2213   ffeste_f2c_prepare_int_ (recl_spec, reclexp);
2214   ffeste_f2c_prepare_charnolen_ (blank_spec, blankexp);
2215 
2216   ffecom_prepare_end ();
2217 
2218   /* Now evaluate run-time expressions as needed.  */
2219 
2220   if (! unitexp)
2221     {
2222       unitexp = ffecom_expr (unit_expr);
2223       ffeste_f2c_compile_ (unitfield, unitexp);
2224     }
2225 
2226   ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec, fileexp,
2227 			    filelenexp);
2228   ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
2229   ffeste_f2c_compile_charnolen_ (accessfield, access_spec, accessexp);
2230   ffeste_f2c_compile_charnolen_ (formfield, form_spec, formexp);
2231   ffeste_f2c_compile_int_ (reclfield, recl_spec, reclexp);
2232   ffeste_f2c_compile_charnolen_ (blankfield, blank_spec, blankexp);
2233 
2234   ttype = build_pointer_type (TREE_TYPE (t));
2235   t = ffecom_1 (ADDR_EXPR, ttype, t);
2236 
2237   t = build_tree_list (NULL_TREE, t);
2238 
2239   return t;
2240 }
2241 
2242 /* Generate code for BACKSPACE/ENDFILE/REWIND.  */
2243 
2244 static void
ffeste_subr_beru_(ffestpBeruStmt * info,ffecomGfrt rt)2245 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
2246 {
2247   tree alist;
2248   bool iostat;
2249   bool errl;
2250 
2251   ffeste_emit_line_note_ ();
2252 
2253 #define specified(something) (info->beru_spec[something].kw_or_val_present)
2254 
2255   iostat = specified (FFESTP_beruixIOSTAT);
2256   errl = specified (FFESTP_beruixERR);
2257 
2258 #undef specified
2259 
2260   /* ~~For now, we assume the unit number is specified and is not ASTERISK,
2261      because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
2262      without any unit specifier.  f2c, however, supports the former
2263      construct.	 When it is time to add this feature to the FFE, which
2264      probably is fairly easy, ffestc_R919 and company will want to pass an
2265      ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
2266      ffeste_R919 and company, and they will want to pass that same value to
2267      this function, and that argument will replace the constant _unitINTEXPR_
2268      in the call below.	 Right now, the default unit number, 6, is ignored.  */
2269 
2270   ffeste_start_stmt_ ();
2271 
2272   if (errl)
2273     {
2274       /* Have ERR= specification.   */
2275 
2276       ffeste_io_err_
2277 	= ffeste_io_abort_
2278 	= ffecom_lookup_label
2279 	(info->beru_spec[FFESTP_beruixERR].u.label);
2280       ffeste_io_abort_is_temp_ = FALSE;
2281     }
2282   else
2283     {
2284       /* No ERR= specification.  */
2285 
2286       ffeste_io_err_ = NULL_TREE;
2287 
2288       if ((ffeste_io_abort_is_temp_ = iostat))
2289 	ffeste_io_abort_ = ffecom_temp_label ();
2290       else
2291 	ffeste_io_abort_ = NULL_TREE;
2292     }
2293 
2294   if (iostat)
2295     {
2296       /* Have IOSTAT= specification.  */
2297 
2298       ffeste_io_iostat_is_temp_ = FALSE;
2299       ffeste_io_iostat_ = ffecom_expr
2300 	(info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2301     }
2302   else if (ffeste_io_abort_ != NULL_TREE)
2303     {
2304       /* Have no IOSTAT= but have ERR=.  */
2305 
2306       ffeste_io_iostat_is_temp_ = TRUE;
2307       ffeste_io_iostat_
2308 	= ffecom_make_tempvar ("beru", ffecom_integer_type_node,
2309 			       FFETARGET_charactersizeNONE, -1);
2310     }
2311   else
2312     {
2313       /* No IOSTAT= or ERR= specification.  */
2314 
2315       ffeste_io_iostat_is_temp_ = FALSE;
2316       ffeste_io_iostat_ = NULL_TREE;
2317     }
2318 
2319   /* Now prescan, then convert, all the arguments.  */
2320 
2321   alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2322 			     info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
2323 
2324   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
2325      label, since we're gonna fall through to there anyway. */
2326 
2327   ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
2328 		   ! ffeste_io_abort_is_temp_);
2329 
2330   /* If we've got a temp label, generate its code here. */
2331 
2332   if (ffeste_io_abort_is_temp_)
2333     {
2334       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2335       emit_nop ();
2336       expand_label (ffeste_io_abort_);
2337 
2338       assert (ffeste_io_err_ == NULL_TREE);
2339     }
2340 
2341   ffeste_end_stmt_ ();
2342 }
2343 
2344 /* END DO statement
2345 
2346    Also invoked by _labeldef_branch_finish_ (or, in cases
2347    of errors, other _labeldef_ functions) when the label definition is
2348    for a DO-target (LOOPEND) label, once per matching/outstanding DO
2349    block on the stack.  */
2350 
2351 void
ffeste_do(ffestw block)2352 ffeste_do (ffestw block)
2353 {
2354   ffeste_emit_line_note_ ();
2355 
2356   if (ffestw_do_tvar (block) == 0)
2357     {
2358       expand_end_loop ();		/* DO WHILE and just DO. */
2359 
2360       ffeste_end_block_ (block);
2361     }
2362   else
2363     ffeste_end_iterdo_ (block,
2364 			ffestw_do_tvar (block),
2365 			ffestw_do_incr_saved (block),
2366 			ffestw_do_count_var (block));
2367 }
2368 
2369 /* End of statement following logical IF.
2370 
2371    Applies to *only* logical IF, not to IF-THEN.  */
2372 
2373 void
ffeste_end_R807()2374 ffeste_end_R807 ()
2375 {
2376   ffeste_emit_line_note_ ();
2377 
2378   expand_end_cond ();
2379 
2380   ffeste_end_block_ (NULL);
2381 }
2382 
2383 /* Generate "code" for branch label definition.  */
2384 
2385 void
ffeste_labeldef_branch(ffelab label)2386 ffeste_labeldef_branch (ffelab label)
2387 {
2388   tree glabel;
2389 
2390   glabel = ffecom_lookup_label (label);
2391   assert (glabel != NULL_TREE);
2392   if (TREE_CODE (glabel) == ERROR_MARK)
2393     return;
2394 
2395   assert (DECL_INITIAL (glabel) == NULL_TREE);
2396 
2397   DECL_INITIAL (glabel) = error_mark_node;
2398   DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
2399   DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
2400 
2401   emit_nop ();
2402 
2403   expand_label (glabel);
2404 }
2405 
2406 /* Generate "code" for FORMAT label definition.  */
2407 
2408 void
ffeste_labeldef_format(ffelab label)2409 ffeste_labeldef_format (ffelab label)
2410 {
2411   ffeste_label_formatdef_ = label;
2412 }
2413 
2414 /* Assignment statement (outside of WHERE).  */
2415 
2416 void
ffeste_R737A(ffebld dest,ffebld source)2417 ffeste_R737A (ffebld dest, ffebld source)
2418 {
2419   ffeste_check_simple_ ();
2420 
2421   ffeste_emit_line_note_ ();
2422 
2423   ffeste_start_stmt_ ();
2424 
2425   ffecom_expand_let_stmt (dest, source);
2426 
2427   ffeste_end_stmt_ ();
2428 }
2429 
2430 /* Block IF (IF-THEN) statement.  */
2431 
2432 void
ffeste_R803(ffestw block,ffebld expr)2433 ffeste_R803 (ffestw block, ffebld expr)
2434 {
2435   tree temp;
2436 
2437   ffeste_check_simple_ ();
2438 
2439   ffeste_emit_line_note_ ();
2440 
2441   ffeste_start_block_ (block);
2442 
2443   temp = ffecom_make_tempvar ("ifthen", integer_type_node,
2444 			      FFETARGET_charactersizeNONE, -1);
2445 
2446   ffeste_start_stmt_ ();
2447 
2448   ffecom_prepare_expr (expr);
2449 
2450   if (ffecom_prepare_end ())
2451     {
2452       tree result;
2453 
2454       result = ffecom_modify (void_type_node,
2455 			      temp,
2456 			      ffecom_truth_value (ffecom_expr (expr)));
2457 
2458       expand_expr_stmt (result);
2459 
2460       ffeste_end_stmt_ ();
2461     }
2462   else
2463     {
2464       ffeste_end_stmt_ ();
2465 
2466       temp = ffecom_truth_value (ffecom_expr (expr));
2467     }
2468 
2469   expand_start_cond (temp, 0);
2470 
2471   /* No fake `else' constructs introduced (yet).  */
2472   ffestw_set_ifthen_fake_else (block, 0);
2473 }
2474 
2475 /* ELSE IF statement.  */
2476 
2477 void
ffeste_R804(ffestw block,ffebld expr)2478 ffeste_R804 (ffestw block, ffebld expr)
2479 {
2480   tree temp;
2481 
2482   ffeste_check_simple_ ();
2483 
2484   ffeste_emit_line_note_ ();
2485 
2486   /* Since ELSEIF(expr) might require preparations for expr,
2487      implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF.  */
2488 
2489   expand_start_else ();
2490 
2491   ffeste_start_block_ (block);
2492 
2493   temp = ffecom_make_tempvar ("elseif", integer_type_node,
2494 			      FFETARGET_charactersizeNONE, -1);
2495 
2496   ffeste_start_stmt_ ();
2497 
2498   ffecom_prepare_expr (expr);
2499 
2500   if (ffecom_prepare_end ())
2501     {
2502       tree result;
2503 
2504       result = ffecom_modify (void_type_node,
2505 			      temp,
2506 			      ffecom_truth_value (ffecom_expr (expr)));
2507 
2508       expand_expr_stmt (result);
2509 
2510       ffeste_end_stmt_ ();
2511     }
2512   else
2513     {
2514       /* In this case, we could probably have used expand_start_elseif
2515 	 instead, saving the need for a fake `else' construct.  But,
2516 	 until it's clear that'd improve performance, it's easier this
2517 	 way, since we have to expand_start_else before we get to this
2518 	 test, given the current design.  */
2519 
2520       ffeste_end_stmt_ ();
2521 
2522       temp = ffecom_truth_value (ffecom_expr (expr));
2523     }
2524 
2525   expand_start_cond (temp, 0);
2526 
2527   /* Increment number of fake `else' constructs introduced.  */
2528   ffestw_set_ifthen_fake_else (block,
2529 			       ffestw_ifthen_fake_else (block) + 1);
2530 }
2531 
2532 /* ELSE statement.  */
2533 
2534 void
ffeste_R805(ffestw block UNUSED)2535 ffeste_R805 (ffestw block UNUSED)
2536 {
2537   ffeste_check_simple_ ();
2538 
2539   ffeste_emit_line_note_ ();
2540 
2541   expand_start_else ();
2542 }
2543 
2544 /* END IF statement.  */
2545 
2546 void
ffeste_R806(ffestw block)2547 ffeste_R806 (ffestw block)
2548 {
2549   int i = ffestw_ifthen_fake_else (block) + 1;
2550 
2551   ffeste_emit_line_note_ ();
2552 
2553   for (; i; --i)
2554     {
2555       expand_end_cond ();
2556 
2557       ffeste_end_block_ (block);
2558     }
2559 }
2560 
2561 /* Logical IF statement.  */
2562 
2563 void
ffeste_R807(ffebld expr)2564 ffeste_R807 (ffebld expr)
2565 {
2566   tree temp;
2567 
2568   ffeste_check_simple_ ();
2569 
2570   ffeste_emit_line_note_ ();
2571 
2572   ffeste_start_block_ (NULL);
2573 
2574   temp = ffecom_make_tempvar ("if", integer_type_node,
2575 			      FFETARGET_charactersizeNONE, -1);
2576 
2577   ffeste_start_stmt_ ();
2578 
2579   ffecom_prepare_expr (expr);
2580 
2581   if (ffecom_prepare_end ())
2582     {
2583       tree result;
2584 
2585       result = ffecom_modify (void_type_node,
2586 			      temp,
2587 			      ffecom_truth_value (ffecom_expr (expr)));
2588 
2589       expand_expr_stmt (result);
2590 
2591       ffeste_end_stmt_ ();
2592     }
2593   else
2594     {
2595       ffeste_end_stmt_ ();
2596 
2597       temp = ffecom_truth_value (ffecom_expr (expr));
2598     }
2599 
2600   expand_start_cond (temp, 0);
2601 }
2602 
2603 /* SELECT CASE statement.  */
2604 
2605 void
ffeste_R809(ffestw block,ffebld expr)2606 ffeste_R809 (ffestw block, ffebld expr)
2607 {
2608   ffeste_check_simple_ ();
2609 
2610   ffeste_emit_line_note_ ();
2611 
2612   ffeste_start_block_ (block);
2613 
2614   if ((expr == NULL)
2615       || (ffeinfo_basictype (ffebld_info (expr))
2616 	  == FFEINFO_basictypeANY))
2617     ffestw_set_select_texpr (block, error_mark_node);
2618   else if (ffeinfo_basictype (ffebld_info (expr))
2619 	   == FFEINFO_basictypeCHARACTER)
2620     {
2621       /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2622 
2623       /* xgettext:no-c-format */
2624       ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
2625 			FFEBAD_severityFATAL);
2626       ffebad_here (0, ffestw_line (block), ffestw_col (block));
2627       ffebad_finish ();
2628       ffestw_set_select_texpr (block, error_mark_node);
2629     }
2630   else
2631     {
2632       tree result;
2633       tree texpr;
2634 
2635       result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
2636 				    ffeinfo_size (ffebld_info (expr)),
2637 				    -1);
2638 
2639       ffeste_start_stmt_ ();
2640 
2641       ffecom_prepare_expr (expr);
2642 
2643       ffecom_prepare_end ();
2644 
2645       texpr = ffecom_expr (expr);
2646 
2647       assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
2648 	      == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
2649 
2650       texpr = ffecom_modify (void_type_node,
2651 			     result,
2652 			     texpr);
2653       expand_expr_stmt (texpr);
2654 
2655       ffeste_end_stmt_ ();
2656 
2657       expand_start_case (1, result, TREE_TYPE (result),
2658 			 "SELECT CASE statement");
2659       ffestw_set_select_texpr (block, texpr);
2660       ffestw_set_select_break (block, FALSE);
2661     }
2662 }
2663 
2664 /* CASE statement.
2665 
2666    If casenum is 0, it's CASE DEFAULT.	Else it's the case ranges at
2667    the start of the first_stmt list in the select object at the top of
2668    the stack that match casenum.  */
2669 
2670 void
ffeste_R810(ffestw block,unsigned long casenum)2671 ffeste_R810 (ffestw block, unsigned long casenum)
2672 {
2673   ffestwSelect s = ffestw_select (block);
2674   ffestwCase c;
2675   tree texprlow;
2676   tree texprhigh;
2677   tree tlabel;
2678   int pushok;
2679   tree duplicate;
2680 
2681   ffeste_check_simple_ ();
2682 
2683   if (s->first_stmt == (ffestwCase) &s->first_rel)
2684     c = NULL;
2685   else
2686     c = s->first_stmt;
2687 
2688   ffeste_emit_line_note_ ();
2689 
2690   if (ffestw_select_texpr (block) == error_mark_node)
2691     return;
2692 
2693   /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2694 
2695   tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2696 
2697   if (ffestw_select_break (block))
2698     expand_exit_something ();
2699   else
2700     ffestw_set_select_break (block, TRUE);
2701 
2702   if ((c == NULL) || (casenum != c->casenum))
2703     {
2704       if (casenum == 0)	/* Intentional CASE DEFAULT. */
2705 	{
2706 	  pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2707 	  assert (pushok == 0);
2708 	}
2709     }
2710   else
2711     do
2712       {
2713 	texprlow = (c->low == NULL) ? NULL_TREE
2714 	  : ffecom_constantunion_with_type (&ffebld_constant_union (c->low),
2715 				  ffecom_tree_type[s->type][s->kindtype], c->low->consttype);
2716 	if (c->low != c->high)
2717 	  {
2718 	    texprhigh = (c->high == NULL) ? NULL_TREE
2719 	      : ffecom_constantunion_with_type (&ffebld_constant_union (c->high),
2720 				      ffecom_tree_type[s->type][s->kindtype], c->high->consttype);
2721 	    pushok = pushcase_range (texprlow, texprhigh, convert,
2722 				     tlabel, &duplicate);
2723 	  }
2724 	else
2725 	  pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2726 	assert((pushok !=2) || (pushok !=0));
2727 	if (pushok==2)
2728 	  {
2729 	    ffebad_start_msg ("SELECT (at %0) has duplicate cases -- check integer overflow of CASE(s)",
2730 	      FFEBAD_severityFATAL);
2731 	    ffebad_here (0, ffestw_line (block), ffestw_col (block));
2732 	    ffebad_finish ();
2733 	    ffestw_set_select_texpr (block, error_mark_node);
2734 	  }
2735 	c = c->next_stmt;
2736 	/* Unlink prev.  */
2737 	c->previous_stmt->previous_stmt->next_stmt = c;
2738 	c->previous_stmt = c->previous_stmt->previous_stmt;
2739       }
2740     while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2741 }
2742 
2743 /* END SELECT statement.  */
2744 
2745 void
ffeste_R811(ffestw block)2746 ffeste_R811 (ffestw block)
2747 {
2748   ffeste_emit_line_note_ ();
2749 
2750   /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2751 
2752   if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
2753     expand_end_case (ffestw_select_texpr (block));
2754 
2755   ffeste_end_block_ (block);
2756 }
2757 
2758 /* Iterative DO statement.  */
2759 
2760 void
ffeste_R819A(ffestw block,ffelab label UNUSED,ffebld var,ffebld start,ffelexToken start_token,ffebld end,ffelexToken end_token,ffebld incr,ffelexToken incr_token)2761 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
2762 	      ffebld start, ffelexToken start_token,
2763 	      ffebld end, ffelexToken end_token,
2764 	      ffebld incr, ffelexToken incr_token)
2765 {
2766   ffeste_check_simple_ ();
2767 
2768   ffeste_emit_line_note_ ();
2769 
2770   ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
2771 			var,
2772 			start, start_token,
2773 			end, end_token,
2774 			incr, incr_token,
2775 			"Iterative DO loop");
2776 }
2777 
2778 /* DO WHILE statement.  */
2779 
2780 void
ffeste_R819B(ffestw block,ffelab label UNUSED,ffebld expr)2781 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
2782 {
2783   tree result;
2784 
2785   ffeste_check_simple_ ();
2786 
2787   ffeste_emit_line_note_ ();
2788 
2789   ffeste_start_block_ (block);
2790 
2791   if (expr)
2792     {
2793       struct nesting *loop;
2794       tree mod;
2795 
2796       result = ffecom_make_tempvar ("dowhile", integer_type_node,
2797 				    FFETARGET_charactersizeNONE, -1);
2798       loop = expand_start_loop (1);
2799 
2800       ffeste_start_stmt_ ();
2801 
2802       ffecom_prepare_expr (expr);
2803 
2804       ffecom_prepare_end ();
2805 
2806       mod = ffecom_modify (void_type_node,
2807 			   result,
2808 			   ffecom_truth_value (ffecom_expr (expr)));
2809       expand_expr_stmt (mod);
2810 
2811       ffeste_end_stmt_ ();
2812 
2813       ffestw_set_do_hook (block, loop);
2814       expand_exit_loop_top_cond (0, result);
2815     }
2816   else
2817     ffestw_set_do_hook (block, expand_start_loop (1));
2818 
2819   ffestw_set_do_tvar (block, NULL_TREE);
2820 }
2821 
2822 /* END DO statement.
2823 
2824    This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
2825    CONTINUE (except that it has to have a label that is the target of
2826    one or more iterative DO statement), not the Fortran-90 structured
2827    END DO, which is handled elsewhere, as is the actual mechanism of
2828    ending an iterative DO statement, even one that ends at a label.  */
2829 
2830 void
ffeste_R825()2831 ffeste_R825 ()
2832 {
2833   ffeste_check_simple_ ();
2834 
2835   ffeste_emit_line_note_ ();
2836 
2837   emit_nop ();
2838 }
2839 
2840 /* CYCLE statement.  */
2841 
2842 void
ffeste_R834(ffestw block)2843 ffeste_R834 (ffestw block)
2844 {
2845   ffeste_check_simple_ ();
2846 
2847   ffeste_emit_line_note_ ();
2848 
2849   expand_continue_loop (ffestw_do_hook (block));
2850 }
2851 
2852 /* EXIT statement.  */
2853 
2854 void
ffeste_R835(ffestw block)2855 ffeste_R835 (ffestw block)
2856 {
2857   ffeste_check_simple_ ();
2858 
2859   ffeste_emit_line_note_ ();
2860 
2861   expand_exit_loop (ffestw_do_hook (block));
2862 }
2863 
2864 /* GOTO statement.  */
2865 
2866 void
ffeste_R836(ffelab label)2867 ffeste_R836 (ffelab label)
2868 {
2869   tree glabel;
2870 
2871   ffeste_check_simple_ ();
2872 
2873   ffeste_emit_line_note_ ();
2874 
2875   glabel = ffecom_lookup_label (label);
2876   if ((glabel != NULL_TREE)
2877       && (TREE_CODE (glabel) != ERROR_MARK))
2878     {
2879       expand_goto (glabel);
2880       TREE_USED (glabel) = 1;
2881     }
2882 }
2883 
2884 /* Computed GOTO statement.  */
2885 
2886 void
ffeste_R837(ffelab * labels,int count,ffebld expr)2887 ffeste_R837 (ffelab *labels, int count, ffebld expr)
2888 {
2889   int i;
2890   tree texpr;
2891   tree value;
2892   tree tlabel;
2893   int pushok;
2894   tree duplicate;
2895 
2896   ffeste_check_simple_ ();
2897 
2898   ffeste_emit_line_note_ ();
2899 
2900   ffeste_start_stmt_ ();
2901 
2902   ffecom_prepare_expr (expr);
2903 
2904   ffecom_prepare_end ();
2905 
2906   texpr = ffecom_expr (expr);
2907 
2908   expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
2909 
2910   for (i = 0; i < count; ++i)
2911     {
2912       value = build_int_2 (i + 1, 0);
2913       tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2914 
2915       pushok = pushcase (value, convert, tlabel, &duplicate);
2916       assert (pushok == 0);
2917 
2918       tlabel = ffecom_lookup_label (labels[i]);
2919       if ((tlabel == NULL_TREE)
2920 	  || (TREE_CODE (tlabel) == ERROR_MARK))
2921 	continue;
2922 
2923       expand_goto (tlabel);
2924       TREE_USED (tlabel) = 1;
2925     }
2926   expand_end_case (texpr);
2927 
2928   ffeste_end_stmt_ ();
2929 }
2930 
2931 /* ASSIGN statement.  */
2932 
2933 void
ffeste_R838(ffelab label,ffebld target)2934 ffeste_R838 (ffelab label, ffebld target)
2935 {
2936   tree expr_tree;
2937   tree label_tree;
2938   tree target_tree;
2939 
2940   ffeste_check_simple_ ();
2941 
2942   ffeste_emit_line_note_ ();
2943 
2944     /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2945        seen here should never require use of temporaries.  */
2946 
2947   label_tree = ffecom_lookup_label (label);
2948   if ((label_tree != NULL_TREE)
2949       && (TREE_CODE (label_tree) != ERROR_MARK))
2950     {
2951       label_tree = ffecom_1 (ADDR_EXPR,
2952 			     build_pointer_type (void_type_node),
2953 			     label_tree);
2954       TREE_CONSTANT (label_tree) = 1;
2955 
2956       target_tree = ffecom_expr_assign_w (target);
2957       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
2958 	  < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
2959 	error ("ASSIGN to variable that is too small");
2960 
2961       label_tree = convert (TREE_TYPE (target_tree), label_tree);
2962 
2963       expr_tree = ffecom_modify (void_type_node,
2964 				 target_tree,
2965 				 label_tree);
2966       expand_expr_stmt (expr_tree);
2967     }
2968 }
2969 
2970 /* Assigned GOTO statement.  */
2971 
2972 void
ffeste_R839(ffebld target)2973 ffeste_R839 (ffebld target)
2974 {
2975   tree t;
2976 
2977   ffeste_check_simple_ ();
2978 
2979   ffeste_emit_line_note_ ();
2980 
2981   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2982      seen here should never require use of temporaries.  */
2983 
2984   t = ffecom_expr_assign (target);
2985   if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2986       < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2987     error ("ASSIGNed GOTO target variable is too small");
2988 
2989   expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
2990 }
2991 
2992 /* Arithmetic IF statement.  */
2993 
2994 void
ffeste_R840(ffebld expr,ffelab neg,ffelab zero,ffelab pos)2995 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
2996 {
2997   tree gneg = ffecom_lookup_label (neg);
2998   tree gzero = ffecom_lookup_label (zero);
2999   tree gpos = ffecom_lookup_label (pos);
3000   tree texpr;
3001 
3002   ffeste_check_simple_ ();
3003 
3004   ffeste_emit_line_note_ ();
3005 
3006   if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
3007     return;
3008   if ((TREE_CODE (gneg) == ERROR_MARK)
3009       || (TREE_CODE (gzero) == ERROR_MARK)
3010       || (TREE_CODE (gpos) == ERROR_MARK))
3011     return;
3012 
3013   ffeste_start_stmt_ ();
3014 
3015   ffecom_prepare_expr (expr);
3016 
3017   ffecom_prepare_end ();
3018 
3019   if (neg == zero)
3020     {
3021       if (neg == pos)
3022 	expand_goto (gzero);
3023       else
3024 	{
3025 	  /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos.  */
3026 	  texpr = ffecom_expr (expr);
3027 	  texpr = ffecom_2 (LE_EXPR, integer_type_node,
3028 			    texpr,
3029 			    convert (TREE_TYPE (texpr),
3030 				     integer_zero_node));
3031 	  expand_start_cond (ffecom_truth_value (texpr), 0);
3032 	  expand_goto (gzero);
3033 	  expand_start_else ();
3034 	  expand_goto (gpos);
3035 	  expand_end_cond ();
3036 	}
3037     }
3038   else if (neg == pos)
3039     {
3040       /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero.  */
3041       texpr = ffecom_expr (expr);
3042       texpr = ffecom_2 (NE_EXPR, integer_type_node,
3043 			texpr,
3044 			convert (TREE_TYPE (texpr),
3045 				 integer_zero_node));
3046       expand_start_cond (ffecom_truth_value (texpr), 0);
3047       expand_goto (gneg);
3048       expand_start_else ();
3049       expand_goto (gzero);
3050       expand_end_cond ();
3051     }
3052   else if (zero == pos)
3053     {
3054       /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg.  */
3055       texpr = ffecom_expr (expr);
3056       texpr = ffecom_2 (GE_EXPR, integer_type_node,
3057 			texpr,
3058 			convert (TREE_TYPE (texpr),
3059 				 integer_zero_node));
3060       expand_start_cond (ffecom_truth_value (texpr), 0);
3061       expand_goto (gzero);
3062       expand_start_else ();
3063       expand_goto (gneg);
3064       expand_end_cond ();
3065     }
3066   else
3067     {
3068       /* Use a SAVE_EXPR in combo with:
3069 	 IF (expr.LT.0) THEN GOTO neg
3070 	 ELSEIF (expr.GT.0) THEN GOTO pos
3071 	 ELSE GOTO zero.  */
3072       tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
3073 
3074       texpr = ffecom_2 (LT_EXPR, integer_type_node,
3075 			expr_saved,
3076 			convert (TREE_TYPE (expr_saved),
3077 				 integer_zero_node));
3078       expand_start_cond (ffecom_truth_value (texpr), 0);
3079       expand_goto (gneg);
3080       texpr = ffecom_2 (GT_EXPR, integer_type_node,
3081 			expr_saved,
3082 			convert (TREE_TYPE (expr_saved),
3083 				 integer_zero_node));
3084       expand_start_elseif (ffecom_truth_value (texpr));
3085       expand_goto (gpos);
3086       expand_start_else ();
3087       expand_goto (gzero);
3088       expand_end_cond ();
3089     }
3090 
3091   ffeste_end_stmt_ ();
3092 }
3093 
3094 /* CONTINUE statement.  */
3095 
3096 void
ffeste_R841()3097 ffeste_R841 ()
3098 {
3099   ffeste_check_simple_ ();
3100 
3101   ffeste_emit_line_note_ ();
3102 
3103   emit_nop ();
3104 }
3105 
3106 /* STOP statement.  */
3107 
3108 void
ffeste_R842(ffebld expr)3109 ffeste_R842 (ffebld expr)
3110 {
3111   tree callit;
3112   ffelexToken msg;
3113 
3114   ffeste_check_simple_ ();
3115 
3116   ffeste_emit_line_note_ ();
3117 
3118   if ((expr == NULL)
3119       || (ffeinfo_basictype (ffebld_info (expr))
3120 	  == FFEINFO_basictypeANY))
3121     {
3122       msg = ffelex_token_new_character ("",
3123 					ffelex_token_where_line (ffesta_tokens[0]),
3124 					ffelex_token_where_column (ffesta_tokens[0]));
3125       expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3126 				(msg));
3127       ffelex_token_kill (msg);
3128       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3129 					  FFEINFO_kindtypeCHARACTERDEFAULT,
3130 					  0, FFEINFO_kindENTITY,
3131 					  FFEINFO_whereCONSTANT, 0));
3132     }
3133   else if (ffeinfo_basictype (ffebld_info (expr))
3134 	   == FFEINFO_basictypeINTEGER)
3135     {
3136       char num[50];
3137 
3138       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3139       assert (ffeinfo_kindtype (ffebld_info (expr))
3140 	      == FFEINFO_kindtypeINTEGERDEFAULT);
3141       sprintf (num, "%" ffetargetIntegerDefault_f "d",
3142 	       ffebld_constant_integer1 (ffebld_conter (expr)));
3143       msg = ffelex_token_new_character (num,
3144 					ffelex_token_where_line (ffesta_tokens[0]),
3145 					ffelex_token_where_column (ffesta_tokens[0]));
3146       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3147       ffelex_token_kill (msg);
3148       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3149 					  FFEINFO_kindtypeCHARACTERDEFAULT,
3150 					  0, FFEINFO_kindENTITY,
3151 					  FFEINFO_whereCONSTANT, 0));
3152     }
3153   else
3154     {
3155       assert (ffeinfo_basictype (ffebld_info (expr))
3156 	      == FFEINFO_basictypeCHARACTER);
3157       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3158       assert (ffeinfo_kindtype (ffebld_info (expr))
3159 	      == FFEINFO_kindtypeCHARACTERDEFAULT);
3160     }
3161 
3162   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3163      seen here should never require use of temporaries.  */
3164 
3165   callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3166 			     ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3167 			     NULL_TREE);
3168   TREE_SIDE_EFFECTS (callit) = 1;
3169 
3170   expand_expr_stmt (callit);
3171 }
3172 
3173 /* PAUSE statement.  */
3174 
3175 void
ffeste_R843(ffebld expr)3176 ffeste_R843 (ffebld expr)
3177 {
3178   tree callit;
3179   ffelexToken msg;
3180 
3181   ffeste_check_simple_ ();
3182 
3183   ffeste_emit_line_note_ ();
3184 
3185   if ((expr == NULL)
3186       || (ffeinfo_basictype (ffebld_info (expr))
3187 	  == FFEINFO_basictypeANY))
3188     {
3189       msg = ffelex_token_new_character ("",
3190 					ffelex_token_where_line (ffesta_tokens[0]),
3191 					ffelex_token_where_column (ffesta_tokens[0]));
3192       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3193       ffelex_token_kill (msg);
3194       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3195 					  FFEINFO_kindtypeCHARACTERDEFAULT,
3196 					  0, FFEINFO_kindENTITY,
3197 					  FFEINFO_whereCONSTANT, 0));
3198     }
3199   else if (ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeINTEGER)
3200     {
3201       char num[50];
3202 
3203       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3204       assert (ffeinfo_kindtype (ffebld_info (expr))
3205 	      == FFEINFO_kindtypeINTEGERDEFAULT);
3206       sprintf (num, "%" ffetargetIntegerDefault_f "d",
3207 	       ffebld_constant_integer1 (ffebld_conter (expr)));
3208       msg = ffelex_token_new_character (num, ffelex_token_where_line (ffesta_tokens[0]),
3209 					ffelex_token_where_column (ffesta_tokens[0]));
3210       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3211       ffelex_token_kill (msg);
3212       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3213 					  FFEINFO_kindtypeCHARACTERDEFAULT,
3214 					  0, FFEINFO_kindENTITY,
3215 					  FFEINFO_whereCONSTANT, 0));
3216     }
3217   else
3218     {
3219       assert (ffeinfo_basictype (ffebld_info (expr))
3220 	      == FFEINFO_basictypeCHARACTER);
3221       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3222       assert (ffeinfo_kindtype (ffebld_info (expr))
3223 	      == FFEINFO_kindtypeCHARACTERDEFAULT);
3224     }
3225 
3226   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3227      seen here should never require use of temporaries.  */
3228 
3229   callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3230 			     ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3231 			     NULL_TREE);
3232   TREE_SIDE_EFFECTS (callit) = 1;
3233 
3234   expand_expr_stmt (callit);
3235 }
3236 
3237 /* OPEN statement.  */
3238 
3239 void
ffeste_R904(ffestpOpenStmt * info)3240 ffeste_R904 (ffestpOpenStmt *info)
3241 {
3242   tree args;
3243   bool iostat;
3244   bool errl;
3245 
3246   ffeste_check_simple_ ();
3247 
3248   ffeste_emit_line_note_ ();
3249 
3250 #define specified(something) (info->open_spec[something].kw_or_val_present)
3251 
3252   iostat = specified (FFESTP_openixIOSTAT);
3253   errl = specified (FFESTP_openixERR);
3254 
3255 #undef specified
3256 
3257   ffeste_start_stmt_ ();
3258 
3259   if (errl)
3260     {
3261       ffeste_io_err_
3262 	= ffeste_io_abort_
3263 	= ffecom_lookup_label
3264 	(info->open_spec[FFESTP_openixERR].u.label);
3265       ffeste_io_abort_is_temp_ = FALSE;
3266     }
3267   else
3268     {
3269       ffeste_io_err_ = NULL_TREE;
3270 
3271       if ((ffeste_io_abort_is_temp_ = iostat))
3272 	ffeste_io_abort_ = ffecom_temp_label ();
3273       else
3274 	ffeste_io_abort_ = NULL_TREE;
3275     }
3276 
3277   if (iostat)
3278     {
3279       /* Have IOSTAT= specification.  */
3280 
3281       ffeste_io_iostat_is_temp_ = FALSE;
3282       ffeste_io_iostat_ = ffecom_expr
3283 	(info->open_spec[FFESTP_openixIOSTAT].u.expr);
3284     }
3285   else if (ffeste_io_abort_ != NULL_TREE)
3286     {
3287       /* Have no IOSTAT= but have ERR=.  */
3288 
3289       ffeste_io_iostat_is_temp_ = TRUE;
3290       ffeste_io_iostat_
3291 	= ffecom_make_tempvar ("open", ffecom_integer_type_node,
3292 			       FFETARGET_charactersizeNONE, -1);
3293     }
3294   else
3295     {
3296       /* No IOSTAT= or ERR= specification.  */
3297 
3298       ffeste_io_iostat_is_temp_ = FALSE;
3299       ffeste_io_iostat_ = NULL_TREE;
3300     }
3301 
3302   /* Now prescan, then convert, all the arguments.  */
3303 
3304   args = ffeste_io_olist_ (errl || iostat,
3305 			   info->open_spec[FFESTP_openixUNIT].u.expr,
3306 			   &info->open_spec[FFESTP_openixFILE],
3307 			   &info->open_spec[FFESTP_openixSTATUS],
3308 			   &info->open_spec[FFESTP_openixACCESS],
3309 			   &info->open_spec[FFESTP_openixFORM],
3310 			   &info->open_spec[FFESTP_openixRECL],
3311 			   &info->open_spec[FFESTP_openixBLANK]);
3312 
3313   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3314        label, since we're gonna fall through to there anyway. */
3315 
3316   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
3317 		   ! ffeste_io_abort_is_temp_);
3318 
3319   /* If we've got a temp label, generate its code here.  */
3320 
3321   if (ffeste_io_abort_is_temp_)
3322     {
3323       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3324       emit_nop ();
3325       expand_label (ffeste_io_abort_);
3326 
3327       assert (ffeste_io_err_ == NULL_TREE);
3328     }
3329 
3330   ffeste_end_stmt_ ();
3331 }
3332 
3333 /* CLOSE statement.  */
3334 
3335 void
ffeste_R907(ffestpCloseStmt * info)3336 ffeste_R907 (ffestpCloseStmt *info)
3337 {
3338   tree args;
3339   bool iostat;
3340   bool errl;
3341 
3342   ffeste_check_simple_ ();
3343 
3344   ffeste_emit_line_note_ ();
3345 
3346 #define specified(something) (info->close_spec[something].kw_or_val_present)
3347 
3348   iostat = specified (FFESTP_closeixIOSTAT);
3349   errl = specified (FFESTP_closeixERR);
3350 
3351 #undef specified
3352 
3353   ffeste_start_stmt_ ();
3354 
3355   if (errl)
3356     {
3357       ffeste_io_err_
3358 	= ffeste_io_abort_
3359 	= ffecom_lookup_label
3360 	(info->close_spec[FFESTP_closeixERR].u.label);
3361       ffeste_io_abort_is_temp_ = FALSE;
3362     }
3363   else
3364     {
3365       ffeste_io_err_ = NULL_TREE;
3366 
3367       if ((ffeste_io_abort_is_temp_ = iostat))
3368 	ffeste_io_abort_ = ffecom_temp_label ();
3369       else
3370 	ffeste_io_abort_ = NULL_TREE;
3371     }
3372 
3373   if (iostat)
3374     {
3375       /* Have IOSTAT= specification.  */
3376 
3377       ffeste_io_iostat_is_temp_ = FALSE;
3378       ffeste_io_iostat_ = ffecom_expr
3379 	(info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3380     }
3381   else if (ffeste_io_abort_ != NULL_TREE)
3382     {
3383       /* Have no IOSTAT= but have ERR=.  */
3384 
3385       ffeste_io_iostat_is_temp_ = TRUE;
3386       ffeste_io_iostat_
3387 	= ffecom_make_tempvar ("close", ffecom_integer_type_node,
3388 			       FFETARGET_charactersizeNONE, -1);
3389     }
3390   else
3391     {
3392       /* No IOSTAT= or ERR= specification.  */
3393 
3394       ffeste_io_iostat_is_temp_ = FALSE;
3395       ffeste_io_iostat_ = NULL_TREE;
3396     }
3397 
3398   /* Now prescan, then convert, all the arguments.  */
3399 
3400   args = ffeste_io_cllist_ (errl || iostat,
3401 			    info->close_spec[FFESTP_closeixUNIT].u.expr,
3402 			    &info->close_spec[FFESTP_closeixSTATUS]);
3403 
3404   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3405        label, since we're gonna fall through to there anyway. */
3406 
3407   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
3408 		   ! ffeste_io_abort_is_temp_);
3409 
3410   /* If we've got a temp label, generate its code here. */
3411 
3412   if (ffeste_io_abort_is_temp_)
3413     {
3414       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3415       emit_nop ();
3416       expand_label (ffeste_io_abort_);
3417 
3418       assert (ffeste_io_err_ == NULL_TREE);
3419     }
3420 
3421   ffeste_end_stmt_ ();
3422 }
3423 
3424 /* READ(...) statement -- start.  */
3425 
3426 void
ffeste_R909_start(ffestpReadStmt * info,bool only_format UNUSED,ffestvUnit unit,ffestvFormat format,bool rec,bool key UNUSED)3427 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3428 		   ffestvUnit unit, ffestvFormat format, bool rec,
3429 		   bool key UNUSED)
3430 {
3431   ffecomGfrt start;
3432   ffecomGfrt end;
3433   tree cilist;
3434   bool iostat;
3435   bool errl;
3436   bool endl;
3437 
3438   ffeste_check_start_ ();
3439 
3440   ffeste_emit_line_note_ ();
3441 
3442   /* First determine the start, per-item, and end run-time functions to
3443      call.  The per-item function is picked by choosing an ffeste function
3444      to call to handle a given item; it knows how to generate a call to the
3445      appropriate run-time function, and is called an "I/O driver".  */
3446 
3447   switch (format)
3448     {
3449     case FFESTV_formatNONE:	/* no FMT= */
3450       ffeste_io_driver_ = ffeste_io_douio_;
3451       if (rec)
3452 	start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
3453       else
3454 	start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
3455       break;
3456 
3457     case FFESTV_formatLABEL:	/* FMT=10 */
3458     case FFESTV_formatCHAREXPR:	/* FMT='(I10)' */
3459     case FFESTV_formatINTEXPR:	/* FMT=I [after ASSIGN 10 TO I] */
3460       ffeste_io_driver_ = ffeste_io_dofio_;
3461       if (rec)
3462 	start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
3463       else if (unit == FFESTV_unitCHAREXPR)
3464 	start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
3465       else
3466 	start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
3467       break;
3468 
3469     case FFESTV_formatASTERISK:	/* FMT=* */
3470       ffeste_io_driver_ = ffeste_io_dolio_;
3471       if (unit == FFESTV_unitCHAREXPR)
3472 	start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
3473       else
3474 	start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
3475       break;
3476 
3477     case FFESTV_formatNAMELIST:	/* FMT=FOO or NML=FOO [NAMELIST
3478 				   /FOO/] */
3479       ffeste_io_driver_ = NULL;	/* No start or driver function. */
3480       start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
3481       break;
3482 
3483     default:
3484       assert ("Weird stuff" == NULL);
3485       start = FFECOM_gfrt, end = FFECOM_gfrt;
3486       break;
3487     }
3488   ffeste_io_endgfrt_ = end;
3489 
3490 #define specified(something) (info->read_spec[something].kw_or_val_present)
3491 
3492   iostat = specified (FFESTP_readixIOSTAT);
3493   errl = specified (FFESTP_readixERR);
3494   endl = specified (FFESTP_readixEND);
3495 
3496 #undef specified
3497 
3498   ffeste_start_stmt_ ();
3499 
3500   if (errl)
3501     {
3502       /* Have ERR= specification.   */
3503 
3504       ffeste_io_err_
3505 	= ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
3506 
3507       if (endl)
3508 	{
3509 	  /* Have both ERR= and END=.  Need a temp label to handle both.  */
3510 	  ffeste_io_end_
3511 	    = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3512 	  ffeste_io_abort_is_temp_ = TRUE;
3513 	  ffeste_io_abort_ = ffecom_temp_label ();
3514 	}
3515       else
3516 	{
3517 	  /* Have ERR= but no END=.  */
3518 	  ffeste_io_end_ = NULL_TREE;
3519 	  if ((ffeste_io_abort_is_temp_ = iostat))
3520 	    ffeste_io_abort_ = ffecom_temp_label ();
3521 	  else
3522 	    ffeste_io_abort_ = ffeste_io_err_;
3523 	}
3524     }
3525   else
3526     {
3527       /* No ERR= specification.  */
3528 
3529       ffeste_io_err_ = NULL_TREE;
3530       if (endl)
3531 	{
3532 	  /* Have END= but no ERR=.  */
3533 	  ffeste_io_end_
3534 	    = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3535 	  if ((ffeste_io_abort_is_temp_ = iostat))
3536 	    ffeste_io_abort_ = ffecom_temp_label ();
3537 	  else
3538 	    ffeste_io_abort_ = ffeste_io_end_;
3539 	}
3540       else
3541 	{
3542 	  /* Have no ERR= or END=.  */
3543 
3544 	  ffeste_io_end_ = NULL_TREE;
3545 	  if ((ffeste_io_abort_is_temp_ = iostat))
3546 	    ffeste_io_abort_ = ffecom_temp_label ();
3547 	  else
3548 	    ffeste_io_abort_ = NULL_TREE;
3549 	}
3550     }
3551 
3552   if (iostat)
3553     {
3554       /* Have IOSTAT= specification.  */
3555 
3556       ffeste_io_iostat_is_temp_ = FALSE;
3557       ffeste_io_iostat_
3558 	= ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
3559     }
3560   else if (ffeste_io_abort_ != NULL_TREE)
3561     {
3562       /* Have no IOSTAT= but have ERR= and/or END=.  */
3563 
3564       ffeste_io_iostat_is_temp_ = TRUE;
3565       ffeste_io_iostat_
3566 	= ffecom_make_tempvar ("read", ffecom_integer_type_node,
3567 			       FFETARGET_charactersizeNONE, -1);
3568     }
3569   else
3570     {
3571       /* No IOSTAT=, ERR=, or END= specification.  */
3572 
3573       ffeste_io_iostat_is_temp_ = FALSE;
3574       ffeste_io_iostat_ = NULL_TREE;
3575     }
3576 
3577   /* Now prescan, then convert, all the arguments.  */
3578 
3579   if (unit == FFESTV_unitCHAREXPR)
3580     cilist = ffeste_io_icilist_ (errl || iostat,
3581 				 info->read_spec[FFESTP_readixUNIT].u.expr,
3582 				 endl || iostat, format,
3583 				 &info->read_spec[FFESTP_readixFORMAT]);
3584   else
3585     cilist = ffeste_io_cilist_ (errl || iostat, unit,
3586 				info->read_spec[FFESTP_readixUNIT].u.expr,
3587 				5, endl || iostat, format,
3588 				&info->read_spec[FFESTP_readixFORMAT],
3589 				rec,
3590 				info->read_spec[FFESTP_readixREC].u.expr);
3591 
3592   /* If there is no end function, then there are no item functions (i.e.
3593      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3594      generate the "if (iostat != 0) goto label;" if the label is temp abort
3595      label, since we're gonna fall through to there anyway.  */
3596 
3597   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3598 		   (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3599 }
3600 
3601 /* READ statement -- I/O item.  */
3602 
3603 void
ffeste_R909_item(ffebld expr,ffelexToken expr_token)3604 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
3605 {
3606   ffeste_check_item_ ();
3607 
3608   if (expr == NULL)
3609     return;
3610 
3611   /* Strip parens off items such as in "READ *,(A)".  This is really a bug
3612      in the user's code, but I've been told lots of code does this.  */
3613   while (ffebld_op (expr) == FFEBLD_opPAREN)
3614     expr = ffebld_left (expr);
3615 
3616   if (ffebld_op (expr) == FFEBLD_opANY)
3617     return;
3618 
3619   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3620     ffeste_io_impdo_ (expr, expr_token);
3621   else
3622     {
3623       ffeste_start_stmt_ ();
3624 
3625       ffecom_prepare_arg_ptr_to_expr (expr);
3626 
3627       ffecom_prepare_end ();
3628 
3629       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3630 
3631       ffeste_end_stmt_ ();
3632     }
3633 }
3634 
3635 /* READ statement -- end.  */
3636 
3637 void
ffeste_R909_finish()3638 ffeste_R909_finish ()
3639 {
3640   ffeste_check_finish_ ();
3641 
3642   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3643      label, since we're gonna fall through to there anyway. */
3644 
3645   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3646     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3647 				       NULL_TREE),
3648 		     ! ffeste_io_abort_is_temp_);
3649 
3650   /* If we've got a temp label, generate its code here and have it fan out
3651      to the END= or ERR= label as appropriate. */
3652 
3653   if (ffeste_io_abort_is_temp_)
3654     {
3655       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3656       emit_nop ();
3657       expand_label (ffeste_io_abort_);
3658 
3659       /* "if (iostat<0) goto end_label;".  */
3660 
3661       if ((ffeste_io_end_ != NULL_TREE)
3662 	  && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
3663 	{
3664 	  expand_start_cond (ffecom_truth_value
3665 			     (ffecom_2 (LT_EXPR, integer_type_node,
3666 					ffeste_io_iostat_,
3667 					ffecom_integer_zero_node)),
3668 			     0);
3669 	  expand_goto (ffeste_io_end_);
3670 	  expand_end_cond ();
3671 	}
3672 
3673       /* "if (iostat>0) goto err_label;".  */
3674 
3675       if ((ffeste_io_err_ != NULL_TREE)
3676 	  && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
3677 	{
3678 	  expand_start_cond (ffecom_truth_value
3679 			     (ffecom_2 (GT_EXPR, integer_type_node,
3680 					ffeste_io_iostat_,
3681 					ffecom_integer_zero_node)),
3682 			     0);
3683 	  expand_goto (ffeste_io_err_);
3684 	  expand_end_cond ();
3685 	}
3686     }
3687 
3688   ffeste_end_stmt_ ();
3689 }
3690 
3691 /* WRITE statement -- start.  */
3692 
3693 void
ffeste_R910_start(ffestpWriteStmt * info,ffestvUnit unit,ffestvFormat format,bool rec)3694 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
3695 		   ffestvFormat format, bool rec)
3696 {
3697   ffecomGfrt start;
3698   ffecomGfrt end;
3699   tree cilist;
3700   bool iostat;
3701   bool errl;
3702 
3703   ffeste_check_start_ ();
3704 
3705   ffeste_emit_line_note_ ();
3706 
3707   /* First determine the start, per-item, and end run-time functions to
3708      call.  The per-item function is picked by choosing an ffeste function
3709      to call to handle a given item; it knows how to generate a call to the
3710      appropriate run-time function, and is called an "I/O driver".  */
3711 
3712   switch (format)
3713     {
3714     case FFESTV_formatNONE:	/* no FMT= */
3715       ffeste_io_driver_ = ffeste_io_douio_;
3716       if (rec)
3717 	start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
3718       else
3719 	start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
3720       break;
3721 
3722     case FFESTV_formatLABEL:	/* FMT=10 */
3723     case FFESTV_formatCHAREXPR:	/* FMT='(I10)' */
3724     case FFESTV_formatINTEXPR:	/* FMT=I [after ASSIGN 10 TO I] */
3725       ffeste_io_driver_ = ffeste_io_dofio_;
3726       if (rec)
3727 	start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
3728       else if (unit == FFESTV_unitCHAREXPR)
3729 	start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
3730       else
3731 	start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3732       break;
3733 
3734     case FFESTV_formatASTERISK:	/* FMT=* */
3735       ffeste_io_driver_ = ffeste_io_dolio_;
3736       if (unit == FFESTV_unitCHAREXPR)
3737 	start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
3738       else
3739 	start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3740       break;
3741 
3742     case FFESTV_formatNAMELIST:	/* FMT=FOO or NML=FOO [NAMELIST
3743 				   /FOO/] */
3744       ffeste_io_driver_ = NULL;	/* No start or driver function. */
3745       start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3746       break;
3747 
3748     default:
3749       assert ("Weird stuff" == NULL);
3750       start = FFECOM_gfrt, end = FFECOM_gfrt;
3751       break;
3752     }
3753   ffeste_io_endgfrt_ = end;
3754 
3755 #define specified(something) (info->write_spec[something].kw_or_val_present)
3756 
3757   iostat = specified (FFESTP_writeixIOSTAT);
3758   errl = specified (FFESTP_writeixERR);
3759 
3760 #undef specified
3761 
3762   ffeste_start_stmt_ ();
3763 
3764   ffeste_io_end_ = NULL_TREE;
3765 
3766   if (errl)
3767     {
3768       /* Have ERR= specification.   */
3769 
3770       ffeste_io_err_
3771 	= ffeste_io_abort_
3772 	= ffecom_lookup_label
3773 	(info->write_spec[FFESTP_writeixERR].u.label);
3774       ffeste_io_abort_is_temp_ = FALSE;
3775     }
3776   else
3777     {
3778       /* No ERR= specification.  */
3779 
3780       ffeste_io_err_ = NULL_TREE;
3781 
3782       if ((ffeste_io_abort_is_temp_ = iostat))
3783 	ffeste_io_abort_ = ffecom_temp_label ();
3784       else
3785 	ffeste_io_abort_ = NULL_TREE;
3786     }
3787 
3788   if (iostat)
3789     {
3790       /* Have IOSTAT= specification.  */
3791 
3792       ffeste_io_iostat_is_temp_ = FALSE;
3793       ffeste_io_iostat_ = ffecom_expr
3794 	(info->write_spec[FFESTP_writeixIOSTAT].u.expr);
3795     }
3796   else if (ffeste_io_abort_ != NULL_TREE)
3797     {
3798       /* Have no IOSTAT= but have ERR=.  */
3799 
3800       ffeste_io_iostat_is_temp_ = TRUE;
3801       ffeste_io_iostat_
3802 	= ffecom_make_tempvar ("write", ffecom_integer_type_node,
3803 			       FFETARGET_charactersizeNONE, -1);
3804     }
3805   else
3806     {
3807       /* No IOSTAT= or ERR= specification.  */
3808 
3809       ffeste_io_iostat_is_temp_ = FALSE;
3810       ffeste_io_iostat_ = NULL_TREE;
3811     }
3812 
3813   /* Now prescan, then convert, all the arguments.  */
3814 
3815   if (unit == FFESTV_unitCHAREXPR)
3816     cilist = ffeste_io_icilist_ (errl || iostat,
3817 				 info->write_spec[FFESTP_writeixUNIT].u.expr,
3818 				 FALSE, format,
3819 				 &info->write_spec[FFESTP_writeixFORMAT]);
3820   else
3821     cilist = ffeste_io_cilist_ (errl || iostat, unit,
3822 				info->write_spec[FFESTP_writeixUNIT].u.expr,
3823 				6, FALSE, format,
3824 				&info->write_spec[FFESTP_writeixFORMAT],
3825 				rec,
3826 				info->write_spec[FFESTP_writeixREC].u.expr);
3827 
3828   /* If there is no end function, then there are no item functions (i.e.
3829      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3830      generate the "if (iostat != 0) goto label;" if the label is temp abort
3831      label, since we're gonna fall through to there anyway.  */
3832 
3833   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3834 		   (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3835 }
3836 
3837 /* WRITE statement -- I/O item.  */
3838 
3839 void
ffeste_R910_item(ffebld expr,ffelexToken expr_token)3840 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
3841 {
3842   ffeste_check_item_ ();
3843 
3844   if (expr == NULL)
3845     return;
3846 
3847   if (ffebld_op (expr) == FFEBLD_opANY)
3848     return;
3849 
3850   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3851     ffeste_io_impdo_ (expr, expr_token);
3852   else
3853     {
3854       ffeste_start_stmt_ ();
3855 
3856       ffecom_prepare_arg_ptr_to_expr (expr);
3857 
3858       ffecom_prepare_end ();
3859 
3860       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3861 
3862       ffeste_end_stmt_ ();
3863     }
3864 }
3865 
3866 /* WRITE statement -- end.  */
3867 
3868 void
ffeste_R910_finish()3869 ffeste_R910_finish ()
3870 {
3871   ffeste_check_finish_ ();
3872 
3873   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3874      label, since we're gonna fall through to there anyway. */
3875 
3876   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3877     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3878 				       NULL_TREE),
3879 		     ! ffeste_io_abort_is_temp_);
3880 
3881   /* If we've got a temp label, generate its code here. */
3882 
3883   if (ffeste_io_abort_is_temp_)
3884     {
3885       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3886       emit_nop ();
3887       expand_label (ffeste_io_abort_);
3888 
3889       assert (ffeste_io_err_ == NULL_TREE);
3890     }
3891 
3892   ffeste_end_stmt_ ();
3893 }
3894 
3895 /* PRINT statement -- start.  */
3896 
3897 void
ffeste_R911_start(ffestpPrintStmt * info,ffestvFormat format)3898 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
3899 {
3900   ffecomGfrt start;
3901   ffecomGfrt end;
3902   tree cilist;
3903 
3904   ffeste_check_start_ ();
3905 
3906   ffeste_emit_line_note_ ();
3907 
3908   /* First determine the start, per-item, and end run-time functions to
3909      call.  The per-item function is picked by choosing an ffeste function
3910      to call to handle a given item; it knows how to generate a call to the
3911      appropriate run-time function, and is called an "I/O driver".  */
3912 
3913   switch (format)
3914     {
3915     case FFESTV_formatLABEL:	/* FMT=10 */
3916     case FFESTV_formatCHAREXPR:	/* FMT='(I10)' */
3917     case FFESTV_formatINTEXPR:	/* FMT=I [after ASSIGN 10 TO I] */
3918       ffeste_io_driver_ = ffeste_io_dofio_;
3919       start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3920       break;
3921 
3922     case FFESTV_formatASTERISK:	/* FMT=* */
3923       ffeste_io_driver_ = ffeste_io_dolio_;
3924       start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3925       break;
3926 
3927     case FFESTV_formatNAMELIST:	/* FMT=FOO or NML=FOO [NAMELIST
3928 				   /FOO/] */
3929       ffeste_io_driver_ = NULL;	/* No start or driver function. */
3930       start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3931       break;
3932 
3933     default:
3934       assert ("Weird stuff" == NULL);
3935       start = FFECOM_gfrt, end = FFECOM_gfrt;
3936       break;
3937     }
3938   ffeste_io_endgfrt_ = end;
3939 
3940   ffeste_start_stmt_ ();
3941 
3942   ffeste_io_end_ = NULL_TREE;
3943   ffeste_io_err_ = NULL_TREE;
3944   ffeste_io_abort_ = NULL_TREE;
3945   ffeste_io_abort_is_temp_ = FALSE;
3946   ffeste_io_iostat_is_temp_ = FALSE;
3947   ffeste_io_iostat_ = NULL_TREE;
3948 
3949   /* Now prescan, then convert, all the arguments.  */
3950 
3951   cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
3952 			      &info->print_spec[FFESTP_printixFORMAT],
3953 			      FALSE, NULL);
3954 
3955   /* If there is no end function, then there are no item functions (i.e.
3956      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3957      generate the "if (iostat != 0) goto label;" if the label is temp abort
3958      label, since we're gonna fall through to there anyway.  */
3959 
3960   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3961 		   (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3962 }
3963 
3964 /* PRINT statement -- I/O item.  */
3965 
3966 void
ffeste_R911_item(ffebld expr,ffelexToken expr_token)3967 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
3968 {
3969   ffeste_check_item_ ();
3970 
3971   if (expr == NULL)
3972     return;
3973 
3974   if (ffebld_op (expr) == FFEBLD_opANY)
3975     return;
3976 
3977   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3978     ffeste_io_impdo_ (expr, expr_token);
3979   else
3980     {
3981       ffeste_start_stmt_ ();
3982 
3983       ffecom_prepare_arg_ptr_to_expr (expr);
3984 
3985       ffecom_prepare_end ();
3986 
3987       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3988 
3989       ffeste_end_stmt_ ();
3990     }
3991 }
3992 
3993 /* PRINT statement -- end.  */
3994 
3995 void
ffeste_R911_finish()3996 ffeste_R911_finish ()
3997 {
3998   ffeste_check_finish_ ();
3999 
4000   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4001     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4002 				       NULL_TREE),
4003 		     FALSE);
4004 
4005   ffeste_end_stmt_ ();
4006 }
4007 
4008 /* BACKSPACE statement.  */
4009 
4010 void
ffeste_R919(ffestpBeruStmt * info)4011 ffeste_R919 (ffestpBeruStmt *info)
4012 {
4013   ffeste_check_simple_ ();
4014 
4015   ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4016 }
4017 
4018 /* ENDFILE statement.  */
4019 
4020 void
ffeste_R920(ffestpBeruStmt * info)4021 ffeste_R920 (ffestpBeruStmt *info)
4022 {
4023   ffeste_check_simple_ ();
4024 
4025   ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4026 }
4027 
4028 /* REWIND statement.  */
4029 
4030 void
ffeste_R921(ffestpBeruStmt * info)4031 ffeste_R921 (ffestpBeruStmt *info)
4032 {
4033   ffeste_check_simple_ ();
4034 
4035   ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4036 }
4037 
4038 /* INQUIRE statement (non-IOLENGTH version).  */
4039 
4040 void
ffeste_R923A(ffestpInquireStmt * info,bool by_file UNUSED)4041 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4042 {
4043   tree args;
4044   bool iostat;
4045   bool errl;
4046 
4047   ffeste_check_simple_ ();
4048 
4049   ffeste_emit_line_note_ ();
4050 
4051 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4052 
4053   iostat = specified (FFESTP_inquireixIOSTAT);
4054   errl = specified (FFESTP_inquireixERR);
4055 
4056 #undef specified
4057 
4058   ffeste_start_stmt_ ();
4059 
4060   if (errl)
4061     {
4062       ffeste_io_err_
4063 	= ffeste_io_abort_
4064 	= ffecom_lookup_label
4065 	(info->inquire_spec[FFESTP_inquireixERR].u.label);
4066       ffeste_io_abort_is_temp_ = FALSE;
4067     }
4068   else
4069     {
4070       ffeste_io_err_ = NULL_TREE;
4071 
4072       if ((ffeste_io_abort_is_temp_ = iostat))
4073 	ffeste_io_abort_ = ffecom_temp_label ();
4074       else
4075 	ffeste_io_abort_ = NULL_TREE;
4076     }
4077 
4078   if (iostat)
4079     {
4080       /* Have IOSTAT= specification.  */
4081 
4082       ffeste_io_iostat_is_temp_ = FALSE;
4083       ffeste_io_iostat_ = ffecom_expr
4084 	(info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4085     }
4086   else if (ffeste_io_abort_ != NULL_TREE)
4087     {
4088       /* Have no IOSTAT= but have ERR=.  */
4089 
4090       ffeste_io_iostat_is_temp_ = TRUE;
4091       ffeste_io_iostat_
4092 	= ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
4093 			       FFETARGET_charactersizeNONE, -1);
4094     }
4095   else
4096     {
4097       /* No IOSTAT= or ERR= specification.  */
4098 
4099       ffeste_io_iostat_is_temp_ = FALSE;
4100       ffeste_io_iostat_ = NULL_TREE;
4101     }
4102 
4103   /* Now prescan, then convert, all the arguments.  */
4104 
4105   args
4106     = ffeste_io_inlist_ (errl || iostat,
4107 			 &info->inquire_spec[FFESTP_inquireixUNIT],
4108 			 &info->inquire_spec[FFESTP_inquireixFILE],
4109 			 &info->inquire_spec[FFESTP_inquireixEXIST],
4110 			 &info->inquire_spec[FFESTP_inquireixOPENED],
4111 			 &info->inquire_spec[FFESTP_inquireixNUMBER],
4112 			 &info->inquire_spec[FFESTP_inquireixNAMED],
4113 			 &info->inquire_spec[FFESTP_inquireixNAME],
4114 			 &info->inquire_spec[FFESTP_inquireixACCESS],
4115 			 &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4116 			 &info->inquire_spec[FFESTP_inquireixDIRECT],
4117 			 &info->inquire_spec[FFESTP_inquireixFORM],
4118 			 &info->inquire_spec[FFESTP_inquireixFORMATTED],
4119 			 &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4120 			 &info->inquire_spec[FFESTP_inquireixRECL],
4121 			 &info->inquire_spec[FFESTP_inquireixNEXTREC],
4122 			 &info->inquire_spec[FFESTP_inquireixBLANK]);
4123 
4124   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4125      label, since we're gonna fall through to there anyway. */
4126 
4127   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
4128 		   ! ffeste_io_abort_is_temp_);
4129 
4130   /* If we've got a temp label, generate its code here.  */
4131 
4132   if (ffeste_io_abort_is_temp_)
4133     {
4134       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4135       emit_nop ();
4136       expand_label (ffeste_io_abort_);
4137 
4138       assert (ffeste_io_err_ == NULL_TREE);
4139     }
4140 
4141   ffeste_end_stmt_ ();
4142 }
4143 
4144 /* INQUIRE(IOLENGTH=expr) statement -- start.  */
4145 
4146 void
ffeste_R923B_start(ffestpInquireStmt * info UNUSED)4147 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4148 {
4149   ffeste_check_start_ ();
4150 
4151   assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4152 
4153   ffeste_emit_line_note_ ();
4154 }
4155 
4156 /* INQUIRE(IOLENGTH=expr) statement -- I/O item.  */
4157 
4158 void
ffeste_R923B_item(ffebld expr UNUSED)4159 ffeste_R923B_item (ffebld expr UNUSED)
4160 {
4161   ffeste_check_item_ ();
4162 }
4163 
4164 /* INQUIRE(IOLENGTH=expr) statement -- end.  */
4165 
4166 void
ffeste_R923B_finish()4167 ffeste_R923B_finish ()
4168 {
4169   ffeste_check_finish_ ();
4170 }
4171 
4172 /* ffeste_R1001 -- FORMAT statement
4173 
4174    ffeste_R1001(format_list);  */
4175 
4176 void
ffeste_R1001(ffests s)4177 ffeste_R1001 (ffests s)
4178 {
4179   tree t;
4180   tree ttype;
4181   tree maxindex;
4182   tree var;
4183 
4184   ffeste_check_simple_ ();
4185 
4186   assert (ffeste_label_formatdef_ != NULL);
4187 
4188   ffeste_emit_line_note_ ();
4189 
4190   t = build_string (ffests_length (s), ffests_text (s));
4191 
4192   TREE_TYPE (t)
4193     = build_type_variant (build_array_type
4194 			  (char_type_node,
4195 			   build_range_type (integer_type_node,
4196 					     integer_one_node,
4197 					     build_int_2 (ffests_length (s),
4198 							  0))),
4199 			  1, 0);
4200   TREE_CONSTANT (t) = 1;
4201   TREE_STATIC (t) = 1;
4202 
4203   var = ffecom_lookup_label (ffeste_label_formatdef_);
4204   if ((var != NULL_TREE)
4205       && (TREE_CODE (var) == VAR_DECL))
4206     {
4207       DECL_INITIAL (var) = t;
4208       maxindex = build_int_2 (ffests_length (s) - 1, 0);
4209       ttype = TREE_TYPE (var);
4210       TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
4211 					      integer_zero_node,
4212 					      maxindex);
4213       if (!TREE_TYPE (maxindex))
4214 	TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
4215       layout_type (ttype);
4216       rest_of_decl_compilation (var, NULL, 1, 0);
4217       expand_decl (var);
4218       expand_decl_init (var);
4219     }
4220 
4221   ffeste_label_formatdef_ = NULL;
4222 }
4223 
4224 /* END PROGRAM.  */
4225 
4226 void
ffeste_R1103()4227 ffeste_R1103 ()
4228 {
4229 }
4230 
4231 /* END BLOCK DATA.  */
4232 
4233 void
ffeste_R1112()4234 ffeste_R1112 ()
4235 {
4236 }
4237 
4238 /* CALL statement.  */
4239 
4240 void
ffeste_R1212(ffebld expr)4241 ffeste_R1212 (ffebld expr)
4242 {
4243   ffebld args;
4244   ffebld arg;
4245   ffebld labels = NULL;	/* First in list of LABTERs. */
4246   ffebld prevlabels = NULL;
4247   ffebld prevargs = NULL;
4248 
4249   ffeste_check_simple_ ();
4250 
4251   args = ffebld_right (expr);
4252 
4253   ffeste_emit_line_note_ ();
4254 
4255   /* Here we split the list at ffebld_right(expr) into two lists: one at
4256      ffebld_right(expr) consisting of all items that are not LABTERs, the
4257      other at labels consisting of all items that are LABTERs.  Then, if
4258      the latter list is NULL, we have an ordinary call, else we have a call
4259      with alternate returns. */
4260 
4261   for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
4262     {
4263       if (((arg = ffebld_head (args)) == NULL)
4264 	  || (ffebld_op (arg) != FFEBLD_opLABTER))
4265 	{
4266 	  if (prevargs == NULL)
4267 	    {
4268 	      prevargs = args;
4269 	      ffebld_set_right (expr, args);
4270 	    }
4271 	  else
4272 	    {
4273 	      ffebld_set_trail (prevargs, args);
4274 	      prevargs = args;
4275 	    }
4276 	}
4277       else
4278 	{
4279 	  if (prevlabels == NULL)
4280 	    {
4281 	      prevlabels = labels = args;
4282 	    }
4283 	  else
4284 	    {
4285 	      ffebld_set_trail (prevlabels, args);
4286 	      prevlabels = args;
4287 	    }
4288 	}
4289     }
4290   if (prevlabels == NULL)
4291     labels = NULL;
4292   else
4293     ffebld_set_trail (prevlabels, NULL);
4294   if (prevargs == NULL)
4295     ffebld_set_right (expr, NULL);
4296   else
4297     ffebld_set_trail (prevargs, NULL);
4298 
4299   ffeste_start_stmt_ ();
4300 
4301   /* No temporaries are actually needed at this level, but we go
4302      through the motions anyway, just to be sure in case they do
4303      get made.  Temporaries needed for arguments should be in the
4304      scopes of inner blocks, and if clean-up actions are supported,
4305      such as CALL-ing an intrinsic that writes to an argument of one
4306      type when a variable of a different type is provided (requiring
4307      assignment to the variable from a temporary after the library
4308      routine returns), the clean-up must be done by the expression
4309      evaluator, generally, to handle alternate returns (which we hope
4310      won't ever be supported by intrinsics, but might be a similar
4311      issue, such as CALL-ing an F90-style subroutine with an INTERFACE
4312      block).  That implies the expression evaluator will have to
4313      recognize the need for its own temporary anyway, meaning it'll
4314      construct a block within the one constructed here.  */
4315 
4316   ffecom_prepare_expr (expr);
4317 
4318   ffecom_prepare_end ();
4319 
4320   if (labels == NULL)
4321     expand_expr_stmt (ffecom_expr (expr));
4322   else
4323     {
4324       tree texpr;
4325       tree value;
4326       tree tlabel;
4327       int caseno;
4328       int pushok;
4329       tree duplicate;
4330       ffebld label;
4331 
4332       texpr = ffecom_expr (expr);
4333       expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
4334 
4335       for (caseno = 1, label = labels;
4336 	   label != NULL;
4337 	   ++caseno, label = ffebld_trail (label))
4338 	{
4339 	  value = build_int_2 (caseno, 0);
4340 	  tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
4341 
4342 	  pushok = pushcase (value, convert, tlabel, &duplicate);
4343 	  assert (pushok == 0);
4344 
4345 	  tlabel
4346 	    = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
4347 	  if ((tlabel == NULL_TREE)
4348 	      || (TREE_CODE (tlabel) == ERROR_MARK))
4349 	    continue;
4350 	  TREE_USED (tlabel) = 1;
4351 	  expand_goto (tlabel);
4352 	}
4353 
4354       expand_end_case (texpr);
4355     }
4356 
4357   ffeste_end_stmt_ ();
4358 }
4359 
4360 /* END FUNCTION.  */
4361 
4362 void
ffeste_R1221()4363 ffeste_R1221 ()
4364 {
4365 }
4366 
4367 /* END SUBROUTINE.  */
4368 
4369 void
ffeste_R1225()4370 ffeste_R1225 ()
4371 {
4372 }
4373 
4374 /* ENTRY statement.  */
4375 
4376 void
ffeste_R1226(ffesymbol entry)4377 ffeste_R1226 (ffesymbol entry)
4378 {
4379   tree label;
4380 
4381   ffeste_check_simple_ ();
4382 
4383   label = ffesymbol_hook (entry).length_tree;
4384 
4385   ffeste_emit_line_note_ ();
4386 
4387   if (label == error_mark_node)
4388     return;
4389 
4390   DECL_INITIAL (label) = error_mark_node;
4391   emit_nop ();
4392   expand_label (label);
4393 }
4394 
4395 /* RETURN statement.  */
4396 
4397 void
ffeste_R1227(ffestw block UNUSED,ffebld expr)4398 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
4399 {
4400   tree rtn;
4401 
4402   ffeste_check_simple_ ();
4403 
4404   ffeste_emit_line_note_ ();
4405 
4406   ffeste_start_stmt_ ();
4407 
4408   ffecom_prepare_return_expr (expr);
4409 
4410   ffecom_prepare_end ();
4411 
4412   rtn = ffecom_return_expr (expr);
4413 
4414   if ((rtn == NULL_TREE)
4415       || (rtn == error_mark_node))
4416     expand_null_return ();
4417   else
4418     {
4419       tree result = DECL_RESULT (current_function_decl);
4420 
4421       if ((result != error_mark_node)
4422 	  && (TREE_TYPE (result) != error_mark_node))
4423 	expand_return (ffecom_modify (NULL_TREE,
4424 				      result,
4425 				      convert (TREE_TYPE (result),
4426 					       rtn)));
4427       else
4428 	expand_null_return ();
4429     }
4430 
4431   ffeste_end_stmt_ ();
4432 }
4433 
4434 /* REWRITE statement -- start.  */
4435 
4436 #if FFESTR_VXT
4437 void
ffeste_V018_start(ffestpRewriteStmt * info,ffestvFormat format)4438 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
4439 {
4440   ffeste_check_start_ ();
4441 }
4442 
4443 /* REWRITE statement -- I/O item.  */
4444 
4445 void
ffeste_V018_item(ffebld expr)4446 ffeste_V018_item (ffebld expr)
4447 {
4448   ffeste_check_item_ ();
4449 }
4450 
4451 /* REWRITE statement -- end.  */
4452 
4453 void
ffeste_V018_finish()4454 ffeste_V018_finish ()
4455 {
4456   ffeste_check_finish_ ();
4457 }
4458 
4459 /* ACCEPT statement -- start.  */
4460 
4461 void
ffeste_V019_start(ffestpAcceptStmt * info,ffestvFormat format)4462 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
4463 {
4464   ffeste_check_start_ ();
4465 }
4466 
4467 /* ACCEPT statement -- I/O item.  */
4468 
4469 void
ffeste_V019_item(ffebld expr)4470 ffeste_V019_item (ffebld expr)
4471 {
4472   ffeste_check_item_ ();
4473 }
4474 
4475 /* ACCEPT statement -- end.  */
4476 
4477 void
ffeste_V019_finish()4478 ffeste_V019_finish ()
4479 {
4480   ffeste_check_finish_ ();
4481 }
4482 
4483 #endif
4484 /* TYPE statement -- start.  */
4485 
4486 void
ffeste_V020_start(ffestpTypeStmt * info UNUSED,ffestvFormat format UNUSED)4487 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
4488 		   ffestvFormat format UNUSED)
4489 {
4490   ffeste_check_start_ ();
4491 }
4492 
4493 /* TYPE statement -- I/O item.  */
4494 
4495 void
ffeste_V020_item(ffebld expr UNUSED)4496 ffeste_V020_item (ffebld expr UNUSED)
4497 {
4498   ffeste_check_item_ ();
4499 }
4500 
4501 /* TYPE statement -- end.  */
4502 
4503 void
ffeste_V020_finish()4504 ffeste_V020_finish ()
4505 {
4506   ffeste_check_finish_ ();
4507 }
4508 
4509 /* DELETE statement.  */
4510 
4511 #if FFESTR_VXT
4512 void
ffeste_V021(ffestpDeleteStmt * info)4513 ffeste_V021 (ffestpDeleteStmt *info)
4514 {
4515   ffeste_check_simple_ ();
4516 }
4517 
4518 /* UNLOCK statement.  */
4519 
4520 void
ffeste_V022(ffestpBeruStmt * info)4521 ffeste_V022 (ffestpBeruStmt *info)
4522 {
4523   ffeste_check_simple_ ();
4524 }
4525 
4526 /* ENCODE statement -- start.  */
4527 
4528 void
ffeste_V023_start(ffestpVxtcodeStmt * info)4529 ffeste_V023_start (ffestpVxtcodeStmt *info)
4530 {
4531   ffeste_check_start_ ();
4532 }
4533 
4534 /* ENCODE statement -- I/O item.  */
4535 
4536 void
ffeste_V023_item(ffebld expr)4537 ffeste_V023_item (ffebld expr)
4538 {
4539   ffeste_check_item_ ();
4540 }
4541 
4542 /* ENCODE statement -- end.  */
4543 
4544 void
ffeste_V023_finish()4545 ffeste_V023_finish ()
4546 {
4547   ffeste_check_finish_ ();
4548 }
4549 
4550 /* DECODE statement -- start.  */
4551 
4552 void
ffeste_V024_start(ffestpVxtcodeStmt * info)4553 ffeste_V024_start (ffestpVxtcodeStmt *info)
4554 {
4555   ffeste_check_start_ ();
4556 }
4557 
4558 /* DECODE statement -- I/O item.  */
4559 
4560 void
ffeste_V024_item(ffebld expr)4561 ffeste_V024_item (ffebld expr)
4562 {
4563   ffeste_check_item_ ();
4564 }
4565 
4566 /* DECODE statement -- end.  */
4567 
4568 void
ffeste_V024_finish()4569 ffeste_V024_finish ()
4570 {
4571   ffeste_check_finish_ ();
4572 }
4573 
4574 /* DEFINEFILE statement -- start.  */
4575 
4576 void
ffeste_V025_start()4577 ffeste_V025_start ()
4578 {
4579   ffeste_check_start_ ();
4580 }
4581 
4582 /* DEFINE FILE statement -- item.  */
4583 
4584 void
ffeste_V025_item(ffebld u,ffebld m,ffebld n,ffebld asv)4585 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
4586 {
4587   ffeste_check_item_ ();
4588 }
4589 
4590 /* DEFINE FILE statement -- end.  */
4591 
4592 void
ffeste_V025_finish()4593 ffeste_V025_finish ()
4594 {
4595   ffeste_check_finish_ ();
4596 }
4597 
4598 /* FIND statement.  */
4599 
4600 void
ffeste_V026(ffestpFindStmt * info)4601 ffeste_V026 (ffestpFindStmt *info)
4602 {
4603   ffeste_check_simple_ ();
4604 }
4605 
4606 #endif
4607 
4608 #ifdef ENABLE_CHECKING
4609 void
ffeste_terminate_2(void)4610 ffeste_terminate_2 (void)
4611 {
4612   assert (! ffeste_top_block_);
4613 }
4614 #endif
4615 
4616 #include "gt-f-ste.h"
4617