Add D30V options
[official-gcc.git] / gcc / f / ste.c
blobea927cca7a505d02a0a70dd69b16d30549cfe85b
1 /* ste.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 2000 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"
35 #if FFECOM_targetCURRENT == FFECOM_targetGCC
36 #include "rtl.h"
37 #include "toplev.h"
38 #include "ggc.h"
39 #endif
41 #include "ste.h"
42 #include "bld.h"
43 #include "com.h"
44 #include "expr.h"
45 #include "lab.h"
46 #include "lex.h"
47 #include "sta.h"
48 #include "stp.h"
49 #include "str.h"
50 #include "sts.h"
51 #include "stt.h"
52 #include "stv.h"
53 #include "stw.h"
54 #include "symbol.h"
56 /* Externals defined here. */
59 /* Simple definitions and enumerations. */
61 typedef enum
63 FFESTE_stateletSIMPLE_, /* Expecting simple/start. */
64 FFESTE_stateletATTRIB_, /* Expecting attrib/item/itemstart. */
65 FFESTE_stateletITEM_, /* Expecting item/itemstart/finish. */
66 FFESTE_stateletITEMVALS_, /* Expecting itemvalue/itemendvals. */
67 FFESTE_
68 } ffesteStatelet_;
70 /* Internal typedefs. */
73 /* Private include files. */
76 /* Internal structure definitions. */
79 /* Static objects accessed by functions in this module. */
81 static ffesteStatelet_ ffeste_statelet_ = FFESTE_stateletSIMPLE_;
82 #if FFECOM_targetCURRENT == FFECOM_targetGCC
83 static ffelab ffeste_label_formatdef_ = NULL;
84 static tree (*ffeste_io_driver_) (ffebld expr); /* do?io. */
85 static ffecomGfrt ffeste_io_endgfrt_; /* end function to call. */
86 static tree ffeste_io_abort_; /* abort-io label or NULL_TREE. */
87 static bool ffeste_io_abort_is_temp_; /* abort-io label is a temp. */
88 static tree ffeste_io_end_; /* END= label or NULL_TREE. */
89 static tree ffeste_io_err_; /* ERR= label or NULL_TREE. */
90 static tree ffeste_io_iostat_; /* IOSTAT= var or NULL_TREE. */
91 static bool ffeste_io_iostat_is_temp_; /* IOSTAT= var is a temp. */
92 #endif
94 /* Static functions (internal). */
96 #if FFECOM_targetCURRENT == FFECOM_targetGCC
97 static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
98 tree *xitersvar, ffebld var,
99 ffebld start, ffelexToken start_token,
100 ffebld end, ffelexToken end_token,
101 ffebld incr, ffelexToken incr_token,
102 const char *msg);
103 static void ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr,
104 tree itersvar);
105 static void ffeste_io_call_ (tree call, bool do_check);
106 static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
107 static tree ffeste_io_dofio_ (ffebld expr);
108 static tree ffeste_io_dolio_ (ffebld expr);
109 static tree ffeste_io_douio_ (ffebld expr);
110 static tree ffeste_io_ialist_ (bool have_err, ffestvUnit unit,
111 ffebld unit_expr, int unit_dflt);
112 static tree ffeste_io_cilist_ (bool have_err, ffestvUnit unit,
113 ffebld unit_expr, int unit_dflt,
114 bool have_end, ffestvFormat format,
115 ffestpFile *format_spec, bool rec,
116 ffebld rec_expr);
117 static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
118 ffestpFile *stat_spec);
119 static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
120 bool have_end, ffestvFormat format,
121 ffestpFile *format_spec);
122 static tree ffeste_io_inlist_ (bool have_err,
123 ffestpFile *unit_spec,
124 ffestpFile *file_spec,
125 ffestpFile *exist_spec,
126 ffestpFile *open_spec,
127 ffestpFile *number_spec,
128 ffestpFile *named_spec,
129 ffestpFile *name_spec,
130 ffestpFile *access_spec,
131 ffestpFile *sequential_spec,
132 ffestpFile *direct_spec,
133 ffestpFile *form_spec,
134 ffestpFile *formatted_spec,
135 ffestpFile *unformatted_spec,
136 ffestpFile *recl_spec,
137 ffestpFile *nextrec_spec,
138 ffestpFile *blank_spec);
139 static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
140 ffestpFile *file_spec,
141 ffestpFile *stat_spec,
142 ffestpFile *access_spec,
143 ffestpFile *form_spec,
144 ffestpFile *recl_spec,
145 ffestpFile *blank_spec);
146 static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
147 #elif FFECOM_targetCURRENT == FFECOM_targetFFE
148 static void ffeste_subr_file_ (const char *kw, ffestpFile *spec);
149 #else
150 #error
151 #endif
153 /* Internal macros. */
155 #if FFECOM_targetCURRENT == FFECOM_targetGCC
156 #define ffeste_emit_line_note_() \
157 emit_line_note (input_filename, lineno)
158 #endif
159 #define ffeste_check_simple_() \
160 assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_)
161 #define ffeste_check_start_() \
162 assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_); \
163 ffeste_statelet_ = FFESTE_stateletATTRIB_
164 #define ffeste_check_attrib_() \
165 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_)
166 #define ffeste_check_item_() \
167 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
168 || ffeste_statelet_ == FFESTE_stateletITEM_); \
169 ffeste_statelet_ = FFESTE_stateletITEM_
170 #define ffeste_check_item_startvals_() \
171 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
172 || ffeste_statelet_ == FFESTE_stateletITEM_); \
173 ffeste_statelet_ = FFESTE_stateletITEMVALS_
174 #define ffeste_check_item_value_() \
175 assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_)
176 #define ffeste_check_item_endvals_() \
177 assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_); \
178 ffeste_statelet_ = FFESTE_stateletITEM_
179 #define ffeste_check_finish_() \
180 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
181 || ffeste_statelet_ == FFESTE_stateletITEM_); \
182 ffeste_statelet_ = FFESTE_stateletSIMPLE_
184 #define ffeste_f2c_init_charnolen_(Exp,Init,Spec) \
185 do \
187 if ((Spec)->kw_or_val_present) \
188 Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &ignore); \
189 else \
190 Exp = null_pointer_node; \
191 if (Exp) \
192 Init = Exp; \
193 else \
195 Init = null_pointer_node; \
196 constantp = FALSE; \
198 } while(0)
200 #define ffeste_f2c_init_char_(Exp,Init,Lenexp,Leninit,Spec) \
201 do \
203 if ((Spec)->kw_or_val_present) \
204 Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &Lenexp); \
205 else \
207 Exp = null_pointer_node; \
208 Lenexp = ffecom_f2c_ftnlen_zero_node; \
210 if (Exp) \
211 Init = Exp; \
212 else \
214 Init = null_pointer_node; \
215 constantp = FALSE; \
217 if (Lenexp) \
218 Leninit = Lenexp; \
219 else \
221 Leninit = ffecom_f2c_ftnlen_zero_node; \
222 constantp = FALSE; \
224 } while(0)
226 #define ffeste_f2c_init_flag_(Flag,Init) \
227 do \
229 Init = convert (ffecom_f2c_flag_type_node, \
230 (Flag) ? integer_one_node : integer_zero_node); \
231 } while(0)
233 #define ffeste_f2c_init_format_(Exp,Init,Spec) \
234 do \
236 Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, NULL); \
237 if (Exp) \
238 Init = Exp; \
239 else \
241 Init = null_pointer_node; \
242 constantp = FALSE; \
244 } while(0)
246 #define ffeste_f2c_init_int_(Exp,Init,Spec) \
247 do \
249 if ((Spec)->kw_or_val_present) \
250 Exp = ffecom_const_expr ((Spec)->u.expr); \
251 else \
252 Exp = ffecom_integer_zero_node; \
253 if (Exp) \
254 Init = Exp; \
255 else \
257 Init = ffecom_integer_zero_node; \
258 constantp = FALSE; \
260 } while(0)
262 #define ffeste_f2c_init_ptrtoint_(Exp,Init,Spec) \
263 do \
265 if ((Spec)->kw_or_val_present) \
266 Exp = ffecom_ptr_to_const_expr ((Spec)->u.expr); \
267 else \
268 Exp = null_pointer_node; \
269 if (Exp) \
270 Init = Exp; \
271 else \
273 Init = null_pointer_node; \
274 constantp = FALSE; \
276 } while(0)
278 #define ffeste_f2c_init_next_(Init) \
279 do \
281 TREE_CHAIN (initn) = build_tree_list ((field = TREE_CHAIN (field)), \
282 (Init)); \
283 initn = TREE_CHAIN(initn); \
284 } while(0)
286 #define ffeste_f2c_prepare_charnolen_(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_char_(Spec,Exp) \
294 do \
296 if (! (Exp)) \
297 ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
298 } while(0)
300 #define ffeste_f2c_prepare_format_(Spec,Exp) \
301 do \
303 if (! (Exp)) \
304 ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
305 } while(0)
307 #define ffeste_f2c_prepare_int_(Spec,Exp) \
308 do \
310 if (! (Exp)) \
311 ffecom_prepare_expr ((Spec)->u.expr); \
312 } while(0)
314 #define ffeste_f2c_prepare_ptrtoint_(Spec,Exp) \
315 do \
317 if (! (Exp)) \
318 ffecom_prepare_ptr_to_expr ((Spec)->u.expr); \
319 } while(0)
321 #define ffeste_f2c_compile_(Field,Exp) \
322 do \
324 tree exz; \
325 if ((Exp)) \
327 exz = ffecom_modify (void_type_node, \
328 ffecom_2 (COMPONENT_REF, TREE_TYPE (Field), \
329 t, (Field)), \
330 (Exp)); \
331 expand_expr_stmt (exz); \
333 } while(0)
335 #define ffeste_f2c_compile_charnolen_(Field,Spec,Exp) \
336 do \
338 tree exq; \
339 if (! (Exp)) \
341 exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &ignore); \
342 ffeste_f2c_compile_ ((Field), exq); \
344 } while(0)
346 #define ffeste_f2c_compile_char_(Field,Lenfield,Spec,Exp,Lenexp) \
347 do \
349 tree exq = (Exp); \
350 tree lenexq = (Lenexp); \
351 int need_exq = (! exq); \
352 int need_lenexq = (! lenexq); \
353 if (need_exq || need_lenexq) \
355 exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &lenexq); \
356 if (need_exq) \
357 ffeste_f2c_compile_ ((Field), exq); \
358 if (need_lenexq) \
359 ffeste_f2c_compile_ ((Lenfield), lenexq); \
361 } while(0)
363 #define ffeste_f2c_compile_format_(Field,Spec,Exp) \
364 do \
366 tree exq; \
367 if (! (Exp)) \
369 exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, NULL); \
370 ffeste_f2c_compile_ ((Field), exq); \
372 } while(0)
374 #define ffeste_f2c_compile_int_(Field,Spec,Exp) \
375 do \
377 tree exq; \
378 if (! (Exp)) \
380 exq = ffecom_expr ((Spec)->u.expr); \
381 ffeste_f2c_compile_ ((Field), exq); \
383 } while(0)
385 #define ffeste_f2c_compile_ptrtoint_(Field,Spec,Exp) \
386 do \
388 tree exq; \
389 if (! (Exp)) \
391 exq = ffecom_ptr_to_expr ((Spec)->u.expr); \
392 ffeste_f2c_compile_ ((Field), exq); \
394 } while(0)
396 /* Start a Fortran block. */
398 #ifdef ENABLE_CHECKING
400 typedef struct gbe_block
402 struct gbe_block *outer;
403 ffestw block;
404 int lineno;
405 const char *input_filename;
406 bool is_stmt;
407 } *gbe_block;
409 gbe_block ffeste_top_block_ = NULL;
411 static void
412 ffeste_start_block_ (ffestw block)
414 gbe_block b = xmalloc (sizeof (*b));
416 b->outer = ffeste_top_block_;
417 b->block = block;
418 b->lineno = lineno;
419 b->input_filename = input_filename;
420 b->is_stmt = FALSE;
422 ffeste_top_block_ = b;
424 ffecom_start_compstmt ();
427 /* End a Fortran block. */
429 static void
430 ffeste_end_block_ (ffestw block)
432 gbe_block b = ffeste_top_block_;
434 assert (b);
435 assert (! b->is_stmt);
436 assert (b->block == block);
437 assert (! b->is_stmt);
439 ffeste_top_block_ = b->outer;
441 free (b);
443 clear_momentary ();
445 ffecom_end_compstmt ();
448 /* Start a Fortran statement.
450 Starts a back-end block, so temporaries can be managed, clean-ups
451 properly handled, etc. Nesting of statements *is* allowed -- the
452 handling of I/O items, even implied-DO I/O lists, within a READ,
453 PRINT, or WRITE statement is one example. */
455 static void
456 ffeste_start_stmt_(void)
458 gbe_block b = xmalloc (sizeof (*b));
460 b->outer = ffeste_top_block_;
461 b->block = NULL;
462 b->lineno = lineno;
463 b->input_filename = input_filename;
464 b->is_stmt = TRUE;
466 ffeste_top_block_ = b;
468 ffecom_start_compstmt ();
471 /* End a Fortran statement. */
473 static void
474 ffeste_end_stmt_(void)
476 gbe_block b = ffeste_top_block_;
478 assert (b);
479 assert (b->is_stmt);
481 ffeste_top_block_ = b->outer;
483 free (b);
485 clear_momentary ();
487 ffecom_end_compstmt ();
490 #else /* ! defined (ENABLE_CHECKING) */
492 #define ffeste_start_block_(b) ffecom_start_compstmt ()
493 #define ffeste_end_block_(b) \
494 do \
496 clear_momentary (); \
497 ffecom_end_compstmt (); \
498 } while(0)
499 #define ffeste_start_stmt_() ffeste_start_block_(NULL)
500 #define ffeste_end_stmt_() ffeste_end_block_(NULL)
502 #endif /* ! defined (ENABLE_CHECKING) */
504 /* Begin an iterative DO loop. Pass the block to start if applicable.
506 NOTE: Does _two_ push_momentary () calls, which the caller must
507 undo (by calling ffeste_end_iterdo_). */
509 #if FFECOM_targetCURRENT == FFECOM_targetGCC
510 static void
511 ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
512 tree *xitersvar, ffebld var,
513 ffebld start, ffelexToken start_token,
514 ffebld end, ffelexToken end_token,
515 ffebld incr, ffelexToken incr_token,
516 const char *msg)
518 tree tvar;
519 tree expr;
520 tree tstart;
521 tree tend;
522 tree tincr;
523 tree tincr_saved;
524 tree niters;
525 struct nesting *expanded_loop;
527 /* Want to have tvar, tincr, and niters for the whole loop body. */
529 if (block)
530 ffeste_start_block_ (block);
531 else
532 ffeste_start_stmt_ ();
534 niters = ffecom_make_tempvar (block ? "do" : "impdo",
535 ffecom_integer_type_node,
536 FFETARGET_charactersizeNONE, -1);
538 ffecom_prepare_expr (incr);
539 ffecom_prepare_expr_rw (NULL_TREE, var);
541 ffecom_prepare_end ();
543 tvar = ffecom_expr_rw (NULL_TREE, var);
544 tincr = ffecom_expr (incr);
546 if (TREE_CODE (tvar) == ERROR_MARK
547 || TREE_CODE (tincr) == ERROR_MARK)
549 if (block)
551 ffeste_end_block_ (block);
552 ffestw_set_do_tvar (block, error_mark_node);
554 else
556 ffeste_end_stmt_ ();
557 *xtvar = error_mark_node;
559 return;
562 /* Check whether incr is known to be zero, complain and fix. */
564 if (integer_zerop (tincr) || real_zerop (tincr))
566 ffebad_start (FFEBAD_DO_STEP_ZERO);
567 ffebad_here (0, ffelex_token_where_line (incr_token),
568 ffelex_token_where_column (incr_token));
569 ffebad_string (msg);
570 ffebad_finish ();
571 tincr = convert (TREE_TYPE (tvar), integer_one_node);
574 tincr_saved = ffecom_save_tree (tincr);
576 preserve_momentary ();
578 /* Want to have tstart, tend for just this statement. */
580 ffeste_start_stmt_ ();
582 ffecom_prepare_expr (start);
583 ffecom_prepare_expr (end);
585 ffecom_prepare_end ();
587 tstart = ffecom_expr (start);
588 tend = ffecom_expr (end);
590 if (TREE_CODE (tstart) == ERROR_MARK
591 || TREE_CODE (tend) == ERROR_MARK)
593 ffeste_end_stmt_ ();
595 if (block)
597 ffeste_end_block_ (block);
598 ffestw_set_do_tvar (block, error_mark_node);
600 else
602 ffeste_end_stmt_ ();
603 *xtvar = error_mark_node;
605 return;
608 /* For warnings only, nothing else happens here. */
610 tree try;
612 if (! ffe_is_onetrip ())
614 try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
615 tend,
616 tstart);
618 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
619 try,
620 tincr);
622 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
623 try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
624 tincr);
625 else
626 try = convert (integer_type_node,
627 ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
628 try,
629 tincr));
631 /* Warn if loop never executed, since we've done the evaluation
632 of the unofficial iteration count already. */
634 try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
635 try,
636 convert (TREE_TYPE (tvar),
637 integer_zero_node)));
639 if (integer_onep (try))
641 ffebad_start (FFEBAD_DO_NULL);
642 ffebad_here (0, ffelex_token_where_line (start_token),
643 ffelex_token_where_column (start_token));
644 ffebad_string (msg);
645 ffebad_finish ();
649 /* Warn if end plus incr would overflow. */
651 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
652 tend,
653 tincr);
655 if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
656 && TREE_CONSTANT_OVERFLOW (try))
658 ffebad_start (FFEBAD_DO_END_OVERFLOW);
659 ffebad_here (0, ffelex_token_where_line (end_token),
660 ffelex_token_where_column (end_token));
661 ffebad_string (msg);
662 ffebad_finish ();
666 /* Do the initial assignment into the DO var. */
668 tstart = ffecom_save_tree (tstart);
670 expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
671 tend,
672 tstart);
674 if (! ffe_is_onetrip ())
676 expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
677 expr,
678 convert (TREE_TYPE (expr), tincr_saved));
681 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
682 expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
683 expr,
684 tincr_saved);
685 else
686 expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
687 expr,
688 tincr_saved);
690 #if 1 /* New, F90-approved approach: convert to default INTEGER. */
691 if (TREE_TYPE (tvar) != error_mark_node)
692 expr = convert (ffecom_integer_type_node, expr);
693 #else /* Old approach; convert to INTEGER unless that's a narrowing. */
694 if ((TREE_TYPE (tvar) != error_mark_node)
695 && ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
696 || ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
697 && ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
698 != INTEGER_CST)
699 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
700 <= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
701 /* Convert unless promoting INTEGER type of any kind downward to
702 default INTEGER; else leave as, say, INTEGER*8 (long long int). */
703 expr = convert (ffecom_integer_type_node, expr);
704 #endif
706 assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
707 == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
709 expr = ffecom_modify (void_type_node, niters, expr);
710 expand_expr_stmt (expr);
712 expr = ffecom_modify (void_type_node, tvar, tstart);
713 expand_expr_stmt (expr);
715 ffeste_end_stmt_ ();
717 expanded_loop = expand_start_loop_continue_elsewhere (!! block);
718 if (block)
719 ffestw_set_do_hook (block, expanded_loop);
721 if (! ffe_is_onetrip ())
723 expr = ffecom_truth_value
724 (ffecom_2 (GE_EXPR, integer_type_node,
725 ffecom_2 (PREDECREMENT_EXPR,
726 TREE_TYPE (niters),
727 niters,
728 convert (TREE_TYPE (niters),
729 ffecom_integer_one_node)),
730 convert (TREE_TYPE (niters),
731 ffecom_integer_zero_node)));
733 expand_exit_loop_if_false (0, expr);
736 if (block)
738 ffestw_set_do_tvar (block, tvar);
739 ffestw_set_do_incr_saved (block, tincr_saved);
740 ffestw_set_do_count_var (block, niters);
742 else
744 *xtvar = tvar;
745 *xtincr = tincr_saved;
746 *xitersvar = niters;
750 #endif
752 /* End an iterative DO loop. Pass the same iteration variable and increment
753 value trees that were generated in the paired _begin_ call. */
755 #if FFECOM_targetCURRENT == FFECOM_targetGCC
756 static void
757 ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
759 tree expr;
760 tree niters = itersvar;
762 if (tvar == error_mark_node)
763 return;
765 expand_loop_continue_here ();
767 ffeste_start_stmt_ ();
769 if (ffe_is_onetrip ())
771 expr = ffecom_truth_value
772 (ffecom_2 (GE_EXPR, integer_type_node,
773 ffecom_2 (PREDECREMENT_EXPR,
774 TREE_TYPE (niters),
775 niters,
776 convert (TREE_TYPE (niters),
777 ffecom_integer_one_node)),
778 convert (TREE_TYPE (niters),
779 ffecom_integer_zero_node)));
781 expand_exit_loop_if_false (0, expr);
784 expr = ffecom_modify (void_type_node, tvar,
785 ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
786 tvar,
787 tincr));
788 expand_expr_stmt (expr);
790 /* Lose the stuff we just built. */
791 ffeste_end_stmt_ ();
793 expand_end_loop ();
795 /* Lose the tvar and incr_saved trees. */
796 if (block)
797 ffeste_end_block_ (block);
798 else
799 ffeste_end_stmt_ ();
801 #endif
803 /* Generate call to run-time I/O routine. */
805 #if FFECOM_targetCURRENT == FFECOM_targetGCC
806 static void
807 ffeste_io_call_ (tree call, bool do_check)
809 /* Generate the call and optional assignment into iostat var. */
811 TREE_SIDE_EFFECTS (call) = 1;
812 if (ffeste_io_iostat_ != NULL_TREE)
813 call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
814 ffeste_io_iostat_, call);
815 expand_expr_stmt (call);
817 if (! do_check
818 || ffeste_io_abort_ == NULL_TREE
819 || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
820 return;
822 /* Generate optional test. */
824 expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
825 expand_goto (ffeste_io_abort_);
826 expand_end_cond ();
828 #endif
830 /* Handle implied-DO in I/O list.
832 Expands code to start up the DO loop. Then for each item in the
833 DO loop, handles appropriately (possibly including recursively calling
834 itself). Then expands code to end the DO loop. */
836 #if FFECOM_targetCURRENT == FFECOM_targetGCC
837 static void
838 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
840 ffebld var = ffebld_head (ffebld_right (impdo));
841 ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
842 ffebld end = ffebld_head (ffebld_trail (ffebld_trail
843 (ffebld_right (impdo))));
844 ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
845 (ffebld_trail (ffebld_right (impdo)))));
846 ffebld list;
847 ffebld item;
848 tree tvar;
849 tree tincr;
850 tree titervar;
852 if (incr == NULL)
854 incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
855 ffebld_set_info (incr, ffeinfo_new
856 (FFEINFO_basictypeINTEGER,
857 FFEINFO_kindtypeINTEGERDEFAULT,
859 FFEINFO_kindENTITY,
860 FFEINFO_whereCONSTANT,
861 FFETARGET_charactersizeNONE));
864 /* Start the DO loop. */
866 start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
867 FFEEXPR_contextLET);
868 end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
869 FFEEXPR_contextLET);
870 incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
871 FFEEXPR_contextLET);
873 ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
874 start, impdo_token,
875 end, impdo_token,
876 incr, impdo_token,
877 "Implied DO loop");
879 /* Handle the list of items. */
881 for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
883 item = ffebld_head (list);
884 if (item == NULL)
885 continue;
887 /* Strip parens off items such as in "READ *,(A)". This is really a bug
888 in the user's code, but I've been told lots of code does this. */
889 while (ffebld_op (item) == FFEBLD_opPAREN)
890 item = ffebld_left (item);
892 if (ffebld_op (item) == FFEBLD_opANY)
893 continue;
895 if (ffebld_op (item) == FFEBLD_opIMPDO)
896 ffeste_io_impdo_ (item, impdo_token);
897 else
899 ffeste_start_stmt_ ();
901 ffecom_prepare_arg_ptr_to_expr (item);
903 ffecom_prepare_end ();
905 ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
907 ffeste_end_stmt_ ();
911 /* Generate end of implied-do construct. */
913 ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
915 #endif
917 /* I/O driver for formatted I/O item (do_fio)
919 Returns a tree for a CALL_EXPR to the do_fio function, which handles
920 a formatted I/O list item, along with the appropriate arguments for
921 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
922 for the CALL_EXPR, expand (emit) the expression, emit any assignment
923 of the result to an IOSTAT= variable, and emit any checking of the
924 result for errors. */
926 #if FFECOM_targetCURRENT == FFECOM_targetGCC
927 static tree
928 ffeste_io_dofio_ (ffebld expr)
930 tree num_elements;
931 tree variable;
932 tree size;
933 tree arglist;
934 ffeinfoBasictype bt;
935 ffeinfoKindtype kt;
936 bool is_complex;
938 bt = ffeinfo_basictype (ffebld_info (expr));
939 kt = ffeinfo_kindtype (ffebld_info (expr));
941 if ((bt == FFEINFO_basictypeANY)
942 || (kt == FFEINFO_kindtypeANY))
943 return error_mark_node;
945 if (bt == FFEINFO_basictypeCOMPLEX)
947 is_complex = TRUE;
948 bt = FFEINFO_basictypeREAL;
950 else
951 is_complex = FALSE;
953 variable = ffecom_arg_ptr_to_expr (expr, &size);
955 if ((variable == error_mark_node)
956 || (size == error_mark_node))
957 return error_mark_node;
959 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
960 { /* "(ftnlen) sizeof(type)" */
961 size = size_binop (CEIL_DIV_EXPR,
962 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
963 size_int (TYPE_PRECISION (char_type_node)
964 / BITS_PER_UNIT));
965 #if 0 /* Assume that while it is possible that char * is wider than
966 ftnlen, no object in Fortran space can get big enough for its
967 size to be wider than ftnlen. I really hope nobody wastes
968 time debugging a case where it can! */
969 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
970 >= TYPE_PRECISION (TREE_TYPE (size)));
971 #endif
972 size = convert (ffecom_f2c_ftnlen_type_node, size);
975 if (ffeinfo_rank (ffebld_info (expr)) == 0
976 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
977 num_elements
978 = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
979 else
981 num_elements
982 = size_binop (CEIL_DIV_EXPR,
983 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
984 convert (sizetype, size));
985 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
986 size_int (TYPE_PRECISION (char_type_node)
987 / BITS_PER_UNIT));
988 num_elements = convert (ffecom_f2c_ftnlen_type_node,
989 num_elements);
992 num_elements
993 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
994 num_elements);
996 variable = convert (string_type_node, variable);
998 arglist = build_tree_list (NULL_TREE, num_elements);
999 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
1000 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
1002 return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
1005 #endif
1006 /* I/O driver for list-directed I/O item (do_lio)
1008 Returns a tree for a CALL_EXPR to the do_lio function, which handles
1009 a list-directed I/O list item, along with the appropriate arguments for
1010 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
1011 for the CALL_EXPR, expand (emit) the expression, emit any assignment
1012 of the result to an IOSTAT= variable, and emit any checking of the
1013 result for errors. */
1015 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1016 static tree
1017 ffeste_io_dolio_ (ffebld expr)
1019 tree type_id;
1020 tree num_elements;
1021 tree variable;
1022 tree size;
1023 tree arglist;
1024 ffeinfoBasictype bt;
1025 ffeinfoKindtype kt;
1026 int tc;
1028 bt = ffeinfo_basictype (ffebld_info (expr));
1029 kt = ffeinfo_kindtype (ffebld_info (expr));
1031 if ((bt == FFEINFO_basictypeANY)
1032 || (kt == FFEINFO_kindtypeANY))
1033 return error_mark_node;
1035 tc = ffecom_f2c_typecode (bt, kt);
1036 assert (tc != -1);
1037 type_id = build_int_2 (tc, 0);
1039 type_id
1040 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
1041 convert (ffecom_f2c_ftnint_type_node,
1042 type_id));
1044 variable = ffecom_arg_ptr_to_expr (expr, &size);
1046 if ((type_id == error_mark_node)
1047 || (variable == error_mark_node)
1048 || (size == error_mark_node))
1049 return error_mark_node;
1051 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
1052 { /* "(ftnlen) sizeof(type)" */
1053 size = size_binop (CEIL_DIV_EXPR,
1054 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1055 size_int (TYPE_PRECISION (char_type_node)
1056 / BITS_PER_UNIT));
1057 #if 0 /* Assume that while it is possible that char * is wider than
1058 ftnlen, no object in Fortran space can get big enough for its
1059 size to be wider than ftnlen. I really hope nobody wastes
1060 time debugging a case where it can! */
1061 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1062 >= TYPE_PRECISION (TREE_TYPE (size)));
1063 #endif
1064 size = convert (ffecom_f2c_ftnlen_type_node, size);
1067 if (ffeinfo_rank (ffebld_info (expr)) == 0
1068 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1069 num_elements = ffecom_integer_one_node;
1070 else
1072 num_elements
1073 = size_binop (CEIL_DIV_EXPR,
1074 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1075 convert (sizetype, size));
1076 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1077 size_int (TYPE_PRECISION (char_type_node)
1078 / BITS_PER_UNIT));
1079 num_elements = convert (ffecom_f2c_ftnlen_type_node,
1080 num_elements);
1083 num_elements
1084 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1085 num_elements);
1087 variable = convert (string_type_node, variable);
1089 arglist = build_tree_list (NULL_TREE, type_id);
1090 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
1091 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
1092 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
1093 = build_tree_list (NULL_TREE, size);
1095 return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
1098 #endif
1099 /* I/O driver for unformatted I/O item (do_uio)
1101 Returns a tree for a CALL_EXPR to the do_uio function, which handles
1102 an unformatted I/O list item, along with the appropriate arguments for
1103 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
1104 for the CALL_EXPR, expand (emit) the expression, emit any assignment
1105 of the result to an IOSTAT= variable, and emit any checking of the
1106 result for errors. */
1108 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1109 static tree
1110 ffeste_io_douio_ (ffebld expr)
1112 tree num_elements;
1113 tree variable;
1114 tree size;
1115 tree arglist;
1116 ffeinfoBasictype bt;
1117 ffeinfoKindtype kt;
1118 bool is_complex;
1120 bt = ffeinfo_basictype (ffebld_info (expr));
1121 kt = ffeinfo_kindtype (ffebld_info (expr));
1123 if ((bt == FFEINFO_basictypeANY)
1124 || (kt == FFEINFO_kindtypeANY))
1125 return error_mark_node;
1127 if (bt == FFEINFO_basictypeCOMPLEX)
1129 is_complex = TRUE;
1130 bt = FFEINFO_basictypeREAL;
1132 else
1133 is_complex = FALSE;
1135 variable = ffecom_arg_ptr_to_expr (expr, &size);
1137 if ((variable == error_mark_node)
1138 || (size == error_mark_node))
1139 return error_mark_node;
1141 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
1142 { /* "(ftnlen) sizeof(type)" */
1143 size = size_binop (CEIL_DIV_EXPR,
1144 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1145 size_int (TYPE_PRECISION (char_type_node)
1146 / BITS_PER_UNIT));
1147 #if 0 /* Assume that while it is possible that char * is wider than
1148 ftnlen, no object in Fortran space can get big enough for its
1149 size to be wider than ftnlen. I really hope nobody wastes
1150 time debugging a case where it can! */
1151 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1152 >= TYPE_PRECISION (TREE_TYPE (size)));
1153 #endif
1154 size = convert (ffecom_f2c_ftnlen_type_node, size);
1157 if (ffeinfo_rank (ffebld_info (expr)) == 0
1158 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1159 num_elements
1160 = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
1161 else
1163 num_elements
1164 = size_binop (CEIL_DIV_EXPR,
1165 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1166 convert (sizetype, size));
1167 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1168 size_int (TYPE_PRECISION (char_type_node)
1169 / BITS_PER_UNIT));
1170 num_elements = convert (ffecom_f2c_ftnlen_type_node,
1171 num_elements);
1174 num_elements
1175 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1176 num_elements);
1178 variable = convert (string_type_node, variable);
1180 arglist = build_tree_list (NULL_TREE, num_elements);
1181 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
1182 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
1184 return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
1187 #endif
1188 /* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
1190 Returns a tree suitable as an argument list containing a pointer to
1191 a BACKSPACE/ENDFILE/REWIND control list. First, generates that control
1192 list, if necessary, along with any static and run-time initializations
1193 that are needed as specified by the arguments to this function.
1195 Must ensure that all expressions are prepared before being evaluated,
1196 for any whose evaluation might result in the generation of temporaries.
1198 Note that this means this function causes a transition, within the
1199 current block being code-generated via the back end, from the
1200 declaration of variables (temporaries) to the expanding of expressions,
1201 statements, etc. */
1203 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1204 static tree
1205 ffeste_io_ialist_ (bool have_err,
1206 ffestvUnit unit,
1207 ffebld unit_expr,
1208 int unit_dflt)
1210 static tree f2c_alist_struct = NULL_TREE;
1211 tree t;
1212 tree ttype;
1213 int yes;
1214 tree field;
1215 tree inits, initn;
1216 bool constantp = TRUE;
1217 static tree errfield, unitfield;
1218 tree errinit, unitinit;
1219 tree unitexp;
1220 static int mynumber = 0;
1222 if (f2c_alist_struct == NULL_TREE)
1224 tree ref;
1226 ref = make_node (RECORD_TYPE);
1228 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1229 ffecom_f2c_flag_type_node);
1230 unitfield = ffecom_decl_field (ref, errfield, "unit",
1231 ffecom_f2c_ftnint_type_node);
1233 TYPE_FIELDS (ref) = errfield;
1234 layout_type (ref);
1236 ggc_add_tree_root (&f2c_alist_struct, 1);
1238 f2c_alist_struct = ref;
1241 /* Try to do as much compile-time initialization of the structure
1242 as possible, to save run time. */
1244 ffeste_f2c_init_flag_ (have_err, errinit);
1246 switch (unit)
1248 case FFESTV_unitNONE:
1249 case FFESTV_unitASTERISK:
1250 unitinit = build_int_2 (unit_dflt, 0);
1251 unitexp = unitinit;
1252 break;
1254 case FFESTV_unitINTEXPR:
1255 unitexp = ffecom_const_expr (unit_expr);
1256 if (unitexp)
1257 unitinit = unitexp;
1258 else
1260 unitinit = ffecom_integer_zero_node;
1261 constantp = FALSE;
1263 break;
1265 default:
1266 assert ("bad unit spec" == NULL);
1267 unitinit = ffecom_integer_zero_node;
1268 unitexp = unitinit;
1269 break;
1272 inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
1273 initn = inits;
1274 ffeste_f2c_init_next_ (unitinit);
1276 inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
1277 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1278 TREE_STATIC (inits) = 1;
1280 yes = suspend_momentary ();
1282 t = build_decl (VAR_DECL,
1283 ffecom_get_invented_identifier ("__g77_alist_%d",
1284 mynumber++),
1285 f2c_alist_struct);
1286 TREE_STATIC (t) = 1;
1287 t = ffecom_start_decl (t, 1);
1288 ffecom_finish_decl (t, inits, 0);
1290 resume_momentary (yes);
1292 /* Prepare run-time expressions. */
1294 if (! unitexp)
1295 ffecom_prepare_expr (unit_expr);
1297 ffecom_prepare_end ();
1299 /* Now evaluate run-time expressions as needed. */
1301 if (! unitexp)
1303 unitexp = ffecom_expr (unit_expr);
1304 ffeste_f2c_compile_ (unitfield, unitexp);
1307 ttype = build_pointer_type (TREE_TYPE (t));
1308 t = ffecom_1 (ADDR_EXPR, ttype, t);
1310 t = build_tree_list (NULL_TREE, t);
1312 return t;
1315 #endif
1316 /* Make arglist with ptr to external-I/O control list.
1318 Returns a tree suitable as an argument list containing a pointer to
1319 an external-I/O control list. First, generates that control
1320 list, if necessary, along with any static and run-time initializations
1321 that are needed as specified by the arguments to this function.
1323 Must ensure that all expressions are prepared before being evaluated,
1324 for any whose evaluation might result in the generation of temporaries.
1326 Note that this means this function causes a transition, within the
1327 current block being code-generated via the back end, from the
1328 declaration of variables (temporaries) to the expanding of expressions,
1329 statements, etc. */
1331 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1332 static tree
1333 ffeste_io_cilist_ (bool have_err,
1334 ffestvUnit unit,
1335 ffebld unit_expr,
1336 int unit_dflt,
1337 bool have_end,
1338 ffestvFormat format,
1339 ffestpFile *format_spec,
1340 bool rec,
1341 ffebld rec_expr)
1343 static tree f2c_cilist_struct = NULL_TREE;
1344 tree t;
1345 tree ttype;
1346 int yes;
1347 tree field;
1348 tree inits, initn;
1349 bool constantp = TRUE;
1350 static tree errfield, unitfield, endfield, formatfield, recfield;
1351 tree errinit, unitinit, endinit, formatinit, recinit;
1352 tree unitexp, formatexp, recexp;
1353 static int mynumber = 0;
1355 if (f2c_cilist_struct == NULL_TREE)
1357 tree ref;
1359 ref = make_node (RECORD_TYPE);
1361 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1362 ffecom_f2c_flag_type_node);
1363 unitfield = ffecom_decl_field (ref, errfield, "unit",
1364 ffecom_f2c_ftnint_type_node);
1365 endfield = ffecom_decl_field (ref, unitfield, "end",
1366 ffecom_f2c_flag_type_node);
1367 formatfield = ffecom_decl_field (ref, endfield, "format",
1368 string_type_node);
1369 recfield = ffecom_decl_field (ref, formatfield, "rec",
1370 ffecom_f2c_ftnint_type_node);
1372 TYPE_FIELDS (ref) = errfield;
1373 layout_type (ref);
1375 ggc_add_tree_root (&f2c_cilist_struct, 1);
1377 f2c_cilist_struct = ref;
1380 /* Try to do as much compile-time initialization of the structure
1381 as possible, to save run time. */
1383 ffeste_f2c_init_flag_ (have_err, errinit);
1385 switch (unit)
1387 case FFESTV_unitNONE:
1388 case FFESTV_unitASTERISK:
1389 unitinit = build_int_2 (unit_dflt, 0);
1390 unitexp = unitinit;
1391 break;
1393 case FFESTV_unitINTEXPR:
1394 unitexp = ffecom_const_expr (unit_expr);
1395 if (unitexp)
1396 unitinit = unitexp;
1397 else
1399 unitinit = ffecom_integer_zero_node;
1400 constantp = FALSE;
1402 break;
1404 default:
1405 assert ("bad unit spec" == NULL);
1406 unitinit = ffecom_integer_zero_node;
1407 unitexp = unitinit;
1408 break;
1411 switch (format)
1413 case FFESTV_formatNONE:
1414 formatinit = null_pointer_node;
1415 formatexp = formatinit;
1416 break;
1418 case FFESTV_formatLABEL:
1419 formatexp = error_mark_node;
1420 formatinit = ffecom_lookup_label (format_spec->u.label);
1421 if ((formatinit == NULL_TREE)
1422 || (TREE_CODE (formatinit) == ERROR_MARK))
1423 break;
1424 formatinit = ffecom_1 (ADDR_EXPR,
1425 build_pointer_type (void_type_node),
1426 formatinit);
1427 TREE_CONSTANT (formatinit) = 1;
1428 break;
1430 case FFESTV_formatCHAREXPR:
1431 formatexp = ffecom_arg_ptr_to_const_expr (format_spec->u.expr, NULL);
1432 if (formatexp)
1433 formatinit = formatexp;
1434 else
1436 formatinit = null_pointer_node;
1437 constantp = FALSE;
1439 break;
1441 case FFESTV_formatASTERISK:
1442 formatinit = null_pointer_node;
1443 formatexp = formatinit;
1444 break;
1446 case FFESTV_formatINTEXPR:
1447 formatinit = null_pointer_node;
1448 formatexp = ffecom_expr_assign (format_spec->u.expr);
1449 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1450 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1451 error ("ASSIGNed FORMAT specifier is too small");
1452 formatexp = convert (string_type_node, formatexp);
1453 break;
1455 case FFESTV_formatNAMELIST:
1456 formatinit = ffecom_expr (format_spec->u.expr);
1457 formatexp = formatinit;
1458 break;
1460 default:
1461 assert ("bad format spec" == NULL);
1462 formatinit = integer_zero_node;
1463 formatexp = formatinit;
1464 break;
1467 ffeste_f2c_init_flag_ (have_end, endinit);
1469 if (rec)
1470 recexp = ffecom_const_expr (rec_expr);
1471 else
1472 recexp = ffecom_integer_zero_node;
1473 if (recexp)
1474 recinit = recexp;
1475 else
1477 recinit = ffecom_integer_zero_node;
1478 constantp = FALSE;
1481 inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
1482 initn = inits;
1483 ffeste_f2c_init_next_ (unitinit);
1484 ffeste_f2c_init_next_ (endinit);
1485 ffeste_f2c_init_next_ (formatinit);
1486 ffeste_f2c_init_next_ (recinit);
1488 inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1489 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1490 TREE_STATIC (inits) = 1;
1492 yes = suspend_momentary ();
1494 t = build_decl (VAR_DECL,
1495 ffecom_get_invented_identifier ("__g77_cilist_%d",
1496 mynumber++),
1497 f2c_cilist_struct);
1498 TREE_STATIC (t) = 1;
1499 t = ffecom_start_decl (t, 1);
1500 ffecom_finish_decl (t, inits, 0);
1502 resume_momentary (yes);
1504 /* Prepare run-time expressions. */
1506 if (! unitexp)
1507 ffecom_prepare_expr (unit_expr);
1509 if (! formatexp)
1510 ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
1512 if (! recexp)
1513 ffecom_prepare_expr (rec_expr);
1515 ffecom_prepare_end ();
1517 /* Now evaluate run-time expressions as needed. */
1519 if (! unitexp)
1521 unitexp = ffecom_expr (unit_expr);
1522 ffeste_f2c_compile_ (unitfield, unitexp);
1525 if (! formatexp)
1527 formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1528 ffeste_f2c_compile_ (formatfield, formatexp);
1530 else if (format == FFESTV_formatINTEXPR)
1531 ffeste_f2c_compile_ (formatfield, formatexp);
1533 if (! recexp)
1535 recexp = ffecom_expr (rec_expr);
1536 ffeste_f2c_compile_ (recfield, recexp);
1539 ttype = build_pointer_type (TREE_TYPE (t));
1540 t = ffecom_1 (ADDR_EXPR, ttype, t);
1542 t = build_tree_list (NULL_TREE, t);
1544 return t;
1547 #endif
1548 /* Make arglist with ptr to CLOSE control list.
1550 Returns a tree suitable as an argument list containing a pointer to
1551 a CLOSE-statement control list. First, generates that control
1552 list, if necessary, along with any static and run-time initializations
1553 that are needed as specified by the arguments to this function.
1555 Must ensure that all expressions are prepared before being evaluated,
1556 for any whose evaluation might result in the generation of temporaries.
1558 Note that this means this function causes a transition, within the
1559 current block being code-generated via the back end, from the
1560 declaration of variables (temporaries) to the expanding of expressions,
1561 statements, etc. */
1563 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1564 static tree
1565 ffeste_io_cllist_ (bool have_err,
1566 ffebld unit_expr,
1567 ffestpFile *stat_spec)
1569 static tree f2c_close_struct = NULL_TREE;
1570 tree t;
1571 tree ttype;
1572 int yes;
1573 tree field;
1574 tree inits, initn;
1575 tree ignore; /* Ignore length info for certain fields. */
1576 bool constantp = TRUE;
1577 static tree errfield, unitfield, statfield;
1578 tree errinit, unitinit, statinit;
1579 tree unitexp, statexp;
1580 static int mynumber = 0;
1582 if (f2c_close_struct == NULL_TREE)
1584 tree ref;
1586 ref = make_node (RECORD_TYPE);
1588 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1589 ffecom_f2c_flag_type_node);
1590 unitfield = ffecom_decl_field (ref, errfield, "unit",
1591 ffecom_f2c_ftnint_type_node);
1592 statfield = ffecom_decl_field (ref, unitfield, "stat",
1593 string_type_node);
1595 TYPE_FIELDS (ref) = errfield;
1596 layout_type (ref);
1598 ggc_add_tree_root (&f2c_close_struct, 1);
1600 f2c_close_struct = ref;
1603 /* Try to do as much compile-time initialization of the structure
1604 as possible, to save run time. */
1606 ffeste_f2c_init_flag_ (have_err, errinit);
1608 unitexp = ffecom_const_expr (unit_expr);
1609 if (unitexp)
1610 unitinit = unitexp;
1611 else
1613 unitinit = ffecom_integer_zero_node;
1614 constantp = FALSE;
1617 ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
1619 inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
1620 initn = inits;
1621 ffeste_f2c_init_next_ (unitinit);
1622 ffeste_f2c_init_next_ (statinit);
1624 inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1625 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1626 TREE_STATIC (inits) = 1;
1628 yes = suspend_momentary ();
1630 t = build_decl (VAR_DECL,
1631 ffecom_get_invented_identifier ("__g77_cllist_%d",
1632 mynumber++),
1633 f2c_close_struct);
1634 TREE_STATIC (t) = 1;
1635 t = ffecom_start_decl (t, 1);
1636 ffecom_finish_decl (t, inits, 0);
1638 resume_momentary (yes);
1640 /* Prepare run-time expressions. */
1642 if (! unitexp)
1643 ffecom_prepare_expr (unit_expr);
1645 if (! statexp)
1646 ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
1648 ffecom_prepare_end ();
1650 /* Now evaluate run-time expressions as needed. */
1652 if (! unitexp)
1654 unitexp = ffecom_expr (unit_expr);
1655 ffeste_f2c_compile_ (unitfield, unitexp);
1658 ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
1660 ttype = build_pointer_type (TREE_TYPE (t));
1661 t = ffecom_1 (ADDR_EXPR, ttype, t);
1663 t = build_tree_list (NULL_TREE, t);
1665 return t;
1668 #endif
1669 /* Make arglist with ptr to internal-I/O control list.
1671 Returns a tree suitable as an argument list containing a pointer to
1672 an internal-I/O control list. First, generates that control
1673 list, if necessary, along with any static and run-time initializations
1674 that are needed as specified by the arguments to this function.
1676 Must ensure that all expressions are prepared before being evaluated,
1677 for any whose evaluation might result in the generation of temporaries.
1679 Note that this means this function causes a transition, within the
1680 current block being code-generated via the back end, from the
1681 declaration of variables (temporaries) to the expanding of expressions,
1682 statements, etc. */
1684 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1685 static tree
1686 ffeste_io_icilist_ (bool have_err,
1687 ffebld unit_expr,
1688 bool have_end,
1689 ffestvFormat format,
1690 ffestpFile *format_spec)
1692 static tree f2c_icilist_struct = NULL_TREE;
1693 tree t;
1694 tree ttype;
1695 int yes;
1696 tree field;
1697 tree inits, initn;
1698 bool constantp = TRUE;
1699 static tree errfield, unitfield, endfield, formatfield, unitlenfield,
1700 unitnumfield;
1701 tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
1702 tree unitexp, formatexp, unitlenexp, unitnumexp;
1703 static int mynumber = 0;
1705 if (f2c_icilist_struct == NULL_TREE)
1707 tree ref;
1709 ref = make_node (RECORD_TYPE);
1711 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1712 ffecom_f2c_flag_type_node);
1713 unitfield = ffecom_decl_field (ref, errfield, "unit",
1714 string_type_node);
1715 endfield = ffecom_decl_field (ref, unitfield, "end",
1716 ffecom_f2c_flag_type_node);
1717 formatfield = ffecom_decl_field (ref, endfield, "format",
1718 string_type_node);
1719 unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
1720 ffecom_f2c_ftnint_type_node);
1721 unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
1722 ffecom_f2c_ftnint_type_node);
1724 TYPE_FIELDS (ref) = errfield;
1725 layout_type (ref);
1727 ggc_add_tree_root (&f2c_icilist_struct, 1);
1729 f2c_icilist_struct = ref;
1732 /* Try to do as much compile-time initialization of the structure
1733 as possible, to save run time. */
1735 ffeste_f2c_init_flag_ (have_err, errinit);
1737 unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
1738 if (unitexp)
1739 unitinit = unitexp;
1740 else
1742 unitinit = null_pointer_node;
1743 constantp = FALSE;
1745 if (unitlenexp)
1746 unitleninit = unitlenexp;
1747 else
1749 unitleninit = ffecom_integer_zero_node;
1750 constantp = FALSE;
1753 /* Now see if we can fully initialize the number of elements, or
1754 if we have to compute that at run time. */
1755 if (ffeinfo_rank (ffebld_info (unit_expr)) == 0
1756 || (unitexp
1757 && TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
1759 /* Not an array, so just one element. */
1760 unitnuminit = ffecom_integer_one_node;
1761 unitnumexp = unitnuminit;
1763 else if (unitexp && unitlenexp)
1765 /* An array, but all the info is constant, so compute now. */
1766 unitnuminit
1767 = size_binop (CEIL_DIV_EXPR,
1768 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1769 convert (sizetype, unitlenexp));
1770 unitnuminit = size_binop (CEIL_DIV_EXPR, unitnuminit,
1771 size_int (TYPE_PRECISION (char_type_node)
1772 / BITS_PER_UNIT));
1773 unitnumexp = unitnuminit;
1775 else
1777 /* Put off computing until run time. */
1778 unitnuminit = ffecom_integer_zero_node;
1779 unitnumexp = NULL_TREE;
1780 constantp = FALSE;
1783 switch (format)
1785 case FFESTV_formatNONE:
1786 formatinit = null_pointer_node;
1787 formatexp = formatinit;
1788 break;
1790 case FFESTV_formatLABEL:
1791 formatexp = error_mark_node;
1792 formatinit = ffecom_lookup_label (format_spec->u.label);
1793 if ((formatinit == NULL_TREE)
1794 || (TREE_CODE (formatinit) == ERROR_MARK))
1795 break;
1796 formatinit = ffecom_1 (ADDR_EXPR,
1797 build_pointer_type (void_type_node),
1798 formatinit);
1799 TREE_CONSTANT (formatinit) = 1;
1800 break;
1802 case FFESTV_formatCHAREXPR:
1803 ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
1804 break;
1806 case FFESTV_formatASTERISK:
1807 formatinit = null_pointer_node;
1808 formatexp = formatinit;
1809 break;
1811 case FFESTV_formatINTEXPR:
1812 formatinit = null_pointer_node;
1813 formatexp = ffecom_expr_assign (format_spec->u.expr);
1814 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1815 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1816 error ("ASSIGNed FORMAT specifier is too small");
1817 formatexp = convert (string_type_node, formatexp);
1818 break;
1820 default:
1821 assert ("bad format spec" == NULL);
1822 formatinit = ffecom_integer_zero_node;
1823 formatexp = formatinit;
1824 break;
1827 ffeste_f2c_init_flag_ (have_end, endinit);
1829 inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
1830 errinit);
1831 initn = inits;
1832 ffeste_f2c_init_next_ (unitinit);
1833 ffeste_f2c_init_next_ (endinit);
1834 ffeste_f2c_init_next_ (formatinit);
1835 ffeste_f2c_init_next_ (unitleninit);
1836 ffeste_f2c_init_next_ (unitnuminit);
1838 inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1839 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1840 TREE_STATIC (inits) = 1;
1842 yes = suspend_momentary ();
1844 t = build_decl (VAR_DECL,
1845 ffecom_get_invented_identifier ("__g77_icilist_%d",
1846 mynumber++),
1847 f2c_icilist_struct);
1848 TREE_STATIC (t) = 1;
1849 t = ffecom_start_decl (t, 1);
1850 ffecom_finish_decl (t, inits, 0);
1852 resume_momentary (yes);
1854 /* Prepare run-time expressions. */
1856 if (! unitexp)
1857 ffecom_prepare_arg_ptr_to_expr (unit_expr);
1859 ffeste_f2c_prepare_format_ (format_spec, formatexp);
1861 ffecom_prepare_end ();
1863 /* Now evaluate run-time expressions as needed. */
1865 if (! unitexp || ! unitlenexp)
1867 int need_unitexp = (! unitexp);
1868 int need_unitlenexp = (! unitlenexp);
1870 unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
1871 if (need_unitexp)
1872 ffeste_f2c_compile_ (unitfield, unitexp);
1873 if (need_unitlenexp)
1874 ffeste_f2c_compile_ (unitlenfield, unitlenexp);
1877 if (! unitnumexp
1878 && unitexp != error_mark_node
1879 && unitlenexp != error_mark_node)
1881 unitnumexp
1882 = size_binop (CEIL_DIV_EXPR,
1883 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1884 convert (sizetype, unitlenexp));
1885 unitnumexp = size_binop (CEIL_DIV_EXPR, unitnumexp,
1886 size_int (TYPE_PRECISION (char_type_node)
1887 / BITS_PER_UNIT));
1888 ffeste_f2c_compile_ (unitnumfield, unitnumexp);
1891 if (format == FFESTV_formatINTEXPR)
1892 ffeste_f2c_compile_ (formatfield, formatexp);
1893 else
1894 ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
1896 ttype = build_pointer_type (TREE_TYPE (t));
1897 t = ffecom_1 (ADDR_EXPR, ttype, t);
1899 t = build_tree_list (NULL_TREE, t);
1901 return t;
1903 #endif
1905 /* Make arglist with ptr to INQUIRE control list
1907 Returns a tree suitable as an argument list containing a pointer to
1908 an INQUIRE-statement control list. First, generates that control
1909 list, if necessary, along with any static and run-time initializations
1910 that are needed as specified by the arguments to this function.
1912 Must ensure that all expressions are prepared before being evaluated,
1913 for any whose evaluation might result in the generation of temporaries.
1915 Note that this means this function causes a transition, within the
1916 current block being code-generated via the back end, from the
1917 declaration of variables (temporaries) to the expanding of expressions,
1918 statements, etc. */
1920 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1921 static tree
1922 ffeste_io_inlist_ (bool have_err,
1923 ffestpFile *unit_spec,
1924 ffestpFile *file_spec,
1925 ffestpFile *exist_spec,
1926 ffestpFile *open_spec,
1927 ffestpFile *number_spec,
1928 ffestpFile *named_spec,
1929 ffestpFile *name_spec,
1930 ffestpFile *access_spec,
1931 ffestpFile *sequential_spec,
1932 ffestpFile *direct_spec,
1933 ffestpFile *form_spec,
1934 ffestpFile *formatted_spec,
1935 ffestpFile *unformatted_spec,
1936 ffestpFile *recl_spec,
1937 ffestpFile *nextrec_spec,
1938 ffestpFile *blank_spec)
1940 static tree f2c_inquire_struct = NULL_TREE;
1941 tree t;
1942 tree ttype;
1943 int yes;
1944 tree field;
1945 tree inits, initn;
1946 bool constantp = TRUE;
1947 static tree errfield, unitfield, filefield, filelenfield, existfield,
1948 openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
1949 accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
1950 formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
1951 unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
1952 tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
1953 namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
1954 sequentialleninit, directinit, directleninit, forminit, formleninit,
1955 formattedinit, formattedleninit, unformattedinit, unformattedleninit,
1956 reclinit, nextrecinit, blankinit, blankleninit;
1957 tree
1958 unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
1959 nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
1960 directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
1961 unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
1962 static int mynumber = 0;
1964 if (f2c_inquire_struct == NULL_TREE)
1966 tree ref;
1968 ref = make_node (RECORD_TYPE);
1970 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1971 ffecom_f2c_flag_type_node);
1972 unitfield = ffecom_decl_field (ref, errfield, "unit",
1973 ffecom_f2c_ftnint_type_node);
1974 filefield = ffecom_decl_field (ref, unitfield, "file",
1975 string_type_node);
1976 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1977 ffecom_f2c_ftnlen_type_node);
1978 existfield = ffecom_decl_field (ref, filelenfield, "exist",
1979 ffecom_f2c_ptr_to_ftnint_type_node);
1980 openfield = ffecom_decl_field (ref, existfield, "open",
1981 ffecom_f2c_ptr_to_ftnint_type_node);
1982 numberfield = ffecom_decl_field (ref, openfield, "number",
1983 ffecom_f2c_ptr_to_ftnint_type_node);
1984 namedfield = ffecom_decl_field (ref, numberfield, "named",
1985 ffecom_f2c_ptr_to_ftnint_type_node);
1986 namefield = ffecom_decl_field (ref, namedfield, "name",
1987 string_type_node);
1988 namelenfield = ffecom_decl_field (ref, namefield, "namelen",
1989 ffecom_f2c_ftnlen_type_node);
1990 accessfield = ffecom_decl_field (ref, namelenfield, "access",
1991 string_type_node);
1992 accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
1993 ffecom_f2c_ftnlen_type_node);
1994 sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
1995 string_type_node);
1996 sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
1997 "sequentiallen",
1998 ffecom_f2c_ftnlen_type_node);
1999 directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
2000 string_type_node);
2001 directlenfield = ffecom_decl_field (ref, directfield, "directlen",
2002 ffecom_f2c_ftnlen_type_node);
2003 formfield = ffecom_decl_field (ref, directlenfield, "form",
2004 string_type_node);
2005 formlenfield = ffecom_decl_field (ref, formfield, "formlen",
2006 ffecom_f2c_ftnlen_type_node);
2007 formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
2008 string_type_node);
2009 formattedlenfield = ffecom_decl_field (ref, formattedfield,
2010 "formattedlen",
2011 ffecom_f2c_ftnlen_type_node);
2012 unformattedfield = ffecom_decl_field (ref, formattedlenfield,
2013 "unformatted",
2014 string_type_node);
2015 unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
2016 "unformattedlen",
2017 ffecom_f2c_ftnlen_type_node);
2018 reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
2019 ffecom_f2c_ptr_to_ftnint_type_node);
2020 nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
2021 ffecom_f2c_ptr_to_ftnint_type_node);
2022 blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
2023 string_type_node);
2024 blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
2025 ffecom_f2c_ftnlen_type_node);
2027 TYPE_FIELDS (ref) = errfield;
2028 layout_type (ref);
2030 ggc_add_tree_root (&f2c_inquire_struct, 1);
2032 f2c_inquire_struct = ref;
2035 /* Try to do as much compile-time initialization of the structure
2036 as possible, to save run time. */
2038 ffeste_f2c_init_flag_ (have_err, errinit);
2039 ffeste_f2c_init_int_ (unitexp, unitinit, unit_spec);
2040 ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2041 file_spec);
2042 ffeste_f2c_init_ptrtoint_ (existexp, existinit, exist_spec);
2043 ffeste_f2c_init_ptrtoint_ (openexp, openinit, open_spec);
2044 ffeste_f2c_init_ptrtoint_ (numberexp, numberinit, number_spec);
2045 ffeste_f2c_init_ptrtoint_ (namedexp, namedinit, named_spec);
2046 ffeste_f2c_init_char_ (nameexp, nameinit, namelenexp, nameleninit,
2047 name_spec);
2048 ffeste_f2c_init_char_ (accessexp, accessinit, accesslenexp,
2049 accessleninit, access_spec);
2050 ffeste_f2c_init_char_ (sequentialexp, sequentialinit, sequentiallenexp,
2051 sequentialleninit, sequential_spec);
2052 ffeste_f2c_init_char_ (directexp, directinit, directlenexp,
2053 directleninit, direct_spec);
2054 ffeste_f2c_init_char_ (formexp, forminit, formlenexp, formleninit,
2055 form_spec);
2056 ffeste_f2c_init_char_ (formattedexp, formattedinit,
2057 formattedlenexp, formattedleninit, formatted_spec);
2058 ffeste_f2c_init_char_ (unformattedexp, unformattedinit, unformattedlenexp,
2059 unformattedleninit, unformatted_spec);
2060 ffeste_f2c_init_ptrtoint_ (reclexp, reclinit, recl_spec);
2061 ffeste_f2c_init_ptrtoint_ (nextrecexp, nextrecinit, nextrec_spec);
2062 ffeste_f2c_init_char_ (blankexp, blankinit, blanklenexp,
2063 blankleninit, blank_spec);
2065 inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
2066 errinit);
2067 initn = inits;
2068 ffeste_f2c_init_next_ (unitinit);
2069 ffeste_f2c_init_next_ (fileinit);
2070 ffeste_f2c_init_next_ (fileleninit);
2071 ffeste_f2c_init_next_ (existinit);
2072 ffeste_f2c_init_next_ (openinit);
2073 ffeste_f2c_init_next_ (numberinit);
2074 ffeste_f2c_init_next_ (namedinit);
2075 ffeste_f2c_init_next_ (nameinit);
2076 ffeste_f2c_init_next_ (nameleninit);
2077 ffeste_f2c_init_next_ (accessinit);
2078 ffeste_f2c_init_next_ (accessleninit);
2079 ffeste_f2c_init_next_ (sequentialinit);
2080 ffeste_f2c_init_next_ (sequentialleninit);
2081 ffeste_f2c_init_next_ (directinit);
2082 ffeste_f2c_init_next_ (directleninit);
2083 ffeste_f2c_init_next_ (forminit);
2084 ffeste_f2c_init_next_ (formleninit);
2085 ffeste_f2c_init_next_ (formattedinit);
2086 ffeste_f2c_init_next_ (formattedleninit);
2087 ffeste_f2c_init_next_ (unformattedinit);
2088 ffeste_f2c_init_next_ (unformattedleninit);
2089 ffeste_f2c_init_next_ (reclinit);
2090 ffeste_f2c_init_next_ (nextrecinit);
2091 ffeste_f2c_init_next_ (blankinit);
2092 ffeste_f2c_init_next_ (blankleninit);
2094 inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
2095 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2096 TREE_STATIC (inits) = 1;
2098 yes = suspend_momentary ();
2100 t = build_decl (VAR_DECL,
2101 ffecom_get_invented_identifier ("__g77_inlist_%d",
2102 mynumber++),
2103 f2c_inquire_struct);
2104 TREE_STATIC (t) = 1;
2105 t = ffecom_start_decl (t, 1);
2106 ffecom_finish_decl (t, inits, 0);
2108 resume_momentary (yes);
2110 /* Prepare run-time expressions. */
2112 ffeste_f2c_prepare_int_ (unit_spec, unitexp);
2113 ffeste_f2c_prepare_char_ (file_spec, fileexp);
2114 ffeste_f2c_prepare_ptrtoint_ (exist_spec, existexp);
2115 ffeste_f2c_prepare_ptrtoint_ (open_spec, openexp);
2116 ffeste_f2c_prepare_ptrtoint_ (number_spec, numberexp);
2117 ffeste_f2c_prepare_ptrtoint_ (named_spec, namedexp);
2118 ffeste_f2c_prepare_char_ (name_spec, nameexp);
2119 ffeste_f2c_prepare_char_ (access_spec, accessexp);
2120 ffeste_f2c_prepare_char_ (sequential_spec, sequentialexp);
2121 ffeste_f2c_prepare_char_ (direct_spec, directexp);
2122 ffeste_f2c_prepare_char_ (form_spec, formexp);
2123 ffeste_f2c_prepare_char_ (formatted_spec, formattedexp);
2124 ffeste_f2c_prepare_char_ (unformatted_spec, unformattedexp);
2125 ffeste_f2c_prepare_ptrtoint_ (recl_spec, reclexp);
2126 ffeste_f2c_prepare_ptrtoint_ (nextrec_spec, nextrecexp);
2127 ffeste_f2c_prepare_char_ (blank_spec, blankexp);
2129 ffecom_prepare_end ();
2131 /* Now evaluate run-time expressions as needed. */
2133 ffeste_f2c_compile_int_ (unitfield, unit_spec, unitexp);
2134 ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec,
2135 fileexp, filelenexp);
2136 ffeste_f2c_compile_ptrtoint_ (existfield, exist_spec, existexp);
2137 ffeste_f2c_compile_ptrtoint_ (openfield, open_spec, openexp);
2138 ffeste_f2c_compile_ptrtoint_ (numberfield, number_spec, numberexp);
2139 ffeste_f2c_compile_ptrtoint_ (namedfield, named_spec, namedexp);
2140 ffeste_f2c_compile_char_ (namefield, namelenfield, name_spec, nameexp,
2141 namelenexp);
2142 ffeste_f2c_compile_char_ (accessfield, accesslenfield, access_spec,
2143 accessexp, accesslenexp);
2144 ffeste_f2c_compile_char_ (sequentialfield, sequentiallenfield,
2145 sequential_spec, sequentialexp,
2146 sequentiallenexp);
2147 ffeste_f2c_compile_char_ (directfield, directlenfield, direct_spec,
2148 directexp, directlenexp);
2149 ffeste_f2c_compile_char_ (formfield, formlenfield, form_spec, formexp,
2150 formlenexp);
2151 ffeste_f2c_compile_char_ (formattedfield, formattedlenfield, formatted_spec,
2152 formattedexp, formattedlenexp);
2153 ffeste_f2c_compile_char_ (unformattedfield, unformattedlenfield,
2154 unformatted_spec, unformattedexp,
2155 unformattedlenexp);
2156 ffeste_f2c_compile_ptrtoint_ (reclfield, recl_spec, reclexp);
2157 ffeste_f2c_compile_ptrtoint_ (nextrecfield, nextrec_spec, nextrecexp);
2158 ffeste_f2c_compile_char_ (blankfield, blanklenfield, blank_spec, blankexp,
2159 blanklenexp);
2161 ttype = build_pointer_type (TREE_TYPE (t));
2162 t = ffecom_1 (ADDR_EXPR, ttype, t);
2164 t = build_tree_list (NULL_TREE, t);
2166 return t;
2169 #endif
2170 /* Make arglist with ptr to OPEN control list
2172 Returns a tree suitable as an argument list containing a pointer to
2173 an OPEN-statement control list. First, generates that control
2174 list, if necessary, along with any static and run-time initializations
2175 that are needed as specified by the arguments to this function.
2177 Must ensure that all expressions are prepared before being evaluated,
2178 for any whose evaluation might result in the generation of temporaries.
2180 Note that this means this function causes a transition, within the
2181 current block being code-generated via the back end, from the
2182 declaration of variables (temporaries) to the expanding of expressions,
2183 statements, etc. */
2185 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2186 static tree
2187 ffeste_io_olist_ (bool have_err,
2188 ffebld unit_expr,
2189 ffestpFile *file_spec,
2190 ffestpFile *stat_spec,
2191 ffestpFile *access_spec,
2192 ffestpFile *form_spec,
2193 ffestpFile *recl_spec,
2194 ffestpFile *blank_spec)
2196 static tree f2c_open_struct = NULL_TREE;
2197 tree t;
2198 tree ttype;
2199 int yes;
2200 tree field;
2201 tree inits, initn;
2202 tree ignore; /* Ignore length info for certain fields. */
2203 bool constantp = TRUE;
2204 static tree errfield, unitfield, filefield, filelenfield, statfield,
2205 accessfield, formfield, reclfield, blankfield;
2206 tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
2207 forminit, reclinit, blankinit;
2208 tree
2209 unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
2210 blankexp;
2211 static int mynumber = 0;
2213 if (f2c_open_struct == NULL_TREE)
2215 tree ref;
2217 ref = make_node (RECORD_TYPE);
2219 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
2220 ffecom_f2c_flag_type_node);
2221 unitfield = ffecom_decl_field (ref, errfield, "unit",
2222 ffecom_f2c_ftnint_type_node);
2223 filefield = ffecom_decl_field (ref, unitfield, "file",
2224 string_type_node);
2225 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
2226 ffecom_f2c_ftnlen_type_node);
2227 statfield = ffecom_decl_field (ref, filelenfield, "stat",
2228 string_type_node);
2229 accessfield = ffecom_decl_field (ref, statfield, "access",
2230 string_type_node);
2231 formfield = ffecom_decl_field (ref, accessfield, "form",
2232 string_type_node);
2233 reclfield = ffecom_decl_field (ref, formfield, "recl",
2234 ffecom_f2c_ftnint_type_node);
2235 blankfield = ffecom_decl_field (ref, reclfield, "blank",
2236 string_type_node);
2238 TYPE_FIELDS (ref) = errfield;
2239 layout_type (ref);
2241 ggc_add_tree_root (&f2c_open_struct, 1);
2243 f2c_open_struct = ref;
2246 /* Try to do as much compile-time initialization of the structure
2247 as possible, to save run time. */
2249 ffeste_f2c_init_flag_ (have_err, errinit);
2251 unitexp = ffecom_const_expr (unit_expr);
2252 if (unitexp)
2253 unitinit = unitexp;
2254 else
2256 unitinit = ffecom_integer_zero_node;
2257 constantp = FALSE;
2260 ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2261 file_spec);
2262 ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
2263 ffeste_f2c_init_charnolen_ (accessexp, accessinit, access_spec);
2264 ffeste_f2c_init_charnolen_ (formexp, forminit, form_spec);
2265 ffeste_f2c_init_int_ (reclexp, reclinit, recl_spec);
2266 ffeste_f2c_init_charnolen_ (blankexp, blankinit, blank_spec);
2268 inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
2269 initn = inits;
2270 ffeste_f2c_init_next_ (unitinit);
2271 ffeste_f2c_init_next_ (fileinit);
2272 ffeste_f2c_init_next_ (fileleninit);
2273 ffeste_f2c_init_next_ (statinit);
2274 ffeste_f2c_init_next_ (accessinit);
2275 ffeste_f2c_init_next_ (forminit);
2276 ffeste_f2c_init_next_ (reclinit);
2277 ffeste_f2c_init_next_ (blankinit);
2279 inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
2280 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2281 TREE_STATIC (inits) = 1;
2283 yes = suspend_momentary ();
2285 t = build_decl (VAR_DECL,
2286 ffecom_get_invented_identifier ("__g77_olist_%d",
2287 mynumber++),
2288 f2c_open_struct);
2289 TREE_STATIC (t) = 1;
2290 t = ffecom_start_decl (t, 1);
2291 ffecom_finish_decl (t, inits, 0);
2293 resume_momentary (yes);
2295 /* Prepare run-time expressions. */
2297 if (! unitexp)
2298 ffecom_prepare_expr (unit_expr);
2300 ffeste_f2c_prepare_char_ (file_spec, fileexp);
2301 ffeste_f2c_prepare_charnolen_ (stat_spec, statexp);
2302 ffeste_f2c_prepare_charnolen_ (access_spec, accessexp);
2303 ffeste_f2c_prepare_charnolen_ (form_spec, formexp);
2304 ffeste_f2c_prepare_int_ (recl_spec, reclexp);
2305 ffeste_f2c_prepare_charnolen_ (blank_spec, blankexp);
2307 ffecom_prepare_end ();
2309 /* Now evaluate run-time expressions as needed. */
2311 if (! unitexp)
2313 unitexp = ffecom_expr (unit_expr);
2314 ffeste_f2c_compile_ (unitfield, unitexp);
2317 ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec, fileexp,
2318 filelenexp);
2319 ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
2320 ffeste_f2c_compile_charnolen_ (accessfield, access_spec, accessexp);
2321 ffeste_f2c_compile_charnolen_ (formfield, form_spec, formexp);
2322 ffeste_f2c_compile_int_ (reclfield, recl_spec, reclexp);
2323 ffeste_f2c_compile_charnolen_ (blankfield, blank_spec, blankexp);
2325 ttype = build_pointer_type (TREE_TYPE (t));
2326 t = ffecom_1 (ADDR_EXPR, ttype, t);
2328 t = build_tree_list (NULL_TREE, t);
2330 return t;
2333 #endif
2334 /* Display file-statement specifier. */
2336 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2337 static void
2338 ffeste_subr_file_ (const char *kw, ffestpFile *spec)
2340 if (!spec->kw_or_val_present)
2341 return;
2342 fputs (kw, dmpout);
2343 if (spec->value_present)
2345 fputc ('=', dmpout);
2346 if (spec->value_is_label)
2348 assert (spec->value_is_label == 2); /* Temporary checking only. */
2349 fprintf (dmpout, "%" ffelabValue_f "u",
2350 ffelab_value (spec->u.label));
2352 else
2353 ffebld_dump (spec->u.expr);
2355 fputc (',', dmpout);
2357 #endif
2359 /* Generate code for BACKSPACE/ENDFILE/REWIND. */
2361 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2362 static void
2363 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
2365 tree alist;
2366 bool iostat;
2367 bool errl;
2369 ffeste_emit_line_note_ ();
2371 #define specified(something) (info->beru_spec[something].kw_or_val_present)
2373 iostat = specified (FFESTP_beruixIOSTAT);
2374 errl = specified (FFESTP_beruixERR);
2376 #undef specified
2378 /* ~~For now, we assume the unit number is specified and is not ASTERISK,
2379 because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
2380 without any unit specifier. f2c, however, supports the former
2381 construct. When it is time to add this feature to the FFE, which
2382 probably is fairly easy, ffestc_R919 and company will want to pass an
2383 ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
2384 ffeste_R919 and company, and they will want to pass that same value to
2385 this function, and that argument will replace the constant _unitINTEXPR_
2386 in the call below. Right now, the default unit number, 6, is ignored. */
2388 ffeste_start_stmt_ ();
2390 if (errl)
2392 /* Have ERR= specification. */
2394 ffeste_io_err_
2395 = ffeste_io_abort_
2396 = ffecom_lookup_label
2397 (info->beru_spec[FFESTP_beruixERR].u.label);
2398 ffeste_io_abort_is_temp_ = FALSE;
2400 else
2402 /* No ERR= specification. */
2404 ffeste_io_err_ = NULL_TREE;
2406 if ((ffeste_io_abort_is_temp_ = iostat))
2407 ffeste_io_abort_ = ffecom_temp_label ();
2408 else
2409 ffeste_io_abort_ = NULL_TREE;
2412 if (iostat)
2414 /* Have IOSTAT= specification. */
2416 ffeste_io_iostat_is_temp_ = FALSE;
2417 ffeste_io_iostat_ = ffecom_expr
2418 (info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2420 else if (ffeste_io_abort_ != NULL_TREE)
2422 /* Have no IOSTAT= but have ERR=. */
2424 ffeste_io_iostat_is_temp_ = TRUE;
2425 ffeste_io_iostat_
2426 = ffecom_make_tempvar ("beru", ffecom_integer_type_node,
2427 FFETARGET_charactersizeNONE, -1);
2429 else
2431 /* No IOSTAT= or ERR= specification. */
2433 ffeste_io_iostat_is_temp_ = FALSE;
2434 ffeste_io_iostat_ = NULL_TREE;
2437 /* Now prescan, then convert, all the arguments. */
2439 alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2440 info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
2442 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
2443 label, since we're gonna fall through to there anyway. */
2445 ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
2446 ! ffeste_io_abort_is_temp_);
2448 /* If we've got a temp label, generate its code here. */
2450 if (ffeste_io_abort_is_temp_)
2452 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2453 emit_nop ();
2454 expand_label (ffeste_io_abort_);
2456 assert (ffeste_io_err_ == NULL_TREE);
2459 ffeste_end_stmt_ ();
2461 #endif
2463 /* END DO statement
2465 Also invoked by _labeldef_branch_finish_ (or, in cases
2466 of errors, other _labeldef_ functions) when the label definition is
2467 for a DO-target (LOOPEND) label, once per matching/outstanding DO
2468 block on the stack. */
2470 void
2471 ffeste_do (ffestw block)
2473 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2474 fputs ("+ END_DO\n", dmpout);
2475 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2476 ffeste_emit_line_note_ ();
2478 if (ffestw_do_tvar (block) == 0)
2480 expand_end_loop (); /* DO WHILE and just DO. */
2482 ffeste_end_block_ (block);
2484 else
2485 ffeste_end_iterdo_ (block,
2486 ffestw_do_tvar (block),
2487 ffestw_do_incr_saved (block),
2488 ffestw_do_count_var (block));
2489 #else
2490 #error
2491 #endif
2494 /* End of statement following logical IF.
2496 Applies to *only* logical IF, not to IF-THEN. */
2498 void
2499 ffeste_end_R807 ()
2501 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2502 fputs ("+ END_IF\n", dmpout); /* Also see ffeste_R806. */
2503 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2504 ffeste_emit_line_note_ ();
2506 expand_end_cond ();
2508 ffeste_end_block_ (NULL);
2509 #else
2510 #error
2511 #endif
2514 /* Generate "code" for branch label definition. */
2516 void
2517 ffeste_labeldef_branch (ffelab label)
2519 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2520 fprintf (dmpout, "+ label %lu\n", ffelab_value (label));
2521 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2523 tree glabel;
2525 glabel = ffecom_lookup_label (label);
2526 assert (glabel != NULL_TREE);
2527 if (TREE_CODE (glabel) == ERROR_MARK)
2528 return;
2530 assert (DECL_INITIAL (glabel) == NULL_TREE);
2532 DECL_INITIAL (glabel) = error_mark_node;
2533 DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
2534 DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
2536 emit_nop ();
2538 expand_label (glabel);
2540 #else
2541 #error
2542 #endif
2545 /* Generate "code" for FORMAT label definition. */
2547 void
2548 ffeste_labeldef_format (ffelab label)
2550 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2551 fprintf (dmpout, "$ label %lu\n", ffelab_value (label));
2552 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2553 ffeste_label_formatdef_ = label;
2554 #else
2555 #error
2556 #endif
2559 /* Assignment statement (outside of WHERE). */
2561 void
2562 ffeste_R737A (ffebld dest, ffebld source)
2564 ffeste_check_simple_ ();
2566 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2567 fputs ("+ let ", dmpout);
2568 ffebld_dump (dest);
2569 fputs ("=", dmpout);
2570 ffebld_dump (source);
2571 fputc ('\n', dmpout);
2572 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2573 ffeste_emit_line_note_ ();
2575 ffeste_start_stmt_ ();
2577 ffecom_expand_let_stmt (dest, source);
2579 ffeste_end_stmt_ ();
2580 #else
2581 #error
2582 #endif
2585 /* Block IF (IF-THEN) statement. */
2587 void
2588 ffeste_R803 (ffestw block, ffebld expr)
2590 ffeste_check_simple_ ();
2592 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2593 fputs ("+ IF_block (", dmpout);
2594 ffebld_dump (expr);
2595 fputs (")\n", dmpout);
2596 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2598 tree temp;
2600 ffeste_emit_line_note_ ();
2602 ffeste_start_block_ (block);
2604 temp = ffecom_make_tempvar ("ifthen", integer_type_node,
2605 FFETARGET_charactersizeNONE, -1);
2607 ffeste_start_stmt_ ();
2609 ffecom_prepare_expr (expr);
2611 if (ffecom_prepare_end ())
2613 tree result;
2615 result = ffecom_modify (void_type_node,
2616 temp,
2617 ffecom_truth_value (ffecom_expr (expr)));
2619 expand_expr_stmt (result);
2621 ffeste_end_stmt_ ();
2623 else
2625 ffeste_end_stmt_ ();
2627 temp = ffecom_truth_value (ffecom_expr (expr));
2630 expand_start_cond (temp, 0);
2632 /* No fake `else' constructs introduced (yet). */
2633 ffestw_set_ifthen_fake_else (block, 0);
2635 #else
2636 #error
2637 #endif
2640 /* ELSE IF statement. */
2642 void
2643 ffeste_R804 (ffestw block, ffebld expr)
2645 ffeste_check_simple_ ();
2647 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2648 fputs ("+ ELSE_IF (", dmpout);
2649 ffebld_dump (expr);
2650 fputs (")\n", dmpout);
2651 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2653 tree temp;
2655 ffeste_emit_line_note_ ();
2657 /* Since ELSEIF(expr) might require preparations for expr,
2658 implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF. */
2660 expand_start_else ();
2662 ffeste_start_block_ (block);
2664 temp = ffecom_make_tempvar ("elseif", integer_type_node,
2665 FFETARGET_charactersizeNONE, -1);
2667 ffeste_start_stmt_ ();
2669 ffecom_prepare_expr (expr);
2671 if (ffecom_prepare_end ())
2673 tree result;
2675 result = ffecom_modify (void_type_node,
2676 temp,
2677 ffecom_truth_value (ffecom_expr (expr)));
2679 expand_expr_stmt (result);
2681 ffeste_end_stmt_ ();
2683 else
2685 /* In this case, we could probably have used expand_start_elseif
2686 instead, saving the need for a fake `else' construct. But,
2687 until it's clear that'd improve performance, it's easier this
2688 way, since we have to expand_start_else before we get to this
2689 test, given the current design. */
2691 ffeste_end_stmt_ ();
2693 temp = ffecom_truth_value (ffecom_expr (expr));
2696 expand_start_cond (temp, 0);
2698 /* Increment number of fake `else' constructs introduced. */
2699 ffestw_set_ifthen_fake_else (block,
2700 ffestw_ifthen_fake_else (block) + 1);
2702 #else
2703 #error
2704 #endif
2707 /* ELSE statement. */
2709 void
2710 ffeste_R805 (ffestw block UNUSED)
2712 ffeste_check_simple_ ();
2714 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2715 fputs ("+ ELSE\n", dmpout);
2716 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2717 ffeste_emit_line_note_ ();
2719 expand_start_else ();
2720 #else
2721 #error
2722 #endif
2725 /* END IF statement. */
2727 void
2728 ffeste_R806 (ffestw block)
2730 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2731 fputs ("+ END_IF_then\n", dmpout); /* Also see ffeste_shriek_if_. */
2732 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2734 int i = ffestw_ifthen_fake_else (block) + 1;
2736 ffeste_emit_line_note_ ();
2738 for (; i; --i)
2740 expand_end_cond ();
2742 ffeste_end_block_ (block);
2745 #else
2746 #error
2747 #endif
2750 /* Logical IF statement. */
2752 void
2753 ffeste_R807 (ffebld expr)
2755 ffeste_check_simple_ ();
2757 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2758 fputs ("+ IF_logical (", dmpout);
2759 ffebld_dump (expr);
2760 fputs (")\n", dmpout);
2761 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2763 tree temp;
2765 ffeste_emit_line_note_ ();
2767 ffeste_start_block_ (NULL);
2769 temp = ffecom_make_tempvar ("if", integer_type_node,
2770 FFETARGET_charactersizeNONE, -1);
2772 ffeste_start_stmt_ ();
2774 ffecom_prepare_expr (expr);
2776 if (ffecom_prepare_end ())
2778 tree result;
2780 result = ffecom_modify (void_type_node,
2781 temp,
2782 ffecom_truth_value (ffecom_expr (expr)));
2784 expand_expr_stmt (result);
2786 ffeste_end_stmt_ ();
2788 else
2790 ffeste_end_stmt_ ();
2792 temp = ffecom_truth_value (ffecom_expr (expr));
2795 expand_start_cond (temp, 0);
2797 #else
2798 #error
2799 #endif
2802 /* SELECT CASE statement. */
2804 void
2805 ffeste_R809 (ffestw block, ffebld expr)
2807 ffeste_check_simple_ ();
2809 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2810 fputs ("+ SELECT_CASE (", dmpout);
2811 ffebld_dump (expr);
2812 fputs (")\n", dmpout);
2813 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2814 ffeste_emit_line_note_ ();
2816 ffeste_start_block_ (block);
2818 if ((expr == NULL)
2819 || (ffeinfo_basictype (ffebld_info (expr))
2820 == FFEINFO_basictypeANY))
2821 ffestw_set_select_texpr (block, error_mark_node);
2822 else if (ffeinfo_basictype (ffebld_info (expr))
2823 == FFEINFO_basictypeCHARACTER)
2825 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2827 ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
2828 FFEBAD_severityFATAL);
2829 ffebad_here (0, ffestw_line (block), ffestw_col (block));
2830 ffebad_finish ();
2831 ffestw_set_select_texpr (block, error_mark_node);
2833 else
2835 tree result;
2836 tree texpr;
2838 result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
2839 ffeinfo_size (ffebld_info (expr)),
2840 -1);
2842 ffeste_start_stmt_ ();
2844 ffecom_prepare_expr (expr);
2846 ffecom_prepare_end ();
2848 texpr = ffecom_expr (expr);
2850 assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
2851 == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
2853 texpr = ffecom_modify (void_type_node,
2854 result,
2855 texpr);
2856 expand_expr_stmt (texpr);
2858 ffeste_end_stmt_ ();
2860 expand_start_case (1, result, TREE_TYPE (result),
2861 "SELECT CASE statement");
2862 ffestw_set_select_texpr (block, texpr);
2863 ffestw_set_select_break (block, FALSE);
2865 #else
2866 #error
2867 #endif
2870 /* CASE statement.
2872 If casenum is 0, it's CASE DEFAULT. Else it's the case ranges at
2873 the start of the first_stmt list in the select object at the top of
2874 the stack that match casenum. */
2876 void
2877 ffeste_R810 (ffestw block, unsigned long casenum)
2879 ffestwSelect s = ffestw_select (block);
2880 ffestwCase c;
2882 ffeste_check_simple_ ();
2884 if (s->first_stmt == (ffestwCase) &s->first_rel)
2885 c = NULL;
2886 else
2887 c = s->first_stmt;
2889 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2890 if ((c == NULL) || (casenum != c->casenum))
2892 if (casenum == 0) /* Intentional CASE DEFAULT. */
2893 fputs ("+ CASE_DEFAULT", dmpout);
2895 else
2897 bool comma = FALSE;
2899 fputs ("+ CASE (", dmpout);
2902 if (comma)
2903 fputc (',', dmpout);
2904 else
2905 comma = TRUE;
2906 if (c->low != NULL)
2907 ffebld_constant_dump (c->low);
2908 if (c->low != c->high)
2910 fputc (':', dmpout);
2911 if (c->high != NULL)
2912 ffebld_constant_dump (c->high);
2914 c = c->next_stmt;
2915 /* Unlink prev. */
2916 c->previous_stmt->previous_stmt->next_stmt = c;
2917 c->previous_stmt = c->previous_stmt->previous_stmt;
2919 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2920 fputc (')', dmpout);
2923 fputc ('\n', dmpout);
2924 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2926 tree texprlow;
2927 tree texprhigh;
2928 tree tlabel;
2929 int pushok;
2930 tree duplicate;
2932 ffeste_emit_line_note_ ();
2934 if (ffestw_select_texpr (block) == error_mark_node)
2935 return;
2937 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2939 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2941 if (ffestw_select_break (block))
2942 expand_exit_something ();
2943 else
2944 ffestw_set_select_break (block, TRUE);
2946 if ((c == NULL) || (casenum != c->casenum))
2948 if (casenum == 0) /* Intentional CASE DEFAULT. */
2950 pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2951 assert (pushok == 0);
2954 else
2957 texprlow = (c->low == NULL) ? NULL_TREE
2958 : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
2959 s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2960 if (c->low != c->high)
2962 texprhigh = (c->high == NULL) ? NULL_TREE
2963 : ffecom_constantunion (&ffebld_constant_union (c->high),
2964 s->type, s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2965 pushok = pushcase_range (texprlow, texprhigh, convert,
2966 tlabel, &duplicate);
2968 else
2969 pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2970 assert (pushok == 0);
2971 c = c->next_stmt;
2972 /* Unlink prev. */
2973 c->previous_stmt->previous_stmt->next_stmt = c;
2974 c->previous_stmt = c->previous_stmt->previous_stmt;
2976 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2978 clear_momentary ();
2980 #else
2981 #error
2982 #endif
2985 /* END SELECT statement. */
2987 void
2988 ffeste_R811 (ffestw block)
2990 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2991 fputs ("+ END_SELECT\n", dmpout);
2992 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2993 ffeste_emit_line_note_ ();
2995 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2997 if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
2998 expand_end_case (ffestw_select_texpr (block));
3000 ffeste_end_block_ (block);
3001 #else
3002 #error
3003 #endif
3006 /* Iterative DO statement. */
3008 void
3009 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
3010 ffebld start, ffelexToken start_token,
3011 ffebld end, ffelexToken end_token,
3012 ffebld incr, ffelexToken incr_token)
3014 ffeste_check_simple_ ();
3016 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3017 if ((ffebld_op (incr) == FFEBLD_opCONTER)
3018 && (ffebld_constant_is_zero (ffebld_conter (incr))))
3020 ffebad_start (FFEBAD_DO_STEP_ZERO);
3021 ffebad_here (0, ffelex_token_where_line (incr_token),
3022 ffelex_token_where_column (incr_token));
3023 ffebad_string ("Iterative DO loop");
3024 ffebad_finish ();
3025 /* Don't bother replacing it with 1 yet. */
3028 if (label == NULL)
3029 fputs ("+ DO_iterative_nonlabeled (", dmpout);
3030 else
3031 fprintf (dmpout, "+ DO_iterative_labeled %lu (", ffelab_value (label));
3032 ffebld_dump (var);
3033 fputc ('=', dmpout);
3034 ffebld_dump (start);
3035 fputc (',', dmpout);
3036 ffebld_dump (end);
3037 fputc (',', dmpout);
3038 ffebld_dump (incr);
3039 fputs (")\n", dmpout);
3040 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3042 ffeste_emit_line_note_ ();
3044 ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
3045 var,
3046 start, start_token,
3047 end, end_token,
3048 incr, incr_token,
3049 "Iterative DO loop");
3051 #else
3052 #error
3053 #endif
3056 /* DO WHILE statement. */
3058 void
3059 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
3061 ffeste_check_simple_ ();
3063 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3064 if (label == NULL)
3065 fputs ("+ DO_WHILE_nonlabeled (", dmpout);
3066 else
3067 fprintf (dmpout, "+ DO_WHILE_labeled %lu (", ffelab_value (label));
3068 ffebld_dump (expr);
3069 fputs (")\n", dmpout);
3070 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3072 tree result;
3074 ffeste_emit_line_note_ ();
3076 ffeste_start_block_ (block);
3078 if (expr)
3080 struct nesting *loop;
3081 tree mod;
3083 result = ffecom_make_tempvar ("dowhile", integer_type_node,
3084 FFETARGET_charactersizeNONE, -1);
3085 loop = expand_start_loop (1);
3087 ffeste_start_stmt_ ();
3089 ffecom_prepare_expr (expr);
3091 ffecom_prepare_end ();
3093 mod = ffecom_modify (void_type_node,
3094 result,
3095 ffecom_truth_value (ffecom_expr (expr)));
3096 expand_expr_stmt (mod);
3098 ffeste_end_stmt_ ();
3100 ffestw_set_do_hook (block, loop);
3101 expand_exit_loop_if_false (0, result);
3103 else
3104 ffestw_set_do_hook (block, expand_start_loop (1));
3106 ffestw_set_do_tvar (block, NULL_TREE);
3108 #else
3109 #error
3110 #endif
3113 /* END DO statement.
3115 This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
3116 CONTINUE (except that it has to have a label that is the target of
3117 one or more iterative DO statement), not the Fortran-90 structured
3118 END DO, which is handled elsewhere, as is the actual mechanism of
3119 ending an iterative DO statement, even one that ends at a label. */
3121 void
3122 ffeste_R825 ()
3124 ffeste_check_simple_ ();
3126 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3127 fputs ("+ END_DO_sugar\n", dmpout);
3128 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3129 ffeste_emit_line_note_ ();
3131 emit_nop ();
3132 #else
3133 #error
3134 #endif
3137 /* CYCLE statement. */
3139 void
3140 ffeste_R834 (ffestw block)
3142 ffeste_check_simple_ ();
3144 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3145 fprintf (dmpout, "+ CYCLE block #%lu\n", ffestw_blocknum (block));
3146 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3147 ffeste_emit_line_note_ ();
3149 expand_continue_loop (ffestw_do_hook (block));
3150 #else
3151 #error
3152 #endif
3155 /* EXIT statement. */
3157 void
3158 ffeste_R835 (ffestw block)
3160 ffeste_check_simple_ ();
3162 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3163 fprintf (dmpout, "+ EXIT block #%lu\n", ffestw_blocknum (block));
3164 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3165 ffeste_emit_line_note_ ();
3167 expand_exit_loop (ffestw_do_hook (block));
3168 #else
3169 #error
3170 #endif
3173 /* GOTO statement. */
3175 void
3176 ffeste_R836 (ffelab label)
3178 ffeste_check_simple_ ();
3180 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3181 fprintf (dmpout, "+ GOTO %lu\n", ffelab_value (label));
3182 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3184 tree glabel;
3186 ffeste_emit_line_note_ ();
3188 glabel = ffecom_lookup_label (label);
3189 if ((glabel != NULL_TREE)
3190 && (TREE_CODE (glabel) != ERROR_MARK))
3192 expand_goto (glabel);
3193 TREE_USED (glabel) = 1;
3196 #else
3197 #error
3198 #endif
3201 /* Computed GOTO statement. */
3203 void
3204 ffeste_R837 (ffelab *labels, int count, ffebld expr)
3206 int i;
3208 ffeste_check_simple_ ();
3210 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3211 fputs ("+ CGOTO (", dmpout);
3212 for (i = 0; i < count; ++i)
3214 if (i != 0)
3215 fputc (',', dmpout);
3216 fprintf (dmpout, "%" ffelabValue_f "u", ffelab_value (labels[i]));
3218 fputs ("),", dmpout);
3219 ffebld_dump (expr);
3220 fputc ('\n', dmpout);
3221 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3223 tree texpr;
3224 tree value;
3225 tree tlabel;
3226 int pushok;
3227 tree duplicate;
3229 ffeste_emit_line_note_ ();
3231 ffeste_start_stmt_ ();
3233 ffecom_prepare_expr (expr);
3235 ffecom_prepare_end ();
3237 texpr = ffecom_expr (expr);
3239 expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
3241 for (i = 0; i < count; ++i)
3243 value = build_int_2 (i + 1, 0);
3244 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
3246 pushok = pushcase (value, convert, tlabel, &duplicate);
3247 assert (pushok == 0);
3249 tlabel = ffecom_lookup_label (labels[i]);
3250 if ((tlabel == NULL_TREE)
3251 || (TREE_CODE (tlabel) == ERROR_MARK))
3252 continue;
3254 expand_goto (tlabel);
3255 TREE_USED (tlabel) = 1;
3257 expand_end_case (texpr);
3259 ffeste_end_stmt_ ();
3261 #else
3262 #error
3263 #endif
3266 /* ASSIGN statement. */
3268 void
3269 ffeste_R838 (ffelab label, ffebld target)
3271 ffeste_check_simple_ ();
3273 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3274 fprintf (dmpout, "+ ASSIGN %lu TO ", ffelab_value (label));
3275 ffebld_dump (target);
3276 fputc ('\n', dmpout);
3277 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3279 tree expr_tree;
3280 tree label_tree;
3281 tree target_tree;
3283 ffeste_emit_line_note_ ();
3285 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3286 seen here should never require use of temporaries. */
3288 label_tree = ffecom_lookup_label (label);
3289 if ((label_tree != NULL_TREE)
3290 && (TREE_CODE (label_tree) != ERROR_MARK))
3292 label_tree = ffecom_1 (ADDR_EXPR,
3293 build_pointer_type (void_type_node),
3294 label_tree);
3295 TREE_CONSTANT (label_tree) = 1;
3297 target_tree = ffecom_expr_assign_w (target);
3298 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
3299 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
3300 error ("ASSIGN to variable that is too small");
3302 label_tree = convert (TREE_TYPE (target_tree), label_tree);
3304 expr_tree = ffecom_modify (void_type_node,
3305 target_tree,
3306 label_tree);
3307 expand_expr_stmt (expr_tree);
3309 clear_momentary ();
3312 #else
3313 #error
3314 #endif
3317 /* Assigned GOTO statement. */
3319 void
3320 ffeste_R839 (ffebld target)
3322 ffeste_check_simple_ ();
3324 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3325 fputs ("+ AGOTO ", dmpout);
3326 ffebld_dump (target);
3327 fputc ('\n', dmpout);
3328 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3330 tree t;
3332 ffeste_emit_line_note_ ();
3334 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3335 seen here should never require use of temporaries. */
3337 t = ffecom_expr_assign (target);
3338 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3339 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3340 error ("ASSIGNed GOTO target variable is too small");
3342 expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
3344 clear_momentary ();
3346 #else
3347 #error
3348 #endif
3351 /* Arithmetic IF statement. */
3353 void
3354 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
3356 ffeste_check_simple_ ();
3358 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3359 fputs ("+ IF_arithmetic (", dmpout);
3360 ffebld_dump (expr);
3361 fprintf (dmpout, ") %" ffelabValue_f "u,%" ffelabValue_f "u,%" ffelabValue_f "u\n",
3362 ffelab_value (neg), ffelab_value (zero), ffelab_value (pos));
3363 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3365 tree gneg = ffecom_lookup_label (neg);
3366 tree gzero = ffecom_lookup_label (zero);
3367 tree gpos = ffecom_lookup_label (pos);
3368 tree texpr;
3370 ffeste_emit_line_note_ ();
3372 if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
3373 return;
3374 if ((TREE_CODE (gneg) == ERROR_MARK)
3375 || (TREE_CODE (gzero) == ERROR_MARK)
3376 || (TREE_CODE (gpos) == ERROR_MARK))
3377 return;
3379 ffeste_start_stmt_ ();
3381 ffecom_prepare_expr (expr);
3383 ffecom_prepare_end ();
3385 if (neg == zero)
3387 if (neg == pos)
3388 expand_goto (gzero);
3389 else
3391 /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos. */
3392 texpr = ffecom_expr (expr);
3393 texpr = ffecom_2 (LE_EXPR, integer_type_node,
3394 texpr,
3395 convert (TREE_TYPE (texpr),
3396 integer_zero_node));
3397 expand_start_cond (ffecom_truth_value (texpr), 0);
3398 expand_goto (gzero);
3399 expand_start_else ();
3400 expand_goto (gpos);
3401 expand_end_cond ();
3404 else if (neg == pos)
3406 /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero. */
3407 texpr = ffecom_expr (expr);
3408 texpr = ffecom_2 (NE_EXPR, integer_type_node,
3409 texpr,
3410 convert (TREE_TYPE (texpr),
3411 integer_zero_node));
3412 expand_start_cond (ffecom_truth_value (texpr), 0);
3413 expand_goto (gneg);
3414 expand_start_else ();
3415 expand_goto (gzero);
3416 expand_end_cond ();
3418 else if (zero == pos)
3420 /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg. */
3421 texpr = ffecom_expr (expr);
3422 texpr = ffecom_2 (GE_EXPR, integer_type_node,
3423 texpr,
3424 convert (TREE_TYPE (texpr),
3425 integer_zero_node));
3426 expand_start_cond (ffecom_truth_value (texpr), 0);
3427 expand_goto (gzero);
3428 expand_start_else ();
3429 expand_goto (gneg);
3430 expand_end_cond ();
3432 else
3434 /* Use a SAVE_EXPR in combo with:
3435 IF (expr.LT.0) THEN GOTO neg
3436 ELSEIF (expr.GT.0) THEN GOTO pos
3437 ELSE GOTO zero. */
3438 tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
3440 texpr = ffecom_2 (LT_EXPR, integer_type_node,
3441 expr_saved,
3442 convert (TREE_TYPE (expr_saved),
3443 integer_zero_node));
3444 expand_start_cond (ffecom_truth_value (texpr), 0);
3445 expand_goto (gneg);
3446 texpr = ffecom_2 (GT_EXPR, integer_type_node,
3447 expr_saved,
3448 convert (TREE_TYPE (expr_saved),
3449 integer_zero_node));
3450 expand_start_elseif (ffecom_truth_value (texpr));
3451 expand_goto (gpos);
3452 expand_start_else ();
3453 expand_goto (gzero);
3454 expand_end_cond ();
3457 ffeste_end_stmt_ ();
3459 #else
3460 #error
3461 #endif
3464 /* CONTINUE statement. */
3466 void
3467 ffeste_R841 ()
3469 ffeste_check_simple_ ();
3471 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3472 fputs ("+ CONTINUE\n", dmpout);
3473 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3474 ffeste_emit_line_note_ ();
3476 emit_nop ();
3477 #else
3478 #error
3479 #endif
3482 /* STOP statement. */
3484 void
3485 ffeste_R842 (ffebld expr)
3487 ffeste_check_simple_ ();
3489 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3490 if (expr == NULL)
3492 fputs ("+ STOP\n", dmpout);
3494 else
3496 fputs ("+ STOP_coded ", dmpout);
3497 ffebld_dump (expr);
3498 fputc ('\n', dmpout);
3500 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3502 tree callit;
3503 ffelexToken msg;
3505 ffeste_emit_line_note_ ();
3507 if ((expr == NULL)
3508 || (ffeinfo_basictype (ffebld_info (expr))
3509 == FFEINFO_basictypeANY))
3511 msg = ffelex_token_new_character ("", ffelex_token_where_line
3512 (ffesta_tokens[0]), ffelex_token_where_column
3513 (ffesta_tokens[0]));
3514 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3515 (msg));
3516 ffelex_token_kill (msg);
3517 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3518 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3519 FFEINFO_whereCONSTANT, 0));
3521 else if (ffeinfo_basictype (ffebld_info (expr))
3522 == FFEINFO_basictypeINTEGER)
3524 char num[50];
3526 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3527 assert (ffeinfo_kindtype (ffebld_info (expr))
3528 == FFEINFO_kindtypeINTEGERDEFAULT);
3529 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3530 ffebld_constant_integer1 (ffebld_conter (expr)));
3531 msg = ffelex_token_new_character (num, ffelex_token_where_line
3532 (ffesta_tokens[0]), ffelex_token_where_column
3533 (ffesta_tokens[0]));
3534 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3535 (msg));
3536 ffelex_token_kill (msg);
3537 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3538 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3539 FFEINFO_whereCONSTANT, 0));
3541 else
3543 assert (ffeinfo_basictype (ffebld_info (expr))
3544 == FFEINFO_basictypeCHARACTER);
3545 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3546 assert (ffeinfo_kindtype (ffebld_info (expr))
3547 == FFEINFO_kindtypeCHARACTERDEFAULT);
3550 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3551 seen here should never require use of temporaries. */
3553 callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3554 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3555 NULL_TREE);
3556 TREE_SIDE_EFFECTS (callit) = 1;
3558 expand_expr_stmt (callit);
3560 clear_momentary ();
3562 #else
3563 #error
3564 #endif
3567 /* PAUSE statement. */
3569 void
3570 ffeste_R843 (ffebld expr)
3572 ffeste_check_simple_ ();
3574 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3575 if (expr == NULL)
3577 fputs ("+ PAUSE\n", dmpout);
3579 else
3581 fputs ("+ PAUSE_coded ", dmpout);
3582 ffebld_dump (expr);
3583 fputc ('\n', dmpout);
3585 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3587 tree callit;
3588 ffelexToken msg;
3590 ffeste_emit_line_note_ ();
3592 if ((expr == NULL)
3593 || (ffeinfo_basictype (ffebld_info (expr))
3594 == FFEINFO_basictypeANY))
3596 msg = ffelex_token_new_character ("", ffelex_token_where_line
3597 (ffesta_tokens[0]), ffelex_token_where_column
3598 (ffesta_tokens[0]));
3599 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3600 (msg));
3601 ffelex_token_kill (msg);
3602 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3603 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3604 FFEINFO_whereCONSTANT, 0));
3606 else if (ffeinfo_basictype (ffebld_info (expr))
3607 == FFEINFO_basictypeINTEGER)
3609 char num[50];
3611 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3612 assert (ffeinfo_kindtype (ffebld_info (expr))
3613 == FFEINFO_kindtypeINTEGERDEFAULT);
3614 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3615 ffebld_constant_integer1 (ffebld_conter (expr)));
3616 msg = ffelex_token_new_character (num, ffelex_token_where_line
3617 (ffesta_tokens[0]), ffelex_token_where_column
3618 (ffesta_tokens[0]));
3619 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3620 (msg));
3621 ffelex_token_kill (msg);
3622 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3623 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3624 FFEINFO_whereCONSTANT, 0));
3626 else
3628 assert (ffeinfo_basictype (ffebld_info (expr))
3629 == FFEINFO_basictypeCHARACTER);
3630 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3631 assert (ffeinfo_kindtype (ffebld_info (expr))
3632 == FFEINFO_kindtypeCHARACTERDEFAULT);
3635 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3636 seen here should never require use of temporaries. */
3638 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3639 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3640 NULL_TREE);
3641 TREE_SIDE_EFFECTS (callit) = 1;
3643 expand_expr_stmt (callit);
3645 clear_momentary ();
3647 #if 0 /* Old approach for phantom g77 run-time
3648 library. */
3650 tree callit;
3652 ffeste_emit_line_note_ ();
3654 if (expr == NULL)
3655 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE, NULL_TREE);
3656 else if (ffeinfo_basictype (ffebld_info (expr))
3657 == FFEINFO_basictypeINTEGER)
3658 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
3659 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3660 NULL_TREE);
3661 else if (ffeinfo_basictype (ffebld_info (expr))
3662 == FFEINFO_basictypeCHARACTER)
3663 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
3664 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3665 NULL_TREE);
3666 else
3667 abort ();
3668 TREE_SIDE_EFFECTS (callit) = 1;
3670 expand_expr_stmt (callit);
3672 clear_momentary ();
3674 #endif
3675 #else
3676 #error
3677 #endif
3680 /* OPEN statement. */
3682 void
3683 ffeste_R904 (ffestpOpenStmt *info)
3685 ffeste_check_simple_ ();
3687 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3688 fputs ("+ OPEN (", dmpout);
3689 ffeste_subr_file_ ("UNIT", &info->open_spec[FFESTP_openixUNIT]);
3690 ffeste_subr_file_ ("ACCESS", &info->open_spec[FFESTP_openixACCESS]);
3691 ffeste_subr_file_ ("ACTION", &info->open_spec[FFESTP_openixACTION]);
3692 ffeste_subr_file_ ("ASSOCIATEVARIABLE", &info->open_spec[FFESTP_openixASSOCIATEVARIABLE]);
3693 ffeste_subr_file_ ("BLANK", &info->open_spec[FFESTP_openixBLANK]);
3694 ffeste_subr_file_ ("BLOCKSIZE", &info->open_spec[FFESTP_openixBLOCKSIZE]);
3695 ffeste_subr_file_ ("BUFFERCOUNT", &info->open_spec[FFESTP_openixBUFFERCOUNT]);
3696 ffeste_subr_file_ ("CARRIAGECONTROL", &info->open_spec[FFESTP_openixCARRIAGECONTROL]);
3697 ffeste_subr_file_ ("DEFAULTFILE", &info->open_spec[FFESTP_openixDEFAULTFILE]);
3698 ffeste_subr_file_ ("DELIM", &info->open_spec[FFESTP_openixDELIM]);
3699 ffeste_subr_file_ ("DISPOSE", &info->open_spec[FFESTP_openixDISPOSE]);
3700 ffeste_subr_file_ ("ERR", &info->open_spec[FFESTP_openixERR]);
3701 ffeste_subr_file_ ("EXTENDSIZE", &info->open_spec[FFESTP_openixEXTENDSIZE]);
3702 ffeste_subr_file_ ("FILE", &info->open_spec[FFESTP_openixFILE]);
3703 ffeste_subr_file_ ("FORM", &info->open_spec[FFESTP_openixFORM]);
3704 ffeste_subr_file_ ("INITIALSIZE", &info->open_spec[FFESTP_openixINITIALSIZE]);
3705 ffeste_subr_file_ ("IOSTAT", &info->open_spec[FFESTP_openixIOSTAT]);
3706 ffeste_subr_file_ ("KEY", &info->open_spec[FFESTP_openixKEY]);
3707 ffeste_subr_file_ ("MAXREC", &info->open_spec[FFESTP_openixMAXREC]);
3708 ffeste_subr_file_ ("NOSPANBLOCKS", &info->open_spec[FFESTP_openixNOSPANBLOCKS]);
3709 ffeste_subr_file_ ("ORGANIZATION", &info->open_spec[FFESTP_openixORGANIZATION]);
3710 ffeste_subr_file_ ("PAD", &info->open_spec[FFESTP_openixPAD]);
3711 ffeste_subr_file_ ("POSITION", &info->open_spec[FFESTP_openixPOSITION]);
3712 ffeste_subr_file_ ("READONLY", &info->open_spec[FFESTP_openixREADONLY]);
3713 ffeste_subr_file_ ("RECL", &info->open_spec[FFESTP_openixRECL]);
3714 ffeste_subr_file_ ("RECORDTYPE", &info->open_spec[FFESTP_openixRECORDTYPE]);
3715 ffeste_subr_file_ ("SHARED", &info->open_spec[FFESTP_openixSHARED]);
3716 ffeste_subr_file_ ("STATUS", &info->open_spec[FFESTP_openixSTATUS]);
3717 ffeste_subr_file_ ("USEROPEN", &info->open_spec[FFESTP_openixUSEROPEN]);
3718 fputs (")\n", dmpout);
3719 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3721 tree args;
3722 bool iostat;
3723 bool errl;
3725 ffeste_emit_line_note_ ();
3727 #define specified(something) (info->open_spec[something].kw_or_val_present)
3729 iostat = specified (FFESTP_openixIOSTAT);
3730 errl = specified (FFESTP_openixERR);
3732 #undef specified
3734 ffeste_start_stmt_ ();
3736 if (errl)
3738 ffeste_io_err_
3739 = ffeste_io_abort_
3740 = ffecom_lookup_label
3741 (info->open_spec[FFESTP_openixERR].u.label);
3742 ffeste_io_abort_is_temp_ = FALSE;
3744 else
3746 ffeste_io_err_ = NULL_TREE;
3748 if ((ffeste_io_abort_is_temp_ = iostat))
3749 ffeste_io_abort_ = ffecom_temp_label ();
3750 else
3751 ffeste_io_abort_ = NULL_TREE;
3754 if (iostat)
3756 /* Have IOSTAT= specification. */
3758 ffeste_io_iostat_is_temp_ = FALSE;
3759 ffeste_io_iostat_ = ffecom_expr
3760 (info->open_spec[FFESTP_openixIOSTAT].u.expr);
3762 else if (ffeste_io_abort_ != NULL_TREE)
3764 /* Have no IOSTAT= but have ERR=. */
3766 ffeste_io_iostat_is_temp_ = TRUE;
3767 ffeste_io_iostat_
3768 = ffecom_make_tempvar ("open", ffecom_integer_type_node,
3769 FFETARGET_charactersizeNONE, -1);
3771 else
3773 /* No IOSTAT= or ERR= specification. */
3775 ffeste_io_iostat_is_temp_ = FALSE;
3776 ffeste_io_iostat_ = NULL_TREE;
3779 /* Now prescan, then convert, all the arguments. */
3781 args = ffeste_io_olist_ (errl || iostat,
3782 info->open_spec[FFESTP_openixUNIT].u.expr,
3783 &info->open_spec[FFESTP_openixFILE],
3784 &info->open_spec[FFESTP_openixSTATUS],
3785 &info->open_spec[FFESTP_openixACCESS],
3786 &info->open_spec[FFESTP_openixFORM],
3787 &info->open_spec[FFESTP_openixRECL],
3788 &info->open_spec[FFESTP_openixBLANK]);
3790 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3791 label, since we're gonna fall through to there anyway. */
3793 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
3794 ! ffeste_io_abort_is_temp_);
3796 /* If we've got a temp label, generate its code here. */
3798 if (ffeste_io_abort_is_temp_)
3800 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3801 emit_nop ();
3802 expand_label (ffeste_io_abort_);
3804 assert (ffeste_io_err_ == NULL_TREE);
3807 ffeste_end_stmt_ ();
3809 #else
3810 #error
3811 #endif
3814 /* CLOSE statement. */
3816 void
3817 ffeste_R907 (ffestpCloseStmt *info)
3819 ffeste_check_simple_ ();
3821 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3822 fputs ("+ CLOSE (", dmpout);
3823 ffeste_subr_file_ ("UNIT", &info->close_spec[FFESTP_closeixUNIT]);
3824 ffeste_subr_file_ ("ERR", &info->close_spec[FFESTP_closeixERR]);
3825 ffeste_subr_file_ ("IOSTAT", &info->close_spec[FFESTP_closeixIOSTAT]);
3826 ffeste_subr_file_ ("STATUS", &info->close_spec[FFESTP_closeixSTATUS]);
3827 fputs (")\n", dmpout);
3828 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3830 tree args;
3831 bool iostat;
3832 bool errl;
3834 ffeste_emit_line_note_ ();
3836 #define specified(something) (info->close_spec[something].kw_or_val_present)
3838 iostat = specified (FFESTP_closeixIOSTAT);
3839 errl = specified (FFESTP_closeixERR);
3841 #undef specified
3843 ffeste_start_stmt_ ();
3845 if (errl)
3847 ffeste_io_err_
3848 = ffeste_io_abort_
3849 = ffecom_lookup_label
3850 (info->close_spec[FFESTP_closeixERR].u.label);
3851 ffeste_io_abort_is_temp_ = FALSE;
3853 else
3855 ffeste_io_err_ = NULL_TREE;
3857 if ((ffeste_io_abort_is_temp_ = iostat))
3858 ffeste_io_abort_ = ffecom_temp_label ();
3859 else
3860 ffeste_io_abort_ = NULL_TREE;
3863 if (iostat)
3865 /* Have IOSTAT= specification. */
3867 ffeste_io_iostat_is_temp_ = FALSE;
3868 ffeste_io_iostat_ = ffecom_expr
3869 (info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3871 else if (ffeste_io_abort_ != NULL_TREE)
3873 /* Have no IOSTAT= but have ERR=. */
3875 ffeste_io_iostat_is_temp_ = TRUE;
3876 ffeste_io_iostat_
3877 = ffecom_make_tempvar ("close", ffecom_integer_type_node,
3878 FFETARGET_charactersizeNONE, -1);
3880 else
3882 /* No IOSTAT= or ERR= specification. */
3884 ffeste_io_iostat_is_temp_ = FALSE;
3885 ffeste_io_iostat_ = NULL_TREE;
3888 /* Now prescan, then convert, all the arguments. */
3890 args = ffeste_io_cllist_ (errl || iostat,
3891 info->close_spec[FFESTP_closeixUNIT].u.expr,
3892 &info->close_spec[FFESTP_closeixSTATUS]);
3894 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3895 label, since we're gonna fall through to there anyway. */
3897 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
3898 ! ffeste_io_abort_is_temp_);
3900 /* If we've got a temp label, generate its code here. */
3902 if (ffeste_io_abort_is_temp_)
3904 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3905 emit_nop ();
3906 expand_label (ffeste_io_abort_);
3908 assert (ffeste_io_err_ == NULL_TREE);
3911 ffeste_end_stmt_ ();
3913 #else
3914 #error
3915 #endif
3918 /* READ(...) statement -- start. */
3920 void
3921 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3922 ffestvUnit unit, ffestvFormat format, bool rec,
3923 bool key UNUSED)
3925 ffeste_check_start_ ();
3927 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3928 switch (format)
3930 case FFESTV_formatNONE:
3931 if (rec)
3932 fputs ("+ READ_ufdac", dmpout);
3933 else if (key)
3934 fputs ("+ READ_ufidx", dmpout);
3935 else
3936 fputs ("+ READ_ufseq", dmpout);
3937 break;
3939 case FFESTV_formatLABEL:
3940 case FFESTV_formatCHAREXPR:
3941 case FFESTV_formatINTEXPR:
3942 if (rec)
3943 fputs ("+ READ_fmdac", dmpout);
3944 else if (key)
3945 fputs ("+ READ_fmidx", dmpout);
3946 else if (unit == FFESTV_unitCHAREXPR)
3947 fputs ("+ READ_fmint", dmpout);
3948 else
3949 fputs ("+ READ_fmseq", dmpout);
3950 break;
3952 case FFESTV_formatASTERISK:
3953 if (unit == FFESTV_unitCHAREXPR)
3954 fputs ("+ READ_lsint", dmpout);
3955 else
3956 fputs ("+ READ_lsseq", dmpout);
3957 break;
3959 case FFESTV_formatNAMELIST:
3960 fputs ("+ READ_nlseq", dmpout);
3961 break;
3963 default:
3964 assert ("Unexpected kind of format item in R909 READ" == NULL);
3967 if (only_format)
3969 fputc (' ', dmpout);
3970 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3971 fputc (' ', dmpout);
3973 return;
3976 fputs (" (", dmpout);
3977 ffeste_subr_file_ ("UNIT", &info->read_spec[FFESTP_readixUNIT]);
3978 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3979 ffeste_subr_file_ ("ADVANCE", &info->read_spec[FFESTP_readixADVANCE]);
3980 ffeste_subr_file_ ("EOR", &info->read_spec[FFESTP_readixEOR]);
3981 ffeste_subr_file_ ("ERR", &info->read_spec[FFESTP_readixERR]);
3982 ffeste_subr_file_ ("END", &info->read_spec[FFESTP_readixEND]);
3983 ffeste_subr_file_ ("IOSTAT", &info->read_spec[FFESTP_readixIOSTAT]);
3984 ffeste_subr_file_ ("KEYEQ", &info->read_spec[FFESTP_readixKEYEQ]);
3985 ffeste_subr_file_ ("KEYGE", &info->read_spec[FFESTP_readixKEYGE]);
3986 ffeste_subr_file_ ("KEYGT", &info->read_spec[FFESTP_readixKEYGT]);
3987 ffeste_subr_file_ ("KEYID", &info->read_spec[FFESTP_readixKEYID]);
3988 ffeste_subr_file_ ("NULLS", &info->read_spec[FFESTP_readixNULLS]);
3989 ffeste_subr_file_ ("REC", &info->read_spec[FFESTP_readixREC]);
3990 ffeste_subr_file_ ("SIZE", &info->read_spec[FFESTP_readixSIZE]);
3991 fputs (") ", dmpout);
3992 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3994 ffeste_emit_line_note_ ();
3997 ffecomGfrt start;
3998 ffecomGfrt end;
3999 tree cilist;
4000 bool iostat;
4001 bool errl;
4002 bool endl;
4004 /* First determine the start, per-item, and end run-time functions to
4005 call. The per-item function is picked by choosing an ffeste function
4006 to call to handle a given item; it knows how to generate a call to the
4007 appropriate run-time function, and is called an "I/O driver". */
4009 switch (format)
4011 case FFESTV_formatNONE: /* no FMT= */
4012 ffeste_io_driver_ = ffeste_io_douio_;
4013 if (rec)
4014 start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
4015 #if 0
4016 else if (key)
4017 start = FFECOM_gfrtSRIUE, end = FFECOM_gfrtERIUE;
4018 #endif
4019 else
4020 start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
4021 break;
4023 case FFESTV_formatLABEL: /* FMT=10 */
4024 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4025 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4026 ffeste_io_driver_ = ffeste_io_dofio_;
4027 if (rec)
4028 start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
4029 #if 0
4030 else if (key)
4031 start = FFECOM_gfrtSRIFE, end = FFECOM_gfrtERIFE;
4032 #endif
4033 else if (unit == FFESTV_unitCHAREXPR)
4034 start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
4035 else
4036 start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
4037 break;
4039 case FFESTV_formatASTERISK: /* FMT=* */
4040 ffeste_io_driver_ = ffeste_io_dolio_;
4041 if (unit == FFESTV_unitCHAREXPR)
4042 start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
4043 else
4044 start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
4045 break;
4047 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4048 /FOO/] */
4049 ffeste_io_driver_ = NULL; /* No start or driver function. */
4050 start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
4051 break;
4053 default:
4054 assert ("Weird stuff" == NULL);
4055 start = FFECOM_gfrt, end = FFECOM_gfrt;
4056 break;
4058 ffeste_io_endgfrt_ = end;
4060 #define specified(something) (info->read_spec[something].kw_or_val_present)
4062 iostat = specified (FFESTP_readixIOSTAT);
4063 errl = specified (FFESTP_readixERR);
4064 endl = specified (FFESTP_readixEND);
4066 #undef specified
4068 ffeste_start_stmt_ ();
4070 if (errl)
4072 /* Have ERR= specification. */
4074 ffeste_io_err_
4075 = ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
4077 if (endl)
4079 /* Have both ERR= and END=. Need a temp label to handle both. */
4080 ffeste_io_end_
4081 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
4082 ffeste_io_abort_is_temp_ = TRUE;
4083 ffeste_io_abort_ = ffecom_temp_label ();
4085 else
4087 /* Have ERR= but no END=. */
4088 ffeste_io_end_ = NULL_TREE;
4089 if ((ffeste_io_abort_is_temp_ = iostat))
4090 ffeste_io_abort_ = ffecom_temp_label ();
4091 else
4092 ffeste_io_abort_ = ffeste_io_err_;
4095 else
4097 /* No ERR= specification. */
4099 ffeste_io_err_ = NULL_TREE;
4100 if (endl)
4102 /* Have END= but no ERR=. */
4103 ffeste_io_end_
4104 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
4105 if ((ffeste_io_abort_is_temp_ = iostat))
4106 ffeste_io_abort_ = ffecom_temp_label ();
4107 else
4108 ffeste_io_abort_ = ffeste_io_end_;
4110 else
4112 /* Have no ERR= or END=. */
4114 ffeste_io_end_ = NULL_TREE;
4115 if ((ffeste_io_abort_is_temp_ = iostat))
4116 ffeste_io_abort_ = ffecom_temp_label ();
4117 else
4118 ffeste_io_abort_ = NULL_TREE;
4122 if (iostat)
4124 /* Have IOSTAT= specification. */
4126 ffeste_io_iostat_is_temp_ = FALSE;
4127 ffeste_io_iostat_
4128 = ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
4130 else if (ffeste_io_abort_ != NULL_TREE)
4132 /* Have no IOSTAT= but have ERR= and/or END=. */
4134 ffeste_io_iostat_is_temp_ = TRUE;
4135 ffeste_io_iostat_
4136 = ffecom_make_tempvar ("read", ffecom_integer_type_node,
4137 FFETARGET_charactersizeNONE, -1);
4139 else
4141 /* No IOSTAT=, ERR=, or END= specification. */
4143 ffeste_io_iostat_is_temp_ = FALSE;
4144 ffeste_io_iostat_ = NULL_TREE;
4147 /* Now prescan, then convert, all the arguments. */
4149 if (unit == FFESTV_unitCHAREXPR)
4150 cilist = ffeste_io_icilist_ (errl || iostat,
4151 info->read_spec[FFESTP_readixUNIT].u.expr,
4152 endl || iostat, format,
4153 &info->read_spec[FFESTP_readixFORMAT]);
4154 else
4155 cilist = ffeste_io_cilist_ (errl || iostat, unit,
4156 info->read_spec[FFESTP_readixUNIT].u.expr,
4157 5, endl || iostat, format,
4158 &info->read_spec[FFESTP_readixFORMAT],
4159 rec,
4160 info->read_spec[FFESTP_readixREC].u.expr);
4162 /* If there is no end function, then there are no item functions (i.e.
4163 it's a NAMELIST), and vice versa by the way. In this situation, don't
4164 generate the "if (iostat != 0) goto label;" if the label is temp abort
4165 label, since we're gonna fall through to there anyway. */
4167 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4168 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4170 #else
4171 #error
4172 #endif
4175 /* READ statement -- I/O item. */
4177 void
4178 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
4180 ffeste_check_item_ ();
4182 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4183 ffebld_dump (expr);
4184 fputc (',', dmpout);
4185 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4186 if (expr == NULL)
4187 return;
4189 /* Strip parens off items such as in "READ *,(A)". This is really a bug
4190 in the user's code, but I've been told lots of code does this. */
4191 while (ffebld_op (expr) == FFEBLD_opPAREN)
4192 expr = ffebld_left (expr);
4194 if (ffebld_op (expr) == FFEBLD_opANY)
4195 return;
4197 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4198 ffeste_io_impdo_ (expr, expr_token);
4199 else
4201 ffeste_start_stmt_ ();
4203 ffecom_prepare_arg_ptr_to_expr (expr);
4205 ffecom_prepare_end ();
4207 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4209 ffeste_end_stmt_ ();
4211 #else
4212 #error
4213 #endif
4216 /* READ statement -- end. */
4218 void
4219 ffeste_R909_finish ()
4221 ffeste_check_finish_ ();
4223 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4224 fputc ('\n', dmpout);
4225 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4227 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4228 label, since we're gonna fall through to there anyway. */
4230 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4231 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4232 NULL_TREE),
4233 ! ffeste_io_abort_is_temp_);
4235 /* If we've got a temp label, generate its code here and have it fan out
4236 to the END= or ERR= label as appropriate. */
4238 if (ffeste_io_abort_is_temp_)
4240 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4241 emit_nop ();
4242 expand_label (ffeste_io_abort_);
4244 /* "if (iostat<0) goto end_label;". */
4246 if ((ffeste_io_end_ != NULL_TREE)
4247 && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
4249 expand_start_cond (ffecom_truth_value
4250 (ffecom_2 (LT_EXPR, integer_type_node,
4251 ffeste_io_iostat_,
4252 ffecom_integer_zero_node)),
4254 expand_goto (ffeste_io_end_);
4255 expand_end_cond ();
4258 /* "if (iostat>0) goto err_label;". */
4260 if ((ffeste_io_err_ != NULL_TREE)
4261 && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
4263 expand_start_cond (ffecom_truth_value
4264 (ffecom_2 (GT_EXPR, integer_type_node,
4265 ffeste_io_iostat_,
4266 ffecom_integer_zero_node)),
4268 expand_goto (ffeste_io_err_);
4269 expand_end_cond ();
4273 ffeste_end_stmt_ ();
4274 #else
4275 #error
4276 #endif
4279 /* WRITE statement -- start. */
4281 void
4282 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
4283 ffestvFormat format, bool rec)
4285 ffeste_check_start_ ();
4287 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4288 switch (format)
4290 case FFESTV_formatNONE:
4291 if (rec)
4292 fputs ("+ WRITE_ufdac (", dmpout);
4293 else
4294 fputs ("+ WRITE_ufseq_or_idx (", dmpout);
4295 break;
4297 case FFESTV_formatLABEL:
4298 case FFESTV_formatCHAREXPR:
4299 case FFESTV_formatINTEXPR:
4300 if (rec)
4301 fputs ("+ WRITE_fmdac (", dmpout);
4302 else if (unit == FFESTV_unitCHAREXPR)
4303 fputs ("+ WRITE_fmint (", dmpout);
4304 else
4305 fputs ("+ WRITE_fmseq_or_idx (", dmpout);
4306 break;
4308 case FFESTV_formatASTERISK:
4309 if (unit == FFESTV_unitCHAREXPR)
4310 fputs ("+ WRITE_lsint (", dmpout);
4311 else
4312 fputs ("+ WRITE_lsseq (", dmpout);
4313 break;
4315 case FFESTV_formatNAMELIST:
4316 fputs ("+ WRITE_nlseq (", dmpout);
4317 break;
4319 default:
4320 assert ("Unexpected kind of format item in R910 WRITE" == NULL);
4323 ffeste_subr_file_ ("UNIT", &info->write_spec[FFESTP_writeixUNIT]);
4324 ffeste_subr_file_ ("FORMAT", &info->write_spec[FFESTP_writeixFORMAT]);
4325 ffeste_subr_file_ ("ADVANCE", &info->write_spec[FFESTP_writeixADVANCE]);
4326 ffeste_subr_file_ ("EOR", &info->write_spec[FFESTP_writeixEOR]);
4327 ffeste_subr_file_ ("ERR", &info->write_spec[FFESTP_writeixERR]);
4328 ffeste_subr_file_ ("IOSTAT", &info->write_spec[FFESTP_writeixIOSTAT]);
4329 ffeste_subr_file_ ("REC", &info->write_spec[FFESTP_writeixREC]);
4330 fputs (") ", dmpout);
4331 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4333 ffeste_emit_line_note_ ();
4336 ffecomGfrt start;
4337 ffecomGfrt end;
4338 tree cilist;
4339 bool iostat;
4340 bool errl;
4342 /* First determine the start, per-item, and end run-time functions to
4343 call. The per-item function is picked by choosing an ffeste function
4344 to call to handle a given item; it knows how to generate a call to the
4345 appropriate run-time function, and is called an "I/O driver". */
4347 switch (format)
4349 case FFESTV_formatNONE: /* no FMT= */
4350 ffeste_io_driver_ = ffeste_io_douio_;
4351 if (rec)
4352 start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
4353 else
4354 start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
4355 break;
4357 case FFESTV_formatLABEL: /* FMT=10 */
4358 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4359 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4360 ffeste_io_driver_ = ffeste_io_dofio_;
4361 if (rec)
4362 start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
4363 else if (unit == FFESTV_unitCHAREXPR)
4364 start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
4365 else
4366 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
4367 break;
4369 case FFESTV_formatASTERISK: /* FMT=* */
4370 ffeste_io_driver_ = ffeste_io_dolio_;
4371 if (unit == FFESTV_unitCHAREXPR)
4372 start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
4373 else
4374 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
4375 break;
4377 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4378 /FOO/] */
4379 ffeste_io_driver_ = NULL; /* No start or driver function. */
4380 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
4381 break;
4383 default:
4384 assert ("Weird stuff" == NULL);
4385 start = FFECOM_gfrt, end = FFECOM_gfrt;
4386 break;
4388 ffeste_io_endgfrt_ = end;
4390 #define specified(something) (info->write_spec[something].kw_or_val_present)
4392 iostat = specified (FFESTP_writeixIOSTAT);
4393 errl = specified (FFESTP_writeixERR);
4395 #undef specified
4397 ffeste_start_stmt_ ();
4399 ffeste_io_end_ = NULL_TREE;
4401 if (errl)
4403 /* Have ERR= specification. */
4405 ffeste_io_err_
4406 = ffeste_io_abort_
4407 = ffecom_lookup_label
4408 (info->write_spec[FFESTP_writeixERR].u.label);
4409 ffeste_io_abort_is_temp_ = FALSE;
4411 else
4413 /* No ERR= specification. */
4415 ffeste_io_err_ = NULL_TREE;
4417 if ((ffeste_io_abort_is_temp_ = iostat))
4418 ffeste_io_abort_ = ffecom_temp_label ();
4419 else
4420 ffeste_io_abort_ = NULL_TREE;
4423 if (iostat)
4425 /* Have IOSTAT= specification. */
4427 ffeste_io_iostat_is_temp_ = FALSE;
4428 ffeste_io_iostat_ = ffecom_expr
4429 (info->write_spec[FFESTP_writeixIOSTAT].u.expr);
4431 else if (ffeste_io_abort_ != NULL_TREE)
4433 /* Have no IOSTAT= but have ERR=. */
4435 ffeste_io_iostat_is_temp_ = TRUE;
4436 ffeste_io_iostat_
4437 = ffecom_make_tempvar ("write", ffecom_integer_type_node,
4438 FFETARGET_charactersizeNONE, -1);
4440 else
4442 /* No IOSTAT= or ERR= specification. */
4444 ffeste_io_iostat_is_temp_ = FALSE;
4445 ffeste_io_iostat_ = NULL_TREE;
4448 /* Now prescan, then convert, all the arguments. */
4450 if (unit == FFESTV_unitCHAREXPR)
4451 cilist = ffeste_io_icilist_ (errl || iostat,
4452 info->write_spec[FFESTP_writeixUNIT].u.expr,
4453 FALSE, format,
4454 &info->write_spec[FFESTP_writeixFORMAT]);
4455 else
4456 cilist = ffeste_io_cilist_ (errl || iostat, unit,
4457 info->write_spec[FFESTP_writeixUNIT].u.expr,
4458 6, FALSE, format,
4459 &info->write_spec[FFESTP_writeixFORMAT],
4460 rec,
4461 info->write_spec[FFESTP_writeixREC].u.expr);
4463 /* If there is no end function, then there are no item functions (i.e.
4464 it's a NAMELIST), and vice versa by the way. In this situation, don't
4465 generate the "if (iostat != 0) goto label;" if the label is temp abort
4466 label, since we're gonna fall through to there anyway. */
4468 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4469 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4471 #else
4472 #error
4473 #endif
4476 /* WRITE statement -- I/O item. */
4478 void
4479 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
4481 ffeste_check_item_ ();
4483 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4484 ffebld_dump (expr);
4485 fputc (',', dmpout);
4486 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4487 if (expr == NULL)
4488 return;
4490 if (ffebld_op (expr) == FFEBLD_opANY)
4491 return;
4493 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4494 ffeste_io_impdo_ (expr, expr_token);
4495 else
4497 ffeste_start_stmt_ ();
4499 ffecom_prepare_arg_ptr_to_expr (expr);
4501 ffecom_prepare_end ();
4503 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4505 ffeste_end_stmt_ ();
4507 #else
4508 #error
4509 #endif
4512 /* WRITE statement -- end. */
4514 void
4515 ffeste_R910_finish ()
4517 ffeste_check_finish_ ();
4519 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4520 fputc ('\n', dmpout);
4521 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4523 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4524 label, since we're gonna fall through to there anyway. */
4526 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4527 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4528 NULL_TREE),
4529 ! ffeste_io_abort_is_temp_);
4531 /* If we've got a temp label, generate its code here. */
4533 if (ffeste_io_abort_is_temp_)
4535 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4536 emit_nop ();
4537 expand_label (ffeste_io_abort_);
4539 assert (ffeste_io_err_ == NULL_TREE);
4542 ffeste_end_stmt_ ();
4543 #else
4544 #error
4545 #endif
4548 /* PRINT statement -- start. */
4550 void
4551 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
4553 ffeste_check_start_ ();
4555 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4556 switch (format)
4558 case FFESTV_formatLABEL:
4559 case FFESTV_formatCHAREXPR:
4560 case FFESTV_formatINTEXPR:
4561 fputs ("+ PRINT_fm ", dmpout);
4562 break;
4564 case FFESTV_formatASTERISK:
4565 fputs ("+ PRINT_ls ", dmpout);
4566 break;
4568 case FFESTV_formatNAMELIST:
4569 fputs ("+ PRINT_nl ", dmpout);
4570 break;
4572 default:
4573 assert ("Unexpected kind of format item in R911 PRINT" == NULL);
4575 ffeste_subr_file_ ("FORMAT", &info->print_spec[FFESTP_printixFORMAT]);
4576 fputc (' ', dmpout);
4577 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4579 ffeste_emit_line_note_ ();
4582 ffecomGfrt start;
4583 ffecomGfrt end;
4584 tree cilist;
4586 /* First determine the start, per-item, and end run-time functions to
4587 call. The per-item function is picked by choosing an ffeste function
4588 to call to handle a given item; it knows how to generate a call to the
4589 appropriate run-time function, and is called an "I/O driver". */
4591 switch (format)
4593 case FFESTV_formatLABEL: /* FMT=10 */
4594 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4595 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4596 ffeste_io_driver_ = ffeste_io_dofio_;
4597 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
4598 break;
4600 case FFESTV_formatASTERISK: /* FMT=* */
4601 ffeste_io_driver_ = ffeste_io_dolio_;
4602 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
4603 break;
4605 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4606 /FOO/] */
4607 ffeste_io_driver_ = NULL; /* No start or driver function. */
4608 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
4609 break;
4611 default:
4612 assert ("Weird stuff" == NULL);
4613 start = FFECOM_gfrt, end = FFECOM_gfrt;
4614 break;
4616 ffeste_io_endgfrt_ = end;
4618 ffeste_start_stmt_ ();
4620 ffeste_io_end_ = NULL_TREE;
4621 ffeste_io_err_ = NULL_TREE;
4622 ffeste_io_abort_ = NULL_TREE;
4623 ffeste_io_abort_is_temp_ = FALSE;
4624 ffeste_io_iostat_is_temp_ = FALSE;
4625 ffeste_io_iostat_ = NULL_TREE;
4627 /* Now prescan, then convert, all the arguments. */
4629 cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
4630 &info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
4632 /* If there is no end function, then there are no item functions (i.e.
4633 it's a NAMELIST), and vice versa by the way. In this situation, don't
4634 generate the "if (iostat != 0) goto label;" if the label is temp abort
4635 label, since we're gonna fall through to there anyway. */
4637 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4638 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4640 #else
4641 #error
4642 #endif
4645 /* PRINT statement -- I/O item. */
4647 void
4648 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
4650 ffeste_check_item_ ();
4652 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4653 ffebld_dump (expr);
4654 fputc (',', dmpout);
4655 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4656 if (expr == NULL)
4657 return;
4659 if (ffebld_op (expr) == FFEBLD_opANY)
4660 return;
4662 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4663 ffeste_io_impdo_ (expr, expr_token);
4664 else
4666 ffeste_start_stmt_ ();
4668 ffecom_prepare_arg_ptr_to_expr (expr);
4670 ffecom_prepare_end ();
4672 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4674 ffeste_end_stmt_ ();
4676 #else
4677 #error
4678 #endif
4681 /* PRINT statement -- end. */
4683 void
4684 ffeste_R911_finish ()
4686 ffeste_check_finish_ ();
4688 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4689 fputc ('\n', dmpout);
4690 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4692 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4693 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4694 NULL_TREE),
4695 FALSE);
4697 ffeste_end_stmt_ ();
4698 #else
4699 #error
4700 #endif
4703 /* BACKSPACE statement. */
4705 void
4706 ffeste_R919 (ffestpBeruStmt *info)
4708 ffeste_check_simple_ ();
4710 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4711 fputs ("+ BACKSPACE (", dmpout);
4712 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4713 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4714 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4715 fputs (")\n", dmpout);
4716 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4717 ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4718 #else
4719 #error
4720 #endif
4723 /* ENDFILE statement. */
4725 void
4726 ffeste_R920 (ffestpBeruStmt *info)
4728 ffeste_check_simple_ ();
4730 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4731 fputs ("+ ENDFILE (", dmpout);
4732 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4733 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4734 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4735 fputs (")\n", dmpout);
4736 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4737 ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4738 #else
4739 #error
4740 #endif
4743 /* REWIND statement. */
4745 void
4746 ffeste_R921 (ffestpBeruStmt *info)
4748 ffeste_check_simple_ ();
4750 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4751 fputs ("+ REWIND (", dmpout);
4752 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4753 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4754 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4755 fputs (")\n", dmpout);
4756 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4757 ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4758 #else
4759 #error
4760 #endif
4763 /* INQUIRE statement (non-IOLENGTH version). */
4765 void
4766 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4768 ffeste_check_simple_ ();
4770 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4771 if (by_file)
4773 fputs ("+ INQUIRE_file (", dmpout);
4774 ffeste_subr_file_ ("FILE", &info->inquire_spec[FFESTP_inquireixFILE]);
4776 else
4778 fputs ("+ INQUIRE_unit (", dmpout);
4779 ffeste_subr_file_ ("UNIT", &info->inquire_spec[FFESTP_inquireixUNIT]);
4781 ffeste_subr_file_ ("ACCESS", &info->inquire_spec[FFESTP_inquireixACCESS]);
4782 ffeste_subr_file_ ("ACTION", &info->inquire_spec[FFESTP_inquireixACTION]);
4783 ffeste_subr_file_ ("BLANK", &info->inquire_spec[FFESTP_inquireixBLANK]);
4784 ffeste_subr_file_ ("CARRIAGECONTROL", &info->inquire_spec[FFESTP_inquireixCARRIAGECONTROL]);
4785 ffeste_subr_file_ ("DEFAULTFILE", &info->inquire_spec[FFESTP_inquireixDEFAULTFILE]);
4786 ffeste_subr_file_ ("DELIM", &info->inquire_spec[FFESTP_inquireixDELIM]);
4787 ffeste_subr_file_ ("DIRECT", &info->inquire_spec[FFESTP_inquireixDIRECT]);
4788 ffeste_subr_file_ ("ERR", &info->inquire_spec[FFESTP_inquireixERR]);
4789 ffeste_subr_file_ ("EXIST", &info->inquire_spec[FFESTP_inquireixEXIST]);
4790 ffeste_subr_file_ ("FORM", &info->inquire_spec[FFESTP_inquireixFORM]);
4791 ffeste_subr_file_ ("FORMATTED", &info->inquire_spec[FFESTP_inquireixFORMATTED]);
4792 ffeste_subr_file_ ("IOSTAT", &info->inquire_spec[FFESTP_inquireixIOSTAT]);
4793 ffeste_subr_file_ ("KEYED", &info->inquire_spec[FFESTP_inquireixKEYED]);
4794 ffeste_subr_file_ ("NAME", &info->inquire_spec[FFESTP_inquireixNAME]);
4795 ffeste_subr_file_ ("NAMED", &info->inquire_spec[FFESTP_inquireixNAMED]);
4796 ffeste_subr_file_ ("NEXTREC", &info->inquire_spec[FFESTP_inquireixNEXTREC]);
4797 ffeste_subr_file_ ("NUMBER", &info->inquire_spec[FFESTP_inquireixNUMBER]);
4798 ffeste_subr_file_ ("OPENED", &info->inquire_spec[FFESTP_inquireixOPENED]);
4799 ffeste_subr_file_ ("ORGANIZATION", &info->inquire_spec[FFESTP_inquireixORGANIZATION]);
4800 ffeste_subr_file_ ("PAD", &info->inquire_spec[FFESTP_inquireixPAD]);
4801 ffeste_subr_file_ ("POSITION", &info->inquire_spec[FFESTP_inquireixPOSITION]);
4802 ffeste_subr_file_ ("READ", &info->inquire_spec[FFESTP_inquireixREAD]);
4803 ffeste_subr_file_ ("READWRITE", &info->inquire_spec[FFESTP_inquireixREADWRITE]);
4804 ffeste_subr_file_ ("RECL", &info->inquire_spec[FFESTP_inquireixRECL]);
4805 ffeste_subr_file_ ("RECORDTYPE", &info->inquire_spec[FFESTP_inquireixRECORDTYPE]);
4806 ffeste_subr_file_ ("SEQUENTIAL", &info->inquire_spec[FFESTP_inquireixSEQUENTIAL]);
4807 ffeste_subr_file_ ("UNFORMATTED", &info->inquire_spec[FFESTP_inquireixUNFORMATTED]);
4808 ffeste_subr_file_ ("WRITE", &info->inquire_spec[FFESTP_inquireixWRITE]);
4809 fputs (")\n", dmpout);
4810 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4812 tree args;
4813 bool iostat;
4814 bool errl;
4816 ffeste_emit_line_note_ ();
4818 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4820 iostat = specified (FFESTP_inquireixIOSTAT);
4821 errl = specified (FFESTP_inquireixERR);
4823 #undef specified
4825 ffeste_start_stmt_ ();
4827 if (errl)
4829 ffeste_io_err_
4830 = ffeste_io_abort_
4831 = ffecom_lookup_label
4832 (info->inquire_spec[FFESTP_inquireixERR].u.label);
4833 ffeste_io_abort_is_temp_ = FALSE;
4835 else
4837 ffeste_io_err_ = NULL_TREE;
4839 if ((ffeste_io_abort_is_temp_ = iostat))
4840 ffeste_io_abort_ = ffecom_temp_label ();
4841 else
4842 ffeste_io_abort_ = NULL_TREE;
4845 if (iostat)
4847 /* Have IOSTAT= specification. */
4849 ffeste_io_iostat_is_temp_ = FALSE;
4850 ffeste_io_iostat_ = ffecom_expr
4851 (info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4853 else if (ffeste_io_abort_ != NULL_TREE)
4855 /* Have no IOSTAT= but have ERR=. */
4857 ffeste_io_iostat_is_temp_ = TRUE;
4858 ffeste_io_iostat_
4859 = ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
4860 FFETARGET_charactersizeNONE, -1);
4862 else
4864 /* No IOSTAT= or ERR= specification. */
4866 ffeste_io_iostat_is_temp_ = FALSE;
4867 ffeste_io_iostat_ = NULL_TREE;
4870 /* Now prescan, then convert, all the arguments. */
4872 args
4873 = ffeste_io_inlist_ (errl || iostat,
4874 &info->inquire_spec[FFESTP_inquireixUNIT],
4875 &info->inquire_spec[FFESTP_inquireixFILE],
4876 &info->inquire_spec[FFESTP_inquireixEXIST],
4877 &info->inquire_spec[FFESTP_inquireixOPENED],
4878 &info->inquire_spec[FFESTP_inquireixNUMBER],
4879 &info->inquire_spec[FFESTP_inquireixNAMED],
4880 &info->inquire_spec[FFESTP_inquireixNAME],
4881 &info->inquire_spec[FFESTP_inquireixACCESS],
4882 &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4883 &info->inquire_spec[FFESTP_inquireixDIRECT],
4884 &info->inquire_spec[FFESTP_inquireixFORM],
4885 &info->inquire_spec[FFESTP_inquireixFORMATTED],
4886 &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4887 &info->inquire_spec[FFESTP_inquireixRECL],
4888 &info->inquire_spec[FFESTP_inquireixNEXTREC],
4889 &info->inquire_spec[FFESTP_inquireixBLANK]);
4891 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4892 label, since we're gonna fall through to there anyway. */
4894 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
4895 ! ffeste_io_abort_is_temp_);
4897 /* If we've got a temp label, generate its code here. */
4899 if (ffeste_io_abort_is_temp_)
4901 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4902 emit_nop ();
4903 expand_label (ffeste_io_abort_);
4905 assert (ffeste_io_err_ == NULL_TREE);
4908 ffeste_end_stmt_ ();
4910 #else
4911 #error
4912 #endif
4915 /* INQUIRE(IOLENGTH=expr) statement -- start. */
4917 void
4918 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4920 ffeste_check_start_ ();
4922 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4923 fputs ("+ INQUIRE (", dmpout);
4924 ffeste_subr_file_ ("IOLENGTH", &info->inquire_spec[FFESTP_inquireixIOLENGTH]);
4925 fputs (") ", dmpout);
4926 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4927 assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4929 ffeste_emit_line_note_ ();
4930 #else
4931 #error
4932 #endif
4935 /* INQUIRE(IOLENGTH=expr) statement -- I/O item. */
4937 void
4938 ffeste_R923B_item (ffebld expr UNUSED)
4940 ffeste_check_item_ ();
4942 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4943 ffebld_dump (expr);
4944 fputc (',', dmpout);
4945 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4946 #else
4947 #error
4948 #endif
4951 /* INQUIRE(IOLENGTH=expr) statement -- end. */
4953 void
4954 ffeste_R923B_finish ()
4956 ffeste_check_finish_ ();
4958 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4959 fputc ('\n', dmpout);
4960 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4961 #else
4962 #error
4963 #endif
4966 /* ffeste_R1001 -- FORMAT statement
4968 ffeste_R1001(format_list); */
4970 void
4971 ffeste_R1001 (ffests s)
4973 ffeste_check_simple_ ();
4975 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4976 fprintf (dmpout, "$ FORMAT %.*s\n", (int) ffests_length (s), ffests_text (s));
4977 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4979 tree t;
4980 tree ttype;
4981 tree maxindex;
4982 tree var;
4984 assert (ffeste_label_formatdef_ != NULL);
4986 ffeste_emit_line_note_ ();
4988 t = build_string (ffests_length (s), ffests_text (s));
4990 TREE_TYPE (t)
4991 = build_type_variant (build_array_type
4992 (char_type_node,
4993 build_range_type (integer_type_node,
4994 integer_one_node,
4995 build_int_2 (ffests_length (s),
4996 0))),
4997 1, 0);
4998 TREE_CONSTANT (t) = 1;
4999 TREE_STATIC (t) = 1;
5001 push_obstacks_nochange ();
5002 end_temporary_allocation ();
5004 var = ffecom_lookup_label (ffeste_label_formatdef_);
5005 if ((var != NULL_TREE)
5006 && (TREE_CODE (var) == VAR_DECL))
5008 DECL_INITIAL (var) = t;
5009 maxindex = build_int_2 (ffests_length (s) - 1, 0);
5010 ttype = TREE_TYPE (var);
5011 TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
5012 integer_zero_node,
5013 maxindex);
5014 if (!TREE_TYPE (maxindex))
5015 TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
5016 layout_type (ttype);
5017 rest_of_decl_compilation (var, NULL, 1, 0);
5018 expand_decl (var);
5019 expand_decl_init (var);
5022 resume_temporary_allocation ();
5023 pop_obstacks ();
5025 ffeste_label_formatdef_ = NULL;
5027 #else
5028 #error
5029 #endif
5032 /* END PROGRAM. */
5034 void
5035 ffeste_R1103 ()
5037 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5038 fputs ("+ END_PROGRAM\n", dmpout);
5039 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5040 #else
5041 #error
5042 #endif
5045 /* END BLOCK DATA. */
5047 void
5048 ffeste_R1112 ()
5050 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5051 fputs ("* END_BLOCK_DATA\n", dmpout);
5052 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5053 #else
5054 #error
5055 #endif
5058 /* CALL statement. */
5060 void
5061 ffeste_R1212 (ffebld expr)
5063 ffeste_check_simple_ ();
5065 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5066 fputs ("+ CALL ", dmpout);
5067 ffebld_dump (expr);
5068 fputc ('\n', dmpout);
5069 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5071 ffebld args = ffebld_right (expr);
5072 ffebld arg;
5073 ffebld labels = NULL; /* First in list of LABTERs. */
5074 ffebld prevlabels = NULL;
5075 ffebld prevargs = NULL;
5077 ffeste_emit_line_note_ ();
5079 /* Here we split the list at ffebld_right(expr) into two lists: one at
5080 ffebld_right(expr) consisting of all items that are not LABTERs, the
5081 other at labels consisting of all items that are LABTERs. Then, if
5082 the latter list is NULL, we have an ordinary call, else we have a call
5083 with alternate returns. */
5085 for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
5087 if (((arg = ffebld_head (args)) == NULL)
5088 || (ffebld_op (arg) != FFEBLD_opLABTER))
5090 if (prevargs == NULL)
5092 prevargs = args;
5093 ffebld_set_right (expr, args);
5095 else
5097 ffebld_set_trail (prevargs, args);
5098 prevargs = args;
5101 else
5103 if (prevlabels == NULL)
5105 prevlabels = labels = args;
5107 else
5109 ffebld_set_trail (prevlabels, args);
5110 prevlabels = args;
5114 if (prevlabels == NULL)
5115 labels = NULL;
5116 else
5117 ffebld_set_trail (prevlabels, NULL);
5118 if (prevargs == NULL)
5119 ffebld_set_right (expr, NULL);
5120 else
5121 ffebld_set_trail (prevargs, NULL);
5123 ffeste_start_stmt_ ();
5125 /* No temporaries are actually needed at this level, but we go
5126 through the motions anyway, just to be sure in case they do
5127 get made. Temporaries needed for arguments should be in the
5128 scopes of inner blocks, and if clean-up actions are supported,
5129 such as CALL-ing an intrinsic that writes to an argument of one
5130 type when a variable of a different type is provided (requiring
5131 assignment to the variable from a temporary after the library
5132 routine returns), the clean-up must be done by the expression
5133 evaluator, generally, to handle alternate returns (which we hope
5134 won't ever be supported by intrinsics, but might be a similar
5135 issue, such as CALL-ing an F90-style subroutine with an INTERFACE
5136 block). That implies the expression evaluator will have to
5137 recognize the need for its own temporary anyway, meaning it'll
5138 construct a block within the one constructed here. */
5140 ffecom_prepare_expr (expr);
5142 ffecom_prepare_end ();
5144 if (labels == NULL)
5145 expand_expr_stmt (ffecom_expr (expr));
5146 else
5148 tree texpr;
5149 tree value;
5150 tree tlabel;
5151 int caseno;
5152 int pushok;
5153 tree duplicate;
5154 ffebld label;
5156 texpr = ffecom_expr (expr);
5157 expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
5159 for (caseno = 1, label = labels;
5160 label != NULL;
5161 ++caseno, label = ffebld_trail (label))
5163 value = build_int_2 (caseno, 0);
5164 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
5166 pushok = pushcase (value, convert, tlabel, &duplicate);
5167 assert (pushok == 0);
5169 tlabel
5170 = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
5171 if ((tlabel == NULL_TREE)
5172 || (TREE_CODE (tlabel) == ERROR_MARK))
5173 continue;
5174 TREE_USED (tlabel) = 1;
5175 expand_goto (tlabel);
5178 expand_end_case (texpr);
5181 ffeste_end_stmt_ ();
5183 #else
5184 #error
5185 #endif
5188 /* END FUNCTION. */
5190 void
5191 ffeste_R1221 ()
5193 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5194 fputs ("+ END_FUNCTION\n", dmpout);
5195 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5196 #else
5197 #error
5198 #endif
5201 /* END SUBROUTINE. */
5203 void
5204 ffeste_R1225 ()
5206 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5207 fprintf (dmpout, "+ END_SUBROUTINE\n");
5208 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5209 #else
5210 #error
5211 #endif
5214 /* ENTRY statement. */
5216 void
5217 ffeste_R1226 (ffesymbol entry)
5219 ffeste_check_simple_ ();
5221 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5222 fprintf (dmpout, "+ ENTRY %s", ffesymbol_text (entry));
5223 if (ffesymbol_dummyargs (entry) != NULL)
5225 ffebld argh;
5227 fputc ('(', dmpout);
5228 for (argh = ffesymbol_dummyargs (entry);
5229 argh != NULL;
5230 argh = ffebld_trail (argh))
5232 assert (ffebld_head (argh) != NULL);
5233 switch (ffebld_op (ffebld_head (argh)))
5235 case FFEBLD_opSYMTER:
5236 fputs (ffesymbol_text (ffebld_symter (ffebld_head (argh))),
5237 dmpout);
5238 break;
5240 case FFEBLD_opSTAR:
5241 fputc ('*', dmpout);
5242 break;
5244 default:
5245 fputc ('?', dmpout);
5246 ffebld_dump (ffebld_head (argh));
5247 fputc ('?', dmpout);
5248 break;
5250 if (ffebld_trail (argh) != NULL)
5251 fputc (',', dmpout);
5253 fputc (')', dmpout);
5255 fputc ('\n', dmpout);
5256 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5258 tree label = ffesymbol_hook (entry).length_tree;
5260 ffeste_emit_line_note_ ();
5262 if (label == error_mark_node)
5263 return;
5265 DECL_INITIAL (label) = error_mark_node;
5266 emit_nop ();
5267 expand_label (label);
5269 #else
5270 #error
5271 #endif
5274 /* RETURN statement. */
5276 void
5277 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
5279 ffeste_check_simple_ ();
5281 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5282 if (expr == NULL)
5284 fputs ("+ RETURN\n", dmpout);
5286 else
5288 fputs ("+ RETURN_alternate ", dmpout);
5289 ffebld_dump (expr);
5290 fputc ('\n', dmpout);
5292 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5294 tree rtn;
5296 ffeste_emit_line_note_ ();
5298 ffeste_start_stmt_ ();
5300 ffecom_prepare_return_expr (expr);
5302 ffecom_prepare_end ();
5304 rtn = ffecom_return_expr (expr);
5306 if ((rtn == NULL_TREE)
5307 || (rtn == error_mark_node))
5308 expand_null_return ();
5309 else
5311 tree result = DECL_RESULT (current_function_decl);
5313 if ((result != error_mark_node)
5314 && (TREE_TYPE (result) != error_mark_node))
5315 expand_return (ffecom_modify (NULL_TREE,
5316 result,
5317 convert (TREE_TYPE (result),
5318 rtn)));
5319 else
5320 expand_null_return ();
5323 ffeste_end_stmt_ ();
5325 #else
5326 #error
5327 #endif
5330 /* REWRITE statement -- start. */
5332 #if FFESTR_VXT
5333 void
5334 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
5336 ffeste_check_start_ ();
5338 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5339 switch (format)
5341 case FFESTV_formatNONE:
5342 fputs ("+ REWRITE_uf (", dmpout);
5343 break;
5345 case FFESTV_formatLABEL:
5346 case FFESTV_formatCHAREXPR:
5347 case FFESTV_formatINTEXPR:
5348 fputs ("+ REWRITE_fm (", dmpout);
5349 break;
5351 default:
5352 assert ("Unexpected kind of format item in V018 REWRITE" == NULL);
5354 ffeste_subr_file_ ("UNIT", &info->rewrite_spec[FFESTP_rewriteixUNIT]);
5355 ffeste_subr_file_ ("FMT", &info->rewrite_spec[FFESTP_rewriteixFMT]);
5356 ffeste_subr_file_ ("ERR", &info->rewrite_spec[FFESTP_rewriteixERR]);
5357 ffeste_subr_file_ ("IOSTAT", &info->rewrite_spec[FFESTP_rewriteixIOSTAT]);
5358 fputs (") ", dmpout);
5359 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5360 #else
5361 #error
5362 #endif
5365 /* REWRITE statement -- I/O item. */
5367 void
5368 ffeste_V018_item (ffebld expr)
5370 ffeste_check_item_ ();
5372 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5373 ffebld_dump (expr);
5374 fputc (',', dmpout);
5375 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5376 #else
5377 #error
5378 #endif
5381 /* REWRITE statement -- end. */
5383 void
5384 ffeste_V018_finish ()
5386 ffeste_check_finish_ ();
5388 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5389 fputc ('\n', dmpout);
5390 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5391 #else
5392 #error
5393 #endif
5396 /* ACCEPT statement -- start. */
5398 void
5399 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
5401 ffeste_check_start_ ();
5403 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5404 switch (format)
5406 case FFESTV_formatLABEL:
5407 case FFESTV_formatCHAREXPR:
5408 case FFESTV_formatINTEXPR:
5409 fputs ("+ ACCEPT_fm ", dmpout);
5410 break;
5412 case FFESTV_formatASTERISK:
5413 fputs ("+ ACCEPT_ls ", dmpout);
5414 break;
5416 case FFESTV_formatNAMELIST:
5417 fputs ("+ ACCEPT_nl ", dmpout);
5418 break;
5420 default:
5421 assert ("Unexpected kind of format item in V019 ACCEPT" == NULL);
5423 ffeste_subr_file_ ("FORMAT", &info->accept_spec[FFESTP_acceptixFORMAT]);
5424 fputc (' ', dmpout);
5425 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5426 #else
5427 #error
5428 #endif
5431 /* ACCEPT statement -- I/O item. */
5433 void
5434 ffeste_V019_item (ffebld expr)
5436 ffeste_check_item_ ();
5438 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5439 ffebld_dump (expr);
5440 fputc (',', dmpout);
5441 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5442 #else
5443 #error
5444 #endif
5447 /* ACCEPT statement -- end. */
5449 void
5450 ffeste_V019_finish ()
5452 ffeste_check_finish_ ();
5454 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5455 fputc ('\n', dmpout);
5456 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5457 #else
5458 #error
5459 #endif
5462 #endif
5463 /* TYPE statement -- start. */
5465 void
5466 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
5467 ffestvFormat format UNUSED)
5469 ffeste_check_start_ ();
5471 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5472 switch (format)
5474 case FFESTV_formatLABEL:
5475 case FFESTV_formatCHAREXPR:
5476 case FFESTV_formatINTEXPR:
5477 fputs ("+ TYPE_fm ", dmpout);
5478 break;
5480 case FFESTV_formatASTERISK:
5481 fputs ("+ TYPE_ls ", dmpout);
5482 break;
5484 case FFESTV_formatNAMELIST:
5485 fputs ("* TYPE_nl ", dmpout);
5486 break;
5488 default:
5489 assert ("Unexpected kind of format item in V020 TYPE" == NULL);
5491 ffeste_subr_file_ ("FORMAT", &info->type_spec[FFESTP_typeixFORMAT]);
5492 fputc (' ', dmpout);
5493 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5494 #else
5495 #error
5496 #endif
5499 /* TYPE statement -- I/O item. */
5501 void
5502 ffeste_V020_item (ffebld expr UNUSED)
5504 ffeste_check_item_ ();
5506 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5507 ffebld_dump (expr);
5508 fputc (',', dmpout);
5509 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5510 #else
5511 #error
5512 #endif
5515 /* TYPE statement -- end. */
5517 void
5518 ffeste_V020_finish ()
5520 ffeste_check_finish_ ();
5522 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5523 fputc ('\n', dmpout);
5524 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5525 #else
5526 #error
5527 #endif
5530 /* DELETE statement. */
5532 #if FFESTR_VXT
5533 void
5534 ffeste_V021 (ffestpDeleteStmt *info)
5536 ffeste_check_simple_ ();
5538 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5539 fputs ("+ DELETE (", dmpout);
5540 ffeste_subr_file_ ("UNIT", &info->delete_spec[FFESTP_deleteixUNIT]);
5541 ffeste_subr_file_ ("REC", &info->delete_spec[FFESTP_deleteixREC]);
5542 ffeste_subr_file_ ("ERR", &info->delete_spec[FFESTP_deleteixERR]);
5543 ffeste_subr_file_ ("IOSTAT", &info->delete_spec[FFESTP_deleteixIOSTAT]);
5544 fputs (")\n", dmpout);
5545 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5546 #else
5547 #error
5548 #endif
5551 /* UNLOCK statement. */
5553 void
5554 ffeste_V022 (ffestpBeruStmt *info)
5556 ffeste_check_simple_ ();
5558 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5559 fputs ("+ UNLOCK (", dmpout);
5560 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
5561 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
5562 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
5563 fputs (")\n", dmpout);
5564 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5565 #else
5566 #error
5567 #endif
5570 /* ENCODE statement -- start. */
5572 void
5573 ffeste_V023_start (ffestpVxtcodeStmt *info)
5575 ffeste_check_start_ ();
5577 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5578 fputs ("+ ENCODE (", dmpout);
5579 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5580 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5581 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5582 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5583 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5584 fputs (") ", dmpout);
5585 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5586 #else
5587 #error
5588 #endif
5591 /* ENCODE statement -- I/O item. */
5593 void
5594 ffeste_V023_item (ffebld expr)
5596 ffeste_check_item_ ();
5598 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5599 ffebld_dump (expr);
5600 fputc (',', dmpout);
5601 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5602 #else
5603 #error
5604 #endif
5607 /* ENCODE statement -- end. */
5609 void
5610 ffeste_V023_finish ()
5612 ffeste_check_finish_ ();
5614 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5615 fputc ('\n', dmpout);
5616 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5617 #else
5618 #error
5619 #endif
5622 /* DECODE statement -- start. */
5624 void
5625 ffeste_V024_start (ffestpVxtcodeStmt *info)
5627 ffeste_check_start_ ();
5629 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5630 fputs ("+ DECODE (", dmpout);
5631 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5632 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5633 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5634 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5635 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5636 fputs (") ", dmpout);
5637 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5638 #else
5639 #error
5640 #endif
5643 /* DECODE statement -- I/O item. */
5645 void
5646 ffeste_V024_item (ffebld expr)
5648 ffeste_check_item_ ();
5650 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5651 ffebld_dump (expr);
5652 fputc (',', dmpout);
5653 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5654 #else
5655 #error
5656 #endif
5659 /* DECODE statement -- end. */
5661 void
5662 ffeste_V024_finish ()
5664 ffeste_check_finish_ ();
5666 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5667 fputc ('\n', dmpout);
5668 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5669 #else
5670 #error
5671 #endif
5674 /* DEFINEFILE statement -- start. */
5676 void
5677 ffeste_V025_start ()
5679 ffeste_check_start_ ();
5681 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5682 fputs ("+ DEFINE_FILE ", dmpout);
5683 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5684 #else
5685 #error
5686 #endif
5689 /* DEFINE FILE statement -- item. */
5691 void
5692 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
5694 ffeste_check_item_ ();
5696 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5697 ffebld_dump (u);
5698 fputc ('(', dmpout);
5699 ffebld_dump (m);
5700 fputc (',', dmpout);
5701 ffebld_dump (n);
5702 fputs (",U,", dmpout);
5703 ffebld_dump (asv);
5704 fputs ("),", dmpout);
5705 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5706 #else
5707 #error
5708 #endif
5711 /* DEFINE FILE statement -- end. */
5713 void
5714 ffeste_V025_finish ()
5716 ffeste_check_finish_ ();
5718 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5719 fputc ('\n', dmpout);
5720 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5721 #else
5722 #error
5723 #endif
5726 /* FIND statement. */
5728 void
5729 ffeste_V026 (ffestpFindStmt *info)
5731 ffeste_check_simple_ ();
5733 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5734 fputs ("+ FIND (", dmpout);
5735 ffeste_subr_file_ ("UNIT", &info->find_spec[FFESTP_findixUNIT]);
5736 ffeste_subr_file_ ("REC", &info->find_spec[FFESTP_findixREC]);
5737 ffeste_subr_file_ ("ERR", &info->find_spec[FFESTP_findixERR]);
5738 ffeste_subr_file_ ("IOSTAT", &info->find_spec[FFESTP_findixIOSTAT]);
5739 fputs (")\n", dmpout);
5740 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5741 #else
5742 #error
5743 #endif
5746 #endif
5748 #ifdef ENABLE_CHECKING
5749 void
5750 ffeste_terminate_2 (void)
5752 assert (! ffeste_top_block_);
5754 #endif