i386-protos.h (x86_emit_floatuns): Declare.
[official-gcc.git] / gcc / f / ste.c
bloba620acd1f15d22dd313f48da8790c3c158f8236f
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.
5 This file is part of GNU Fortran.
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.
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.
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.
22 Related Modules:
23 ste.c
25 Description:
26 Implements the various statements and such like.
28 Modifications:
31 /* Include files. */
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"
52 /* Externals defined here. */
55 /* Simple definitions and enumerations. */
57 typedef enum
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_;
66 /* Internal typedefs. */
69 /* Private include files. */
72 /* Internal structure definitions. */
75 /* Static objects accessed by functions in this module. */
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. */
88 /* Static functions (internal). */
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);
141 /* Internal macros. */
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_
170 #define ffeste_f2c_init_charnolen_(Exp,Init,Spec) \
171 do \
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 \
181 Init = null_pointer_node; \
182 constantp = FALSE; \
184 } while(0)
186 #define ffeste_f2c_init_char_(Exp,Init,Lenexp,Leninit,Spec) \
187 do \
189 if ((Spec)->kw_or_val_present) \
190 Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &Lenexp); \
191 else \
193 Exp = null_pointer_node; \
194 Lenexp = ffecom_f2c_ftnlen_zero_node; \
196 if (Exp) \
197 Init = Exp; \
198 else \
200 Init = null_pointer_node; \
201 constantp = FALSE; \
203 if (Lenexp) \
204 Leninit = Lenexp; \
205 else \
207 Leninit = ffecom_f2c_ftnlen_zero_node; \
208 constantp = FALSE; \
210 } while(0)
212 #define ffeste_f2c_init_flag_(Flag,Init) \
213 do \
215 Init = convert (ffecom_f2c_flag_type_node, \
216 (Flag) ? integer_one_node : integer_zero_node); \
217 } while(0)
219 #define ffeste_f2c_init_format_(Exp,Init,Spec) \
220 do \
222 Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, NULL); \
223 if (Exp) \
224 Init = Exp; \
225 else \
227 Init = null_pointer_node; \
228 constantp = FALSE; \
230 } while(0)
232 #define ffeste_f2c_init_int_(Exp,Init,Spec) \
233 do \
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 \
243 Init = ffecom_integer_zero_node; \
244 constantp = FALSE; \
246 } while(0)
248 #define ffeste_f2c_init_ptrtoint_(Exp,Init,Spec) \
249 do \
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 \
259 Init = null_pointer_node; \
260 constantp = FALSE; \
262 } while(0)
264 #define ffeste_f2c_init_next_(Init) \
265 do \
267 TREE_CHAIN (initn) = build_tree_list ((field = TREE_CHAIN (field)), \
268 (Init)); \
269 initn = TREE_CHAIN(initn); \
270 } while(0)
272 #define ffeste_f2c_prepare_charnolen_(Spec,Exp) \
273 do \
275 if (! (Exp)) \
276 ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
277 } while(0)
279 #define ffeste_f2c_prepare_char_(Spec,Exp) \
280 do \
282 if (! (Exp)) \
283 ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
284 } while(0)
286 #define ffeste_f2c_prepare_format_(Spec,Exp) \
287 do \
289 if (! (Exp)) \
290 ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
291 } while(0)
293 #define ffeste_f2c_prepare_int_(Spec,Exp) \
294 do \
296 if (! (Exp)) \
297 ffecom_prepare_expr ((Spec)->u.expr); \
298 } while(0)
300 #define ffeste_f2c_prepare_ptrtoint_(Spec,Exp) \
301 do \
303 if (! (Exp)) \
304 ffecom_prepare_ptr_to_expr ((Spec)->u.expr); \
305 } while(0)
307 #define ffeste_f2c_compile_(Field,Exp) \
308 do \
310 tree exz; \
311 if ((Exp)) \
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); \
319 } while(0)
321 #define ffeste_f2c_compile_charnolen_(Field,Spec,Exp) \
322 do \
324 tree exq; \
325 if (! (Exp)) \
327 exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &ignore); \
328 ffeste_f2c_compile_ ((Field), exq); \
330 } while(0)
332 #define ffeste_f2c_compile_char_(Field,Lenfield,Spec,Exp,Lenexp) \
333 do \
335 tree exq = (Exp); \
336 tree lenexq = (Lenexp); \
337 int need_exq = (! exq); \
338 int need_lenexq = (! lenexq); \
339 if (need_exq || need_lenexq) \
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); \
347 } while(0)
349 #define ffeste_f2c_compile_format_(Field,Spec,Exp) \
350 do \
352 tree exq; \
353 if (! (Exp)) \
355 exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, NULL); \
356 ffeste_f2c_compile_ ((Field), exq); \
358 } while(0)
360 #define ffeste_f2c_compile_int_(Field,Spec,Exp) \
361 do \
363 tree exq; \
364 if (! (Exp)) \
366 exq = ffecom_expr ((Spec)->u.expr); \
367 ffeste_f2c_compile_ ((Field), exq); \
369 } while(0)
371 #define ffeste_f2c_compile_ptrtoint_(Field,Spec,Exp) \
372 do \
374 tree exq; \
375 if (! (Exp)) \
377 exq = ffecom_ptr_to_expr ((Spec)->u.expr); \
378 ffeste_f2c_compile_ ((Field), exq); \
380 } while(0)
382 /* Start a Fortran block. */
384 #ifdef ENABLE_CHECKING
386 typedef struct gbe_block
388 struct gbe_block *outer;
389 ffestw block;
390 int lineno;
391 const char *input_filename;
392 bool is_stmt;
393 } *gbe_block;
395 gbe_block ffeste_top_block_ = NULL;
397 static void
398 ffeste_start_block_ (ffestw block)
400 gbe_block b = xmalloc (sizeof (*b));
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;
408 ffeste_top_block_ = b;
410 ffecom_start_compstmt ();
413 /* End a Fortran block. */
415 static void
416 ffeste_end_block_ (ffestw block)
418 gbe_block b = ffeste_top_block_;
420 assert (b);
421 assert (! b->is_stmt);
422 assert (b->block == block);
423 assert (! b->is_stmt);
425 ffeste_top_block_ = b->outer;
427 free (b);
429 ffecom_end_compstmt ();
432 /* Start a Fortran statement.
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. */
439 static void
440 ffeste_start_stmt_(void)
442 gbe_block b = xmalloc (sizeof (*b));
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;
450 ffeste_top_block_ = b;
452 ffecom_start_compstmt ();
455 /* End a Fortran statement. */
457 static void
458 ffeste_end_stmt_(void)
460 gbe_block b = ffeste_top_block_;
462 assert (b);
463 assert (b->is_stmt);
465 ffeste_top_block_ = b->outer;
467 free (b);
469 ffecom_end_compstmt ();
472 #else /* ! defined (ENABLE_CHECKING) */
474 #define ffeste_start_block_(b) ffecom_start_compstmt ()
475 #define ffeste_end_block_(b) \
476 do \
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)
483 #endif /* ! defined (ENABLE_CHECKING) */
485 /* Begin an iterative DO loop. Pass the block to start if
486 applicable. */
488 static void
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)
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;
505 /* Want to have tvar, tincr, and niters for the whole loop body. */
507 if (block)
508 ffeste_start_block_ (block);
509 else
510 ffeste_start_stmt_ ();
512 niters = ffecom_make_tempvar (block ? "do" : "impdo",
513 ffecom_integer_type_node,
514 FFETARGET_charactersizeNONE, -1);
516 ffecom_prepare_expr (incr);
517 ffecom_prepare_expr_rw (NULL_TREE, var);
519 ffecom_prepare_end ();
521 tvar = ffecom_expr_rw (NULL_TREE, var);
522 tincr = ffecom_expr (incr);
524 if (TREE_CODE (tvar) == ERROR_MARK
525 || TREE_CODE (tincr) == ERROR_MARK)
527 if (block)
529 ffeste_end_block_ (block);
530 ffestw_set_do_tvar (block, error_mark_node);
532 else
534 ffeste_end_stmt_ ();
535 *xtvar = error_mark_node;
537 return;
540 /* Check whether incr is known to be zero, complain and fix. */
542 if (integer_zerop (tincr) || real_zerop (tincr))
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);
552 tincr_saved = ffecom_save_tree (tincr);
554 /* Want to have tstart, tend for just this statement. */
556 ffeste_start_stmt_ ();
558 ffecom_prepare_expr (start);
559 ffecom_prepare_expr (end);
561 ffecom_prepare_end ();
563 tstart = ffecom_expr (start);
564 tend = ffecom_expr (end);
566 if (TREE_CODE (tstart) == ERROR_MARK
567 || TREE_CODE (tend) == ERROR_MARK)
569 ffeste_end_stmt_ ();
571 if (block)
573 ffeste_end_block_ (block);
574 ffestw_set_do_tvar (block, error_mark_node);
576 else
578 ffeste_end_stmt_ ();
579 *xtvar = error_mark_node;
581 return;
584 /* For warnings only, nothing else happens here. */
586 tree try;
588 if (! ffe_is_onetrip ())
590 try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
591 tend,
592 tstart);
594 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
595 try,
596 tincr);
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));
607 /* Warn if loop never executed, since we've done the evaluation
608 of the unofficial iteration count already. */
610 try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
611 try,
612 convert (TREE_TYPE (tvar),
613 integer_zero_node)));
615 if (integer_onep (try))
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 ();
625 /* Warn if end plus incr would overflow. */
627 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
628 tend,
629 tincr);
631 if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
632 && TREE_CONSTANT_OVERFLOW (try))
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 ();
642 /* Do the initial assignment into the DO var. */
644 tstart = ffecom_save_tree (tstart);
646 expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
647 tend,
648 tstart);
650 if (! ffe_is_onetrip ())
652 expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
653 expr,
654 convert (TREE_TYPE (expr), tincr_saved));
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);
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
682 assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
683 == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
685 expr = ffecom_modify (void_type_node, niters, expr);
686 expand_expr_stmt (expr);
688 expr = ffecom_modify (void_type_node, tvar, tstart);
689 expand_expr_stmt (expr);
691 ffeste_end_stmt_ ();
693 expanded_loop = expand_start_loop_continue_elsewhere (!! block);
694 if (block)
695 ffestw_set_do_hook (block, expanded_loop);
697 if (! ffe_is_onetrip ())
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)));
709 expand_exit_loop_top_cond (0, expr);
712 if (block)
714 ffestw_set_do_tvar (block, tvar);
715 ffestw_set_do_incr_saved (block, tincr_saved);
716 ffestw_set_do_count_var (block, niters);
718 else
720 *xtvar = tvar;
721 *xtincr = tincr_saved;
722 *xitersvar = niters;
726 /* End an iterative DO loop. Pass the same iteration variable and increment
727 value trees that were generated in the paired _begin_ call. */
729 static void
730 ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
732 tree expr;
733 tree niters = itersvar;
735 if (tvar == error_mark_node)
736 return;
738 expand_loop_continue_here ();
740 ffeste_start_stmt_ ();
742 if (ffe_is_onetrip ())
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)));
754 expand_exit_loop_if_false (0, expr);
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);
763 /* Lose the stuff we just built. */
764 ffeste_end_stmt_ ();
766 expand_end_loop ();
768 /* Lose the tvar and incr_saved trees. */
769 if (block)
770 ffeste_end_block_ (block);
771 else
772 ffeste_end_stmt_ ();
775 /* Generate call to run-time I/O routine. */
777 static void
778 ffeste_io_call_ (tree call, bool do_check)
780 /* Generate the call and optional assignment into iostat var. */
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);
788 if (! do_check
789 || ffeste_io_abort_ == NULL_TREE
790 || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
791 return;
793 /* Generate optional test. */
795 expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
796 expand_goto (ffeste_io_abort_);
797 expand_end_cond ();
800 /* Handle implied-DO in I/O list.
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. */
806 static void
807 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
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;
821 if (incr == NULL)
823 incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
824 ffebld_set_info (incr, ffeinfo_new
825 (FFEINFO_basictypeINTEGER,
826 FFEINFO_kindtypeINTEGERDEFAULT,
828 FFEINFO_kindENTITY,
829 FFEINFO_whereCONSTANT,
830 FFETARGET_charactersizeNONE));
833 /* Start the DO loop. */
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);
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");
848 /* Handle the list of items. */
850 for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
852 item = ffebld_head (list);
853 if (item == NULL)
854 continue;
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);
861 if (ffebld_op (item) == FFEBLD_opANY)
862 continue;
864 if (ffebld_op (item) == FFEBLD_opIMPDO)
865 ffeste_io_impdo_ (item, impdo_token);
866 else
868 ffeste_start_stmt_ ();
870 ffecom_prepare_arg_ptr_to_expr (item);
872 ffecom_prepare_end ();
874 ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
876 ffeste_end_stmt_ ();
880 /* Generate end of implied-do construct. */
882 ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
885 /* I/O driver for formatted I/O item (do_fio)
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. */
894 static tree
895 ffeste_io_dofio_ (ffebld expr)
897 tree num_elements;
898 tree variable;
899 tree size;
900 tree arglist;
901 ffeinfoBasictype bt;
902 ffeinfoKindtype kt;
903 bool is_complex;
905 bt = ffeinfo_basictype (ffebld_info (expr));
906 kt = ffeinfo_kindtype (ffebld_info (expr));
908 if ((bt == FFEINFO_basictypeANY)
909 || (kt == FFEINFO_kindtypeANY))
910 return error_mark_node;
912 if (bt == FFEINFO_basictypeCOMPLEX)
914 is_complex = TRUE;
915 bt = FFEINFO_basictypeREAL;
917 else
918 is_complex = FALSE;
920 variable = ffecom_arg_ptr_to_expr (expr, &size);
922 if ((variable == error_mark_node)
923 || (size == error_mark_node))
924 return error_mark_node;
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);
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
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);
959 num_elements
960 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
961 num_elements);
963 variable = convert (string_type_node, variable);
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);
969 return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
972 /* I/O driver for list-directed I/O item (do_lio)
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. */
981 static tree
982 ffeste_io_dolio_ (ffebld expr)
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;
993 bt = ffeinfo_basictype (ffebld_info (expr));
994 kt = ffeinfo_kindtype (ffebld_info (expr));
996 if ((bt == FFEINFO_basictypeANY)
997 || (kt == FFEINFO_kindtypeANY))
998 return error_mark_node;
1000 tc = ffecom_f2c_typecode (bt, kt);
1001 assert (tc != -1);
1002 type_id = build_int_2 (tc, 0);
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));
1009 variable = ffecom_arg_ptr_to_expr (expr, &size);
1011 if ((type_id == error_mark_node)
1012 || (variable == error_mark_node)
1013 || (size == error_mark_node))
1014 return error_mark_node;
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);
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
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);
1048 num_elements
1049 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1050 num_elements);
1052 variable = convert (string_type_node, variable);
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);
1060 return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
1063 /* I/O driver for unformatted I/O item (do_uio)
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. */
1072 static tree
1073 ffeste_io_douio_ (ffebld expr)
1075 tree num_elements;
1076 tree variable;
1077 tree size;
1078 tree arglist;
1079 ffeinfoBasictype bt;
1080 ffeinfoKindtype kt;
1081 bool is_complex;
1083 bt = ffeinfo_basictype (ffebld_info (expr));
1084 kt = ffeinfo_kindtype (ffebld_info (expr));
1086 if ((bt == FFEINFO_basictypeANY)
1087 || (kt == FFEINFO_kindtypeANY))
1088 return error_mark_node;
1090 if (bt == FFEINFO_basictypeCOMPLEX)
1092 is_complex = TRUE;
1093 bt = FFEINFO_basictypeREAL;
1095 else
1096 is_complex = FALSE;
1098 variable = ffecom_arg_ptr_to_expr (expr, &size);
1100 if ((variable == error_mark_node)
1101 || (size == error_mark_node))
1102 return error_mark_node;
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);
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
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);
1137 num_elements
1138 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1139 num_elements);
1141 variable = convert (string_type_node, variable);
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);
1147 return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
1150 /* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
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.
1157 Must ensure that all expressions are prepared before being evaluated,
1158 for any whose evaluation might result in the generation of temporaries.
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. */
1165 static GTY(()) tree f2c_alist_struct;
1166 static tree
1167 ffeste_io_ialist_ (bool have_err,
1168 ffestvUnit unit,
1169 ffebld unit_expr,
1170 int unit_dflt)
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;
1182 if (f2c_alist_struct == NULL_TREE)
1184 tree ref;
1186 ref = make_node (RECORD_TYPE);
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);
1193 TYPE_FIELDS (ref) = errfield;
1194 layout_type (ref);
1196 f2c_alist_struct = ref;
1199 /* Try to do as much compile-time initialization of the structure
1200 as possible, to save run time. */
1202 ffeste_f2c_init_flag_ (have_err, errinit);
1204 switch (unit)
1206 case FFESTV_unitNONE:
1207 case FFESTV_unitASTERISK:
1208 unitinit = build_int_2 (unit_dflt, 0);
1209 unitexp = unitinit;
1210 break;
1212 case FFESTV_unitINTEXPR:
1213 unitexp = ffecom_const_expr (unit_expr);
1214 if (unitexp)
1215 unitinit = unitexp;
1216 else
1218 unitinit = ffecom_integer_zero_node;
1219 constantp = FALSE;
1221 break;
1223 default:
1224 assert ("bad unit spec" == NULL);
1225 unitinit = ffecom_integer_zero_node;
1226 unitexp = unitinit;
1227 break;
1230 inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
1231 initn = inits;
1232 ffeste_f2c_init_next_ (unitinit);
1234 inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
1235 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1236 TREE_STATIC (inits) = 1;
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);
1246 /* Prepare run-time expressions. */
1248 if (! unitexp)
1249 ffecom_prepare_expr (unit_expr);
1251 ffecom_prepare_end ();
1253 /* Now evaluate run-time expressions as needed. */
1255 if (! unitexp)
1257 unitexp = ffecom_expr (unit_expr);
1258 ffeste_f2c_compile_ (unitfield, unitexp);
1261 ttype = build_pointer_type (TREE_TYPE (t));
1262 t = ffecom_1 (ADDR_EXPR, ttype, t);
1264 t = build_tree_list (NULL_TREE, t);
1266 return t;
1269 /* Make arglist with ptr to external-I/O control list.
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.
1276 Must ensure that all expressions are prepared before being evaluated,
1277 for any whose evaluation might result in the generation of temporaries.
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. */
1284 static GTY(()) tree f2c_cilist_struct;
1285 static tree
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)
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;
1306 if (f2c_cilist_struct == NULL_TREE)
1308 tree ref;
1310 ref = make_node (RECORD_TYPE);
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);
1323 TYPE_FIELDS (ref) = errfield;
1324 layout_type (ref);
1326 f2c_cilist_struct = ref;
1329 /* Try to do as much compile-time initialization of the structure
1330 as possible, to save run time. */
1332 ffeste_f2c_init_flag_ (have_err, errinit);
1334 switch (unit)
1336 case FFESTV_unitNONE:
1337 case FFESTV_unitASTERISK:
1338 unitinit = build_int_2 (unit_dflt, 0);
1339 unitexp = unitinit;
1340 break;
1342 case FFESTV_unitINTEXPR:
1343 unitexp = ffecom_const_expr (unit_expr);
1344 if (unitexp)
1345 unitinit = unitexp;
1346 else
1348 unitinit = ffecom_integer_zero_node;
1349 constantp = FALSE;
1351 break;
1353 default:
1354 assert ("bad unit spec" == NULL);
1355 unitinit = ffecom_integer_zero_node;
1356 unitexp = unitinit;
1357 break;
1360 switch (format)
1362 case FFESTV_formatNONE:
1363 formatinit = null_pointer_node;
1364 formatexp = formatinit;
1365 break;
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;
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
1385 formatinit = null_pointer_node;
1386 constantp = FALSE;
1388 break;
1390 case FFESTV_formatASTERISK:
1391 formatinit = null_pointer_node;
1392 formatexp = formatinit;
1393 break;
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;
1404 case FFESTV_formatNAMELIST:
1405 formatinit = ffecom_expr (format_spec->u.expr);
1406 formatexp = formatinit;
1407 break;
1409 default:
1410 assert ("bad format spec" == NULL);
1411 formatinit = integer_zero_node;
1412 formatexp = formatinit;
1413 break;
1416 ffeste_f2c_init_flag_ (have_end, endinit);
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
1426 recinit = ffecom_integer_zero_node;
1427 constantp = FALSE;
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);
1437 inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1438 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1439 TREE_STATIC (inits) = 1;
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);
1449 /* Prepare run-time expressions. */
1451 if (! unitexp)
1452 ffecom_prepare_expr (unit_expr);
1454 if (! formatexp)
1455 ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
1457 if (! recexp)
1458 ffecom_prepare_expr (rec_expr);
1460 ffecom_prepare_end ();
1462 /* Now evaluate run-time expressions as needed. */
1464 if (! unitexp)
1466 unitexp = ffecom_expr (unit_expr);
1467 ffeste_f2c_compile_ (unitfield, unitexp);
1470 if (! formatexp)
1472 formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1473 ffeste_f2c_compile_ (formatfield, formatexp);
1475 else if (format == FFESTV_formatINTEXPR)
1476 ffeste_f2c_compile_ (formatfield, formatexp);
1478 if (! recexp)
1480 recexp = ffecom_expr (rec_expr);
1481 ffeste_f2c_compile_ (recfield, recexp);
1484 ttype = build_pointer_type (TREE_TYPE (t));
1485 t = ffecom_1 (ADDR_EXPR, ttype, t);
1487 t = build_tree_list (NULL_TREE, t);
1489 return t;
1492 /* Make arglist with ptr to CLOSE control list.
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.
1499 Must ensure that all expressions are prepared before being evaluated,
1500 for any whose evaluation might result in the generation of temporaries.
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. */
1507 static GTY(()) tree f2c_close_struct;
1508 static tree
1509 ffeste_io_cllist_ (bool have_err,
1510 ffebld unit_expr,
1511 ffestpFile *stat_spec)
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;
1524 if (f2c_close_struct == NULL_TREE)
1526 tree ref;
1528 ref = make_node (RECORD_TYPE);
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);
1537 TYPE_FIELDS (ref) = errfield;
1538 layout_type (ref);
1540 f2c_close_struct = ref;
1543 /* Try to do as much compile-time initialization of the structure
1544 as possible, to save run time. */
1546 ffeste_f2c_init_flag_ (have_err, errinit);
1548 unitexp = ffecom_const_expr (unit_expr);
1549 if (unitexp)
1550 unitinit = unitexp;
1551 else
1553 unitinit = ffecom_integer_zero_node;
1554 constantp = FALSE;
1557 ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
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);
1564 inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1565 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1566 TREE_STATIC (inits) = 1;
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);
1576 /* Prepare run-time expressions. */
1578 if (! unitexp)
1579 ffecom_prepare_expr (unit_expr);
1581 if (! statexp)
1582 ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
1584 ffecom_prepare_end ();
1586 /* Now evaluate run-time expressions as needed. */
1588 if (! unitexp)
1590 unitexp = ffecom_expr (unit_expr);
1591 ffeste_f2c_compile_ (unitfield, unitexp);
1594 ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
1596 ttype = build_pointer_type (TREE_TYPE (t));
1597 t = ffecom_1 (ADDR_EXPR, ttype, t);
1599 t = build_tree_list (NULL_TREE, t);
1601 return t;
1604 /* Make arglist with ptr to internal-I/O control list.
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.
1611 Must ensure that all expressions are prepared before being evaluated,
1612 for any whose evaluation might result in the generation of temporaries.
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. */
1619 static GTY(()) tree f2c_icilist_struct;
1620 static tree
1621 ffeste_io_icilist_ (bool have_err,
1622 ffebld unit_expr,
1623 bool have_end,
1624 ffestvFormat format,
1625 ffestpFile *format_spec)
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;
1638 if (f2c_icilist_struct == NULL_TREE)
1640 tree ref;
1642 ref = make_node (RECORD_TYPE);
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);
1657 TYPE_FIELDS (ref) = errfield;
1658 layout_type (ref);
1660 f2c_icilist_struct = ref;
1663 /* Try to do as much compile-time initialization of the structure
1664 as possible, to save run time. */
1666 ffeste_f2c_init_flag_ (have_err, errinit);
1668 unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
1669 if (unitexp)
1670 unitinit = unitexp;
1671 else
1673 unitinit = null_pointer_node;
1674 constantp = FALSE;
1676 if (unitlenexp)
1677 unitleninit = unitlenexp;
1678 else
1680 unitleninit = ffecom_integer_zero_node;
1681 constantp = FALSE;
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))
1690 /* Not an array, so just one element. */
1691 unitnuminit = ffecom_integer_one_node;
1692 unitnumexp = unitnuminit;
1694 else if (unitexp && unitlenexp)
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;
1706 else
1708 /* Put off computing until run time. */
1709 unitnuminit = ffecom_integer_zero_node;
1710 unitnumexp = NULL_TREE;
1711 constantp = FALSE;
1714 switch (format)
1716 case FFESTV_formatNONE:
1717 formatinit = null_pointer_node;
1718 formatexp = formatinit;
1719 break;
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;
1733 case FFESTV_formatCHAREXPR:
1734 ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
1735 break;
1737 case FFESTV_formatASTERISK:
1738 formatinit = null_pointer_node;
1739 formatexp = formatinit;
1740 break;
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;
1751 default:
1752 assert ("bad format spec" == NULL);
1753 formatinit = ffecom_integer_zero_node;
1754 formatexp = formatinit;
1755 break;
1758 ffeste_f2c_init_flag_ (have_end, endinit);
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);
1769 inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1770 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1771 TREE_STATIC (inits) = 1;
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);
1781 /* Prepare run-time expressions. */
1783 if (! unitexp)
1784 ffecom_prepare_arg_ptr_to_expr (unit_expr);
1786 ffeste_f2c_prepare_format_ (format_spec, formatexp);
1788 ffecom_prepare_end ();
1790 /* Now evaluate run-time expressions as needed. */
1792 if (! unitexp || ! unitlenexp)
1794 int need_unitexp = (! unitexp);
1795 int need_unitlenexp = (! unitlenexp);
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);
1804 if (! unitnumexp
1805 && unitexp != error_mark_node
1806 && unitlenexp != error_mark_node)
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);
1818 if (format == FFESTV_formatINTEXPR)
1819 ffeste_f2c_compile_ (formatfield, formatexp);
1820 else
1821 ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
1823 ttype = build_pointer_type (TREE_TYPE (t));
1824 t = ffecom_1 (ADDR_EXPR, ttype, t);
1826 t = build_tree_list (NULL_TREE, t);
1828 return t;
1831 /* Make arglist with ptr to INQUIRE control list
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.
1838 Must ensure that all expressions are prepared before being evaluated,
1839 for any whose evaluation might result in the generation of temporaries.
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. */
1846 static GTY(()) tree f2c_inquire_struct;
1847 static tree
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)
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;
1888 if (f2c_inquire_struct == NULL_TREE)
1890 tree ref;
1892 ref = make_node (RECORD_TYPE);
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);
1951 TYPE_FIELDS (ref) = errfield;
1952 layout_type (ref);
1954 f2c_inquire_struct = ref;
1957 /* Try to do as much compile-time initialization of the structure
1958 as possible, to save run time. */
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);
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);
2016 inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
2017 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2018 TREE_STATIC (inits) = 1;
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);
2028 /* Prepare run-time expressions. */
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);
2047 ffecom_prepare_end ();
2049 /* Now evaluate run-time expressions as needed. */
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);
2079 ttype = build_pointer_type (TREE_TYPE (t));
2080 t = ffecom_1 (ADDR_EXPR, ttype, t);
2082 t = build_tree_list (NULL_TREE, t);
2084 return t;
2087 /* Make arglist with ptr to OPEN control list
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.
2094 Must ensure that all expressions are prepared before being evaluated,
2095 for any whose evaluation might result in the generation of temporaries.
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. */
2102 static GTY(()) tree f2c_open_struct;
2103 static tree
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)
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;
2128 if (f2c_open_struct == NULL_TREE)
2130 tree ref;
2132 ref = make_node (RECORD_TYPE);
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);
2153 TYPE_FIELDS (ref) = errfield;
2154 layout_type (ref);
2156 f2c_open_struct = ref;
2159 /* Try to do as much compile-time initialization of the structure
2160 as possible, to save run time. */
2162 ffeste_f2c_init_flag_ (have_err, errinit);
2164 unitexp = ffecom_const_expr (unit_expr);
2165 if (unitexp)
2166 unitinit = unitexp;
2167 else
2169 unitinit = ffecom_integer_zero_node;
2170 constantp = FALSE;
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);
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);
2192 inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
2193 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2194 TREE_STATIC (inits) = 1;
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);
2204 /* Prepare run-time expressions. */
2206 if (! unitexp)
2207 ffecom_prepare_expr (unit_expr);
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);
2216 ffecom_prepare_end ();
2218 /* Now evaluate run-time expressions as needed. */
2220 if (! unitexp)
2222 unitexp = ffecom_expr (unit_expr);
2223 ffeste_f2c_compile_ (unitfield, unitexp);
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);
2234 ttype = build_pointer_type (TREE_TYPE (t));
2235 t = ffecom_1 (ADDR_EXPR, ttype, t);
2237 t = build_tree_list (NULL_TREE, t);
2239 return t;
2242 /* Generate code for BACKSPACE/ENDFILE/REWIND. */
2244 static void
2245 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
2247 tree alist;
2248 bool iostat;
2249 bool errl;
2251 ffeste_emit_line_note_ ();
2253 #define specified(something) (info->beru_spec[something].kw_or_val_present)
2255 iostat = specified (FFESTP_beruixIOSTAT);
2256 errl = specified (FFESTP_beruixERR);
2258 #undef specified
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. */
2270 ffeste_start_stmt_ ();
2272 if (errl)
2274 /* Have ERR= specification. */
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;
2282 else
2284 /* No ERR= specification. */
2286 ffeste_io_err_ = NULL_TREE;
2288 if ((ffeste_io_abort_is_temp_ = iostat))
2289 ffeste_io_abort_ = ffecom_temp_label ();
2290 else
2291 ffeste_io_abort_ = NULL_TREE;
2294 if (iostat)
2296 /* Have IOSTAT= specification. */
2298 ffeste_io_iostat_is_temp_ = FALSE;
2299 ffeste_io_iostat_ = ffecom_expr
2300 (info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2302 else if (ffeste_io_abort_ != NULL_TREE)
2304 /* Have no IOSTAT= but have ERR=. */
2306 ffeste_io_iostat_is_temp_ = TRUE;
2307 ffeste_io_iostat_
2308 = ffecom_make_tempvar ("beru", ffecom_integer_type_node,
2309 FFETARGET_charactersizeNONE, -1);
2311 else
2313 /* No IOSTAT= or ERR= specification. */
2315 ffeste_io_iostat_is_temp_ = FALSE;
2316 ffeste_io_iostat_ = NULL_TREE;
2319 /* Now prescan, then convert, all the arguments. */
2321 alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2322 info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
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. */
2327 ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
2328 ! ffeste_io_abort_is_temp_);
2330 /* If we've got a temp label, generate its code here. */
2332 if (ffeste_io_abort_is_temp_)
2334 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2335 emit_nop ();
2336 expand_label (ffeste_io_abort_);
2338 assert (ffeste_io_err_ == NULL_TREE);
2341 ffeste_end_stmt_ ();
2344 /* END DO statement
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. */
2351 void
2352 ffeste_do (ffestw block)
2354 ffeste_emit_line_note_ ();
2356 if (ffestw_do_tvar (block) == 0)
2358 expand_end_loop (); /* DO WHILE and just DO. */
2360 ffeste_end_block_ (block);
2362 else
2363 ffeste_end_iterdo_ (block,
2364 ffestw_do_tvar (block),
2365 ffestw_do_incr_saved (block),
2366 ffestw_do_count_var (block));
2369 /* End of statement following logical IF.
2371 Applies to *only* logical IF, not to IF-THEN. */
2373 void
2374 ffeste_end_R807 ()
2376 ffeste_emit_line_note_ ();
2378 expand_end_cond ();
2380 ffeste_end_block_ (NULL);
2383 /* Generate "code" for branch label definition. */
2385 void
2386 ffeste_labeldef_branch (ffelab label)
2388 tree glabel;
2390 glabel = ffecom_lookup_label (label);
2391 assert (glabel != NULL_TREE);
2392 if (TREE_CODE (glabel) == ERROR_MARK)
2393 return;
2395 assert (DECL_INITIAL (glabel) == NULL_TREE);
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);
2401 emit_nop ();
2403 expand_label (glabel);
2406 /* Generate "code" for FORMAT label definition. */
2408 void
2409 ffeste_labeldef_format (ffelab label)
2411 ffeste_label_formatdef_ = label;
2414 /* Assignment statement (outside of WHERE). */
2416 void
2417 ffeste_R737A (ffebld dest, ffebld source)
2419 ffeste_check_simple_ ();
2421 ffeste_emit_line_note_ ();
2423 ffeste_start_stmt_ ();
2425 ffecom_expand_let_stmt (dest, source);
2427 ffeste_end_stmt_ ();
2430 /* Block IF (IF-THEN) statement. */
2432 void
2433 ffeste_R803 (ffestw block, ffebld expr)
2435 tree temp;
2437 ffeste_check_simple_ ();
2439 ffeste_emit_line_note_ ();
2441 ffeste_start_block_ (block);
2443 temp = ffecom_make_tempvar ("ifthen", integer_type_node,
2444 FFETARGET_charactersizeNONE, -1);
2446 ffeste_start_stmt_ ();
2448 ffecom_prepare_expr (expr);
2450 if (ffecom_prepare_end ())
2452 tree result;
2454 result = ffecom_modify (void_type_node,
2455 temp,
2456 ffecom_truth_value (ffecom_expr (expr)));
2458 expand_expr_stmt (result);
2460 ffeste_end_stmt_ ();
2462 else
2464 ffeste_end_stmt_ ();
2466 temp = ffecom_truth_value (ffecom_expr (expr));
2469 expand_start_cond (temp, 0);
2471 /* No fake `else' constructs introduced (yet). */
2472 ffestw_set_ifthen_fake_else (block, 0);
2475 /* ELSE IF statement. */
2477 void
2478 ffeste_R804 (ffestw block, ffebld expr)
2480 tree temp;
2482 ffeste_check_simple_ ();
2484 ffeste_emit_line_note_ ();
2486 /* Since ELSEIF(expr) might require preparations for expr,
2487 implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF. */
2489 expand_start_else ();
2491 ffeste_start_block_ (block);
2493 temp = ffecom_make_tempvar ("elseif", integer_type_node,
2494 FFETARGET_charactersizeNONE, -1);
2496 ffeste_start_stmt_ ();
2498 ffecom_prepare_expr (expr);
2500 if (ffecom_prepare_end ())
2502 tree result;
2504 result = ffecom_modify (void_type_node,
2505 temp,
2506 ffecom_truth_value (ffecom_expr (expr)));
2508 expand_expr_stmt (result);
2510 ffeste_end_stmt_ ();
2512 else
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. */
2520 ffeste_end_stmt_ ();
2522 temp = ffecom_truth_value (ffecom_expr (expr));
2525 expand_start_cond (temp, 0);
2527 /* Increment number of fake `else' constructs introduced. */
2528 ffestw_set_ifthen_fake_else (block,
2529 ffestw_ifthen_fake_else (block) + 1);
2532 /* ELSE statement. */
2534 void
2535 ffeste_R805 (ffestw block UNUSED)
2537 ffeste_check_simple_ ();
2539 ffeste_emit_line_note_ ();
2541 expand_start_else ();
2544 /* END IF statement. */
2546 void
2547 ffeste_R806 (ffestw block)
2549 int i = ffestw_ifthen_fake_else (block) + 1;
2551 ffeste_emit_line_note_ ();
2553 for (; i; --i)
2555 expand_end_cond ();
2557 ffeste_end_block_ (block);
2561 /* Logical IF statement. */
2563 void
2564 ffeste_R807 (ffebld expr)
2566 tree temp;
2568 ffeste_check_simple_ ();
2570 ffeste_emit_line_note_ ();
2572 ffeste_start_block_ (NULL);
2574 temp = ffecom_make_tempvar ("if", integer_type_node,
2575 FFETARGET_charactersizeNONE, -1);
2577 ffeste_start_stmt_ ();
2579 ffecom_prepare_expr (expr);
2581 if (ffecom_prepare_end ())
2583 tree result;
2585 result = ffecom_modify (void_type_node,
2586 temp,
2587 ffecom_truth_value (ffecom_expr (expr)));
2589 expand_expr_stmt (result);
2591 ffeste_end_stmt_ ();
2593 else
2595 ffeste_end_stmt_ ();
2597 temp = ffecom_truth_value (ffecom_expr (expr));
2600 expand_start_cond (temp, 0);
2603 /* SELECT CASE statement. */
2605 void
2606 ffeste_R809 (ffestw block, ffebld expr)
2608 ffeste_check_simple_ ();
2610 ffeste_emit_line_note_ ();
2612 ffeste_start_block_ (block);
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)
2621 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
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);
2630 else
2632 tree result;
2633 tree texpr;
2635 result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
2636 ffeinfo_size (ffebld_info (expr)),
2637 -1);
2639 ffeste_start_stmt_ ();
2641 ffecom_prepare_expr (expr);
2643 ffecom_prepare_end ();
2645 texpr = ffecom_expr (expr);
2647 assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
2648 == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
2650 texpr = ffecom_modify (void_type_node,
2651 result,
2652 texpr);
2653 expand_expr_stmt (texpr);
2655 ffeste_end_stmt_ ();
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);
2664 /* CASE statement.
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. */
2670 void
2671 ffeste_R810 (ffestw block, unsigned long casenum)
2673 ffestwSelect s = ffestw_select (block);
2674 ffestwCase c;
2675 tree texprlow;
2676 tree texprhigh;
2677 tree tlabel;
2678 int pushok;
2679 tree duplicate;
2681 ffeste_check_simple_ ();
2683 if (s->first_stmt == (ffestwCase) &s->first_rel)
2684 c = NULL;
2685 else
2686 c = s->first_stmt;
2688 ffeste_emit_line_note_ ();
2690 if (ffestw_select_texpr (block) == error_mark_node)
2691 return;
2693 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2695 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2697 if (ffestw_select_break (block))
2698 expand_exit_something ();
2699 else
2700 ffestw_set_select_break (block, TRUE);
2702 if ((c == NULL) || (casenum != c->casenum))
2704 if (casenum == 0) /* Intentional CASE DEFAULT. */
2706 pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2707 assert (pushok == 0);
2710 else
2713 texprlow = (c->low == NULL) ? NULL_TREE
2714 : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
2715 s->kindtype,
2716 ffecom_tree_type[s->type][s->kindtype]);
2717 if (c->low != c->high)
2719 texprhigh = (c->high == NULL) ? NULL_TREE
2720 : ffecom_constantunion (&ffebld_constant_union (c->high),
2721 s->type, s->kindtype,
2722 ffecom_tree_type[s->type][s->kindtype]);
2723 pushok = pushcase_range (texprlow, texprhigh, convert,
2724 tlabel, &duplicate);
2726 else
2727 pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2728 assert((pushok !=2) || (pushok !=0));
2729 if (pushok==2)
2731 ffebad_start_msg ("SELECT (at %0) has duplicate cases -- check integer overflow of CASE(s)",
2732 FFEBAD_severityFATAL);
2733 ffebad_here (0, ffestw_line (block), ffestw_col (block));
2734 ffebad_finish ();
2735 ffestw_set_select_texpr (block, error_mark_node);
2737 c = c->next_stmt;
2738 /* Unlink prev. */
2739 c->previous_stmt->previous_stmt->next_stmt = c;
2740 c->previous_stmt = c->previous_stmt->previous_stmt;
2742 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2745 /* END SELECT statement. */
2747 void
2748 ffeste_R811 (ffestw block)
2750 ffeste_emit_line_note_ ();
2752 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2754 if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
2755 expand_end_case (ffestw_select_texpr (block));
2757 ffeste_end_block_ (block);
2760 /* Iterative DO statement. */
2762 void
2763 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
2764 ffebld start, ffelexToken start_token,
2765 ffebld end, ffelexToken end_token,
2766 ffebld incr, ffelexToken incr_token)
2768 ffeste_check_simple_ ();
2770 ffeste_emit_line_note_ ();
2772 ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
2773 var,
2774 start, start_token,
2775 end, end_token,
2776 incr, incr_token,
2777 "Iterative DO loop");
2780 /* DO WHILE statement. */
2782 void
2783 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
2785 tree result;
2787 ffeste_check_simple_ ();
2789 ffeste_emit_line_note_ ();
2791 ffeste_start_block_ (block);
2793 if (expr)
2795 struct nesting *loop;
2796 tree mod;
2798 result = ffecom_make_tempvar ("dowhile", integer_type_node,
2799 FFETARGET_charactersizeNONE, -1);
2800 loop = expand_start_loop (1);
2802 ffeste_start_stmt_ ();
2804 ffecom_prepare_expr (expr);
2806 ffecom_prepare_end ();
2808 mod = ffecom_modify (void_type_node,
2809 result,
2810 ffecom_truth_value (ffecom_expr (expr)));
2811 expand_expr_stmt (mod);
2813 ffeste_end_stmt_ ();
2815 ffestw_set_do_hook (block, loop);
2816 expand_exit_loop_top_cond (0, result);
2818 else
2819 ffestw_set_do_hook (block, expand_start_loop (1));
2821 ffestw_set_do_tvar (block, NULL_TREE);
2824 /* END DO statement.
2826 This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
2827 CONTINUE (except that it has to have a label that is the target of
2828 one or more iterative DO statement), not the Fortran-90 structured
2829 END DO, which is handled elsewhere, as is the actual mechanism of
2830 ending an iterative DO statement, even one that ends at a label. */
2832 void
2833 ffeste_R825 ()
2835 ffeste_check_simple_ ();
2837 ffeste_emit_line_note_ ();
2839 emit_nop ();
2842 /* CYCLE statement. */
2844 void
2845 ffeste_R834 (ffestw block)
2847 ffeste_check_simple_ ();
2849 ffeste_emit_line_note_ ();
2851 expand_continue_loop (ffestw_do_hook (block));
2854 /* EXIT statement. */
2856 void
2857 ffeste_R835 (ffestw block)
2859 ffeste_check_simple_ ();
2861 ffeste_emit_line_note_ ();
2863 expand_exit_loop (ffestw_do_hook (block));
2866 /* GOTO statement. */
2868 void
2869 ffeste_R836 (ffelab label)
2871 tree glabel;
2873 ffeste_check_simple_ ();
2875 ffeste_emit_line_note_ ();
2877 glabel = ffecom_lookup_label (label);
2878 if ((glabel != NULL_TREE)
2879 && (TREE_CODE (glabel) != ERROR_MARK))
2881 expand_goto (glabel);
2882 TREE_USED (glabel) = 1;
2886 /* Computed GOTO statement. */
2888 void
2889 ffeste_R837 (ffelab *labels, int count, ffebld expr)
2891 int i;
2892 tree texpr;
2893 tree value;
2894 tree tlabel;
2895 int pushok;
2896 tree duplicate;
2898 ffeste_check_simple_ ();
2900 ffeste_emit_line_note_ ();
2902 ffeste_start_stmt_ ();
2904 ffecom_prepare_expr (expr);
2906 ffecom_prepare_end ();
2908 texpr = ffecom_expr (expr);
2910 expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
2912 for (i = 0; i < count; ++i)
2914 value = build_int_2 (i + 1, 0);
2915 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2917 pushok = pushcase (value, convert, tlabel, &duplicate);
2918 assert (pushok == 0);
2920 tlabel = ffecom_lookup_label (labels[i]);
2921 if ((tlabel == NULL_TREE)
2922 || (TREE_CODE (tlabel) == ERROR_MARK))
2923 continue;
2925 expand_goto (tlabel);
2926 TREE_USED (tlabel) = 1;
2928 expand_end_case (texpr);
2930 ffeste_end_stmt_ ();
2933 /* ASSIGN statement. */
2935 void
2936 ffeste_R838 (ffelab label, ffebld target)
2938 tree expr_tree;
2939 tree label_tree;
2940 tree target_tree;
2942 ffeste_check_simple_ ();
2944 ffeste_emit_line_note_ ();
2946 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2947 seen here should never require use of temporaries. */
2949 label_tree = ffecom_lookup_label (label);
2950 if ((label_tree != NULL_TREE)
2951 && (TREE_CODE (label_tree) != ERROR_MARK))
2953 label_tree = ffecom_1 (ADDR_EXPR,
2954 build_pointer_type (void_type_node),
2955 label_tree);
2956 TREE_CONSTANT (label_tree) = 1;
2958 target_tree = ffecom_expr_assign_w (target);
2959 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
2960 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
2961 error ("ASSIGN to variable that is too small");
2963 label_tree = convert (TREE_TYPE (target_tree), label_tree);
2965 expr_tree = ffecom_modify (void_type_node,
2966 target_tree,
2967 label_tree);
2968 expand_expr_stmt (expr_tree);
2972 /* Assigned GOTO statement. */
2974 void
2975 ffeste_R839 (ffebld target)
2977 tree t;
2979 ffeste_check_simple_ ();
2981 ffeste_emit_line_note_ ();
2983 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2984 seen here should never require use of temporaries. */
2986 t = ffecom_expr_assign (target);
2987 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2988 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2989 error ("ASSIGNed GOTO target variable is too small");
2991 expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
2994 /* Arithmetic IF statement. */
2996 void
2997 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
2999 tree gneg = ffecom_lookup_label (neg);
3000 tree gzero = ffecom_lookup_label (zero);
3001 tree gpos = ffecom_lookup_label (pos);
3002 tree texpr;
3004 ffeste_check_simple_ ();
3006 ffeste_emit_line_note_ ();
3008 if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
3009 return;
3010 if ((TREE_CODE (gneg) == ERROR_MARK)
3011 || (TREE_CODE (gzero) == ERROR_MARK)
3012 || (TREE_CODE (gpos) == ERROR_MARK))
3013 return;
3015 ffeste_start_stmt_ ();
3017 ffecom_prepare_expr (expr);
3019 ffecom_prepare_end ();
3021 if (neg == zero)
3023 if (neg == pos)
3024 expand_goto (gzero);
3025 else
3027 /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos. */
3028 texpr = ffecom_expr (expr);
3029 texpr = ffecom_2 (LE_EXPR, integer_type_node,
3030 texpr,
3031 convert (TREE_TYPE (texpr),
3032 integer_zero_node));
3033 expand_start_cond (ffecom_truth_value (texpr), 0);
3034 expand_goto (gzero);
3035 expand_start_else ();
3036 expand_goto (gpos);
3037 expand_end_cond ();
3040 else if (neg == pos)
3042 /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero. */
3043 texpr = ffecom_expr (expr);
3044 texpr = ffecom_2 (NE_EXPR, integer_type_node,
3045 texpr,
3046 convert (TREE_TYPE (texpr),
3047 integer_zero_node));
3048 expand_start_cond (ffecom_truth_value (texpr), 0);
3049 expand_goto (gneg);
3050 expand_start_else ();
3051 expand_goto (gzero);
3052 expand_end_cond ();
3054 else if (zero == pos)
3056 /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg. */
3057 texpr = ffecom_expr (expr);
3058 texpr = ffecom_2 (GE_EXPR, integer_type_node,
3059 texpr,
3060 convert (TREE_TYPE (texpr),
3061 integer_zero_node));
3062 expand_start_cond (ffecom_truth_value (texpr), 0);
3063 expand_goto (gzero);
3064 expand_start_else ();
3065 expand_goto (gneg);
3066 expand_end_cond ();
3068 else
3070 /* Use a SAVE_EXPR in combo with:
3071 IF (expr.LT.0) THEN GOTO neg
3072 ELSEIF (expr.GT.0) THEN GOTO pos
3073 ELSE GOTO zero. */
3074 tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
3076 texpr = ffecom_2 (LT_EXPR, integer_type_node,
3077 expr_saved,
3078 convert (TREE_TYPE (expr_saved),
3079 integer_zero_node));
3080 expand_start_cond (ffecom_truth_value (texpr), 0);
3081 expand_goto (gneg);
3082 texpr = ffecom_2 (GT_EXPR, integer_type_node,
3083 expr_saved,
3084 convert (TREE_TYPE (expr_saved),
3085 integer_zero_node));
3086 expand_start_elseif (ffecom_truth_value (texpr));
3087 expand_goto (gpos);
3088 expand_start_else ();
3089 expand_goto (gzero);
3090 expand_end_cond ();
3093 ffeste_end_stmt_ ();
3096 /* CONTINUE statement. */
3098 void
3099 ffeste_R841 ()
3101 ffeste_check_simple_ ();
3103 ffeste_emit_line_note_ ();
3105 emit_nop ();
3108 /* STOP statement. */
3110 void
3111 ffeste_R842 (ffebld expr)
3113 tree callit;
3114 ffelexToken msg;
3116 ffeste_check_simple_ ();
3118 ffeste_emit_line_note_ ();
3120 if ((expr == NULL)
3121 || (ffeinfo_basictype (ffebld_info (expr))
3122 == FFEINFO_basictypeANY))
3124 msg = ffelex_token_new_character ("",
3125 ffelex_token_where_line (ffesta_tokens[0]),
3126 ffelex_token_where_column (ffesta_tokens[0]));
3127 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3128 (msg));
3129 ffelex_token_kill (msg);
3130 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3131 FFEINFO_kindtypeCHARACTERDEFAULT,
3132 0, FFEINFO_kindENTITY,
3133 FFEINFO_whereCONSTANT, 0));
3135 else if (ffeinfo_basictype (ffebld_info (expr))
3136 == FFEINFO_basictypeINTEGER)
3138 char num[50];
3140 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3141 assert (ffeinfo_kindtype (ffebld_info (expr))
3142 == FFEINFO_kindtypeINTEGERDEFAULT);
3143 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3144 ffebld_constant_integer1 (ffebld_conter (expr)));
3145 msg = ffelex_token_new_character (num,
3146 ffelex_token_where_line (ffesta_tokens[0]),
3147 ffelex_token_where_column (ffesta_tokens[0]));
3148 expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3149 ffelex_token_kill (msg);
3150 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3151 FFEINFO_kindtypeCHARACTERDEFAULT,
3152 0, FFEINFO_kindENTITY,
3153 FFEINFO_whereCONSTANT, 0));
3155 else
3157 assert (ffeinfo_basictype (ffebld_info (expr))
3158 == FFEINFO_basictypeCHARACTER);
3159 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3160 assert (ffeinfo_kindtype (ffebld_info (expr))
3161 == FFEINFO_kindtypeCHARACTERDEFAULT);
3164 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3165 seen here should never require use of temporaries. */
3167 callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3168 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3169 NULL_TREE);
3170 TREE_SIDE_EFFECTS (callit) = 1;
3172 expand_expr_stmt (callit);
3175 /* PAUSE statement. */
3177 void
3178 ffeste_R843 (ffebld expr)
3180 tree callit;
3181 ffelexToken msg;
3183 ffeste_check_simple_ ();
3185 ffeste_emit_line_note_ ();
3187 if ((expr == NULL)
3188 || (ffeinfo_basictype (ffebld_info (expr))
3189 == FFEINFO_basictypeANY))
3191 msg = ffelex_token_new_character ("",
3192 ffelex_token_where_line (ffesta_tokens[0]),
3193 ffelex_token_where_column (ffesta_tokens[0]));
3194 expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3195 ffelex_token_kill (msg);
3196 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3197 FFEINFO_kindtypeCHARACTERDEFAULT,
3198 0, FFEINFO_kindENTITY,
3199 FFEINFO_whereCONSTANT, 0));
3201 else if (ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeINTEGER)
3203 char num[50];
3205 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3206 assert (ffeinfo_kindtype (ffebld_info (expr))
3207 == FFEINFO_kindtypeINTEGERDEFAULT);
3208 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3209 ffebld_constant_integer1 (ffebld_conter (expr)));
3210 msg = ffelex_token_new_character (num, ffelex_token_where_line (ffesta_tokens[0]),
3211 ffelex_token_where_column (ffesta_tokens[0]));
3212 expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3213 ffelex_token_kill (msg);
3214 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3215 FFEINFO_kindtypeCHARACTERDEFAULT,
3216 0, FFEINFO_kindENTITY,
3217 FFEINFO_whereCONSTANT, 0));
3219 else
3221 assert (ffeinfo_basictype (ffebld_info (expr))
3222 == FFEINFO_basictypeCHARACTER);
3223 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3224 assert (ffeinfo_kindtype (ffebld_info (expr))
3225 == FFEINFO_kindtypeCHARACTERDEFAULT);
3228 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3229 seen here should never require use of temporaries. */
3231 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3232 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3233 NULL_TREE);
3234 TREE_SIDE_EFFECTS (callit) = 1;
3236 expand_expr_stmt (callit);
3239 /* OPEN statement. */
3241 void
3242 ffeste_R904 (ffestpOpenStmt *info)
3244 tree args;
3245 bool iostat;
3246 bool errl;
3248 ffeste_check_simple_ ();
3250 ffeste_emit_line_note_ ();
3252 #define specified(something) (info->open_spec[something].kw_or_val_present)
3254 iostat = specified (FFESTP_openixIOSTAT);
3255 errl = specified (FFESTP_openixERR);
3257 #undef specified
3259 ffeste_start_stmt_ ();
3261 if (errl)
3263 ffeste_io_err_
3264 = ffeste_io_abort_
3265 = ffecom_lookup_label
3266 (info->open_spec[FFESTP_openixERR].u.label);
3267 ffeste_io_abort_is_temp_ = FALSE;
3269 else
3271 ffeste_io_err_ = NULL_TREE;
3273 if ((ffeste_io_abort_is_temp_ = iostat))
3274 ffeste_io_abort_ = ffecom_temp_label ();
3275 else
3276 ffeste_io_abort_ = NULL_TREE;
3279 if (iostat)
3281 /* Have IOSTAT= specification. */
3283 ffeste_io_iostat_is_temp_ = FALSE;
3284 ffeste_io_iostat_ = ffecom_expr
3285 (info->open_spec[FFESTP_openixIOSTAT].u.expr);
3287 else if (ffeste_io_abort_ != NULL_TREE)
3289 /* Have no IOSTAT= but have ERR=. */
3291 ffeste_io_iostat_is_temp_ = TRUE;
3292 ffeste_io_iostat_
3293 = ffecom_make_tempvar ("open", ffecom_integer_type_node,
3294 FFETARGET_charactersizeNONE, -1);
3296 else
3298 /* No IOSTAT= or ERR= specification. */
3300 ffeste_io_iostat_is_temp_ = FALSE;
3301 ffeste_io_iostat_ = NULL_TREE;
3304 /* Now prescan, then convert, all the arguments. */
3306 args = ffeste_io_olist_ (errl || iostat,
3307 info->open_spec[FFESTP_openixUNIT].u.expr,
3308 &info->open_spec[FFESTP_openixFILE],
3309 &info->open_spec[FFESTP_openixSTATUS],
3310 &info->open_spec[FFESTP_openixACCESS],
3311 &info->open_spec[FFESTP_openixFORM],
3312 &info->open_spec[FFESTP_openixRECL],
3313 &info->open_spec[FFESTP_openixBLANK]);
3315 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3316 label, since we're gonna fall through to there anyway. */
3318 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
3319 ! ffeste_io_abort_is_temp_);
3321 /* If we've got a temp label, generate its code here. */
3323 if (ffeste_io_abort_is_temp_)
3325 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3326 emit_nop ();
3327 expand_label (ffeste_io_abort_);
3329 assert (ffeste_io_err_ == NULL_TREE);
3332 ffeste_end_stmt_ ();
3335 /* CLOSE statement. */
3337 void
3338 ffeste_R907 (ffestpCloseStmt *info)
3340 tree args;
3341 bool iostat;
3342 bool errl;
3344 ffeste_check_simple_ ();
3346 ffeste_emit_line_note_ ();
3348 #define specified(something) (info->close_spec[something].kw_or_val_present)
3350 iostat = specified (FFESTP_closeixIOSTAT);
3351 errl = specified (FFESTP_closeixERR);
3353 #undef specified
3355 ffeste_start_stmt_ ();
3357 if (errl)
3359 ffeste_io_err_
3360 = ffeste_io_abort_
3361 = ffecom_lookup_label
3362 (info->close_spec[FFESTP_closeixERR].u.label);
3363 ffeste_io_abort_is_temp_ = FALSE;
3365 else
3367 ffeste_io_err_ = NULL_TREE;
3369 if ((ffeste_io_abort_is_temp_ = iostat))
3370 ffeste_io_abort_ = ffecom_temp_label ();
3371 else
3372 ffeste_io_abort_ = NULL_TREE;
3375 if (iostat)
3377 /* Have IOSTAT= specification. */
3379 ffeste_io_iostat_is_temp_ = FALSE;
3380 ffeste_io_iostat_ = ffecom_expr
3381 (info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3383 else if (ffeste_io_abort_ != NULL_TREE)
3385 /* Have no IOSTAT= but have ERR=. */
3387 ffeste_io_iostat_is_temp_ = TRUE;
3388 ffeste_io_iostat_
3389 = ffecom_make_tempvar ("close", ffecom_integer_type_node,
3390 FFETARGET_charactersizeNONE, -1);
3392 else
3394 /* No IOSTAT= or ERR= specification. */
3396 ffeste_io_iostat_is_temp_ = FALSE;
3397 ffeste_io_iostat_ = NULL_TREE;
3400 /* Now prescan, then convert, all the arguments. */
3402 args = ffeste_io_cllist_ (errl || iostat,
3403 info->close_spec[FFESTP_closeixUNIT].u.expr,
3404 &info->close_spec[FFESTP_closeixSTATUS]);
3406 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3407 label, since we're gonna fall through to there anyway. */
3409 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
3410 ! ffeste_io_abort_is_temp_);
3412 /* If we've got a temp label, generate its code here. */
3414 if (ffeste_io_abort_is_temp_)
3416 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3417 emit_nop ();
3418 expand_label (ffeste_io_abort_);
3420 assert (ffeste_io_err_ == NULL_TREE);
3423 ffeste_end_stmt_ ();
3426 /* READ(...) statement -- start. */
3428 void
3429 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3430 ffestvUnit unit, ffestvFormat format, bool rec,
3431 bool key UNUSED)
3433 ffecomGfrt start;
3434 ffecomGfrt end;
3435 tree cilist;
3436 bool iostat;
3437 bool errl;
3438 bool endl;
3440 ffeste_check_start_ ();
3442 ffeste_emit_line_note_ ();
3444 /* First determine the start, per-item, and end run-time functions to
3445 call. The per-item function is picked by choosing an ffeste function
3446 to call to handle a given item; it knows how to generate a call to the
3447 appropriate run-time function, and is called an "I/O driver". */
3449 switch (format)
3451 case FFESTV_formatNONE: /* no FMT= */
3452 ffeste_io_driver_ = ffeste_io_douio_;
3453 if (rec)
3454 start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
3455 else
3456 start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
3457 break;
3459 case FFESTV_formatLABEL: /* FMT=10 */
3460 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3461 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3462 ffeste_io_driver_ = ffeste_io_dofio_;
3463 if (rec)
3464 start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
3465 else if (unit == FFESTV_unitCHAREXPR)
3466 start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
3467 else
3468 start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
3469 break;
3471 case FFESTV_formatASTERISK: /* FMT=* */
3472 ffeste_io_driver_ = ffeste_io_dolio_;
3473 if (unit == FFESTV_unitCHAREXPR)
3474 start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
3475 else
3476 start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
3477 break;
3479 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3480 /FOO/] */
3481 ffeste_io_driver_ = NULL; /* No start or driver function. */
3482 start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
3483 break;
3485 default:
3486 assert ("Weird stuff" == NULL);
3487 start = FFECOM_gfrt, end = FFECOM_gfrt;
3488 break;
3490 ffeste_io_endgfrt_ = end;
3492 #define specified(something) (info->read_spec[something].kw_or_val_present)
3494 iostat = specified (FFESTP_readixIOSTAT);
3495 errl = specified (FFESTP_readixERR);
3496 endl = specified (FFESTP_readixEND);
3498 #undef specified
3500 ffeste_start_stmt_ ();
3502 if (errl)
3504 /* Have ERR= specification. */
3506 ffeste_io_err_
3507 = ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
3509 if (endl)
3511 /* Have both ERR= and END=. Need a temp label to handle both. */
3512 ffeste_io_end_
3513 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3514 ffeste_io_abort_is_temp_ = TRUE;
3515 ffeste_io_abort_ = ffecom_temp_label ();
3517 else
3519 /* Have ERR= but no END=. */
3520 ffeste_io_end_ = NULL_TREE;
3521 if ((ffeste_io_abort_is_temp_ = iostat))
3522 ffeste_io_abort_ = ffecom_temp_label ();
3523 else
3524 ffeste_io_abort_ = ffeste_io_err_;
3527 else
3529 /* No ERR= specification. */
3531 ffeste_io_err_ = NULL_TREE;
3532 if (endl)
3534 /* Have END= but no ERR=. */
3535 ffeste_io_end_
3536 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3537 if ((ffeste_io_abort_is_temp_ = iostat))
3538 ffeste_io_abort_ = ffecom_temp_label ();
3539 else
3540 ffeste_io_abort_ = ffeste_io_end_;
3542 else
3544 /* Have no ERR= or END=. */
3546 ffeste_io_end_ = NULL_TREE;
3547 if ((ffeste_io_abort_is_temp_ = iostat))
3548 ffeste_io_abort_ = ffecom_temp_label ();
3549 else
3550 ffeste_io_abort_ = NULL_TREE;
3554 if (iostat)
3556 /* Have IOSTAT= specification. */
3558 ffeste_io_iostat_is_temp_ = FALSE;
3559 ffeste_io_iostat_
3560 = ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
3562 else if (ffeste_io_abort_ != NULL_TREE)
3564 /* Have no IOSTAT= but have ERR= and/or END=. */
3566 ffeste_io_iostat_is_temp_ = TRUE;
3567 ffeste_io_iostat_
3568 = ffecom_make_tempvar ("read", ffecom_integer_type_node,
3569 FFETARGET_charactersizeNONE, -1);
3571 else
3573 /* No IOSTAT=, ERR=, or END= specification. */
3575 ffeste_io_iostat_is_temp_ = FALSE;
3576 ffeste_io_iostat_ = NULL_TREE;
3579 /* Now prescan, then convert, all the arguments. */
3581 if (unit == FFESTV_unitCHAREXPR)
3582 cilist = ffeste_io_icilist_ (errl || iostat,
3583 info->read_spec[FFESTP_readixUNIT].u.expr,
3584 endl || iostat, format,
3585 &info->read_spec[FFESTP_readixFORMAT]);
3586 else
3587 cilist = ffeste_io_cilist_ (errl || iostat, unit,
3588 info->read_spec[FFESTP_readixUNIT].u.expr,
3589 5, endl || iostat, format,
3590 &info->read_spec[FFESTP_readixFORMAT],
3591 rec,
3592 info->read_spec[FFESTP_readixREC].u.expr);
3594 /* If there is no end function, then there are no item functions (i.e.
3595 it's a NAMELIST), and vice versa by the way. In this situation, don't
3596 generate the "if (iostat != 0) goto label;" if the label is temp abort
3597 label, since we're gonna fall through to there anyway. */
3599 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3600 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3603 /* READ statement -- I/O item. */
3605 void
3606 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
3608 ffeste_check_item_ ();
3610 if (expr == NULL)
3611 return;
3613 /* Strip parens off items such as in "READ *,(A)". This is really a bug
3614 in the user's code, but I've been told lots of code does this. */
3615 while (ffebld_op (expr) == FFEBLD_opPAREN)
3616 expr = ffebld_left (expr);
3618 if (ffebld_op (expr) == FFEBLD_opANY)
3619 return;
3621 if (ffebld_op (expr) == FFEBLD_opIMPDO)
3622 ffeste_io_impdo_ (expr, expr_token);
3623 else
3625 ffeste_start_stmt_ ();
3627 ffecom_prepare_arg_ptr_to_expr (expr);
3629 ffecom_prepare_end ();
3631 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3633 ffeste_end_stmt_ ();
3637 /* READ statement -- end. */
3639 void
3640 ffeste_R909_finish ()
3642 ffeste_check_finish_ ();
3644 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3645 label, since we're gonna fall through to there anyway. */
3647 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3648 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3649 NULL_TREE),
3650 ! ffeste_io_abort_is_temp_);
3652 /* If we've got a temp label, generate its code here and have it fan out
3653 to the END= or ERR= label as appropriate. */
3655 if (ffeste_io_abort_is_temp_)
3657 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3658 emit_nop ();
3659 expand_label (ffeste_io_abort_);
3661 /* "if (iostat<0) goto end_label;". */
3663 if ((ffeste_io_end_ != NULL_TREE)
3664 && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
3666 expand_start_cond (ffecom_truth_value
3667 (ffecom_2 (LT_EXPR, integer_type_node,
3668 ffeste_io_iostat_,
3669 ffecom_integer_zero_node)),
3671 expand_goto (ffeste_io_end_);
3672 expand_end_cond ();
3675 /* "if (iostat>0) goto err_label;". */
3677 if ((ffeste_io_err_ != NULL_TREE)
3678 && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
3680 expand_start_cond (ffecom_truth_value
3681 (ffecom_2 (GT_EXPR, integer_type_node,
3682 ffeste_io_iostat_,
3683 ffecom_integer_zero_node)),
3685 expand_goto (ffeste_io_err_);
3686 expand_end_cond ();
3690 ffeste_end_stmt_ ();
3693 /* WRITE statement -- start. */
3695 void
3696 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
3697 ffestvFormat format, bool rec)
3699 ffecomGfrt start;
3700 ffecomGfrt end;
3701 tree cilist;
3702 bool iostat;
3703 bool errl;
3705 ffeste_check_start_ ();
3707 ffeste_emit_line_note_ ();
3709 /* First determine the start, per-item, and end run-time functions to
3710 call. The per-item function is picked by choosing an ffeste function
3711 to call to handle a given item; it knows how to generate a call to the
3712 appropriate run-time function, and is called an "I/O driver". */
3714 switch (format)
3716 case FFESTV_formatNONE: /* no FMT= */
3717 ffeste_io_driver_ = ffeste_io_douio_;
3718 if (rec)
3719 start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
3720 else
3721 start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
3722 break;
3724 case FFESTV_formatLABEL: /* FMT=10 */
3725 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3726 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3727 ffeste_io_driver_ = ffeste_io_dofio_;
3728 if (rec)
3729 start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
3730 else if (unit == FFESTV_unitCHAREXPR)
3731 start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
3732 else
3733 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3734 break;
3736 case FFESTV_formatASTERISK: /* FMT=* */
3737 ffeste_io_driver_ = ffeste_io_dolio_;
3738 if (unit == FFESTV_unitCHAREXPR)
3739 start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
3740 else
3741 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3742 break;
3744 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3745 /FOO/] */
3746 ffeste_io_driver_ = NULL; /* No start or driver function. */
3747 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3748 break;
3750 default:
3751 assert ("Weird stuff" == NULL);
3752 start = FFECOM_gfrt, end = FFECOM_gfrt;
3753 break;
3755 ffeste_io_endgfrt_ = end;
3757 #define specified(something) (info->write_spec[something].kw_or_val_present)
3759 iostat = specified (FFESTP_writeixIOSTAT);
3760 errl = specified (FFESTP_writeixERR);
3762 #undef specified
3764 ffeste_start_stmt_ ();
3766 ffeste_io_end_ = NULL_TREE;
3768 if (errl)
3770 /* Have ERR= specification. */
3772 ffeste_io_err_
3773 = ffeste_io_abort_
3774 = ffecom_lookup_label
3775 (info->write_spec[FFESTP_writeixERR].u.label);
3776 ffeste_io_abort_is_temp_ = FALSE;
3778 else
3780 /* No ERR= specification. */
3782 ffeste_io_err_ = NULL_TREE;
3784 if ((ffeste_io_abort_is_temp_ = iostat))
3785 ffeste_io_abort_ = ffecom_temp_label ();
3786 else
3787 ffeste_io_abort_ = NULL_TREE;
3790 if (iostat)
3792 /* Have IOSTAT= specification. */
3794 ffeste_io_iostat_is_temp_ = FALSE;
3795 ffeste_io_iostat_ = ffecom_expr
3796 (info->write_spec[FFESTP_writeixIOSTAT].u.expr);
3798 else if (ffeste_io_abort_ != NULL_TREE)
3800 /* Have no IOSTAT= but have ERR=. */
3802 ffeste_io_iostat_is_temp_ = TRUE;
3803 ffeste_io_iostat_
3804 = ffecom_make_tempvar ("write", ffecom_integer_type_node,
3805 FFETARGET_charactersizeNONE, -1);
3807 else
3809 /* No IOSTAT= or ERR= specification. */
3811 ffeste_io_iostat_is_temp_ = FALSE;
3812 ffeste_io_iostat_ = NULL_TREE;
3815 /* Now prescan, then convert, all the arguments. */
3817 if (unit == FFESTV_unitCHAREXPR)
3818 cilist = ffeste_io_icilist_ (errl || iostat,
3819 info->write_spec[FFESTP_writeixUNIT].u.expr,
3820 FALSE, format,
3821 &info->write_spec[FFESTP_writeixFORMAT]);
3822 else
3823 cilist = ffeste_io_cilist_ (errl || iostat, unit,
3824 info->write_spec[FFESTP_writeixUNIT].u.expr,
3825 6, FALSE, format,
3826 &info->write_spec[FFESTP_writeixFORMAT],
3827 rec,
3828 info->write_spec[FFESTP_writeixREC].u.expr);
3830 /* If there is no end function, then there are no item functions (i.e.
3831 it's a NAMELIST), and vice versa by the way. In this situation, don't
3832 generate the "if (iostat != 0) goto label;" if the label is temp abort
3833 label, since we're gonna fall through to there anyway. */
3835 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3836 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3839 /* WRITE statement -- I/O item. */
3841 void
3842 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
3844 ffeste_check_item_ ();
3846 if (expr == NULL)
3847 return;
3849 if (ffebld_op (expr) == FFEBLD_opANY)
3850 return;
3852 if (ffebld_op (expr) == FFEBLD_opIMPDO)
3853 ffeste_io_impdo_ (expr, expr_token);
3854 else
3856 ffeste_start_stmt_ ();
3858 ffecom_prepare_arg_ptr_to_expr (expr);
3860 ffecom_prepare_end ();
3862 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3864 ffeste_end_stmt_ ();
3868 /* WRITE statement -- end. */
3870 void
3871 ffeste_R910_finish ()
3873 ffeste_check_finish_ ();
3875 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3876 label, since we're gonna fall through to there anyway. */
3878 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3879 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3880 NULL_TREE),
3881 ! ffeste_io_abort_is_temp_);
3883 /* If we've got a temp label, generate its code here. */
3885 if (ffeste_io_abort_is_temp_)
3887 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3888 emit_nop ();
3889 expand_label (ffeste_io_abort_);
3891 assert (ffeste_io_err_ == NULL_TREE);
3894 ffeste_end_stmt_ ();
3897 /* PRINT statement -- start. */
3899 void
3900 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
3902 ffecomGfrt start;
3903 ffecomGfrt end;
3904 tree cilist;
3906 ffeste_check_start_ ();
3908 ffeste_emit_line_note_ ();
3910 /* First determine the start, per-item, and end run-time functions to
3911 call. The per-item function is picked by choosing an ffeste function
3912 to call to handle a given item; it knows how to generate a call to the
3913 appropriate run-time function, and is called an "I/O driver". */
3915 switch (format)
3917 case FFESTV_formatLABEL: /* FMT=10 */
3918 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3919 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3920 ffeste_io_driver_ = ffeste_io_dofio_;
3921 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3922 break;
3924 case FFESTV_formatASTERISK: /* FMT=* */
3925 ffeste_io_driver_ = ffeste_io_dolio_;
3926 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3927 break;
3929 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3930 /FOO/] */
3931 ffeste_io_driver_ = NULL; /* No start or driver function. */
3932 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3933 break;
3935 default:
3936 assert ("Weird stuff" == NULL);
3937 start = FFECOM_gfrt, end = FFECOM_gfrt;
3938 break;
3940 ffeste_io_endgfrt_ = end;
3942 ffeste_start_stmt_ ();
3944 ffeste_io_end_ = NULL_TREE;
3945 ffeste_io_err_ = NULL_TREE;
3946 ffeste_io_abort_ = NULL_TREE;
3947 ffeste_io_abort_is_temp_ = FALSE;
3948 ffeste_io_iostat_is_temp_ = FALSE;
3949 ffeste_io_iostat_ = NULL_TREE;
3951 /* Now prescan, then convert, all the arguments. */
3953 cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
3954 &info->print_spec[FFESTP_printixFORMAT],
3955 FALSE, NULL);
3957 /* If there is no end function, then there are no item functions (i.e.
3958 it's a NAMELIST), and vice versa by the way. In this situation, don't
3959 generate the "if (iostat != 0) goto label;" if the label is temp abort
3960 label, since we're gonna fall through to there anyway. */
3962 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3963 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3966 /* PRINT statement -- I/O item. */
3968 void
3969 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
3971 ffeste_check_item_ ();
3973 if (expr == NULL)
3974 return;
3976 if (ffebld_op (expr) == FFEBLD_opANY)
3977 return;
3979 if (ffebld_op (expr) == FFEBLD_opIMPDO)
3980 ffeste_io_impdo_ (expr, expr_token);
3981 else
3983 ffeste_start_stmt_ ();
3985 ffecom_prepare_arg_ptr_to_expr (expr);
3987 ffecom_prepare_end ();
3989 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3991 ffeste_end_stmt_ ();
3995 /* PRINT statement -- end. */
3997 void
3998 ffeste_R911_finish ()
4000 ffeste_check_finish_ ();
4002 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4003 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4004 NULL_TREE),
4005 FALSE);
4007 ffeste_end_stmt_ ();
4010 /* BACKSPACE statement. */
4012 void
4013 ffeste_R919 (ffestpBeruStmt *info)
4015 ffeste_check_simple_ ();
4017 ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4020 /* ENDFILE statement. */
4022 void
4023 ffeste_R920 (ffestpBeruStmt *info)
4025 ffeste_check_simple_ ();
4027 ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4030 /* REWIND statement. */
4032 void
4033 ffeste_R921 (ffestpBeruStmt *info)
4035 ffeste_check_simple_ ();
4037 ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4040 /* INQUIRE statement (non-IOLENGTH version). */
4042 void
4043 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4045 tree args;
4046 bool iostat;
4047 bool errl;
4049 ffeste_check_simple_ ();
4051 ffeste_emit_line_note_ ();
4053 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4055 iostat = specified (FFESTP_inquireixIOSTAT);
4056 errl = specified (FFESTP_inquireixERR);
4058 #undef specified
4060 ffeste_start_stmt_ ();
4062 if (errl)
4064 ffeste_io_err_
4065 = ffeste_io_abort_
4066 = ffecom_lookup_label
4067 (info->inquire_spec[FFESTP_inquireixERR].u.label);
4068 ffeste_io_abort_is_temp_ = FALSE;
4070 else
4072 ffeste_io_err_ = NULL_TREE;
4074 if ((ffeste_io_abort_is_temp_ = iostat))
4075 ffeste_io_abort_ = ffecom_temp_label ();
4076 else
4077 ffeste_io_abort_ = NULL_TREE;
4080 if (iostat)
4082 /* Have IOSTAT= specification. */
4084 ffeste_io_iostat_is_temp_ = FALSE;
4085 ffeste_io_iostat_ = ffecom_expr
4086 (info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4088 else if (ffeste_io_abort_ != NULL_TREE)
4090 /* Have no IOSTAT= but have ERR=. */
4092 ffeste_io_iostat_is_temp_ = TRUE;
4093 ffeste_io_iostat_
4094 = ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
4095 FFETARGET_charactersizeNONE, -1);
4097 else
4099 /* No IOSTAT= or ERR= specification. */
4101 ffeste_io_iostat_is_temp_ = FALSE;
4102 ffeste_io_iostat_ = NULL_TREE;
4105 /* Now prescan, then convert, all the arguments. */
4107 args
4108 = ffeste_io_inlist_ (errl || iostat,
4109 &info->inquire_spec[FFESTP_inquireixUNIT],
4110 &info->inquire_spec[FFESTP_inquireixFILE],
4111 &info->inquire_spec[FFESTP_inquireixEXIST],
4112 &info->inquire_spec[FFESTP_inquireixOPENED],
4113 &info->inquire_spec[FFESTP_inquireixNUMBER],
4114 &info->inquire_spec[FFESTP_inquireixNAMED],
4115 &info->inquire_spec[FFESTP_inquireixNAME],
4116 &info->inquire_spec[FFESTP_inquireixACCESS],
4117 &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4118 &info->inquire_spec[FFESTP_inquireixDIRECT],
4119 &info->inquire_spec[FFESTP_inquireixFORM],
4120 &info->inquire_spec[FFESTP_inquireixFORMATTED],
4121 &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4122 &info->inquire_spec[FFESTP_inquireixRECL],
4123 &info->inquire_spec[FFESTP_inquireixNEXTREC],
4124 &info->inquire_spec[FFESTP_inquireixBLANK]);
4126 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4127 label, since we're gonna fall through to there anyway. */
4129 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
4130 ! ffeste_io_abort_is_temp_);
4132 /* If we've got a temp label, generate its code here. */
4134 if (ffeste_io_abort_is_temp_)
4136 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4137 emit_nop ();
4138 expand_label (ffeste_io_abort_);
4140 assert (ffeste_io_err_ == NULL_TREE);
4143 ffeste_end_stmt_ ();
4146 /* INQUIRE(IOLENGTH=expr) statement -- start. */
4148 void
4149 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4151 ffeste_check_start_ ();
4153 assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4155 ffeste_emit_line_note_ ();
4158 /* INQUIRE(IOLENGTH=expr) statement -- I/O item. */
4160 void
4161 ffeste_R923B_item (ffebld expr UNUSED)
4163 ffeste_check_item_ ();
4166 /* INQUIRE(IOLENGTH=expr) statement -- end. */
4168 void
4169 ffeste_R923B_finish ()
4171 ffeste_check_finish_ ();
4174 /* ffeste_R1001 -- FORMAT statement
4176 ffeste_R1001(format_list); */
4178 void
4179 ffeste_R1001 (ffests s)
4181 tree t;
4182 tree ttype;
4183 tree maxindex;
4184 tree var;
4186 ffeste_check_simple_ ();
4188 assert (ffeste_label_formatdef_ != NULL);
4190 ffeste_emit_line_note_ ();
4192 t = build_string (ffests_length (s), ffests_text (s));
4194 TREE_TYPE (t)
4195 = build_type_variant (build_array_type
4196 (char_type_node,
4197 build_range_type (integer_type_node,
4198 integer_one_node,
4199 build_int_2 (ffests_length (s),
4200 0))),
4201 1, 0);
4202 TREE_CONSTANT (t) = 1;
4203 TREE_STATIC (t) = 1;
4205 var = ffecom_lookup_label (ffeste_label_formatdef_);
4206 if ((var != NULL_TREE)
4207 && (TREE_CODE (var) == VAR_DECL))
4209 DECL_INITIAL (var) = t;
4210 maxindex = build_int_2 (ffests_length (s) - 1, 0);
4211 ttype = TREE_TYPE (var);
4212 TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
4213 integer_zero_node,
4214 maxindex);
4215 if (!TREE_TYPE (maxindex))
4216 TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
4217 layout_type (ttype);
4218 rest_of_decl_compilation (var, NULL, 1, 0);
4219 expand_decl (var);
4220 expand_decl_init (var);
4223 ffeste_label_formatdef_ = NULL;
4226 /* END PROGRAM. */
4228 void
4229 ffeste_R1103 ()
4233 /* END BLOCK DATA. */
4235 void
4236 ffeste_R1112 ()
4240 /* CALL statement. */
4242 void
4243 ffeste_R1212 (ffebld expr)
4245 ffebld args;
4246 ffebld arg;
4247 ffebld labels = NULL; /* First in list of LABTERs. */
4248 ffebld prevlabels = NULL;
4249 ffebld prevargs = NULL;
4251 ffeste_check_simple_ ();
4253 args = ffebld_right (expr);
4255 ffeste_emit_line_note_ ();
4257 /* Here we split the list at ffebld_right(expr) into two lists: one at
4258 ffebld_right(expr) consisting of all items that are not LABTERs, the
4259 other at labels consisting of all items that are LABTERs. Then, if
4260 the latter list is NULL, we have an ordinary call, else we have a call
4261 with alternate returns. */
4263 for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
4265 if (((arg = ffebld_head (args)) == NULL)
4266 || (ffebld_op (arg) != FFEBLD_opLABTER))
4268 if (prevargs == NULL)
4270 prevargs = args;
4271 ffebld_set_right (expr, args);
4273 else
4275 ffebld_set_trail (prevargs, args);
4276 prevargs = args;
4279 else
4281 if (prevlabels == NULL)
4283 prevlabels = labels = args;
4285 else
4287 ffebld_set_trail (prevlabels, args);
4288 prevlabels = args;
4292 if (prevlabels == NULL)
4293 labels = NULL;
4294 else
4295 ffebld_set_trail (prevlabels, NULL);
4296 if (prevargs == NULL)
4297 ffebld_set_right (expr, NULL);
4298 else
4299 ffebld_set_trail (prevargs, NULL);
4301 ffeste_start_stmt_ ();
4303 /* No temporaries are actually needed at this level, but we go
4304 through the motions anyway, just to be sure in case they do
4305 get made. Temporaries needed for arguments should be in the
4306 scopes of inner blocks, and if clean-up actions are supported,
4307 such as CALL-ing an intrinsic that writes to an argument of one
4308 type when a variable of a different type is provided (requiring
4309 assignment to the variable from a temporary after the library
4310 routine returns), the clean-up must be done by the expression
4311 evaluator, generally, to handle alternate returns (which we hope
4312 won't ever be supported by intrinsics, but might be a similar
4313 issue, such as CALL-ing an F90-style subroutine with an INTERFACE
4314 block). That implies the expression evaluator will have to
4315 recognize the need for its own temporary anyway, meaning it'll
4316 construct a block within the one constructed here. */
4318 ffecom_prepare_expr (expr);
4320 ffecom_prepare_end ();
4322 if (labels == NULL)
4323 expand_expr_stmt (ffecom_expr (expr));
4324 else
4326 tree texpr;
4327 tree value;
4328 tree tlabel;
4329 int caseno;
4330 int pushok;
4331 tree duplicate;
4332 ffebld label;
4334 texpr = ffecom_expr (expr);
4335 expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
4337 for (caseno = 1, label = labels;
4338 label != NULL;
4339 ++caseno, label = ffebld_trail (label))
4341 value = build_int_2 (caseno, 0);
4342 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
4344 pushok = pushcase (value, convert, tlabel, &duplicate);
4345 assert (pushok == 0);
4347 tlabel
4348 = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
4349 if ((tlabel == NULL_TREE)
4350 || (TREE_CODE (tlabel) == ERROR_MARK))
4351 continue;
4352 TREE_USED (tlabel) = 1;
4353 expand_goto (tlabel);
4356 expand_end_case (texpr);
4359 ffeste_end_stmt_ ();
4362 /* END FUNCTION. */
4364 void
4365 ffeste_R1221 ()
4369 /* END SUBROUTINE. */
4371 void
4372 ffeste_R1225 ()
4376 /* ENTRY statement. */
4378 void
4379 ffeste_R1226 (ffesymbol entry)
4381 tree label;
4383 ffeste_check_simple_ ();
4385 label = ffesymbol_hook (entry).length_tree;
4387 ffeste_emit_line_note_ ();
4389 if (label == error_mark_node)
4390 return;
4392 DECL_INITIAL (label) = error_mark_node;
4393 emit_nop ();
4394 expand_label (label);
4397 /* RETURN statement. */
4399 void
4400 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
4402 tree rtn;
4404 ffeste_check_simple_ ();
4406 ffeste_emit_line_note_ ();
4408 ffeste_start_stmt_ ();
4410 ffecom_prepare_return_expr (expr);
4412 ffecom_prepare_end ();
4414 rtn = ffecom_return_expr (expr);
4416 if ((rtn == NULL_TREE)
4417 || (rtn == error_mark_node))
4418 expand_null_return ();
4419 else
4421 tree result = DECL_RESULT (current_function_decl);
4423 if ((result != error_mark_node)
4424 && (TREE_TYPE (result) != error_mark_node))
4425 expand_return (ffecom_modify (NULL_TREE,
4426 result,
4427 convert (TREE_TYPE (result),
4428 rtn)));
4429 else
4430 expand_null_return ();
4433 ffeste_end_stmt_ ();
4436 /* REWRITE statement -- start. */
4438 #if FFESTR_VXT
4439 void
4440 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
4442 ffeste_check_start_ ();
4445 /* REWRITE statement -- I/O item. */
4447 void
4448 ffeste_V018_item (ffebld expr)
4450 ffeste_check_item_ ();
4453 /* REWRITE statement -- end. */
4455 void
4456 ffeste_V018_finish ()
4458 ffeste_check_finish_ ();
4461 /* ACCEPT statement -- start. */
4463 void
4464 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
4466 ffeste_check_start_ ();
4469 /* ACCEPT statement -- I/O item. */
4471 void
4472 ffeste_V019_item (ffebld expr)
4474 ffeste_check_item_ ();
4477 /* ACCEPT statement -- end. */
4479 void
4480 ffeste_V019_finish ()
4482 ffeste_check_finish_ ();
4485 #endif
4486 /* TYPE statement -- start. */
4488 void
4489 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
4490 ffestvFormat format UNUSED)
4492 ffeste_check_start_ ();
4495 /* TYPE statement -- I/O item. */
4497 void
4498 ffeste_V020_item (ffebld expr UNUSED)
4500 ffeste_check_item_ ();
4503 /* TYPE statement -- end. */
4505 void
4506 ffeste_V020_finish ()
4508 ffeste_check_finish_ ();
4511 /* DELETE statement. */
4513 #if FFESTR_VXT
4514 void
4515 ffeste_V021 (ffestpDeleteStmt *info)
4517 ffeste_check_simple_ ();
4520 /* UNLOCK statement. */
4522 void
4523 ffeste_V022 (ffestpBeruStmt *info)
4525 ffeste_check_simple_ ();
4528 /* ENCODE statement -- start. */
4530 void
4531 ffeste_V023_start (ffestpVxtcodeStmt *info)
4533 ffeste_check_start_ ();
4536 /* ENCODE statement -- I/O item. */
4538 void
4539 ffeste_V023_item (ffebld expr)
4541 ffeste_check_item_ ();
4544 /* ENCODE statement -- end. */
4546 void
4547 ffeste_V023_finish ()
4549 ffeste_check_finish_ ();
4552 /* DECODE statement -- start. */
4554 void
4555 ffeste_V024_start (ffestpVxtcodeStmt *info)
4557 ffeste_check_start_ ();
4560 /* DECODE statement -- I/O item. */
4562 void
4563 ffeste_V024_item (ffebld expr)
4565 ffeste_check_item_ ();
4568 /* DECODE statement -- end. */
4570 void
4571 ffeste_V024_finish ()
4573 ffeste_check_finish_ ();
4576 /* DEFINEFILE statement -- start. */
4578 void
4579 ffeste_V025_start ()
4581 ffeste_check_start_ ();
4584 /* DEFINE FILE statement -- item. */
4586 void
4587 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
4589 ffeste_check_item_ ();
4592 /* DEFINE FILE statement -- end. */
4594 void
4595 ffeste_V025_finish ()
4597 ffeste_check_finish_ ();
4600 /* FIND statement. */
4602 void
4603 ffeste_V026 (ffestpFindStmt *info)
4605 ffeste_check_simple_ ();
4608 #endif
4610 #ifdef ENABLE_CHECKING
4611 void
4612 ffeste_terminate_2 (void)
4614 assert (! ffeste_top_block_);
4616 #endif
4618 #include "gt-f-ste.h"