* Makefile.in (SYSTEM_H): Define.
[official-gcc.git] / gcc / f / ste.c
blob5b4c68eb2d19e9686358eacbd22bb5af6e079a6b
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 ffecom_end_compstmt ();
446 /* Start a Fortran statement.
448 Starts a back-end block, so temporaries can be managed, clean-ups
449 properly handled, etc. Nesting of statements *is* allowed -- the
450 handling of I/O items, even implied-DO I/O lists, within a READ,
451 PRINT, or WRITE statement is one example. */
453 static void
454 ffeste_start_stmt_(void)
456 gbe_block b = xmalloc (sizeof (*b));
458 b->outer = ffeste_top_block_;
459 b->block = NULL;
460 b->lineno = lineno;
461 b->input_filename = input_filename;
462 b->is_stmt = TRUE;
464 ffeste_top_block_ = b;
466 ffecom_start_compstmt ();
469 /* End a Fortran statement. */
471 static void
472 ffeste_end_stmt_(void)
474 gbe_block b = ffeste_top_block_;
476 assert (b);
477 assert (b->is_stmt);
479 ffeste_top_block_ = b->outer;
481 free (b);
483 ffecom_end_compstmt ();
486 #else /* ! defined (ENABLE_CHECKING) */
488 #define ffeste_start_block_(b) ffecom_start_compstmt ()
489 #define ffeste_end_block_(b) \
490 do \
492 ffecom_end_compstmt (); \
493 } while(0)
494 #define ffeste_start_stmt_() ffeste_start_block_(NULL)
495 #define ffeste_end_stmt_() ffeste_end_block_(NULL)
497 #endif /* ! defined (ENABLE_CHECKING) */
499 /* Begin an iterative DO loop. Pass the block to start if
500 applicable. */
502 #if FFECOM_targetCURRENT == FFECOM_targetGCC
503 static void
504 ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
505 tree *xitersvar, ffebld var,
506 ffebld start, ffelexToken start_token,
507 ffebld end, ffelexToken end_token,
508 ffebld incr, ffelexToken incr_token,
509 const char *msg)
511 tree tvar;
512 tree expr;
513 tree tstart;
514 tree tend;
515 tree tincr;
516 tree tincr_saved;
517 tree niters;
518 struct nesting *expanded_loop;
520 /* Want to have tvar, tincr, and niters for the whole loop body. */
522 if (block)
523 ffeste_start_block_ (block);
524 else
525 ffeste_start_stmt_ ();
527 niters = ffecom_make_tempvar (block ? "do" : "impdo",
528 ffecom_integer_type_node,
529 FFETARGET_charactersizeNONE, -1);
531 ffecom_prepare_expr (incr);
532 ffecom_prepare_expr_rw (NULL_TREE, var);
534 ffecom_prepare_end ();
536 tvar = ffecom_expr_rw (NULL_TREE, var);
537 tincr = ffecom_expr (incr);
539 if (TREE_CODE (tvar) == ERROR_MARK
540 || TREE_CODE (tincr) == ERROR_MARK)
542 if (block)
544 ffeste_end_block_ (block);
545 ffestw_set_do_tvar (block, error_mark_node);
547 else
549 ffeste_end_stmt_ ();
550 *xtvar = error_mark_node;
552 return;
555 /* Check whether incr is known to be zero, complain and fix. */
557 if (integer_zerop (tincr) || real_zerop (tincr))
559 ffebad_start (FFEBAD_DO_STEP_ZERO);
560 ffebad_here (0, ffelex_token_where_line (incr_token),
561 ffelex_token_where_column (incr_token));
562 ffebad_string (msg);
563 ffebad_finish ();
564 tincr = convert (TREE_TYPE (tvar), integer_one_node);
567 tincr_saved = ffecom_save_tree (tincr);
569 /* Want to have tstart, tend for just this statement. */
571 ffeste_start_stmt_ ();
573 ffecom_prepare_expr (start);
574 ffecom_prepare_expr (end);
576 ffecom_prepare_end ();
578 tstart = ffecom_expr (start);
579 tend = ffecom_expr (end);
581 if (TREE_CODE (tstart) == ERROR_MARK
582 || TREE_CODE (tend) == ERROR_MARK)
584 ffeste_end_stmt_ ();
586 if (block)
588 ffeste_end_block_ (block);
589 ffestw_set_do_tvar (block, error_mark_node);
591 else
593 ffeste_end_stmt_ ();
594 *xtvar = error_mark_node;
596 return;
599 /* For warnings only, nothing else happens here. */
601 tree try;
603 if (! ffe_is_onetrip ())
605 try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
606 tend,
607 tstart);
609 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
610 try,
611 tincr);
613 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
614 try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
615 tincr);
616 else
617 try = convert (integer_type_node,
618 ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
619 try,
620 tincr));
622 /* Warn if loop never executed, since we've done the evaluation
623 of the unofficial iteration count already. */
625 try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
626 try,
627 convert (TREE_TYPE (tvar),
628 integer_zero_node)));
630 if (integer_onep (try))
632 ffebad_start (FFEBAD_DO_NULL);
633 ffebad_here (0, ffelex_token_where_line (start_token),
634 ffelex_token_where_column (start_token));
635 ffebad_string (msg);
636 ffebad_finish ();
640 /* Warn if end plus incr would overflow. */
642 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
643 tend,
644 tincr);
646 if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
647 && TREE_CONSTANT_OVERFLOW (try))
649 ffebad_start (FFEBAD_DO_END_OVERFLOW);
650 ffebad_here (0, ffelex_token_where_line (end_token),
651 ffelex_token_where_column (end_token));
652 ffebad_string (msg);
653 ffebad_finish ();
657 /* Do the initial assignment into the DO var. */
659 tstart = ffecom_save_tree (tstart);
661 expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
662 tend,
663 tstart);
665 if (! ffe_is_onetrip ())
667 expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
668 expr,
669 convert (TREE_TYPE (expr), tincr_saved));
672 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
673 expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
674 expr,
675 tincr_saved);
676 else
677 expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
678 expr,
679 tincr_saved);
681 #if 1 /* New, F90-approved approach: convert to default INTEGER. */
682 if (TREE_TYPE (tvar) != error_mark_node)
683 expr = convert (ffecom_integer_type_node, expr);
684 #else /* Old approach; convert to INTEGER unless that's a narrowing. */
685 if ((TREE_TYPE (tvar) != error_mark_node)
686 && ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
687 || ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
688 && ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
689 != INTEGER_CST)
690 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
691 <= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
692 /* Convert unless promoting INTEGER type of any kind downward to
693 default INTEGER; else leave as, say, INTEGER*8 (long long int). */
694 expr = convert (ffecom_integer_type_node, expr);
695 #endif
697 assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
698 == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
700 expr = ffecom_modify (void_type_node, niters, expr);
701 expand_expr_stmt (expr);
703 expr = ffecom_modify (void_type_node, tvar, tstart);
704 expand_expr_stmt (expr);
706 ffeste_end_stmt_ ();
708 expanded_loop = expand_start_loop_continue_elsewhere (!! block);
709 if (block)
710 ffestw_set_do_hook (block, expanded_loop);
712 if (! ffe_is_onetrip ())
714 expr = ffecom_truth_value
715 (ffecom_2 (GE_EXPR, integer_type_node,
716 ffecom_2 (PREDECREMENT_EXPR,
717 TREE_TYPE (niters),
718 niters,
719 convert (TREE_TYPE (niters),
720 ffecom_integer_one_node)),
721 convert (TREE_TYPE (niters),
722 ffecom_integer_zero_node)));
724 expand_exit_loop_if_false (0, expr);
727 if (block)
729 ffestw_set_do_tvar (block, tvar);
730 ffestw_set_do_incr_saved (block, tincr_saved);
731 ffestw_set_do_count_var (block, niters);
733 else
735 *xtvar = tvar;
736 *xtincr = tincr_saved;
737 *xitersvar = niters;
741 #endif
743 /* End an iterative DO loop. Pass the same iteration variable and increment
744 value trees that were generated in the paired _begin_ call. */
746 #if FFECOM_targetCURRENT == FFECOM_targetGCC
747 static void
748 ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
750 tree expr;
751 tree niters = itersvar;
753 if (tvar == error_mark_node)
754 return;
756 expand_loop_continue_here ();
758 ffeste_start_stmt_ ();
760 if (ffe_is_onetrip ())
762 expr = ffecom_truth_value
763 (ffecom_2 (GE_EXPR, integer_type_node,
764 ffecom_2 (PREDECREMENT_EXPR,
765 TREE_TYPE (niters),
766 niters,
767 convert (TREE_TYPE (niters),
768 ffecom_integer_one_node)),
769 convert (TREE_TYPE (niters),
770 ffecom_integer_zero_node)));
772 expand_exit_loop_if_false (0, expr);
775 expr = ffecom_modify (void_type_node, tvar,
776 ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
777 tvar,
778 tincr));
779 expand_expr_stmt (expr);
781 /* Lose the stuff we just built. */
782 ffeste_end_stmt_ ();
784 expand_end_loop ();
786 /* Lose the tvar and incr_saved trees. */
787 if (block)
788 ffeste_end_block_ (block);
789 else
790 ffeste_end_stmt_ ();
792 #endif
794 /* Generate call to run-time I/O routine. */
796 #if FFECOM_targetCURRENT == FFECOM_targetGCC
797 static void
798 ffeste_io_call_ (tree call, bool do_check)
800 /* Generate the call and optional assignment into iostat var. */
802 TREE_SIDE_EFFECTS (call) = 1;
803 if (ffeste_io_iostat_ != NULL_TREE)
804 call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
805 ffeste_io_iostat_, call);
806 expand_expr_stmt (call);
808 if (! do_check
809 || ffeste_io_abort_ == NULL_TREE
810 || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
811 return;
813 /* Generate optional test. */
815 expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
816 expand_goto (ffeste_io_abort_);
817 expand_end_cond ();
819 #endif
821 /* Handle implied-DO in I/O list.
823 Expands code to start up the DO loop. Then for each item in the
824 DO loop, handles appropriately (possibly including recursively calling
825 itself). Then expands code to end the DO loop. */
827 #if FFECOM_targetCURRENT == FFECOM_targetGCC
828 static void
829 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
831 ffebld var = ffebld_head (ffebld_right (impdo));
832 ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
833 ffebld end = ffebld_head (ffebld_trail (ffebld_trail
834 (ffebld_right (impdo))));
835 ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
836 (ffebld_trail (ffebld_right (impdo)))));
837 ffebld list;
838 ffebld item;
839 tree tvar;
840 tree tincr;
841 tree titervar;
843 if (incr == NULL)
845 incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
846 ffebld_set_info (incr, ffeinfo_new
847 (FFEINFO_basictypeINTEGER,
848 FFEINFO_kindtypeINTEGERDEFAULT,
850 FFEINFO_kindENTITY,
851 FFEINFO_whereCONSTANT,
852 FFETARGET_charactersizeNONE));
855 /* Start the DO loop. */
857 start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
858 FFEEXPR_contextLET);
859 end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
860 FFEEXPR_contextLET);
861 incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
862 FFEEXPR_contextLET);
864 ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
865 start, impdo_token,
866 end, impdo_token,
867 incr, impdo_token,
868 "Implied DO loop");
870 /* Handle the list of items. */
872 for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
874 item = ffebld_head (list);
875 if (item == NULL)
876 continue;
878 /* Strip parens off items such as in "READ *,(A)". This is really a bug
879 in the user's code, but I've been told lots of code does this. */
880 while (ffebld_op (item) == FFEBLD_opPAREN)
881 item = ffebld_left (item);
883 if (ffebld_op (item) == FFEBLD_opANY)
884 continue;
886 if (ffebld_op (item) == FFEBLD_opIMPDO)
887 ffeste_io_impdo_ (item, impdo_token);
888 else
890 ffeste_start_stmt_ ();
892 ffecom_prepare_arg_ptr_to_expr (item);
894 ffecom_prepare_end ();
896 ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
898 ffeste_end_stmt_ ();
902 /* Generate end of implied-do construct. */
904 ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
906 #endif
908 /* I/O driver for formatted I/O item (do_fio)
910 Returns a tree for a CALL_EXPR to the do_fio function, which handles
911 a formatted I/O list item, along with the appropriate arguments for
912 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
913 for the CALL_EXPR, expand (emit) the expression, emit any assignment
914 of the result to an IOSTAT= variable, and emit any checking of the
915 result for errors. */
917 #if FFECOM_targetCURRENT == FFECOM_targetGCC
918 static tree
919 ffeste_io_dofio_ (ffebld expr)
921 tree num_elements;
922 tree variable;
923 tree size;
924 tree arglist;
925 ffeinfoBasictype bt;
926 ffeinfoKindtype kt;
927 bool is_complex;
929 bt = ffeinfo_basictype (ffebld_info (expr));
930 kt = ffeinfo_kindtype (ffebld_info (expr));
932 if ((bt == FFEINFO_basictypeANY)
933 || (kt == FFEINFO_kindtypeANY))
934 return error_mark_node;
936 if (bt == FFEINFO_basictypeCOMPLEX)
938 is_complex = TRUE;
939 bt = FFEINFO_basictypeREAL;
941 else
942 is_complex = FALSE;
944 variable = ffecom_arg_ptr_to_expr (expr, &size);
946 if ((variable == error_mark_node)
947 || (size == error_mark_node))
948 return error_mark_node;
950 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
951 { /* "(ftnlen) sizeof(type)" */
952 size = size_binop (CEIL_DIV_EXPR,
953 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
954 size_int (TYPE_PRECISION (char_type_node)
955 / BITS_PER_UNIT));
956 #if 0 /* Assume that while it is possible that char * is wider than
957 ftnlen, no object in Fortran space can get big enough for its
958 size to be wider than ftnlen. I really hope nobody wastes
959 time debugging a case where it can! */
960 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
961 >= TYPE_PRECISION (TREE_TYPE (size)));
962 #endif
963 size = convert (ffecom_f2c_ftnlen_type_node, size);
966 if (ffeinfo_rank (ffebld_info (expr)) == 0
967 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
968 num_elements
969 = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
970 else
972 num_elements
973 = size_binop (CEIL_DIV_EXPR,
974 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
975 convert (sizetype, size));
976 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
977 size_int (TYPE_PRECISION (char_type_node)
978 / BITS_PER_UNIT));
979 num_elements = convert (ffecom_f2c_ftnlen_type_node,
980 num_elements);
983 num_elements
984 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
985 num_elements);
987 variable = convert (string_type_node, variable);
989 arglist = build_tree_list (NULL_TREE, num_elements);
990 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
991 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
993 return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
996 #endif
997 /* I/O driver for list-directed I/O item (do_lio)
999 Returns a tree for a CALL_EXPR to the do_lio function, which handles
1000 a list-directed I/O list item, along with the appropriate arguments for
1001 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
1002 for the CALL_EXPR, expand (emit) the expression, emit any assignment
1003 of the result to an IOSTAT= variable, and emit any checking of the
1004 result for errors. */
1006 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1007 static tree
1008 ffeste_io_dolio_ (ffebld expr)
1010 tree type_id;
1011 tree num_elements;
1012 tree variable;
1013 tree size;
1014 tree arglist;
1015 ffeinfoBasictype bt;
1016 ffeinfoKindtype kt;
1017 int tc;
1019 bt = ffeinfo_basictype (ffebld_info (expr));
1020 kt = ffeinfo_kindtype (ffebld_info (expr));
1022 if ((bt == FFEINFO_basictypeANY)
1023 || (kt == FFEINFO_kindtypeANY))
1024 return error_mark_node;
1026 tc = ffecom_f2c_typecode (bt, kt);
1027 assert (tc != -1);
1028 type_id = build_int_2 (tc, 0);
1030 type_id
1031 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
1032 convert (ffecom_f2c_ftnint_type_node,
1033 type_id));
1035 variable = ffecom_arg_ptr_to_expr (expr, &size);
1037 if ((type_id == error_mark_node)
1038 || (variable == error_mark_node)
1039 || (size == error_mark_node))
1040 return error_mark_node;
1042 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
1043 { /* "(ftnlen) sizeof(type)" */
1044 size = size_binop (CEIL_DIV_EXPR,
1045 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1046 size_int (TYPE_PRECISION (char_type_node)
1047 / BITS_PER_UNIT));
1048 #if 0 /* Assume that while it is possible that char * is wider than
1049 ftnlen, no object in Fortran space can get big enough for its
1050 size to be wider than ftnlen. I really hope nobody wastes
1051 time debugging a case where it can! */
1052 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1053 >= TYPE_PRECISION (TREE_TYPE (size)));
1054 #endif
1055 size = convert (ffecom_f2c_ftnlen_type_node, size);
1058 if (ffeinfo_rank (ffebld_info (expr)) == 0
1059 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1060 num_elements = ffecom_integer_one_node;
1061 else
1063 num_elements
1064 = size_binop (CEIL_DIV_EXPR,
1065 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1066 convert (sizetype, size));
1067 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1068 size_int (TYPE_PRECISION (char_type_node)
1069 / BITS_PER_UNIT));
1070 num_elements = convert (ffecom_f2c_ftnlen_type_node,
1071 num_elements);
1074 num_elements
1075 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1076 num_elements);
1078 variable = convert (string_type_node, variable);
1080 arglist = build_tree_list (NULL_TREE, type_id);
1081 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
1082 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
1083 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
1084 = build_tree_list (NULL_TREE, size);
1086 return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
1089 #endif
1090 /* I/O driver for unformatted I/O item (do_uio)
1092 Returns a tree for a CALL_EXPR to the do_uio function, which handles
1093 an unformatted I/O list item, along with the appropriate arguments for
1094 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
1095 for the CALL_EXPR, expand (emit) the expression, emit any assignment
1096 of the result to an IOSTAT= variable, and emit any checking of the
1097 result for errors. */
1099 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1100 static tree
1101 ffeste_io_douio_ (ffebld expr)
1103 tree num_elements;
1104 tree variable;
1105 tree size;
1106 tree arglist;
1107 ffeinfoBasictype bt;
1108 ffeinfoKindtype kt;
1109 bool is_complex;
1111 bt = ffeinfo_basictype (ffebld_info (expr));
1112 kt = ffeinfo_kindtype (ffebld_info (expr));
1114 if ((bt == FFEINFO_basictypeANY)
1115 || (kt == FFEINFO_kindtypeANY))
1116 return error_mark_node;
1118 if (bt == FFEINFO_basictypeCOMPLEX)
1120 is_complex = TRUE;
1121 bt = FFEINFO_basictypeREAL;
1123 else
1124 is_complex = FALSE;
1126 variable = ffecom_arg_ptr_to_expr (expr, &size);
1128 if ((variable == error_mark_node)
1129 || (size == error_mark_node))
1130 return error_mark_node;
1132 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
1133 { /* "(ftnlen) sizeof(type)" */
1134 size = size_binop (CEIL_DIV_EXPR,
1135 TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1136 size_int (TYPE_PRECISION (char_type_node)
1137 / BITS_PER_UNIT));
1138 #if 0 /* Assume that while it is possible that char * is wider than
1139 ftnlen, no object in Fortran space can get big enough for its
1140 size to be wider than ftnlen. I really hope nobody wastes
1141 time debugging a case where it can! */
1142 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1143 >= TYPE_PRECISION (TREE_TYPE (size)));
1144 #endif
1145 size = convert (ffecom_f2c_ftnlen_type_node, size);
1148 if (ffeinfo_rank (ffebld_info (expr)) == 0
1149 || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1150 num_elements
1151 = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
1152 else
1154 num_elements
1155 = size_binop (CEIL_DIV_EXPR,
1156 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1157 convert (sizetype, size));
1158 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1159 size_int (TYPE_PRECISION (char_type_node)
1160 / BITS_PER_UNIT));
1161 num_elements = convert (ffecom_f2c_ftnlen_type_node,
1162 num_elements);
1165 num_elements
1166 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1167 num_elements);
1169 variable = convert (string_type_node, variable);
1171 arglist = build_tree_list (NULL_TREE, num_elements);
1172 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
1173 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
1175 return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
1178 #endif
1179 /* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
1181 Returns a tree suitable as an argument list containing a pointer to
1182 a BACKSPACE/ENDFILE/REWIND control list. First, generates that control
1183 list, if necessary, along with any static and run-time initializations
1184 that are needed as specified by the arguments to this function.
1186 Must ensure that all expressions are prepared before being evaluated,
1187 for any whose evaluation might result in the generation of temporaries.
1189 Note that this means this function causes a transition, within the
1190 current block being code-generated via the back end, from the
1191 declaration of variables (temporaries) to the expanding of expressions,
1192 statements, etc. */
1194 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1195 static tree
1196 ffeste_io_ialist_ (bool have_err,
1197 ffestvUnit unit,
1198 ffebld unit_expr,
1199 int unit_dflt)
1201 static tree f2c_alist_struct = NULL_TREE;
1202 tree t;
1203 tree ttype;
1204 tree field;
1205 tree inits, initn;
1206 bool constantp = TRUE;
1207 static tree errfield, unitfield;
1208 tree errinit, unitinit;
1209 tree unitexp;
1210 static int mynumber = 0;
1212 if (f2c_alist_struct == NULL_TREE)
1214 tree ref;
1216 ref = make_node (RECORD_TYPE);
1218 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1219 ffecom_f2c_flag_type_node);
1220 unitfield = ffecom_decl_field (ref, errfield, "unit",
1221 ffecom_f2c_ftnint_type_node);
1223 TYPE_FIELDS (ref) = errfield;
1224 layout_type (ref);
1226 ggc_add_tree_root (&f2c_alist_struct, 1);
1228 f2c_alist_struct = ref;
1231 /* Try to do as much compile-time initialization of the structure
1232 as possible, to save run time. */
1234 ffeste_f2c_init_flag_ (have_err, errinit);
1236 switch (unit)
1238 case FFESTV_unitNONE:
1239 case FFESTV_unitASTERISK:
1240 unitinit = build_int_2 (unit_dflt, 0);
1241 unitexp = unitinit;
1242 break;
1244 case FFESTV_unitINTEXPR:
1245 unitexp = ffecom_const_expr (unit_expr);
1246 if (unitexp)
1247 unitinit = unitexp;
1248 else
1250 unitinit = ffecom_integer_zero_node;
1251 constantp = FALSE;
1253 break;
1255 default:
1256 assert ("bad unit spec" == NULL);
1257 unitinit = ffecom_integer_zero_node;
1258 unitexp = unitinit;
1259 break;
1262 inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
1263 initn = inits;
1264 ffeste_f2c_init_next_ (unitinit);
1266 inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
1267 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1268 TREE_STATIC (inits) = 1;
1270 t = build_decl (VAR_DECL,
1271 ffecom_get_invented_identifier ("__g77_alist_%d",
1272 mynumber++),
1273 f2c_alist_struct);
1274 TREE_STATIC (t) = 1;
1275 t = ffecom_start_decl (t, 1);
1276 ffecom_finish_decl (t, inits, 0);
1278 /* Prepare run-time expressions. */
1280 if (! unitexp)
1281 ffecom_prepare_expr (unit_expr);
1283 ffecom_prepare_end ();
1285 /* Now evaluate run-time expressions as needed. */
1287 if (! unitexp)
1289 unitexp = ffecom_expr (unit_expr);
1290 ffeste_f2c_compile_ (unitfield, unitexp);
1293 ttype = build_pointer_type (TREE_TYPE (t));
1294 t = ffecom_1 (ADDR_EXPR, ttype, t);
1296 t = build_tree_list (NULL_TREE, t);
1298 return t;
1301 #endif
1302 /* Make arglist with ptr to external-I/O control list.
1304 Returns a tree suitable as an argument list containing a pointer to
1305 an external-I/O control list. First, generates that control
1306 list, if necessary, along with any static and run-time initializations
1307 that are needed as specified by the arguments to this function.
1309 Must ensure that all expressions are prepared before being evaluated,
1310 for any whose evaluation might result in the generation of temporaries.
1312 Note that this means this function causes a transition, within the
1313 current block being code-generated via the back end, from the
1314 declaration of variables (temporaries) to the expanding of expressions,
1315 statements, etc. */
1317 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1318 static tree
1319 ffeste_io_cilist_ (bool have_err,
1320 ffestvUnit unit,
1321 ffebld unit_expr,
1322 int unit_dflt,
1323 bool have_end,
1324 ffestvFormat format,
1325 ffestpFile *format_spec,
1326 bool rec,
1327 ffebld rec_expr)
1329 static tree f2c_cilist_struct = NULL_TREE;
1330 tree t;
1331 tree ttype;
1332 tree field;
1333 tree inits, initn;
1334 bool constantp = TRUE;
1335 static tree errfield, unitfield, endfield, formatfield, recfield;
1336 tree errinit, unitinit, endinit, formatinit, recinit;
1337 tree unitexp, formatexp, recexp;
1338 static int mynumber = 0;
1340 if (f2c_cilist_struct == NULL_TREE)
1342 tree ref;
1344 ref = make_node (RECORD_TYPE);
1346 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1347 ffecom_f2c_flag_type_node);
1348 unitfield = ffecom_decl_field (ref, errfield, "unit",
1349 ffecom_f2c_ftnint_type_node);
1350 endfield = ffecom_decl_field (ref, unitfield, "end",
1351 ffecom_f2c_flag_type_node);
1352 formatfield = ffecom_decl_field (ref, endfield, "format",
1353 string_type_node);
1354 recfield = ffecom_decl_field (ref, formatfield, "rec",
1355 ffecom_f2c_ftnint_type_node);
1357 TYPE_FIELDS (ref) = errfield;
1358 layout_type (ref);
1360 ggc_add_tree_root (&f2c_cilist_struct, 1);
1362 f2c_cilist_struct = ref;
1365 /* Try to do as much compile-time initialization of the structure
1366 as possible, to save run time. */
1368 ffeste_f2c_init_flag_ (have_err, errinit);
1370 switch (unit)
1372 case FFESTV_unitNONE:
1373 case FFESTV_unitASTERISK:
1374 unitinit = build_int_2 (unit_dflt, 0);
1375 unitexp = unitinit;
1376 break;
1378 case FFESTV_unitINTEXPR:
1379 unitexp = ffecom_const_expr (unit_expr);
1380 if (unitexp)
1381 unitinit = unitexp;
1382 else
1384 unitinit = ffecom_integer_zero_node;
1385 constantp = FALSE;
1387 break;
1389 default:
1390 assert ("bad unit spec" == NULL);
1391 unitinit = ffecom_integer_zero_node;
1392 unitexp = unitinit;
1393 break;
1396 switch (format)
1398 case FFESTV_formatNONE:
1399 formatinit = null_pointer_node;
1400 formatexp = formatinit;
1401 break;
1403 case FFESTV_formatLABEL:
1404 formatexp = error_mark_node;
1405 formatinit = ffecom_lookup_label (format_spec->u.label);
1406 if ((formatinit == NULL_TREE)
1407 || (TREE_CODE (formatinit) == ERROR_MARK))
1408 break;
1409 formatinit = ffecom_1 (ADDR_EXPR,
1410 build_pointer_type (void_type_node),
1411 formatinit);
1412 TREE_CONSTANT (formatinit) = 1;
1413 break;
1415 case FFESTV_formatCHAREXPR:
1416 formatexp = ffecom_arg_ptr_to_const_expr (format_spec->u.expr, NULL);
1417 if (formatexp)
1418 formatinit = formatexp;
1419 else
1421 formatinit = null_pointer_node;
1422 constantp = FALSE;
1424 break;
1426 case FFESTV_formatASTERISK:
1427 formatinit = null_pointer_node;
1428 formatexp = formatinit;
1429 break;
1431 case FFESTV_formatINTEXPR:
1432 formatinit = null_pointer_node;
1433 formatexp = ffecom_expr_assign (format_spec->u.expr);
1434 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1435 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1436 error ("ASSIGNed FORMAT specifier is too small");
1437 formatexp = convert (string_type_node, formatexp);
1438 break;
1440 case FFESTV_formatNAMELIST:
1441 formatinit = ffecom_expr (format_spec->u.expr);
1442 formatexp = formatinit;
1443 break;
1445 default:
1446 assert ("bad format spec" == NULL);
1447 formatinit = integer_zero_node;
1448 formatexp = formatinit;
1449 break;
1452 ffeste_f2c_init_flag_ (have_end, endinit);
1454 if (rec)
1455 recexp = ffecom_const_expr (rec_expr);
1456 else
1457 recexp = ffecom_integer_zero_node;
1458 if (recexp)
1459 recinit = recexp;
1460 else
1462 recinit = ffecom_integer_zero_node;
1463 constantp = FALSE;
1466 inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
1467 initn = inits;
1468 ffeste_f2c_init_next_ (unitinit);
1469 ffeste_f2c_init_next_ (endinit);
1470 ffeste_f2c_init_next_ (formatinit);
1471 ffeste_f2c_init_next_ (recinit);
1473 inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1474 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1475 TREE_STATIC (inits) = 1;
1477 t = build_decl (VAR_DECL,
1478 ffecom_get_invented_identifier ("__g77_cilist_%d",
1479 mynumber++),
1480 f2c_cilist_struct);
1481 TREE_STATIC (t) = 1;
1482 t = ffecom_start_decl (t, 1);
1483 ffecom_finish_decl (t, inits, 0);
1485 /* Prepare run-time expressions. */
1487 if (! unitexp)
1488 ffecom_prepare_expr (unit_expr);
1490 if (! formatexp)
1491 ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
1493 if (! recexp)
1494 ffecom_prepare_expr (rec_expr);
1496 ffecom_prepare_end ();
1498 /* Now evaluate run-time expressions as needed. */
1500 if (! unitexp)
1502 unitexp = ffecom_expr (unit_expr);
1503 ffeste_f2c_compile_ (unitfield, unitexp);
1506 if (! formatexp)
1508 formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1509 ffeste_f2c_compile_ (formatfield, formatexp);
1511 else if (format == FFESTV_formatINTEXPR)
1512 ffeste_f2c_compile_ (formatfield, formatexp);
1514 if (! recexp)
1516 recexp = ffecom_expr (rec_expr);
1517 ffeste_f2c_compile_ (recfield, recexp);
1520 ttype = build_pointer_type (TREE_TYPE (t));
1521 t = ffecom_1 (ADDR_EXPR, ttype, t);
1523 t = build_tree_list (NULL_TREE, t);
1525 return t;
1528 #endif
1529 /* Make arglist with ptr to CLOSE control list.
1531 Returns a tree suitable as an argument list containing a pointer to
1532 a CLOSE-statement control list. First, generates that control
1533 list, if necessary, along with any static and run-time initializations
1534 that are needed as specified by the arguments to this function.
1536 Must ensure that all expressions are prepared before being evaluated,
1537 for any whose evaluation might result in the generation of temporaries.
1539 Note that this means this function causes a transition, within the
1540 current block being code-generated via the back end, from the
1541 declaration of variables (temporaries) to the expanding of expressions,
1542 statements, etc. */
1544 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1545 static tree
1546 ffeste_io_cllist_ (bool have_err,
1547 ffebld unit_expr,
1548 ffestpFile *stat_spec)
1550 static tree f2c_close_struct = NULL_TREE;
1551 tree t;
1552 tree ttype;
1553 tree field;
1554 tree inits, initn;
1555 tree ignore; /* Ignore length info for certain fields. */
1556 bool constantp = TRUE;
1557 static tree errfield, unitfield, statfield;
1558 tree errinit, unitinit, statinit;
1559 tree unitexp, statexp;
1560 static int mynumber = 0;
1562 if (f2c_close_struct == NULL_TREE)
1564 tree ref;
1566 ref = make_node (RECORD_TYPE);
1568 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1569 ffecom_f2c_flag_type_node);
1570 unitfield = ffecom_decl_field (ref, errfield, "unit",
1571 ffecom_f2c_ftnint_type_node);
1572 statfield = ffecom_decl_field (ref, unitfield, "stat",
1573 string_type_node);
1575 TYPE_FIELDS (ref) = errfield;
1576 layout_type (ref);
1578 ggc_add_tree_root (&f2c_close_struct, 1);
1580 f2c_close_struct = ref;
1583 /* Try to do as much compile-time initialization of the structure
1584 as possible, to save run time. */
1586 ffeste_f2c_init_flag_ (have_err, errinit);
1588 unitexp = ffecom_const_expr (unit_expr);
1589 if (unitexp)
1590 unitinit = unitexp;
1591 else
1593 unitinit = ffecom_integer_zero_node;
1594 constantp = FALSE;
1597 ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
1599 inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
1600 initn = inits;
1601 ffeste_f2c_init_next_ (unitinit);
1602 ffeste_f2c_init_next_ (statinit);
1604 inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1605 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1606 TREE_STATIC (inits) = 1;
1608 t = build_decl (VAR_DECL,
1609 ffecom_get_invented_identifier ("__g77_cllist_%d",
1610 mynumber++),
1611 f2c_close_struct);
1612 TREE_STATIC (t) = 1;
1613 t = ffecom_start_decl (t, 1);
1614 ffecom_finish_decl (t, inits, 0);
1616 /* Prepare run-time expressions. */
1618 if (! unitexp)
1619 ffecom_prepare_expr (unit_expr);
1621 if (! statexp)
1622 ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
1624 ffecom_prepare_end ();
1626 /* Now evaluate run-time expressions as needed. */
1628 if (! unitexp)
1630 unitexp = ffecom_expr (unit_expr);
1631 ffeste_f2c_compile_ (unitfield, unitexp);
1634 ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
1636 ttype = build_pointer_type (TREE_TYPE (t));
1637 t = ffecom_1 (ADDR_EXPR, ttype, t);
1639 t = build_tree_list (NULL_TREE, t);
1641 return t;
1644 #endif
1645 /* Make arglist with ptr to internal-I/O control list.
1647 Returns a tree suitable as an argument list containing a pointer to
1648 an internal-I/O control list. First, generates that control
1649 list, if necessary, along with any static and run-time initializations
1650 that are needed as specified by the arguments to this function.
1652 Must ensure that all expressions are prepared before being evaluated,
1653 for any whose evaluation might result in the generation of temporaries.
1655 Note that this means this function causes a transition, within the
1656 current block being code-generated via the back end, from the
1657 declaration of variables (temporaries) to the expanding of expressions,
1658 statements, etc. */
1660 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1661 static tree
1662 ffeste_io_icilist_ (bool have_err,
1663 ffebld unit_expr,
1664 bool have_end,
1665 ffestvFormat format,
1666 ffestpFile *format_spec)
1668 static tree f2c_icilist_struct = NULL_TREE;
1669 tree t;
1670 tree ttype;
1671 tree field;
1672 tree inits, initn;
1673 bool constantp = TRUE;
1674 static tree errfield, unitfield, endfield, formatfield, unitlenfield,
1675 unitnumfield;
1676 tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
1677 tree unitexp, formatexp, unitlenexp, unitnumexp;
1678 static int mynumber = 0;
1680 if (f2c_icilist_struct == NULL_TREE)
1682 tree ref;
1684 ref = make_node (RECORD_TYPE);
1686 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1687 ffecom_f2c_flag_type_node);
1688 unitfield = ffecom_decl_field (ref, errfield, "unit",
1689 string_type_node);
1690 endfield = ffecom_decl_field (ref, unitfield, "end",
1691 ffecom_f2c_flag_type_node);
1692 formatfield = ffecom_decl_field (ref, endfield, "format",
1693 string_type_node);
1694 unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
1695 ffecom_f2c_ftnint_type_node);
1696 unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
1697 ffecom_f2c_ftnint_type_node);
1699 TYPE_FIELDS (ref) = errfield;
1700 layout_type (ref);
1702 ggc_add_tree_root (&f2c_icilist_struct, 1);
1704 f2c_icilist_struct = ref;
1707 /* Try to do as much compile-time initialization of the structure
1708 as possible, to save run time. */
1710 ffeste_f2c_init_flag_ (have_err, errinit);
1712 unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
1713 if (unitexp)
1714 unitinit = unitexp;
1715 else
1717 unitinit = null_pointer_node;
1718 constantp = FALSE;
1720 if (unitlenexp)
1721 unitleninit = unitlenexp;
1722 else
1724 unitleninit = ffecom_integer_zero_node;
1725 constantp = FALSE;
1728 /* Now see if we can fully initialize the number of elements, or
1729 if we have to compute that at run time. */
1730 if (ffeinfo_rank (ffebld_info (unit_expr)) == 0
1731 || (unitexp
1732 && TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
1734 /* Not an array, so just one element. */
1735 unitnuminit = ffecom_integer_one_node;
1736 unitnumexp = unitnuminit;
1738 else if (unitexp && unitlenexp)
1740 /* An array, but all the info is constant, so compute now. */
1741 unitnuminit
1742 = size_binop (CEIL_DIV_EXPR,
1743 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1744 convert (sizetype, unitlenexp));
1745 unitnuminit = size_binop (CEIL_DIV_EXPR, unitnuminit,
1746 size_int (TYPE_PRECISION (char_type_node)
1747 / BITS_PER_UNIT));
1748 unitnumexp = unitnuminit;
1750 else
1752 /* Put off computing until run time. */
1753 unitnuminit = ffecom_integer_zero_node;
1754 unitnumexp = NULL_TREE;
1755 constantp = FALSE;
1758 switch (format)
1760 case FFESTV_formatNONE:
1761 formatinit = null_pointer_node;
1762 formatexp = formatinit;
1763 break;
1765 case FFESTV_formatLABEL:
1766 formatexp = error_mark_node;
1767 formatinit = ffecom_lookup_label (format_spec->u.label);
1768 if ((formatinit == NULL_TREE)
1769 || (TREE_CODE (formatinit) == ERROR_MARK))
1770 break;
1771 formatinit = ffecom_1 (ADDR_EXPR,
1772 build_pointer_type (void_type_node),
1773 formatinit);
1774 TREE_CONSTANT (formatinit) = 1;
1775 break;
1777 case FFESTV_formatCHAREXPR:
1778 ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
1779 break;
1781 case FFESTV_formatASTERISK:
1782 formatinit = null_pointer_node;
1783 formatexp = formatinit;
1784 break;
1786 case FFESTV_formatINTEXPR:
1787 formatinit = null_pointer_node;
1788 formatexp = ffecom_expr_assign (format_spec->u.expr);
1789 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1790 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1791 error ("ASSIGNed FORMAT specifier is too small");
1792 formatexp = convert (string_type_node, formatexp);
1793 break;
1795 default:
1796 assert ("bad format spec" == NULL);
1797 formatinit = ffecom_integer_zero_node;
1798 formatexp = formatinit;
1799 break;
1802 ffeste_f2c_init_flag_ (have_end, endinit);
1804 inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
1805 errinit);
1806 initn = inits;
1807 ffeste_f2c_init_next_ (unitinit);
1808 ffeste_f2c_init_next_ (endinit);
1809 ffeste_f2c_init_next_ (formatinit);
1810 ffeste_f2c_init_next_ (unitleninit);
1811 ffeste_f2c_init_next_ (unitnuminit);
1813 inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1814 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1815 TREE_STATIC (inits) = 1;
1817 t = build_decl (VAR_DECL,
1818 ffecom_get_invented_identifier ("__g77_icilist_%d",
1819 mynumber++),
1820 f2c_icilist_struct);
1821 TREE_STATIC (t) = 1;
1822 t = ffecom_start_decl (t, 1);
1823 ffecom_finish_decl (t, inits, 0);
1825 /* Prepare run-time expressions. */
1827 if (! unitexp)
1828 ffecom_prepare_arg_ptr_to_expr (unit_expr);
1830 ffeste_f2c_prepare_format_ (format_spec, formatexp);
1832 ffecom_prepare_end ();
1834 /* Now evaluate run-time expressions as needed. */
1836 if (! unitexp || ! unitlenexp)
1838 int need_unitexp = (! unitexp);
1839 int need_unitlenexp = (! unitlenexp);
1841 unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
1842 if (need_unitexp)
1843 ffeste_f2c_compile_ (unitfield, unitexp);
1844 if (need_unitlenexp)
1845 ffeste_f2c_compile_ (unitlenfield, unitlenexp);
1848 if (! unitnumexp
1849 && unitexp != error_mark_node
1850 && unitlenexp != error_mark_node)
1852 unitnumexp
1853 = size_binop (CEIL_DIV_EXPR,
1854 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1855 convert (sizetype, unitlenexp));
1856 unitnumexp = size_binop (CEIL_DIV_EXPR, unitnumexp,
1857 size_int (TYPE_PRECISION (char_type_node)
1858 / BITS_PER_UNIT));
1859 ffeste_f2c_compile_ (unitnumfield, unitnumexp);
1862 if (format == FFESTV_formatINTEXPR)
1863 ffeste_f2c_compile_ (formatfield, formatexp);
1864 else
1865 ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
1867 ttype = build_pointer_type (TREE_TYPE (t));
1868 t = ffecom_1 (ADDR_EXPR, ttype, t);
1870 t = build_tree_list (NULL_TREE, t);
1872 return t;
1874 #endif
1876 /* Make arglist with ptr to INQUIRE control list
1878 Returns a tree suitable as an argument list containing a pointer to
1879 an INQUIRE-statement control list. First, generates that control
1880 list, if necessary, along with any static and run-time initializations
1881 that are needed as specified by the arguments to this function.
1883 Must ensure that all expressions are prepared before being evaluated,
1884 for any whose evaluation might result in the generation of temporaries.
1886 Note that this means this function causes a transition, within the
1887 current block being code-generated via the back end, from the
1888 declaration of variables (temporaries) to the expanding of expressions,
1889 statements, etc. */
1891 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1892 static tree
1893 ffeste_io_inlist_ (bool have_err,
1894 ffestpFile *unit_spec,
1895 ffestpFile *file_spec,
1896 ffestpFile *exist_spec,
1897 ffestpFile *open_spec,
1898 ffestpFile *number_spec,
1899 ffestpFile *named_spec,
1900 ffestpFile *name_spec,
1901 ffestpFile *access_spec,
1902 ffestpFile *sequential_spec,
1903 ffestpFile *direct_spec,
1904 ffestpFile *form_spec,
1905 ffestpFile *formatted_spec,
1906 ffestpFile *unformatted_spec,
1907 ffestpFile *recl_spec,
1908 ffestpFile *nextrec_spec,
1909 ffestpFile *blank_spec)
1911 static tree f2c_inquire_struct = NULL_TREE;
1912 tree t;
1913 tree ttype;
1914 tree field;
1915 tree inits, initn;
1916 bool constantp = TRUE;
1917 static tree errfield, unitfield, filefield, filelenfield, existfield,
1918 openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
1919 accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
1920 formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
1921 unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
1922 tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
1923 namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
1924 sequentialleninit, directinit, directleninit, forminit, formleninit,
1925 formattedinit, formattedleninit, unformattedinit, unformattedleninit,
1926 reclinit, nextrecinit, blankinit, blankleninit;
1927 tree
1928 unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
1929 nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
1930 directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
1931 unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
1932 static int mynumber = 0;
1934 if (f2c_inquire_struct == NULL_TREE)
1936 tree ref;
1938 ref = make_node (RECORD_TYPE);
1940 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1941 ffecom_f2c_flag_type_node);
1942 unitfield = ffecom_decl_field (ref, errfield, "unit",
1943 ffecom_f2c_ftnint_type_node);
1944 filefield = ffecom_decl_field (ref, unitfield, "file",
1945 string_type_node);
1946 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1947 ffecom_f2c_ftnlen_type_node);
1948 existfield = ffecom_decl_field (ref, filelenfield, "exist",
1949 ffecom_f2c_ptr_to_ftnint_type_node);
1950 openfield = ffecom_decl_field (ref, existfield, "open",
1951 ffecom_f2c_ptr_to_ftnint_type_node);
1952 numberfield = ffecom_decl_field (ref, openfield, "number",
1953 ffecom_f2c_ptr_to_ftnint_type_node);
1954 namedfield = ffecom_decl_field (ref, numberfield, "named",
1955 ffecom_f2c_ptr_to_ftnint_type_node);
1956 namefield = ffecom_decl_field (ref, namedfield, "name",
1957 string_type_node);
1958 namelenfield = ffecom_decl_field (ref, namefield, "namelen",
1959 ffecom_f2c_ftnlen_type_node);
1960 accessfield = ffecom_decl_field (ref, namelenfield, "access",
1961 string_type_node);
1962 accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
1963 ffecom_f2c_ftnlen_type_node);
1964 sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
1965 string_type_node);
1966 sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
1967 "sequentiallen",
1968 ffecom_f2c_ftnlen_type_node);
1969 directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
1970 string_type_node);
1971 directlenfield = ffecom_decl_field (ref, directfield, "directlen",
1972 ffecom_f2c_ftnlen_type_node);
1973 formfield = ffecom_decl_field (ref, directlenfield, "form",
1974 string_type_node);
1975 formlenfield = ffecom_decl_field (ref, formfield, "formlen",
1976 ffecom_f2c_ftnlen_type_node);
1977 formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
1978 string_type_node);
1979 formattedlenfield = ffecom_decl_field (ref, formattedfield,
1980 "formattedlen",
1981 ffecom_f2c_ftnlen_type_node);
1982 unformattedfield = ffecom_decl_field (ref, formattedlenfield,
1983 "unformatted",
1984 string_type_node);
1985 unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
1986 "unformattedlen",
1987 ffecom_f2c_ftnlen_type_node);
1988 reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
1989 ffecom_f2c_ptr_to_ftnint_type_node);
1990 nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
1991 ffecom_f2c_ptr_to_ftnint_type_node);
1992 blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
1993 string_type_node);
1994 blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
1995 ffecom_f2c_ftnlen_type_node);
1997 TYPE_FIELDS (ref) = errfield;
1998 layout_type (ref);
2000 ggc_add_tree_root (&f2c_inquire_struct, 1);
2002 f2c_inquire_struct = ref;
2005 /* Try to do as much compile-time initialization of the structure
2006 as possible, to save run time. */
2008 ffeste_f2c_init_flag_ (have_err, errinit);
2009 ffeste_f2c_init_int_ (unitexp, unitinit, unit_spec);
2010 ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2011 file_spec);
2012 ffeste_f2c_init_ptrtoint_ (existexp, existinit, exist_spec);
2013 ffeste_f2c_init_ptrtoint_ (openexp, openinit, open_spec);
2014 ffeste_f2c_init_ptrtoint_ (numberexp, numberinit, number_spec);
2015 ffeste_f2c_init_ptrtoint_ (namedexp, namedinit, named_spec);
2016 ffeste_f2c_init_char_ (nameexp, nameinit, namelenexp, nameleninit,
2017 name_spec);
2018 ffeste_f2c_init_char_ (accessexp, accessinit, accesslenexp,
2019 accessleninit, access_spec);
2020 ffeste_f2c_init_char_ (sequentialexp, sequentialinit, sequentiallenexp,
2021 sequentialleninit, sequential_spec);
2022 ffeste_f2c_init_char_ (directexp, directinit, directlenexp,
2023 directleninit, direct_spec);
2024 ffeste_f2c_init_char_ (formexp, forminit, formlenexp, formleninit,
2025 form_spec);
2026 ffeste_f2c_init_char_ (formattedexp, formattedinit,
2027 formattedlenexp, formattedleninit, formatted_spec);
2028 ffeste_f2c_init_char_ (unformattedexp, unformattedinit, unformattedlenexp,
2029 unformattedleninit, unformatted_spec);
2030 ffeste_f2c_init_ptrtoint_ (reclexp, reclinit, recl_spec);
2031 ffeste_f2c_init_ptrtoint_ (nextrecexp, nextrecinit, nextrec_spec);
2032 ffeste_f2c_init_char_ (blankexp, blankinit, blanklenexp,
2033 blankleninit, blank_spec);
2035 inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
2036 errinit);
2037 initn = inits;
2038 ffeste_f2c_init_next_ (unitinit);
2039 ffeste_f2c_init_next_ (fileinit);
2040 ffeste_f2c_init_next_ (fileleninit);
2041 ffeste_f2c_init_next_ (existinit);
2042 ffeste_f2c_init_next_ (openinit);
2043 ffeste_f2c_init_next_ (numberinit);
2044 ffeste_f2c_init_next_ (namedinit);
2045 ffeste_f2c_init_next_ (nameinit);
2046 ffeste_f2c_init_next_ (nameleninit);
2047 ffeste_f2c_init_next_ (accessinit);
2048 ffeste_f2c_init_next_ (accessleninit);
2049 ffeste_f2c_init_next_ (sequentialinit);
2050 ffeste_f2c_init_next_ (sequentialleninit);
2051 ffeste_f2c_init_next_ (directinit);
2052 ffeste_f2c_init_next_ (directleninit);
2053 ffeste_f2c_init_next_ (forminit);
2054 ffeste_f2c_init_next_ (formleninit);
2055 ffeste_f2c_init_next_ (formattedinit);
2056 ffeste_f2c_init_next_ (formattedleninit);
2057 ffeste_f2c_init_next_ (unformattedinit);
2058 ffeste_f2c_init_next_ (unformattedleninit);
2059 ffeste_f2c_init_next_ (reclinit);
2060 ffeste_f2c_init_next_ (nextrecinit);
2061 ffeste_f2c_init_next_ (blankinit);
2062 ffeste_f2c_init_next_ (blankleninit);
2064 inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
2065 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2066 TREE_STATIC (inits) = 1;
2068 t = build_decl (VAR_DECL,
2069 ffecom_get_invented_identifier ("__g77_inlist_%d",
2070 mynumber++),
2071 f2c_inquire_struct);
2072 TREE_STATIC (t) = 1;
2073 t = ffecom_start_decl (t, 1);
2074 ffecom_finish_decl (t, inits, 0);
2076 /* Prepare run-time expressions. */
2078 ffeste_f2c_prepare_int_ (unit_spec, unitexp);
2079 ffeste_f2c_prepare_char_ (file_spec, fileexp);
2080 ffeste_f2c_prepare_ptrtoint_ (exist_spec, existexp);
2081 ffeste_f2c_prepare_ptrtoint_ (open_spec, openexp);
2082 ffeste_f2c_prepare_ptrtoint_ (number_spec, numberexp);
2083 ffeste_f2c_prepare_ptrtoint_ (named_spec, namedexp);
2084 ffeste_f2c_prepare_char_ (name_spec, nameexp);
2085 ffeste_f2c_prepare_char_ (access_spec, accessexp);
2086 ffeste_f2c_prepare_char_ (sequential_spec, sequentialexp);
2087 ffeste_f2c_prepare_char_ (direct_spec, directexp);
2088 ffeste_f2c_prepare_char_ (form_spec, formexp);
2089 ffeste_f2c_prepare_char_ (formatted_spec, formattedexp);
2090 ffeste_f2c_prepare_char_ (unformatted_spec, unformattedexp);
2091 ffeste_f2c_prepare_ptrtoint_ (recl_spec, reclexp);
2092 ffeste_f2c_prepare_ptrtoint_ (nextrec_spec, nextrecexp);
2093 ffeste_f2c_prepare_char_ (blank_spec, blankexp);
2095 ffecom_prepare_end ();
2097 /* Now evaluate run-time expressions as needed. */
2099 ffeste_f2c_compile_int_ (unitfield, unit_spec, unitexp);
2100 ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec,
2101 fileexp, filelenexp);
2102 ffeste_f2c_compile_ptrtoint_ (existfield, exist_spec, existexp);
2103 ffeste_f2c_compile_ptrtoint_ (openfield, open_spec, openexp);
2104 ffeste_f2c_compile_ptrtoint_ (numberfield, number_spec, numberexp);
2105 ffeste_f2c_compile_ptrtoint_ (namedfield, named_spec, namedexp);
2106 ffeste_f2c_compile_char_ (namefield, namelenfield, name_spec, nameexp,
2107 namelenexp);
2108 ffeste_f2c_compile_char_ (accessfield, accesslenfield, access_spec,
2109 accessexp, accesslenexp);
2110 ffeste_f2c_compile_char_ (sequentialfield, sequentiallenfield,
2111 sequential_spec, sequentialexp,
2112 sequentiallenexp);
2113 ffeste_f2c_compile_char_ (directfield, directlenfield, direct_spec,
2114 directexp, directlenexp);
2115 ffeste_f2c_compile_char_ (formfield, formlenfield, form_spec, formexp,
2116 formlenexp);
2117 ffeste_f2c_compile_char_ (formattedfield, formattedlenfield, formatted_spec,
2118 formattedexp, formattedlenexp);
2119 ffeste_f2c_compile_char_ (unformattedfield, unformattedlenfield,
2120 unformatted_spec, unformattedexp,
2121 unformattedlenexp);
2122 ffeste_f2c_compile_ptrtoint_ (reclfield, recl_spec, reclexp);
2123 ffeste_f2c_compile_ptrtoint_ (nextrecfield, nextrec_spec, nextrecexp);
2124 ffeste_f2c_compile_char_ (blankfield, blanklenfield, blank_spec, blankexp,
2125 blanklenexp);
2127 ttype = build_pointer_type (TREE_TYPE (t));
2128 t = ffecom_1 (ADDR_EXPR, ttype, t);
2130 t = build_tree_list (NULL_TREE, t);
2132 return t;
2135 #endif
2136 /* Make arglist with ptr to OPEN control list
2138 Returns a tree suitable as an argument list containing a pointer to
2139 an OPEN-statement control list. First, generates that control
2140 list, if necessary, along with any static and run-time initializations
2141 that are needed as specified by the arguments to this function.
2143 Must ensure that all expressions are prepared before being evaluated,
2144 for any whose evaluation might result in the generation of temporaries.
2146 Note that this means this function causes a transition, within the
2147 current block being code-generated via the back end, from the
2148 declaration of variables (temporaries) to the expanding of expressions,
2149 statements, etc. */
2151 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2152 static tree
2153 ffeste_io_olist_ (bool have_err,
2154 ffebld unit_expr,
2155 ffestpFile *file_spec,
2156 ffestpFile *stat_spec,
2157 ffestpFile *access_spec,
2158 ffestpFile *form_spec,
2159 ffestpFile *recl_spec,
2160 ffestpFile *blank_spec)
2162 static tree f2c_open_struct = NULL_TREE;
2163 tree t;
2164 tree ttype;
2165 tree field;
2166 tree inits, initn;
2167 tree ignore; /* Ignore length info for certain fields. */
2168 bool constantp = TRUE;
2169 static tree errfield, unitfield, filefield, filelenfield, statfield,
2170 accessfield, formfield, reclfield, blankfield;
2171 tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
2172 forminit, reclinit, blankinit;
2173 tree
2174 unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
2175 blankexp;
2176 static int mynumber = 0;
2178 if (f2c_open_struct == NULL_TREE)
2180 tree ref;
2182 ref = make_node (RECORD_TYPE);
2184 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
2185 ffecom_f2c_flag_type_node);
2186 unitfield = ffecom_decl_field (ref, errfield, "unit",
2187 ffecom_f2c_ftnint_type_node);
2188 filefield = ffecom_decl_field (ref, unitfield, "file",
2189 string_type_node);
2190 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
2191 ffecom_f2c_ftnlen_type_node);
2192 statfield = ffecom_decl_field (ref, filelenfield, "stat",
2193 string_type_node);
2194 accessfield = ffecom_decl_field (ref, statfield, "access",
2195 string_type_node);
2196 formfield = ffecom_decl_field (ref, accessfield, "form",
2197 string_type_node);
2198 reclfield = ffecom_decl_field (ref, formfield, "recl",
2199 ffecom_f2c_ftnint_type_node);
2200 blankfield = ffecom_decl_field (ref, reclfield, "blank",
2201 string_type_node);
2203 TYPE_FIELDS (ref) = errfield;
2204 layout_type (ref);
2206 ggc_add_tree_root (&f2c_open_struct, 1);
2208 f2c_open_struct = ref;
2211 /* Try to do as much compile-time initialization of the structure
2212 as possible, to save run time. */
2214 ffeste_f2c_init_flag_ (have_err, errinit);
2216 unitexp = ffecom_const_expr (unit_expr);
2217 if (unitexp)
2218 unitinit = unitexp;
2219 else
2221 unitinit = ffecom_integer_zero_node;
2222 constantp = FALSE;
2225 ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2226 file_spec);
2227 ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
2228 ffeste_f2c_init_charnolen_ (accessexp, accessinit, access_spec);
2229 ffeste_f2c_init_charnolen_ (formexp, forminit, form_spec);
2230 ffeste_f2c_init_int_ (reclexp, reclinit, recl_spec);
2231 ffeste_f2c_init_charnolen_ (blankexp, blankinit, blank_spec);
2233 inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
2234 initn = inits;
2235 ffeste_f2c_init_next_ (unitinit);
2236 ffeste_f2c_init_next_ (fileinit);
2237 ffeste_f2c_init_next_ (fileleninit);
2238 ffeste_f2c_init_next_ (statinit);
2239 ffeste_f2c_init_next_ (accessinit);
2240 ffeste_f2c_init_next_ (forminit);
2241 ffeste_f2c_init_next_ (reclinit);
2242 ffeste_f2c_init_next_ (blankinit);
2244 inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
2245 TREE_CONSTANT (inits) = constantp ? 1 : 0;
2246 TREE_STATIC (inits) = 1;
2248 t = build_decl (VAR_DECL,
2249 ffecom_get_invented_identifier ("__g77_olist_%d",
2250 mynumber++),
2251 f2c_open_struct);
2252 TREE_STATIC (t) = 1;
2253 t = ffecom_start_decl (t, 1);
2254 ffecom_finish_decl (t, inits, 0);
2256 /* Prepare run-time expressions. */
2258 if (! unitexp)
2259 ffecom_prepare_expr (unit_expr);
2261 ffeste_f2c_prepare_char_ (file_spec, fileexp);
2262 ffeste_f2c_prepare_charnolen_ (stat_spec, statexp);
2263 ffeste_f2c_prepare_charnolen_ (access_spec, accessexp);
2264 ffeste_f2c_prepare_charnolen_ (form_spec, formexp);
2265 ffeste_f2c_prepare_int_ (recl_spec, reclexp);
2266 ffeste_f2c_prepare_charnolen_ (blank_spec, blankexp);
2268 ffecom_prepare_end ();
2270 /* Now evaluate run-time expressions as needed. */
2272 if (! unitexp)
2274 unitexp = ffecom_expr (unit_expr);
2275 ffeste_f2c_compile_ (unitfield, unitexp);
2278 ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec, fileexp,
2279 filelenexp);
2280 ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
2281 ffeste_f2c_compile_charnolen_ (accessfield, access_spec, accessexp);
2282 ffeste_f2c_compile_charnolen_ (formfield, form_spec, formexp);
2283 ffeste_f2c_compile_int_ (reclfield, recl_spec, reclexp);
2284 ffeste_f2c_compile_charnolen_ (blankfield, blank_spec, blankexp);
2286 ttype = build_pointer_type (TREE_TYPE (t));
2287 t = ffecom_1 (ADDR_EXPR, ttype, t);
2289 t = build_tree_list (NULL_TREE, t);
2291 return t;
2294 #endif
2295 /* Display file-statement specifier. */
2297 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2298 static void
2299 ffeste_subr_file_ (const char *kw, ffestpFile *spec)
2301 if (!spec->kw_or_val_present)
2302 return;
2303 fputs (kw, dmpout);
2304 if (spec->value_present)
2306 fputc ('=', dmpout);
2307 if (spec->value_is_label)
2309 assert (spec->value_is_label == 2); /* Temporary checking only. */
2310 fprintf (dmpout, "%" ffelabValue_f "u",
2311 ffelab_value (spec->u.label));
2313 else
2314 ffebld_dump (spec->u.expr);
2316 fputc (',', dmpout);
2318 #endif
2320 /* Generate code for BACKSPACE/ENDFILE/REWIND. */
2322 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2323 static void
2324 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
2326 tree alist;
2327 bool iostat;
2328 bool errl;
2330 ffeste_emit_line_note_ ();
2332 #define specified(something) (info->beru_spec[something].kw_or_val_present)
2334 iostat = specified (FFESTP_beruixIOSTAT);
2335 errl = specified (FFESTP_beruixERR);
2337 #undef specified
2339 /* ~~For now, we assume the unit number is specified and is not ASTERISK,
2340 because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
2341 without any unit specifier. f2c, however, supports the former
2342 construct. When it is time to add this feature to the FFE, which
2343 probably is fairly easy, ffestc_R919 and company will want to pass an
2344 ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
2345 ffeste_R919 and company, and they will want to pass that same value to
2346 this function, and that argument will replace the constant _unitINTEXPR_
2347 in the call below. Right now, the default unit number, 6, is ignored. */
2349 ffeste_start_stmt_ ();
2351 if (errl)
2353 /* Have ERR= specification. */
2355 ffeste_io_err_
2356 = ffeste_io_abort_
2357 = ffecom_lookup_label
2358 (info->beru_spec[FFESTP_beruixERR].u.label);
2359 ffeste_io_abort_is_temp_ = FALSE;
2361 else
2363 /* No ERR= specification. */
2365 ffeste_io_err_ = NULL_TREE;
2367 if ((ffeste_io_abort_is_temp_ = iostat))
2368 ffeste_io_abort_ = ffecom_temp_label ();
2369 else
2370 ffeste_io_abort_ = NULL_TREE;
2373 if (iostat)
2375 /* Have IOSTAT= specification. */
2377 ffeste_io_iostat_is_temp_ = FALSE;
2378 ffeste_io_iostat_ = ffecom_expr
2379 (info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2381 else if (ffeste_io_abort_ != NULL_TREE)
2383 /* Have no IOSTAT= but have ERR=. */
2385 ffeste_io_iostat_is_temp_ = TRUE;
2386 ffeste_io_iostat_
2387 = ffecom_make_tempvar ("beru", ffecom_integer_type_node,
2388 FFETARGET_charactersizeNONE, -1);
2390 else
2392 /* No IOSTAT= or ERR= specification. */
2394 ffeste_io_iostat_is_temp_ = FALSE;
2395 ffeste_io_iostat_ = NULL_TREE;
2398 /* Now prescan, then convert, all the arguments. */
2400 alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2401 info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
2403 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
2404 label, since we're gonna fall through to there anyway. */
2406 ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
2407 ! ffeste_io_abort_is_temp_);
2409 /* If we've got a temp label, generate its code here. */
2411 if (ffeste_io_abort_is_temp_)
2413 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2414 emit_nop ();
2415 expand_label (ffeste_io_abort_);
2417 assert (ffeste_io_err_ == NULL_TREE);
2420 ffeste_end_stmt_ ();
2422 #endif
2424 /* END DO statement
2426 Also invoked by _labeldef_branch_finish_ (or, in cases
2427 of errors, other _labeldef_ functions) when the label definition is
2428 for a DO-target (LOOPEND) label, once per matching/outstanding DO
2429 block on the stack. */
2431 void
2432 ffeste_do (ffestw block)
2434 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2435 fputs ("+ END_DO\n", dmpout);
2436 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2437 ffeste_emit_line_note_ ();
2439 if (ffestw_do_tvar (block) == 0)
2441 expand_end_loop (); /* DO WHILE and just DO. */
2443 ffeste_end_block_ (block);
2445 else
2446 ffeste_end_iterdo_ (block,
2447 ffestw_do_tvar (block),
2448 ffestw_do_incr_saved (block),
2449 ffestw_do_count_var (block));
2450 #else
2451 #error
2452 #endif
2455 /* End of statement following logical IF.
2457 Applies to *only* logical IF, not to IF-THEN. */
2459 void
2460 ffeste_end_R807 ()
2462 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2463 fputs ("+ END_IF\n", dmpout); /* Also see ffeste_R806. */
2464 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2465 ffeste_emit_line_note_ ();
2467 expand_end_cond ();
2469 ffeste_end_block_ (NULL);
2470 #else
2471 #error
2472 #endif
2475 /* Generate "code" for branch label definition. */
2477 void
2478 ffeste_labeldef_branch (ffelab label)
2480 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2481 fprintf (dmpout, "+ label %lu\n", ffelab_value (label));
2482 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2484 tree glabel;
2486 glabel = ffecom_lookup_label (label);
2487 assert (glabel != NULL_TREE);
2488 if (TREE_CODE (glabel) == ERROR_MARK)
2489 return;
2491 assert (DECL_INITIAL (glabel) == NULL_TREE);
2493 DECL_INITIAL (glabel) = error_mark_node;
2494 DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
2495 DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
2497 emit_nop ();
2499 expand_label (glabel);
2501 #else
2502 #error
2503 #endif
2506 /* Generate "code" for FORMAT label definition. */
2508 void
2509 ffeste_labeldef_format (ffelab label)
2511 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2512 fprintf (dmpout, "$ label %lu\n", ffelab_value (label));
2513 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2514 ffeste_label_formatdef_ = label;
2515 #else
2516 #error
2517 #endif
2520 /* Assignment statement (outside of WHERE). */
2522 void
2523 ffeste_R737A (ffebld dest, ffebld source)
2525 ffeste_check_simple_ ();
2527 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2528 fputs ("+ let ", dmpout);
2529 ffebld_dump (dest);
2530 fputs ("=", dmpout);
2531 ffebld_dump (source);
2532 fputc ('\n', dmpout);
2533 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2534 ffeste_emit_line_note_ ();
2536 ffeste_start_stmt_ ();
2538 ffecom_expand_let_stmt (dest, source);
2540 ffeste_end_stmt_ ();
2541 #else
2542 #error
2543 #endif
2546 /* Block IF (IF-THEN) statement. */
2548 void
2549 ffeste_R803 (ffestw block, ffebld expr)
2551 ffeste_check_simple_ ();
2553 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2554 fputs ("+ IF_block (", dmpout);
2555 ffebld_dump (expr);
2556 fputs (")\n", dmpout);
2557 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2559 tree temp;
2561 ffeste_emit_line_note_ ();
2563 ffeste_start_block_ (block);
2565 temp = ffecom_make_tempvar ("ifthen", integer_type_node,
2566 FFETARGET_charactersizeNONE, -1);
2568 ffeste_start_stmt_ ();
2570 ffecom_prepare_expr (expr);
2572 if (ffecom_prepare_end ())
2574 tree result;
2576 result = ffecom_modify (void_type_node,
2577 temp,
2578 ffecom_truth_value (ffecom_expr (expr)));
2580 expand_expr_stmt (result);
2582 ffeste_end_stmt_ ();
2584 else
2586 ffeste_end_stmt_ ();
2588 temp = ffecom_truth_value (ffecom_expr (expr));
2591 expand_start_cond (temp, 0);
2593 /* No fake `else' constructs introduced (yet). */
2594 ffestw_set_ifthen_fake_else (block, 0);
2596 #else
2597 #error
2598 #endif
2601 /* ELSE IF statement. */
2603 void
2604 ffeste_R804 (ffestw block, ffebld expr)
2606 ffeste_check_simple_ ();
2608 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2609 fputs ("+ ELSE_IF (", dmpout);
2610 ffebld_dump (expr);
2611 fputs (")\n", dmpout);
2612 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2614 tree temp;
2616 ffeste_emit_line_note_ ();
2618 /* Since ELSEIF(expr) might require preparations for expr,
2619 implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF. */
2621 expand_start_else ();
2623 ffeste_start_block_ (block);
2625 temp = ffecom_make_tempvar ("elseif", integer_type_node,
2626 FFETARGET_charactersizeNONE, -1);
2628 ffeste_start_stmt_ ();
2630 ffecom_prepare_expr (expr);
2632 if (ffecom_prepare_end ())
2634 tree result;
2636 result = ffecom_modify (void_type_node,
2637 temp,
2638 ffecom_truth_value (ffecom_expr (expr)));
2640 expand_expr_stmt (result);
2642 ffeste_end_stmt_ ();
2644 else
2646 /* In this case, we could probably have used expand_start_elseif
2647 instead, saving the need for a fake `else' construct. But,
2648 until it's clear that'd improve performance, it's easier this
2649 way, since we have to expand_start_else before we get to this
2650 test, given the current design. */
2652 ffeste_end_stmt_ ();
2654 temp = ffecom_truth_value (ffecom_expr (expr));
2657 expand_start_cond (temp, 0);
2659 /* Increment number of fake `else' constructs introduced. */
2660 ffestw_set_ifthen_fake_else (block,
2661 ffestw_ifthen_fake_else (block) + 1);
2663 #else
2664 #error
2665 #endif
2668 /* ELSE statement. */
2670 void
2671 ffeste_R805 (ffestw block UNUSED)
2673 ffeste_check_simple_ ();
2675 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2676 fputs ("+ ELSE\n", dmpout);
2677 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2678 ffeste_emit_line_note_ ();
2680 expand_start_else ();
2681 #else
2682 #error
2683 #endif
2686 /* END IF statement. */
2688 void
2689 ffeste_R806 (ffestw block)
2691 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2692 fputs ("+ END_IF_then\n", dmpout); /* Also see ffeste_shriek_if_. */
2693 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2695 int i = ffestw_ifthen_fake_else (block) + 1;
2697 ffeste_emit_line_note_ ();
2699 for (; i; --i)
2701 expand_end_cond ();
2703 ffeste_end_block_ (block);
2706 #else
2707 #error
2708 #endif
2711 /* Logical IF statement. */
2713 void
2714 ffeste_R807 (ffebld expr)
2716 ffeste_check_simple_ ();
2718 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2719 fputs ("+ IF_logical (", dmpout);
2720 ffebld_dump (expr);
2721 fputs (")\n", dmpout);
2722 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2724 tree temp;
2726 ffeste_emit_line_note_ ();
2728 ffeste_start_block_ (NULL);
2730 temp = ffecom_make_tempvar ("if", integer_type_node,
2731 FFETARGET_charactersizeNONE, -1);
2733 ffeste_start_stmt_ ();
2735 ffecom_prepare_expr (expr);
2737 if (ffecom_prepare_end ())
2739 tree result;
2741 result = ffecom_modify (void_type_node,
2742 temp,
2743 ffecom_truth_value (ffecom_expr (expr)));
2745 expand_expr_stmt (result);
2747 ffeste_end_stmt_ ();
2749 else
2751 ffeste_end_stmt_ ();
2753 temp = ffecom_truth_value (ffecom_expr (expr));
2756 expand_start_cond (temp, 0);
2758 #else
2759 #error
2760 #endif
2763 /* SELECT CASE statement. */
2765 void
2766 ffeste_R809 (ffestw block, ffebld expr)
2768 ffeste_check_simple_ ();
2770 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2771 fputs ("+ SELECT_CASE (", dmpout);
2772 ffebld_dump (expr);
2773 fputs (")\n", dmpout);
2774 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2775 ffeste_emit_line_note_ ();
2777 ffeste_start_block_ (block);
2779 if ((expr == NULL)
2780 || (ffeinfo_basictype (ffebld_info (expr))
2781 == FFEINFO_basictypeANY))
2782 ffestw_set_select_texpr (block, error_mark_node);
2783 else if (ffeinfo_basictype (ffebld_info (expr))
2784 == FFEINFO_basictypeCHARACTER)
2786 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2788 ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
2789 FFEBAD_severityFATAL);
2790 ffebad_here (0, ffestw_line (block), ffestw_col (block));
2791 ffebad_finish ();
2792 ffestw_set_select_texpr (block, error_mark_node);
2794 else
2796 tree result;
2797 tree texpr;
2799 result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
2800 ffeinfo_size (ffebld_info (expr)),
2801 -1);
2803 ffeste_start_stmt_ ();
2805 ffecom_prepare_expr (expr);
2807 ffecom_prepare_end ();
2809 texpr = ffecom_expr (expr);
2811 assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
2812 == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
2814 texpr = ffecom_modify (void_type_node,
2815 result,
2816 texpr);
2817 expand_expr_stmt (texpr);
2819 ffeste_end_stmt_ ();
2821 expand_start_case (1, result, TREE_TYPE (result),
2822 "SELECT CASE statement");
2823 ffestw_set_select_texpr (block, texpr);
2824 ffestw_set_select_break (block, FALSE);
2826 #else
2827 #error
2828 #endif
2831 /* CASE statement.
2833 If casenum is 0, it's CASE DEFAULT. Else it's the case ranges at
2834 the start of the first_stmt list in the select object at the top of
2835 the stack that match casenum. */
2837 void
2838 ffeste_R810 (ffestw block, unsigned long casenum)
2840 ffestwSelect s = ffestw_select (block);
2841 ffestwCase c;
2843 ffeste_check_simple_ ();
2845 if (s->first_stmt == (ffestwCase) &s->first_rel)
2846 c = NULL;
2847 else
2848 c = s->first_stmt;
2850 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2851 if ((c == NULL) || (casenum != c->casenum))
2853 if (casenum == 0) /* Intentional CASE DEFAULT. */
2854 fputs ("+ CASE_DEFAULT", dmpout);
2856 else
2858 bool comma = FALSE;
2860 fputs ("+ CASE (", dmpout);
2863 if (comma)
2864 fputc (',', dmpout);
2865 else
2866 comma = TRUE;
2867 if (c->low != NULL)
2868 ffebld_constant_dump (c->low);
2869 if (c->low != c->high)
2871 fputc (':', dmpout);
2872 if (c->high != NULL)
2873 ffebld_constant_dump (c->high);
2875 c = c->next_stmt;
2876 /* Unlink prev. */
2877 c->previous_stmt->previous_stmt->next_stmt = c;
2878 c->previous_stmt = c->previous_stmt->previous_stmt;
2880 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2881 fputc (')', dmpout);
2884 fputc ('\n', dmpout);
2885 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2887 tree texprlow;
2888 tree texprhigh;
2889 tree tlabel;
2890 int pushok;
2891 tree duplicate;
2893 ffeste_emit_line_note_ ();
2895 if (ffestw_select_texpr (block) == error_mark_node)
2896 return;
2898 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2900 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2902 if (ffestw_select_break (block))
2903 expand_exit_something ();
2904 else
2905 ffestw_set_select_break (block, TRUE);
2907 if ((c == NULL) || (casenum != c->casenum))
2909 if (casenum == 0) /* Intentional CASE DEFAULT. */
2911 pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2912 assert (pushok == 0);
2915 else
2918 texprlow = (c->low == NULL) ? NULL_TREE
2919 : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
2920 s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2921 if (c->low != c->high)
2923 texprhigh = (c->high == NULL) ? NULL_TREE
2924 : ffecom_constantunion (&ffebld_constant_union (c->high),
2925 s->type, s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2926 pushok = pushcase_range (texprlow, texprhigh, convert,
2927 tlabel, &duplicate);
2929 else
2930 pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2931 assert (pushok == 0);
2932 c = c->next_stmt;
2933 /* Unlink prev. */
2934 c->previous_stmt->previous_stmt->next_stmt = c;
2935 c->previous_stmt = c->previous_stmt->previous_stmt;
2937 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2939 #else
2940 #error
2941 #endif
2944 /* END SELECT statement. */
2946 void
2947 ffeste_R811 (ffestw block)
2949 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2950 fputs ("+ END_SELECT\n", dmpout);
2951 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2952 ffeste_emit_line_note_ ();
2954 /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2956 if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
2957 expand_end_case (ffestw_select_texpr (block));
2959 ffeste_end_block_ (block);
2960 #else
2961 #error
2962 #endif
2965 /* Iterative DO statement. */
2967 void
2968 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
2969 ffebld start, ffelexToken start_token,
2970 ffebld end, ffelexToken end_token,
2971 ffebld incr, ffelexToken incr_token)
2973 ffeste_check_simple_ ();
2975 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2976 if ((ffebld_op (incr) == FFEBLD_opCONTER)
2977 && (ffebld_constant_is_zero (ffebld_conter (incr))))
2979 ffebad_start (FFEBAD_DO_STEP_ZERO);
2980 ffebad_here (0, ffelex_token_where_line (incr_token),
2981 ffelex_token_where_column (incr_token));
2982 ffebad_string ("Iterative DO loop");
2983 ffebad_finish ();
2984 /* Don't bother replacing it with 1 yet. */
2987 if (label == NULL)
2988 fputs ("+ DO_iterative_nonlabeled (", dmpout);
2989 else
2990 fprintf (dmpout, "+ DO_iterative_labeled %lu (", ffelab_value (label));
2991 ffebld_dump (var);
2992 fputc ('=', dmpout);
2993 ffebld_dump (start);
2994 fputc (',', dmpout);
2995 ffebld_dump (end);
2996 fputc (',', dmpout);
2997 ffebld_dump (incr);
2998 fputs (")\n", dmpout);
2999 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3001 ffeste_emit_line_note_ ();
3003 ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
3004 var,
3005 start, start_token,
3006 end, end_token,
3007 incr, incr_token,
3008 "Iterative DO loop");
3010 #else
3011 #error
3012 #endif
3015 /* DO WHILE statement. */
3017 void
3018 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
3020 ffeste_check_simple_ ();
3022 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3023 if (label == NULL)
3024 fputs ("+ DO_WHILE_nonlabeled (", dmpout);
3025 else
3026 fprintf (dmpout, "+ DO_WHILE_labeled %lu (", ffelab_value (label));
3027 ffebld_dump (expr);
3028 fputs (")\n", dmpout);
3029 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3031 tree result;
3033 ffeste_emit_line_note_ ();
3035 ffeste_start_block_ (block);
3037 if (expr)
3039 struct nesting *loop;
3040 tree mod;
3042 result = ffecom_make_tempvar ("dowhile", integer_type_node,
3043 FFETARGET_charactersizeNONE, -1);
3044 loop = expand_start_loop (1);
3046 ffeste_start_stmt_ ();
3048 ffecom_prepare_expr (expr);
3050 ffecom_prepare_end ();
3052 mod = ffecom_modify (void_type_node,
3053 result,
3054 ffecom_truth_value (ffecom_expr (expr)));
3055 expand_expr_stmt (mod);
3057 ffeste_end_stmt_ ();
3059 ffestw_set_do_hook (block, loop);
3060 expand_exit_loop_if_false (0, result);
3062 else
3063 ffestw_set_do_hook (block, expand_start_loop (1));
3065 ffestw_set_do_tvar (block, NULL_TREE);
3067 #else
3068 #error
3069 #endif
3072 /* END DO statement.
3074 This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
3075 CONTINUE (except that it has to have a label that is the target of
3076 one or more iterative DO statement), not the Fortran-90 structured
3077 END DO, which is handled elsewhere, as is the actual mechanism of
3078 ending an iterative DO statement, even one that ends at a label. */
3080 void
3081 ffeste_R825 ()
3083 ffeste_check_simple_ ();
3085 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3086 fputs ("+ END_DO_sugar\n", dmpout);
3087 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3088 ffeste_emit_line_note_ ();
3090 emit_nop ();
3091 #else
3092 #error
3093 #endif
3096 /* CYCLE statement. */
3098 void
3099 ffeste_R834 (ffestw block)
3101 ffeste_check_simple_ ();
3103 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3104 fprintf (dmpout, "+ CYCLE block #%lu\n", ffestw_blocknum (block));
3105 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3106 ffeste_emit_line_note_ ();
3108 expand_continue_loop (ffestw_do_hook (block));
3109 #else
3110 #error
3111 #endif
3114 /* EXIT statement. */
3116 void
3117 ffeste_R835 (ffestw block)
3119 ffeste_check_simple_ ();
3121 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3122 fprintf (dmpout, "+ EXIT block #%lu\n", ffestw_blocknum (block));
3123 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3124 ffeste_emit_line_note_ ();
3126 expand_exit_loop (ffestw_do_hook (block));
3127 #else
3128 #error
3129 #endif
3132 /* GOTO statement. */
3134 void
3135 ffeste_R836 (ffelab label)
3137 ffeste_check_simple_ ();
3139 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3140 fprintf (dmpout, "+ GOTO %lu\n", ffelab_value (label));
3141 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3143 tree glabel;
3145 ffeste_emit_line_note_ ();
3147 glabel = ffecom_lookup_label (label);
3148 if ((glabel != NULL_TREE)
3149 && (TREE_CODE (glabel) != ERROR_MARK))
3151 expand_goto (glabel);
3152 TREE_USED (glabel) = 1;
3155 #else
3156 #error
3157 #endif
3160 /* Computed GOTO statement. */
3162 void
3163 ffeste_R837 (ffelab *labels, int count, ffebld expr)
3165 int i;
3167 ffeste_check_simple_ ();
3169 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3170 fputs ("+ CGOTO (", dmpout);
3171 for (i = 0; i < count; ++i)
3173 if (i != 0)
3174 fputc (',', dmpout);
3175 fprintf (dmpout, "%" ffelabValue_f "u", ffelab_value (labels[i]));
3177 fputs ("),", dmpout);
3178 ffebld_dump (expr);
3179 fputc ('\n', dmpout);
3180 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3182 tree texpr;
3183 tree value;
3184 tree tlabel;
3185 int pushok;
3186 tree duplicate;
3188 ffeste_emit_line_note_ ();
3190 ffeste_start_stmt_ ();
3192 ffecom_prepare_expr (expr);
3194 ffecom_prepare_end ();
3196 texpr = ffecom_expr (expr);
3198 expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
3200 for (i = 0; i < count; ++i)
3202 value = build_int_2 (i + 1, 0);
3203 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
3205 pushok = pushcase (value, convert, tlabel, &duplicate);
3206 assert (pushok == 0);
3208 tlabel = ffecom_lookup_label (labels[i]);
3209 if ((tlabel == NULL_TREE)
3210 || (TREE_CODE (tlabel) == ERROR_MARK))
3211 continue;
3213 expand_goto (tlabel);
3214 TREE_USED (tlabel) = 1;
3216 expand_end_case (texpr);
3218 ffeste_end_stmt_ ();
3220 #else
3221 #error
3222 #endif
3225 /* ASSIGN statement. */
3227 void
3228 ffeste_R838 (ffelab label, ffebld target)
3230 ffeste_check_simple_ ();
3232 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3233 fprintf (dmpout, "+ ASSIGN %lu TO ", ffelab_value (label));
3234 ffebld_dump (target);
3235 fputc ('\n', dmpout);
3236 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3238 tree expr_tree;
3239 tree label_tree;
3240 tree target_tree;
3242 ffeste_emit_line_note_ ();
3244 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3245 seen here should never require use of temporaries. */
3247 label_tree = ffecom_lookup_label (label);
3248 if ((label_tree != NULL_TREE)
3249 && (TREE_CODE (label_tree) != ERROR_MARK))
3251 label_tree = ffecom_1 (ADDR_EXPR,
3252 build_pointer_type (void_type_node),
3253 label_tree);
3254 TREE_CONSTANT (label_tree) = 1;
3256 target_tree = ffecom_expr_assign_w (target);
3257 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
3258 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
3259 error ("ASSIGN to variable that is too small");
3261 label_tree = convert (TREE_TYPE (target_tree), label_tree);
3263 expr_tree = ffecom_modify (void_type_node,
3264 target_tree,
3265 label_tree);
3266 expand_expr_stmt (expr_tree);
3269 #else
3270 #error
3271 #endif
3274 /* Assigned GOTO statement. */
3276 void
3277 ffeste_R839 (ffebld target)
3279 ffeste_check_simple_ ();
3281 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3282 fputs ("+ AGOTO ", dmpout);
3283 ffebld_dump (target);
3284 fputc ('\n', dmpout);
3285 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3287 tree t;
3289 ffeste_emit_line_note_ ();
3291 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3292 seen here should never require use of temporaries. */
3294 t = ffecom_expr_assign (target);
3295 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3296 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3297 error ("ASSIGNed GOTO target variable is too small");
3299 expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
3301 #else
3302 #error
3303 #endif
3306 /* Arithmetic IF statement. */
3308 void
3309 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
3311 ffeste_check_simple_ ();
3313 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3314 fputs ("+ IF_arithmetic (", dmpout);
3315 ffebld_dump (expr);
3316 fprintf (dmpout, ") %" ffelabValue_f "u,%" ffelabValue_f "u,%" ffelabValue_f "u\n",
3317 ffelab_value (neg), ffelab_value (zero), ffelab_value (pos));
3318 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3320 tree gneg = ffecom_lookup_label (neg);
3321 tree gzero = ffecom_lookup_label (zero);
3322 tree gpos = ffecom_lookup_label (pos);
3323 tree texpr;
3325 ffeste_emit_line_note_ ();
3327 if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
3328 return;
3329 if ((TREE_CODE (gneg) == ERROR_MARK)
3330 || (TREE_CODE (gzero) == ERROR_MARK)
3331 || (TREE_CODE (gpos) == ERROR_MARK))
3332 return;
3334 ffeste_start_stmt_ ();
3336 ffecom_prepare_expr (expr);
3338 ffecom_prepare_end ();
3340 if (neg == zero)
3342 if (neg == pos)
3343 expand_goto (gzero);
3344 else
3346 /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos. */
3347 texpr = ffecom_expr (expr);
3348 texpr = ffecom_2 (LE_EXPR, integer_type_node,
3349 texpr,
3350 convert (TREE_TYPE (texpr),
3351 integer_zero_node));
3352 expand_start_cond (ffecom_truth_value (texpr), 0);
3353 expand_goto (gzero);
3354 expand_start_else ();
3355 expand_goto (gpos);
3356 expand_end_cond ();
3359 else if (neg == pos)
3361 /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero. */
3362 texpr = ffecom_expr (expr);
3363 texpr = ffecom_2 (NE_EXPR, integer_type_node,
3364 texpr,
3365 convert (TREE_TYPE (texpr),
3366 integer_zero_node));
3367 expand_start_cond (ffecom_truth_value (texpr), 0);
3368 expand_goto (gneg);
3369 expand_start_else ();
3370 expand_goto (gzero);
3371 expand_end_cond ();
3373 else if (zero == pos)
3375 /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg. */
3376 texpr = ffecom_expr (expr);
3377 texpr = ffecom_2 (GE_EXPR, integer_type_node,
3378 texpr,
3379 convert (TREE_TYPE (texpr),
3380 integer_zero_node));
3381 expand_start_cond (ffecom_truth_value (texpr), 0);
3382 expand_goto (gzero);
3383 expand_start_else ();
3384 expand_goto (gneg);
3385 expand_end_cond ();
3387 else
3389 /* Use a SAVE_EXPR in combo with:
3390 IF (expr.LT.0) THEN GOTO neg
3391 ELSEIF (expr.GT.0) THEN GOTO pos
3392 ELSE GOTO zero. */
3393 tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
3395 texpr = ffecom_2 (LT_EXPR, integer_type_node,
3396 expr_saved,
3397 convert (TREE_TYPE (expr_saved),
3398 integer_zero_node));
3399 expand_start_cond (ffecom_truth_value (texpr), 0);
3400 expand_goto (gneg);
3401 texpr = ffecom_2 (GT_EXPR, integer_type_node,
3402 expr_saved,
3403 convert (TREE_TYPE (expr_saved),
3404 integer_zero_node));
3405 expand_start_elseif (ffecom_truth_value (texpr));
3406 expand_goto (gpos);
3407 expand_start_else ();
3408 expand_goto (gzero);
3409 expand_end_cond ();
3412 ffeste_end_stmt_ ();
3414 #else
3415 #error
3416 #endif
3419 /* CONTINUE statement. */
3421 void
3422 ffeste_R841 ()
3424 ffeste_check_simple_ ();
3426 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3427 fputs ("+ CONTINUE\n", dmpout);
3428 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3429 ffeste_emit_line_note_ ();
3431 emit_nop ();
3432 #else
3433 #error
3434 #endif
3437 /* STOP statement. */
3439 void
3440 ffeste_R842 (ffebld expr)
3442 ffeste_check_simple_ ();
3444 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3445 if (expr == NULL)
3447 fputs ("+ STOP\n", dmpout);
3449 else
3451 fputs ("+ STOP_coded ", dmpout);
3452 ffebld_dump (expr);
3453 fputc ('\n', dmpout);
3455 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3457 tree callit;
3458 ffelexToken msg;
3460 ffeste_emit_line_note_ ();
3462 if ((expr == NULL)
3463 || (ffeinfo_basictype (ffebld_info (expr))
3464 == FFEINFO_basictypeANY))
3466 msg = ffelex_token_new_character ("", ffelex_token_where_line
3467 (ffesta_tokens[0]), ffelex_token_where_column
3468 (ffesta_tokens[0]));
3469 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3470 (msg));
3471 ffelex_token_kill (msg);
3472 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3473 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3474 FFEINFO_whereCONSTANT, 0));
3476 else if (ffeinfo_basictype (ffebld_info (expr))
3477 == FFEINFO_basictypeINTEGER)
3479 char num[50];
3481 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3482 assert (ffeinfo_kindtype (ffebld_info (expr))
3483 == FFEINFO_kindtypeINTEGERDEFAULT);
3484 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3485 ffebld_constant_integer1 (ffebld_conter (expr)));
3486 msg = ffelex_token_new_character (num, ffelex_token_where_line
3487 (ffesta_tokens[0]), ffelex_token_where_column
3488 (ffesta_tokens[0]));
3489 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3490 (msg));
3491 ffelex_token_kill (msg);
3492 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3493 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3494 FFEINFO_whereCONSTANT, 0));
3496 else
3498 assert (ffeinfo_basictype (ffebld_info (expr))
3499 == FFEINFO_basictypeCHARACTER);
3500 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3501 assert (ffeinfo_kindtype (ffebld_info (expr))
3502 == FFEINFO_kindtypeCHARACTERDEFAULT);
3505 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3506 seen here should never require use of temporaries. */
3508 callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3509 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3510 NULL_TREE);
3511 TREE_SIDE_EFFECTS (callit) = 1;
3513 expand_expr_stmt (callit);
3515 #else
3516 #error
3517 #endif
3520 /* PAUSE statement. */
3522 void
3523 ffeste_R843 (ffebld expr)
3525 ffeste_check_simple_ ();
3527 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3528 if (expr == NULL)
3530 fputs ("+ PAUSE\n", dmpout);
3532 else
3534 fputs ("+ PAUSE_coded ", dmpout);
3535 ffebld_dump (expr);
3536 fputc ('\n', dmpout);
3538 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3540 tree callit;
3541 ffelexToken msg;
3543 ffeste_emit_line_note_ ();
3545 if ((expr == NULL)
3546 || (ffeinfo_basictype (ffebld_info (expr))
3547 == FFEINFO_basictypeANY))
3549 msg = ffelex_token_new_character ("", ffelex_token_where_line
3550 (ffesta_tokens[0]), ffelex_token_where_column
3551 (ffesta_tokens[0]));
3552 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3553 (msg));
3554 ffelex_token_kill (msg);
3555 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3556 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3557 FFEINFO_whereCONSTANT, 0));
3559 else if (ffeinfo_basictype (ffebld_info (expr))
3560 == FFEINFO_basictypeINTEGER)
3562 char num[50];
3564 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3565 assert (ffeinfo_kindtype (ffebld_info (expr))
3566 == FFEINFO_kindtypeINTEGERDEFAULT);
3567 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3568 ffebld_constant_integer1 (ffebld_conter (expr)));
3569 msg = ffelex_token_new_character (num, ffelex_token_where_line
3570 (ffesta_tokens[0]), ffelex_token_where_column
3571 (ffesta_tokens[0]));
3572 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3573 (msg));
3574 ffelex_token_kill (msg);
3575 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3576 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3577 FFEINFO_whereCONSTANT, 0));
3579 else
3581 assert (ffeinfo_basictype (ffebld_info (expr))
3582 == FFEINFO_basictypeCHARACTER);
3583 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3584 assert (ffeinfo_kindtype (ffebld_info (expr))
3585 == FFEINFO_kindtypeCHARACTERDEFAULT);
3588 /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3589 seen here should never require use of temporaries. */
3591 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3592 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3593 NULL_TREE);
3594 TREE_SIDE_EFFECTS (callit) = 1;
3596 expand_expr_stmt (callit);
3598 #if 0 /* Old approach for phantom g77 run-time
3599 library. */
3601 tree callit;
3603 ffeste_emit_line_note_ ();
3605 if (expr == NULL)
3606 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE, NULL_TREE);
3607 else if (ffeinfo_basictype (ffebld_info (expr))
3608 == FFEINFO_basictypeINTEGER)
3609 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
3610 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3611 NULL_TREE);
3612 else if (ffeinfo_basictype (ffebld_info (expr))
3613 == FFEINFO_basictypeCHARACTER)
3614 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
3615 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3616 NULL_TREE);
3617 else
3618 abort ();
3619 TREE_SIDE_EFFECTS (callit) = 1;
3621 expand_expr_stmt (callit);
3623 #endif
3624 #else
3625 #error
3626 #endif
3629 /* OPEN statement. */
3631 void
3632 ffeste_R904 (ffestpOpenStmt *info)
3634 ffeste_check_simple_ ();
3636 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3637 fputs ("+ OPEN (", dmpout);
3638 ffeste_subr_file_ ("UNIT", &info->open_spec[FFESTP_openixUNIT]);
3639 ffeste_subr_file_ ("ACCESS", &info->open_spec[FFESTP_openixACCESS]);
3640 ffeste_subr_file_ ("ACTION", &info->open_spec[FFESTP_openixACTION]);
3641 ffeste_subr_file_ ("ASSOCIATEVARIABLE", &info->open_spec[FFESTP_openixASSOCIATEVARIABLE]);
3642 ffeste_subr_file_ ("BLANK", &info->open_spec[FFESTP_openixBLANK]);
3643 ffeste_subr_file_ ("BLOCKSIZE", &info->open_spec[FFESTP_openixBLOCKSIZE]);
3644 ffeste_subr_file_ ("BUFFERCOUNT", &info->open_spec[FFESTP_openixBUFFERCOUNT]);
3645 ffeste_subr_file_ ("CARRIAGECONTROL", &info->open_spec[FFESTP_openixCARRIAGECONTROL]);
3646 ffeste_subr_file_ ("DEFAULTFILE", &info->open_spec[FFESTP_openixDEFAULTFILE]);
3647 ffeste_subr_file_ ("DELIM", &info->open_spec[FFESTP_openixDELIM]);
3648 ffeste_subr_file_ ("DISPOSE", &info->open_spec[FFESTP_openixDISPOSE]);
3649 ffeste_subr_file_ ("ERR", &info->open_spec[FFESTP_openixERR]);
3650 ffeste_subr_file_ ("EXTENDSIZE", &info->open_spec[FFESTP_openixEXTENDSIZE]);
3651 ffeste_subr_file_ ("FILE", &info->open_spec[FFESTP_openixFILE]);
3652 ffeste_subr_file_ ("FORM", &info->open_spec[FFESTP_openixFORM]);
3653 ffeste_subr_file_ ("INITIALSIZE", &info->open_spec[FFESTP_openixINITIALSIZE]);
3654 ffeste_subr_file_ ("IOSTAT", &info->open_spec[FFESTP_openixIOSTAT]);
3655 ffeste_subr_file_ ("KEY", &info->open_spec[FFESTP_openixKEY]);
3656 ffeste_subr_file_ ("MAXREC", &info->open_spec[FFESTP_openixMAXREC]);
3657 ffeste_subr_file_ ("NOSPANBLOCKS", &info->open_spec[FFESTP_openixNOSPANBLOCKS]);
3658 ffeste_subr_file_ ("ORGANIZATION", &info->open_spec[FFESTP_openixORGANIZATION]);
3659 ffeste_subr_file_ ("PAD", &info->open_spec[FFESTP_openixPAD]);
3660 ffeste_subr_file_ ("POSITION", &info->open_spec[FFESTP_openixPOSITION]);
3661 ffeste_subr_file_ ("READONLY", &info->open_spec[FFESTP_openixREADONLY]);
3662 ffeste_subr_file_ ("RECL", &info->open_spec[FFESTP_openixRECL]);
3663 ffeste_subr_file_ ("RECORDTYPE", &info->open_spec[FFESTP_openixRECORDTYPE]);
3664 ffeste_subr_file_ ("SHARED", &info->open_spec[FFESTP_openixSHARED]);
3665 ffeste_subr_file_ ("STATUS", &info->open_spec[FFESTP_openixSTATUS]);
3666 ffeste_subr_file_ ("USEROPEN", &info->open_spec[FFESTP_openixUSEROPEN]);
3667 fputs (")\n", dmpout);
3668 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3670 tree args;
3671 bool iostat;
3672 bool errl;
3674 ffeste_emit_line_note_ ();
3676 #define specified(something) (info->open_spec[something].kw_or_val_present)
3678 iostat = specified (FFESTP_openixIOSTAT);
3679 errl = specified (FFESTP_openixERR);
3681 #undef specified
3683 ffeste_start_stmt_ ();
3685 if (errl)
3687 ffeste_io_err_
3688 = ffeste_io_abort_
3689 = ffecom_lookup_label
3690 (info->open_spec[FFESTP_openixERR].u.label);
3691 ffeste_io_abort_is_temp_ = FALSE;
3693 else
3695 ffeste_io_err_ = NULL_TREE;
3697 if ((ffeste_io_abort_is_temp_ = iostat))
3698 ffeste_io_abort_ = ffecom_temp_label ();
3699 else
3700 ffeste_io_abort_ = NULL_TREE;
3703 if (iostat)
3705 /* Have IOSTAT= specification. */
3707 ffeste_io_iostat_is_temp_ = FALSE;
3708 ffeste_io_iostat_ = ffecom_expr
3709 (info->open_spec[FFESTP_openixIOSTAT].u.expr);
3711 else if (ffeste_io_abort_ != NULL_TREE)
3713 /* Have no IOSTAT= but have ERR=. */
3715 ffeste_io_iostat_is_temp_ = TRUE;
3716 ffeste_io_iostat_
3717 = ffecom_make_tempvar ("open", ffecom_integer_type_node,
3718 FFETARGET_charactersizeNONE, -1);
3720 else
3722 /* No IOSTAT= or ERR= specification. */
3724 ffeste_io_iostat_is_temp_ = FALSE;
3725 ffeste_io_iostat_ = NULL_TREE;
3728 /* Now prescan, then convert, all the arguments. */
3730 args = ffeste_io_olist_ (errl || iostat,
3731 info->open_spec[FFESTP_openixUNIT].u.expr,
3732 &info->open_spec[FFESTP_openixFILE],
3733 &info->open_spec[FFESTP_openixSTATUS],
3734 &info->open_spec[FFESTP_openixACCESS],
3735 &info->open_spec[FFESTP_openixFORM],
3736 &info->open_spec[FFESTP_openixRECL],
3737 &info->open_spec[FFESTP_openixBLANK]);
3739 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3740 label, since we're gonna fall through to there anyway. */
3742 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
3743 ! ffeste_io_abort_is_temp_);
3745 /* If we've got a temp label, generate its code here. */
3747 if (ffeste_io_abort_is_temp_)
3749 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3750 emit_nop ();
3751 expand_label (ffeste_io_abort_);
3753 assert (ffeste_io_err_ == NULL_TREE);
3756 ffeste_end_stmt_ ();
3758 #else
3759 #error
3760 #endif
3763 /* CLOSE statement. */
3765 void
3766 ffeste_R907 (ffestpCloseStmt *info)
3768 ffeste_check_simple_ ();
3770 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3771 fputs ("+ CLOSE (", dmpout);
3772 ffeste_subr_file_ ("UNIT", &info->close_spec[FFESTP_closeixUNIT]);
3773 ffeste_subr_file_ ("ERR", &info->close_spec[FFESTP_closeixERR]);
3774 ffeste_subr_file_ ("IOSTAT", &info->close_spec[FFESTP_closeixIOSTAT]);
3775 ffeste_subr_file_ ("STATUS", &info->close_spec[FFESTP_closeixSTATUS]);
3776 fputs (")\n", dmpout);
3777 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3779 tree args;
3780 bool iostat;
3781 bool errl;
3783 ffeste_emit_line_note_ ();
3785 #define specified(something) (info->close_spec[something].kw_or_val_present)
3787 iostat = specified (FFESTP_closeixIOSTAT);
3788 errl = specified (FFESTP_closeixERR);
3790 #undef specified
3792 ffeste_start_stmt_ ();
3794 if (errl)
3796 ffeste_io_err_
3797 = ffeste_io_abort_
3798 = ffecom_lookup_label
3799 (info->close_spec[FFESTP_closeixERR].u.label);
3800 ffeste_io_abort_is_temp_ = FALSE;
3802 else
3804 ffeste_io_err_ = NULL_TREE;
3806 if ((ffeste_io_abort_is_temp_ = iostat))
3807 ffeste_io_abort_ = ffecom_temp_label ();
3808 else
3809 ffeste_io_abort_ = NULL_TREE;
3812 if (iostat)
3814 /* Have IOSTAT= specification. */
3816 ffeste_io_iostat_is_temp_ = FALSE;
3817 ffeste_io_iostat_ = ffecom_expr
3818 (info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3820 else if (ffeste_io_abort_ != NULL_TREE)
3822 /* Have no IOSTAT= but have ERR=. */
3824 ffeste_io_iostat_is_temp_ = TRUE;
3825 ffeste_io_iostat_
3826 = ffecom_make_tempvar ("close", ffecom_integer_type_node,
3827 FFETARGET_charactersizeNONE, -1);
3829 else
3831 /* No IOSTAT= or ERR= specification. */
3833 ffeste_io_iostat_is_temp_ = FALSE;
3834 ffeste_io_iostat_ = NULL_TREE;
3837 /* Now prescan, then convert, all the arguments. */
3839 args = ffeste_io_cllist_ (errl || iostat,
3840 info->close_spec[FFESTP_closeixUNIT].u.expr,
3841 &info->close_spec[FFESTP_closeixSTATUS]);
3843 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3844 label, since we're gonna fall through to there anyway. */
3846 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
3847 ! ffeste_io_abort_is_temp_);
3849 /* If we've got a temp label, generate its code here. */
3851 if (ffeste_io_abort_is_temp_)
3853 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3854 emit_nop ();
3855 expand_label (ffeste_io_abort_);
3857 assert (ffeste_io_err_ == NULL_TREE);
3860 ffeste_end_stmt_ ();
3862 #else
3863 #error
3864 #endif
3867 /* READ(...) statement -- start. */
3869 void
3870 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3871 ffestvUnit unit, ffestvFormat format, bool rec,
3872 bool key UNUSED)
3874 ffeste_check_start_ ();
3876 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3877 switch (format)
3879 case FFESTV_formatNONE:
3880 if (rec)
3881 fputs ("+ READ_ufdac", dmpout);
3882 else if (key)
3883 fputs ("+ READ_ufidx", dmpout);
3884 else
3885 fputs ("+ READ_ufseq", dmpout);
3886 break;
3888 case FFESTV_formatLABEL:
3889 case FFESTV_formatCHAREXPR:
3890 case FFESTV_formatINTEXPR:
3891 if (rec)
3892 fputs ("+ READ_fmdac", dmpout);
3893 else if (key)
3894 fputs ("+ READ_fmidx", dmpout);
3895 else if (unit == FFESTV_unitCHAREXPR)
3896 fputs ("+ READ_fmint", dmpout);
3897 else
3898 fputs ("+ READ_fmseq", dmpout);
3899 break;
3901 case FFESTV_formatASTERISK:
3902 if (unit == FFESTV_unitCHAREXPR)
3903 fputs ("+ READ_lsint", dmpout);
3904 else
3905 fputs ("+ READ_lsseq", dmpout);
3906 break;
3908 case FFESTV_formatNAMELIST:
3909 fputs ("+ READ_nlseq", dmpout);
3910 break;
3912 default:
3913 assert ("Unexpected kind of format item in R909 READ" == NULL);
3916 if (only_format)
3918 fputc (' ', dmpout);
3919 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3920 fputc (' ', dmpout);
3922 return;
3925 fputs (" (", dmpout);
3926 ffeste_subr_file_ ("UNIT", &info->read_spec[FFESTP_readixUNIT]);
3927 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3928 ffeste_subr_file_ ("ADVANCE", &info->read_spec[FFESTP_readixADVANCE]);
3929 ffeste_subr_file_ ("EOR", &info->read_spec[FFESTP_readixEOR]);
3930 ffeste_subr_file_ ("ERR", &info->read_spec[FFESTP_readixERR]);
3931 ffeste_subr_file_ ("END", &info->read_spec[FFESTP_readixEND]);
3932 ffeste_subr_file_ ("IOSTAT", &info->read_spec[FFESTP_readixIOSTAT]);
3933 ffeste_subr_file_ ("KEYEQ", &info->read_spec[FFESTP_readixKEYEQ]);
3934 ffeste_subr_file_ ("KEYGE", &info->read_spec[FFESTP_readixKEYGE]);
3935 ffeste_subr_file_ ("KEYGT", &info->read_spec[FFESTP_readixKEYGT]);
3936 ffeste_subr_file_ ("KEYID", &info->read_spec[FFESTP_readixKEYID]);
3937 ffeste_subr_file_ ("NULLS", &info->read_spec[FFESTP_readixNULLS]);
3938 ffeste_subr_file_ ("REC", &info->read_spec[FFESTP_readixREC]);
3939 ffeste_subr_file_ ("SIZE", &info->read_spec[FFESTP_readixSIZE]);
3940 fputs (") ", dmpout);
3941 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3943 ffeste_emit_line_note_ ();
3946 ffecomGfrt start;
3947 ffecomGfrt end;
3948 tree cilist;
3949 bool iostat;
3950 bool errl;
3951 bool endl;
3953 /* First determine the start, per-item, and end run-time functions to
3954 call. The per-item function is picked by choosing an ffeste function
3955 to call to handle a given item; it knows how to generate a call to the
3956 appropriate run-time function, and is called an "I/O driver". */
3958 switch (format)
3960 case FFESTV_formatNONE: /* no FMT= */
3961 ffeste_io_driver_ = ffeste_io_douio_;
3962 if (rec)
3963 start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
3964 #if 0
3965 else if (key)
3966 start = FFECOM_gfrtSRIUE, end = FFECOM_gfrtERIUE;
3967 #endif
3968 else
3969 start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
3970 break;
3972 case FFESTV_formatLABEL: /* FMT=10 */
3973 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3974 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3975 ffeste_io_driver_ = ffeste_io_dofio_;
3976 if (rec)
3977 start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
3978 #if 0
3979 else if (key)
3980 start = FFECOM_gfrtSRIFE, end = FFECOM_gfrtERIFE;
3981 #endif
3982 else if (unit == FFESTV_unitCHAREXPR)
3983 start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
3984 else
3985 start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
3986 break;
3988 case FFESTV_formatASTERISK: /* FMT=* */
3989 ffeste_io_driver_ = ffeste_io_dolio_;
3990 if (unit == FFESTV_unitCHAREXPR)
3991 start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
3992 else
3993 start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
3994 break;
3996 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3997 /FOO/] */
3998 ffeste_io_driver_ = NULL; /* No start or driver function. */
3999 start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
4000 break;
4002 default:
4003 assert ("Weird stuff" == NULL);
4004 start = FFECOM_gfrt, end = FFECOM_gfrt;
4005 break;
4007 ffeste_io_endgfrt_ = end;
4009 #define specified(something) (info->read_spec[something].kw_or_val_present)
4011 iostat = specified (FFESTP_readixIOSTAT);
4012 errl = specified (FFESTP_readixERR);
4013 endl = specified (FFESTP_readixEND);
4015 #undef specified
4017 ffeste_start_stmt_ ();
4019 if (errl)
4021 /* Have ERR= specification. */
4023 ffeste_io_err_
4024 = ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
4026 if (endl)
4028 /* Have both ERR= and END=. Need a temp label to handle both. */
4029 ffeste_io_end_
4030 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
4031 ffeste_io_abort_is_temp_ = TRUE;
4032 ffeste_io_abort_ = ffecom_temp_label ();
4034 else
4036 /* Have ERR= but no END=. */
4037 ffeste_io_end_ = NULL_TREE;
4038 if ((ffeste_io_abort_is_temp_ = iostat))
4039 ffeste_io_abort_ = ffecom_temp_label ();
4040 else
4041 ffeste_io_abort_ = ffeste_io_err_;
4044 else
4046 /* No ERR= specification. */
4048 ffeste_io_err_ = NULL_TREE;
4049 if (endl)
4051 /* Have END= but no ERR=. */
4052 ffeste_io_end_
4053 = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
4054 if ((ffeste_io_abort_is_temp_ = iostat))
4055 ffeste_io_abort_ = ffecom_temp_label ();
4056 else
4057 ffeste_io_abort_ = ffeste_io_end_;
4059 else
4061 /* Have no ERR= or END=. */
4063 ffeste_io_end_ = NULL_TREE;
4064 if ((ffeste_io_abort_is_temp_ = iostat))
4065 ffeste_io_abort_ = ffecom_temp_label ();
4066 else
4067 ffeste_io_abort_ = NULL_TREE;
4071 if (iostat)
4073 /* Have IOSTAT= specification. */
4075 ffeste_io_iostat_is_temp_ = FALSE;
4076 ffeste_io_iostat_
4077 = ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
4079 else if (ffeste_io_abort_ != NULL_TREE)
4081 /* Have no IOSTAT= but have ERR= and/or END=. */
4083 ffeste_io_iostat_is_temp_ = TRUE;
4084 ffeste_io_iostat_
4085 = ffecom_make_tempvar ("read", ffecom_integer_type_node,
4086 FFETARGET_charactersizeNONE, -1);
4088 else
4090 /* No IOSTAT=, ERR=, or END= specification. */
4092 ffeste_io_iostat_is_temp_ = FALSE;
4093 ffeste_io_iostat_ = NULL_TREE;
4096 /* Now prescan, then convert, all the arguments. */
4098 if (unit == FFESTV_unitCHAREXPR)
4099 cilist = ffeste_io_icilist_ (errl || iostat,
4100 info->read_spec[FFESTP_readixUNIT].u.expr,
4101 endl || iostat, format,
4102 &info->read_spec[FFESTP_readixFORMAT]);
4103 else
4104 cilist = ffeste_io_cilist_ (errl || iostat, unit,
4105 info->read_spec[FFESTP_readixUNIT].u.expr,
4106 5, endl || iostat, format,
4107 &info->read_spec[FFESTP_readixFORMAT],
4108 rec,
4109 info->read_spec[FFESTP_readixREC].u.expr);
4111 /* If there is no end function, then there are no item functions (i.e.
4112 it's a NAMELIST), and vice versa by the way. In this situation, don't
4113 generate the "if (iostat != 0) goto label;" if the label is temp abort
4114 label, since we're gonna fall through to there anyway. */
4116 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4117 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4119 #else
4120 #error
4121 #endif
4124 /* READ statement -- I/O item. */
4126 void
4127 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
4129 ffeste_check_item_ ();
4131 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4132 ffebld_dump (expr);
4133 fputc (',', dmpout);
4134 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4135 if (expr == NULL)
4136 return;
4138 /* Strip parens off items such as in "READ *,(A)". This is really a bug
4139 in the user's code, but I've been told lots of code does this. */
4140 while (ffebld_op (expr) == FFEBLD_opPAREN)
4141 expr = ffebld_left (expr);
4143 if (ffebld_op (expr) == FFEBLD_opANY)
4144 return;
4146 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4147 ffeste_io_impdo_ (expr, expr_token);
4148 else
4150 ffeste_start_stmt_ ();
4152 ffecom_prepare_arg_ptr_to_expr (expr);
4154 ffecom_prepare_end ();
4156 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4158 ffeste_end_stmt_ ();
4160 #else
4161 #error
4162 #endif
4165 /* READ statement -- end. */
4167 void
4168 ffeste_R909_finish ()
4170 ffeste_check_finish_ ();
4172 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4173 fputc ('\n', dmpout);
4174 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4176 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4177 label, since we're gonna fall through to there anyway. */
4179 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4180 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4181 NULL_TREE),
4182 ! ffeste_io_abort_is_temp_);
4184 /* If we've got a temp label, generate its code here and have it fan out
4185 to the END= or ERR= label as appropriate. */
4187 if (ffeste_io_abort_is_temp_)
4189 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4190 emit_nop ();
4191 expand_label (ffeste_io_abort_);
4193 /* "if (iostat<0) goto end_label;". */
4195 if ((ffeste_io_end_ != NULL_TREE)
4196 && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
4198 expand_start_cond (ffecom_truth_value
4199 (ffecom_2 (LT_EXPR, integer_type_node,
4200 ffeste_io_iostat_,
4201 ffecom_integer_zero_node)),
4203 expand_goto (ffeste_io_end_);
4204 expand_end_cond ();
4207 /* "if (iostat>0) goto err_label;". */
4209 if ((ffeste_io_err_ != NULL_TREE)
4210 && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
4212 expand_start_cond (ffecom_truth_value
4213 (ffecom_2 (GT_EXPR, integer_type_node,
4214 ffeste_io_iostat_,
4215 ffecom_integer_zero_node)),
4217 expand_goto (ffeste_io_err_);
4218 expand_end_cond ();
4222 ffeste_end_stmt_ ();
4223 #else
4224 #error
4225 #endif
4228 /* WRITE statement -- start. */
4230 void
4231 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
4232 ffestvFormat format, bool rec)
4234 ffeste_check_start_ ();
4236 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4237 switch (format)
4239 case FFESTV_formatNONE:
4240 if (rec)
4241 fputs ("+ WRITE_ufdac (", dmpout);
4242 else
4243 fputs ("+ WRITE_ufseq_or_idx (", dmpout);
4244 break;
4246 case FFESTV_formatLABEL:
4247 case FFESTV_formatCHAREXPR:
4248 case FFESTV_formatINTEXPR:
4249 if (rec)
4250 fputs ("+ WRITE_fmdac (", dmpout);
4251 else if (unit == FFESTV_unitCHAREXPR)
4252 fputs ("+ WRITE_fmint (", dmpout);
4253 else
4254 fputs ("+ WRITE_fmseq_or_idx (", dmpout);
4255 break;
4257 case FFESTV_formatASTERISK:
4258 if (unit == FFESTV_unitCHAREXPR)
4259 fputs ("+ WRITE_lsint (", dmpout);
4260 else
4261 fputs ("+ WRITE_lsseq (", dmpout);
4262 break;
4264 case FFESTV_formatNAMELIST:
4265 fputs ("+ WRITE_nlseq (", dmpout);
4266 break;
4268 default:
4269 assert ("Unexpected kind of format item in R910 WRITE" == NULL);
4272 ffeste_subr_file_ ("UNIT", &info->write_spec[FFESTP_writeixUNIT]);
4273 ffeste_subr_file_ ("FORMAT", &info->write_spec[FFESTP_writeixFORMAT]);
4274 ffeste_subr_file_ ("ADVANCE", &info->write_spec[FFESTP_writeixADVANCE]);
4275 ffeste_subr_file_ ("EOR", &info->write_spec[FFESTP_writeixEOR]);
4276 ffeste_subr_file_ ("ERR", &info->write_spec[FFESTP_writeixERR]);
4277 ffeste_subr_file_ ("IOSTAT", &info->write_spec[FFESTP_writeixIOSTAT]);
4278 ffeste_subr_file_ ("REC", &info->write_spec[FFESTP_writeixREC]);
4279 fputs (") ", dmpout);
4280 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4282 ffeste_emit_line_note_ ();
4285 ffecomGfrt start;
4286 ffecomGfrt end;
4287 tree cilist;
4288 bool iostat;
4289 bool errl;
4291 /* First determine the start, per-item, and end run-time functions to
4292 call. The per-item function is picked by choosing an ffeste function
4293 to call to handle a given item; it knows how to generate a call to the
4294 appropriate run-time function, and is called an "I/O driver". */
4296 switch (format)
4298 case FFESTV_formatNONE: /* no FMT= */
4299 ffeste_io_driver_ = ffeste_io_douio_;
4300 if (rec)
4301 start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
4302 else
4303 start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
4304 break;
4306 case FFESTV_formatLABEL: /* FMT=10 */
4307 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4308 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4309 ffeste_io_driver_ = ffeste_io_dofio_;
4310 if (rec)
4311 start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
4312 else if (unit == FFESTV_unitCHAREXPR)
4313 start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
4314 else
4315 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
4316 break;
4318 case FFESTV_formatASTERISK: /* FMT=* */
4319 ffeste_io_driver_ = ffeste_io_dolio_;
4320 if (unit == FFESTV_unitCHAREXPR)
4321 start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
4322 else
4323 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
4324 break;
4326 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4327 /FOO/] */
4328 ffeste_io_driver_ = NULL; /* No start or driver function. */
4329 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
4330 break;
4332 default:
4333 assert ("Weird stuff" == NULL);
4334 start = FFECOM_gfrt, end = FFECOM_gfrt;
4335 break;
4337 ffeste_io_endgfrt_ = end;
4339 #define specified(something) (info->write_spec[something].kw_or_val_present)
4341 iostat = specified (FFESTP_writeixIOSTAT);
4342 errl = specified (FFESTP_writeixERR);
4344 #undef specified
4346 ffeste_start_stmt_ ();
4348 ffeste_io_end_ = NULL_TREE;
4350 if (errl)
4352 /* Have ERR= specification. */
4354 ffeste_io_err_
4355 = ffeste_io_abort_
4356 = ffecom_lookup_label
4357 (info->write_spec[FFESTP_writeixERR].u.label);
4358 ffeste_io_abort_is_temp_ = FALSE;
4360 else
4362 /* No ERR= specification. */
4364 ffeste_io_err_ = NULL_TREE;
4366 if ((ffeste_io_abort_is_temp_ = iostat))
4367 ffeste_io_abort_ = ffecom_temp_label ();
4368 else
4369 ffeste_io_abort_ = NULL_TREE;
4372 if (iostat)
4374 /* Have IOSTAT= specification. */
4376 ffeste_io_iostat_is_temp_ = FALSE;
4377 ffeste_io_iostat_ = ffecom_expr
4378 (info->write_spec[FFESTP_writeixIOSTAT].u.expr);
4380 else if (ffeste_io_abort_ != NULL_TREE)
4382 /* Have no IOSTAT= but have ERR=. */
4384 ffeste_io_iostat_is_temp_ = TRUE;
4385 ffeste_io_iostat_
4386 = ffecom_make_tempvar ("write", ffecom_integer_type_node,
4387 FFETARGET_charactersizeNONE, -1);
4389 else
4391 /* No IOSTAT= or ERR= specification. */
4393 ffeste_io_iostat_is_temp_ = FALSE;
4394 ffeste_io_iostat_ = NULL_TREE;
4397 /* Now prescan, then convert, all the arguments. */
4399 if (unit == FFESTV_unitCHAREXPR)
4400 cilist = ffeste_io_icilist_ (errl || iostat,
4401 info->write_spec[FFESTP_writeixUNIT].u.expr,
4402 FALSE, format,
4403 &info->write_spec[FFESTP_writeixFORMAT]);
4404 else
4405 cilist = ffeste_io_cilist_ (errl || iostat, unit,
4406 info->write_spec[FFESTP_writeixUNIT].u.expr,
4407 6, FALSE, format,
4408 &info->write_spec[FFESTP_writeixFORMAT],
4409 rec,
4410 info->write_spec[FFESTP_writeixREC].u.expr);
4412 /* If there is no end function, then there are no item functions (i.e.
4413 it's a NAMELIST), and vice versa by the way. In this situation, don't
4414 generate the "if (iostat != 0) goto label;" if the label is temp abort
4415 label, since we're gonna fall through to there anyway. */
4417 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4418 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4420 #else
4421 #error
4422 #endif
4425 /* WRITE statement -- I/O item. */
4427 void
4428 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
4430 ffeste_check_item_ ();
4432 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4433 ffebld_dump (expr);
4434 fputc (',', dmpout);
4435 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4436 if (expr == NULL)
4437 return;
4439 if (ffebld_op (expr) == FFEBLD_opANY)
4440 return;
4442 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4443 ffeste_io_impdo_ (expr, expr_token);
4444 else
4446 ffeste_start_stmt_ ();
4448 ffecom_prepare_arg_ptr_to_expr (expr);
4450 ffecom_prepare_end ();
4452 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4454 ffeste_end_stmt_ ();
4456 #else
4457 #error
4458 #endif
4461 /* WRITE statement -- end. */
4463 void
4464 ffeste_R910_finish ()
4466 ffeste_check_finish_ ();
4468 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4469 fputc ('\n', dmpout);
4470 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4472 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4473 label, since we're gonna fall through to there anyway. */
4475 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4476 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4477 NULL_TREE),
4478 ! ffeste_io_abort_is_temp_);
4480 /* If we've got a temp label, generate its code here. */
4482 if (ffeste_io_abort_is_temp_)
4484 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4485 emit_nop ();
4486 expand_label (ffeste_io_abort_);
4488 assert (ffeste_io_err_ == NULL_TREE);
4491 ffeste_end_stmt_ ();
4492 #else
4493 #error
4494 #endif
4497 /* PRINT statement -- start. */
4499 void
4500 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
4502 ffeste_check_start_ ();
4504 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4505 switch (format)
4507 case FFESTV_formatLABEL:
4508 case FFESTV_formatCHAREXPR:
4509 case FFESTV_formatINTEXPR:
4510 fputs ("+ PRINT_fm ", dmpout);
4511 break;
4513 case FFESTV_formatASTERISK:
4514 fputs ("+ PRINT_ls ", dmpout);
4515 break;
4517 case FFESTV_formatNAMELIST:
4518 fputs ("+ PRINT_nl ", dmpout);
4519 break;
4521 default:
4522 assert ("Unexpected kind of format item in R911 PRINT" == NULL);
4524 ffeste_subr_file_ ("FORMAT", &info->print_spec[FFESTP_printixFORMAT]);
4525 fputc (' ', dmpout);
4526 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4528 ffeste_emit_line_note_ ();
4531 ffecomGfrt start;
4532 ffecomGfrt end;
4533 tree cilist;
4535 /* First determine the start, per-item, and end run-time functions to
4536 call. The per-item function is picked by choosing an ffeste function
4537 to call to handle a given item; it knows how to generate a call to the
4538 appropriate run-time function, and is called an "I/O driver". */
4540 switch (format)
4542 case FFESTV_formatLABEL: /* FMT=10 */
4543 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4544 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4545 ffeste_io_driver_ = ffeste_io_dofio_;
4546 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
4547 break;
4549 case FFESTV_formatASTERISK: /* FMT=* */
4550 ffeste_io_driver_ = ffeste_io_dolio_;
4551 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
4552 break;
4554 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4555 /FOO/] */
4556 ffeste_io_driver_ = NULL; /* No start or driver function. */
4557 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
4558 break;
4560 default:
4561 assert ("Weird stuff" == NULL);
4562 start = FFECOM_gfrt, end = FFECOM_gfrt;
4563 break;
4565 ffeste_io_endgfrt_ = end;
4567 ffeste_start_stmt_ ();
4569 ffeste_io_end_ = NULL_TREE;
4570 ffeste_io_err_ = NULL_TREE;
4571 ffeste_io_abort_ = NULL_TREE;
4572 ffeste_io_abort_is_temp_ = FALSE;
4573 ffeste_io_iostat_is_temp_ = FALSE;
4574 ffeste_io_iostat_ = NULL_TREE;
4576 /* Now prescan, then convert, all the arguments. */
4578 cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
4579 &info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
4581 /* If there is no end function, then there are no item functions (i.e.
4582 it's a NAMELIST), and vice versa by the way. In this situation, don't
4583 generate the "if (iostat != 0) goto label;" if the label is temp abort
4584 label, since we're gonna fall through to there anyway. */
4586 ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
4587 (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
4589 #else
4590 #error
4591 #endif
4594 /* PRINT statement -- I/O item. */
4596 void
4597 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
4599 ffeste_check_item_ ();
4601 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4602 ffebld_dump (expr);
4603 fputc (',', dmpout);
4604 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4605 if (expr == NULL)
4606 return;
4608 if (ffebld_op (expr) == FFEBLD_opANY)
4609 return;
4611 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4612 ffeste_io_impdo_ (expr, expr_token);
4613 else
4615 ffeste_start_stmt_ ();
4617 ffecom_prepare_arg_ptr_to_expr (expr);
4619 ffecom_prepare_end ();
4621 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4623 ffeste_end_stmt_ ();
4625 #else
4626 #error
4627 #endif
4630 /* PRINT statement -- end. */
4632 void
4633 ffeste_R911_finish ()
4635 ffeste_check_finish_ ();
4637 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4638 fputc ('\n', dmpout);
4639 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4641 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4642 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4643 NULL_TREE),
4644 FALSE);
4646 ffeste_end_stmt_ ();
4647 #else
4648 #error
4649 #endif
4652 /* BACKSPACE statement. */
4654 void
4655 ffeste_R919 (ffestpBeruStmt *info)
4657 ffeste_check_simple_ ();
4659 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4660 fputs ("+ BACKSPACE (", dmpout);
4661 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4662 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4663 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4664 fputs (")\n", dmpout);
4665 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4666 ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4667 #else
4668 #error
4669 #endif
4672 /* ENDFILE statement. */
4674 void
4675 ffeste_R920 (ffestpBeruStmt *info)
4677 ffeste_check_simple_ ();
4679 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4680 fputs ("+ ENDFILE (", dmpout);
4681 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4682 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4683 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4684 fputs (")\n", dmpout);
4685 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4686 ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4687 #else
4688 #error
4689 #endif
4692 /* REWIND statement. */
4694 void
4695 ffeste_R921 (ffestpBeruStmt *info)
4697 ffeste_check_simple_ ();
4699 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4700 fputs ("+ REWIND (", dmpout);
4701 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4702 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4703 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4704 fputs (")\n", dmpout);
4705 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4706 ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4707 #else
4708 #error
4709 #endif
4712 /* INQUIRE statement (non-IOLENGTH version). */
4714 void
4715 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4717 ffeste_check_simple_ ();
4719 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4720 if (by_file)
4722 fputs ("+ INQUIRE_file (", dmpout);
4723 ffeste_subr_file_ ("FILE", &info->inquire_spec[FFESTP_inquireixFILE]);
4725 else
4727 fputs ("+ INQUIRE_unit (", dmpout);
4728 ffeste_subr_file_ ("UNIT", &info->inquire_spec[FFESTP_inquireixUNIT]);
4730 ffeste_subr_file_ ("ACCESS", &info->inquire_spec[FFESTP_inquireixACCESS]);
4731 ffeste_subr_file_ ("ACTION", &info->inquire_spec[FFESTP_inquireixACTION]);
4732 ffeste_subr_file_ ("BLANK", &info->inquire_spec[FFESTP_inquireixBLANK]);
4733 ffeste_subr_file_ ("CARRIAGECONTROL", &info->inquire_spec[FFESTP_inquireixCARRIAGECONTROL]);
4734 ffeste_subr_file_ ("DEFAULTFILE", &info->inquire_spec[FFESTP_inquireixDEFAULTFILE]);
4735 ffeste_subr_file_ ("DELIM", &info->inquire_spec[FFESTP_inquireixDELIM]);
4736 ffeste_subr_file_ ("DIRECT", &info->inquire_spec[FFESTP_inquireixDIRECT]);
4737 ffeste_subr_file_ ("ERR", &info->inquire_spec[FFESTP_inquireixERR]);
4738 ffeste_subr_file_ ("EXIST", &info->inquire_spec[FFESTP_inquireixEXIST]);
4739 ffeste_subr_file_ ("FORM", &info->inquire_spec[FFESTP_inquireixFORM]);
4740 ffeste_subr_file_ ("FORMATTED", &info->inquire_spec[FFESTP_inquireixFORMATTED]);
4741 ffeste_subr_file_ ("IOSTAT", &info->inquire_spec[FFESTP_inquireixIOSTAT]);
4742 ffeste_subr_file_ ("KEYED", &info->inquire_spec[FFESTP_inquireixKEYED]);
4743 ffeste_subr_file_ ("NAME", &info->inquire_spec[FFESTP_inquireixNAME]);
4744 ffeste_subr_file_ ("NAMED", &info->inquire_spec[FFESTP_inquireixNAMED]);
4745 ffeste_subr_file_ ("NEXTREC", &info->inquire_spec[FFESTP_inquireixNEXTREC]);
4746 ffeste_subr_file_ ("NUMBER", &info->inquire_spec[FFESTP_inquireixNUMBER]);
4747 ffeste_subr_file_ ("OPENED", &info->inquire_spec[FFESTP_inquireixOPENED]);
4748 ffeste_subr_file_ ("ORGANIZATION", &info->inquire_spec[FFESTP_inquireixORGANIZATION]);
4749 ffeste_subr_file_ ("PAD", &info->inquire_spec[FFESTP_inquireixPAD]);
4750 ffeste_subr_file_ ("POSITION", &info->inquire_spec[FFESTP_inquireixPOSITION]);
4751 ffeste_subr_file_ ("READ", &info->inquire_spec[FFESTP_inquireixREAD]);
4752 ffeste_subr_file_ ("READWRITE", &info->inquire_spec[FFESTP_inquireixREADWRITE]);
4753 ffeste_subr_file_ ("RECL", &info->inquire_spec[FFESTP_inquireixRECL]);
4754 ffeste_subr_file_ ("RECORDTYPE", &info->inquire_spec[FFESTP_inquireixRECORDTYPE]);
4755 ffeste_subr_file_ ("SEQUENTIAL", &info->inquire_spec[FFESTP_inquireixSEQUENTIAL]);
4756 ffeste_subr_file_ ("UNFORMATTED", &info->inquire_spec[FFESTP_inquireixUNFORMATTED]);
4757 ffeste_subr_file_ ("WRITE", &info->inquire_spec[FFESTP_inquireixWRITE]);
4758 fputs (")\n", dmpout);
4759 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4761 tree args;
4762 bool iostat;
4763 bool errl;
4765 ffeste_emit_line_note_ ();
4767 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4769 iostat = specified (FFESTP_inquireixIOSTAT);
4770 errl = specified (FFESTP_inquireixERR);
4772 #undef specified
4774 ffeste_start_stmt_ ();
4776 if (errl)
4778 ffeste_io_err_
4779 = ffeste_io_abort_
4780 = ffecom_lookup_label
4781 (info->inquire_spec[FFESTP_inquireixERR].u.label);
4782 ffeste_io_abort_is_temp_ = FALSE;
4784 else
4786 ffeste_io_err_ = NULL_TREE;
4788 if ((ffeste_io_abort_is_temp_ = iostat))
4789 ffeste_io_abort_ = ffecom_temp_label ();
4790 else
4791 ffeste_io_abort_ = NULL_TREE;
4794 if (iostat)
4796 /* Have IOSTAT= specification. */
4798 ffeste_io_iostat_is_temp_ = FALSE;
4799 ffeste_io_iostat_ = ffecom_expr
4800 (info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4802 else if (ffeste_io_abort_ != NULL_TREE)
4804 /* Have no IOSTAT= but have ERR=. */
4806 ffeste_io_iostat_is_temp_ = TRUE;
4807 ffeste_io_iostat_
4808 = ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
4809 FFETARGET_charactersizeNONE, -1);
4811 else
4813 /* No IOSTAT= or ERR= specification. */
4815 ffeste_io_iostat_is_temp_ = FALSE;
4816 ffeste_io_iostat_ = NULL_TREE;
4819 /* Now prescan, then convert, all the arguments. */
4821 args
4822 = ffeste_io_inlist_ (errl || iostat,
4823 &info->inquire_spec[FFESTP_inquireixUNIT],
4824 &info->inquire_spec[FFESTP_inquireixFILE],
4825 &info->inquire_spec[FFESTP_inquireixEXIST],
4826 &info->inquire_spec[FFESTP_inquireixOPENED],
4827 &info->inquire_spec[FFESTP_inquireixNUMBER],
4828 &info->inquire_spec[FFESTP_inquireixNAMED],
4829 &info->inquire_spec[FFESTP_inquireixNAME],
4830 &info->inquire_spec[FFESTP_inquireixACCESS],
4831 &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4832 &info->inquire_spec[FFESTP_inquireixDIRECT],
4833 &info->inquire_spec[FFESTP_inquireixFORM],
4834 &info->inquire_spec[FFESTP_inquireixFORMATTED],
4835 &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4836 &info->inquire_spec[FFESTP_inquireixRECL],
4837 &info->inquire_spec[FFESTP_inquireixNEXTREC],
4838 &info->inquire_spec[FFESTP_inquireixBLANK]);
4840 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4841 label, since we're gonna fall through to there anyway. */
4843 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
4844 ! ffeste_io_abort_is_temp_);
4846 /* If we've got a temp label, generate its code here. */
4848 if (ffeste_io_abort_is_temp_)
4850 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4851 emit_nop ();
4852 expand_label (ffeste_io_abort_);
4854 assert (ffeste_io_err_ == NULL_TREE);
4857 ffeste_end_stmt_ ();
4859 #else
4860 #error
4861 #endif
4864 /* INQUIRE(IOLENGTH=expr) statement -- start. */
4866 void
4867 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4869 ffeste_check_start_ ();
4871 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4872 fputs ("+ INQUIRE (", dmpout);
4873 ffeste_subr_file_ ("IOLENGTH", &info->inquire_spec[FFESTP_inquireixIOLENGTH]);
4874 fputs (") ", dmpout);
4875 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4876 assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4878 ffeste_emit_line_note_ ();
4879 #else
4880 #error
4881 #endif
4884 /* INQUIRE(IOLENGTH=expr) statement -- I/O item. */
4886 void
4887 ffeste_R923B_item (ffebld expr UNUSED)
4889 ffeste_check_item_ ();
4891 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4892 ffebld_dump (expr);
4893 fputc (',', dmpout);
4894 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4895 #else
4896 #error
4897 #endif
4900 /* INQUIRE(IOLENGTH=expr) statement -- end. */
4902 void
4903 ffeste_R923B_finish ()
4905 ffeste_check_finish_ ();
4907 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4908 fputc ('\n', dmpout);
4909 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4910 #else
4911 #error
4912 #endif
4915 /* ffeste_R1001 -- FORMAT statement
4917 ffeste_R1001(format_list); */
4919 void
4920 ffeste_R1001 (ffests s)
4922 ffeste_check_simple_ ();
4924 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4925 fprintf (dmpout, "$ FORMAT %.*s\n", (int) ffests_length (s), ffests_text (s));
4926 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4928 tree t;
4929 tree ttype;
4930 tree maxindex;
4931 tree var;
4933 assert (ffeste_label_formatdef_ != NULL);
4935 ffeste_emit_line_note_ ();
4937 t = build_string (ffests_length (s), ffests_text (s));
4939 TREE_TYPE (t)
4940 = build_type_variant (build_array_type
4941 (char_type_node,
4942 build_range_type (integer_type_node,
4943 integer_one_node,
4944 build_int_2 (ffests_length (s),
4945 0))),
4946 1, 0);
4947 TREE_CONSTANT (t) = 1;
4948 TREE_STATIC (t) = 1;
4950 var = ffecom_lookup_label (ffeste_label_formatdef_);
4951 if ((var != NULL_TREE)
4952 && (TREE_CODE (var) == VAR_DECL))
4954 DECL_INITIAL (var) = t;
4955 maxindex = build_int_2 (ffests_length (s) - 1, 0);
4956 ttype = TREE_TYPE (var);
4957 TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
4958 integer_zero_node,
4959 maxindex);
4960 if (!TREE_TYPE (maxindex))
4961 TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
4962 layout_type (ttype);
4963 rest_of_decl_compilation (var, NULL, 1, 0);
4964 expand_decl (var);
4965 expand_decl_init (var);
4968 ffeste_label_formatdef_ = NULL;
4970 #else
4971 #error
4972 #endif
4975 /* END PROGRAM. */
4977 void
4978 ffeste_R1103 ()
4980 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4981 fputs ("+ END_PROGRAM\n", dmpout);
4982 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4983 #else
4984 #error
4985 #endif
4988 /* END BLOCK DATA. */
4990 void
4991 ffeste_R1112 ()
4993 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4994 fputs ("* END_BLOCK_DATA\n", dmpout);
4995 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4996 #else
4997 #error
4998 #endif
5001 /* CALL statement. */
5003 void
5004 ffeste_R1212 (ffebld expr)
5006 ffeste_check_simple_ ();
5008 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5009 fputs ("+ CALL ", dmpout);
5010 ffebld_dump (expr);
5011 fputc ('\n', dmpout);
5012 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5014 ffebld args = ffebld_right (expr);
5015 ffebld arg;
5016 ffebld labels = NULL; /* First in list of LABTERs. */
5017 ffebld prevlabels = NULL;
5018 ffebld prevargs = NULL;
5020 ffeste_emit_line_note_ ();
5022 /* Here we split the list at ffebld_right(expr) into two lists: one at
5023 ffebld_right(expr) consisting of all items that are not LABTERs, the
5024 other at labels consisting of all items that are LABTERs. Then, if
5025 the latter list is NULL, we have an ordinary call, else we have a call
5026 with alternate returns. */
5028 for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
5030 if (((arg = ffebld_head (args)) == NULL)
5031 || (ffebld_op (arg) != FFEBLD_opLABTER))
5033 if (prevargs == NULL)
5035 prevargs = args;
5036 ffebld_set_right (expr, args);
5038 else
5040 ffebld_set_trail (prevargs, args);
5041 prevargs = args;
5044 else
5046 if (prevlabels == NULL)
5048 prevlabels = labels = args;
5050 else
5052 ffebld_set_trail (prevlabels, args);
5053 prevlabels = args;
5057 if (prevlabels == NULL)
5058 labels = NULL;
5059 else
5060 ffebld_set_trail (prevlabels, NULL);
5061 if (prevargs == NULL)
5062 ffebld_set_right (expr, NULL);
5063 else
5064 ffebld_set_trail (prevargs, NULL);
5066 ffeste_start_stmt_ ();
5068 /* No temporaries are actually needed at this level, but we go
5069 through the motions anyway, just to be sure in case they do
5070 get made. Temporaries needed for arguments should be in the
5071 scopes of inner blocks, and if clean-up actions are supported,
5072 such as CALL-ing an intrinsic that writes to an argument of one
5073 type when a variable of a different type is provided (requiring
5074 assignment to the variable from a temporary after the library
5075 routine returns), the clean-up must be done by the expression
5076 evaluator, generally, to handle alternate returns (which we hope
5077 won't ever be supported by intrinsics, but might be a similar
5078 issue, such as CALL-ing an F90-style subroutine with an INTERFACE
5079 block). That implies the expression evaluator will have to
5080 recognize the need for its own temporary anyway, meaning it'll
5081 construct a block within the one constructed here. */
5083 ffecom_prepare_expr (expr);
5085 ffecom_prepare_end ();
5087 if (labels == NULL)
5088 expand_expr_stmt (ffecom_expr (expr));
5089 else
5091 tree texpr;
5092 tree value;
5093 tree tlabel;
5094 int caseno;
5095 int pushok;
5096 tree duplicate;
5097 ffebld label;
5099 texpr = ffecom_expr (expr);
5100 expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
5102 for (caseno = 1, label = labels;
5103 label != NULL;
5104 ++caseno, label = ffebld_trail (label))
5106 value = build_int_2 (caseno, 0);
5107 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
5109 pushok = pushcase (value, convert, tlabel, &duplicate);
5110 assert (pushok == 0);
5112 tlabel
5113 = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
5114 if ((tlabel == NULL_TREE)
5115 || (TREE_CODE (tlabel) == ERROR_MARK))
5116 continue;
5117 TREE_USED (tlabel) = 1;
5118 expand_goto (tlabel);
5121 expand_end_case (texpr);
5124 ffeste_end_stmt_ ();
5126 #else
5127 #error
5128 #endif
5131 /* END FUNCTION. */
5133 void
5134 ffeste_R1221 ()
5136 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5137 fputs ("+ END_FUNCTION\n", dmpout);
5138 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5139 #else
5140 #error
5141 #endif
5144 /* END SUBROUTINE. */
5146 void
5147 ffeste_R1225 ()
5149 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5150 fprintf (dmpout, "+ END_SUBROUTINE\n");
5151 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5152 #else
5153 #error
5154 #endif
5157 /* ENTRY statement. */
5159 void
5160 ffeste_R1226 (ffesymbol entry)
5162 ffeste_check_simple_ ();
5164 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5165 fprintf (dmpout, "+ ENTRY %s", ffesymbol_text (entry));
5166 if (ffesymbol_dummyargs (entry) != NULL)
5168 ffebld argh;
5170 fputc ('(', dmpout);
5171 for (argh = ffesymbol_dummyargs (entry);
5172 argh != NULL;
5173 argh = ffebld_trail (argh))
5175 assert (ffebld_head (argh) != NULL);
5176 switch (ffebld_op (ffebld_head (argh)))
5178 case FFEBLD_opSYMTER:
5179 fputs (ffesymbol_text (ffebld_symter (ffebld_head (argh))),
5180 dmpout);
5181 break;
5183 case FFEBLD_opSTAR:
5184 fputc ('*', dmpout);
5185 break;
5187 default:
5188 fputc ('?', dmpout);
5189 ffebld_dump (ffebld_head (argh));
5190 fputc ('?', dmpout);
5191 break;
5193 if (ffebld_trail (argh) != NULL)
5194 fputc (',', dmpout);
5196 fputc (')', dmpout);
5198 fputc ('\n', dmpout);
5199 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5201 tree label = ffesymbol_hook (entry).length_tree;
5203 ffeste_emit_line_note_ ();
5205 if (label == error_mark_node)
5206 return;
5208 DECL_INITIAL (label) = error_mark_node;
5209 emit_nop ();
5210 expand_label (label);
5212 #else
5213 #error
5214 #endif
5217 /* RETURN statement. */
5219 void
5220 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
5222 ffeste_check_simple_ ();
5224 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5225 if (expr == NULL)
5227 fputs ("+ RETURN\n", dmpout);
5229 else
5231 fputs ("+ RETURN_alternate ", dmpout);
5232 ffebld_dump (expr);
5233 fputc ('\n', dmpout);
5235 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5237 tree rtn;
5239 ffeste_emit_line_note_ ();
5241 ffeste_start_stmt_ ();
5243 ffecom_prepare_return_expr (expr);
5245 ffecom_prepare_end ();
5247 rtn = ffecom_return_expr (expr);
5249 if ((rtn == NULL_TREE)
5250 || (rtn == error_mark_node))
5251 expand_null_return ();
5252 else
5254 tree result = DECL_RESULT (current_function_decl);
5256 if ((result != error_mark_node)
5257 && (TREE_TYPE (result) != error_mark_node))
5258 expand_return (ffecom_modify (NULL_TREE,
5259 result,
5260 convert (TREE_TYPE (result),
5261 rtn)));
5262 else
5263 expand_null_return ();
5266 ffeste_end_stmt_ ();
5268 #else
5269 #error
5270 #endif
5273 /* REWRITE statement -- start. */
5275 #if FFESTR_VXT
5276 void
5277 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
5279 ffeste_check_start_ ();
5281 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5282 switch (format)
5284 case FFESTV_formatNONE:
5285 fputs ("+ REWRITE_uf (", dmpout);
5286 break;
5288 case FFESTV_formatLABEL:
5289 case FFESTV_formatCHAREXPR:
5290 case FFESTV_formatINTEXPR:
5291 fputs ("+ REWRITE_fm (", dmpout);
5292 break;
5294 default:
5295 assert ("Unexpected kind of format item in V018 REWRITE" == NULL);
5297 ffeste_subr_file_ ("UNIT", &info->rewrite_spec[FFESTP_rewriteixUNIT]);
5298 ffeste_subr_file_ ("FMT", &info->rewrite_spec[FFESTP_rewriteixFMT]);
5299 ffeste_subr_file_ ("ERR", &info->rewrite_spec[FFESTP_rewriteixERR]);
5300 ffeste_subr_file_ ("IOSTAT", &info->rewrite_spec[FFESTP_rewriteixIOSTAT]);
5301 fputs (") ", dmpout);
5302 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5303 #else
5304 #error
5305 #endif
5308 /* REWRITE statement -- I/O item. */
5310 void
5311 ffeste_V018_item (ffebld expr)
5313 ffeste_check_item_ ();
5315 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5316 ffebld_dump (expr);
5317 fputc (',', dmpout);
5318 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5319 #else
5320 #error
5321 #endif
5324 /* REWRITE statement -- end. */
5326 void
5327 ffeste_V018_finish ()
5329 ffeste_check_finish_ ();
5331 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5332 fputc ('\n', dmpout);
5333 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5334 #else
5335 #error
5336 #endif
5339 /* ACCEPT statement -- start. */
5341 void
5342 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
5344 ffeste_check_start_ ();
5346 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5347 switch (format)
5349 case FFESTV_formatLABEL:
5350 case FFESTV_formatCHAREXPR:
5351 case FFESTV_formatINTEXPR:
5352 fputs ("+ ACCEPT_fm ", dmpout);
5353 break;
5355 case FFESTV_formatASTERISK:
5356 fputs ("+ ACCEPT_ls ", dmpout);
5357 break;
5359 case FFESTV_formatNAMELIST:
5360 fputs ("+ ACCEPT_nl ", dmpout);
5361 break;
5363 default:
5364 assert ("Unexpected kind of format item in V019 ACCEPT" == NULL);
5366 ffeste_subr_file_ ("FORMAT", &info->accept_spec[FFESTP_acceptixFORMAT]);
5367 fputc (' ', dmpout);
5368 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5369 #else
5370 #error
5371 #endif
5374 /* ACCEPT statement -- I/O item. */
5376 void
5377 ffeste_V019_item (ffebld expr)
5379 ffeste_check_item_ ();
5381 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5382 ffebld_dump (expr);
5383 fputc (',', dmpout);
5384 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5385 #else
5386 #error
5387 #endif
5390 /* ACCEPT statement -- end. */
5392 void
5393 ffeste_V019_finish ()
5395 ffeste_check_finish_ ();
5397 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5398 fputc ('\n', dmpout);
5399 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5400 #else
5401 #error
5402 #endif
5405 #endif
5406 /* TYPE statement -- start. */
5408 void
5409 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
5410 ffestvFormat format UNUSED)
5412 ffeste_check_start_ ();
5414 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5415 switch (format)
5417 case FFESTV_formatLABEL:
5418 case FFESTV_formatCHAREXPR:
5419 case FFESTV_formatINTEXPR:
5420 fputs ("+ TYPE_fm ", dmpout);
5421 break;
5423 case FFESTV_formatASTERISK:
5424 fputs ("+ TYPE_ls ", dmpout);
5425 break;
5427 case FFESTV_formatNAMELIST:
5428 fputs ("* TYPE_nl ", dmpout);
5429 break;
5431 default:
5432 assert ("Unexpected kind of format item in V020 TYPE" == NULL);
5434 ffeste_subr_file_ ("FORMAT", &info->type_spec[FFESTP_typeixFORMAT]);
5435 fputc (' ', dmpout);
5436 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5437 #else
5438 #error
5439 #endif
5442 /* TYPE statement -- I/O item. */
5444 void
5445 ffeste_V020_item (ffebld expr UNUSED)
5447 ffeste_check_item_ ();
5449 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5450 ffebld_dump (expr);
5451 fputc (',', dmpout);
5452 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5453 #else
5454 #error
5455 #endif
5458 /* TYPE statement -- end. */
5460 void
5461 ffeste_V020_finish ()
5463 ffeste_check_finish_ ();
5465 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5466 fputc ('\n', dmpout);
5467 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5468 #else
5469 #error
5470 #endif
5473 /* DELETE statement. */
5475 #if FFESTR_VXT
5476 void
5477 ffeste_V021 (ffestpDeleteStmt *info)
5479 ffeste_check_simple_ ();
5481 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5482 fputs ("+ DELETE (", dmpout);
5483 ffeste_subr_file_ ("UNIT", &info->delete_spec[FFESTP_deleteixUNIT]);
5484 ffeste_subr_file_ ("REC", &info->delete_spec[FFESTP_deleteixREC]);
5485 ffeste_subr_file_ ("ERR", &info->delete_spec[FFESTP_deleteixERR]);
5486 ffeste_subr_file_ ("IOSTAT", &info->delete_spec[FFESTP_deleteixIOSTAT]);
5487 fputs (")\n", dmpout);
5488 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5489 #else
5490 #error
5491 #endif
5494 /* UNLOCK statement. */
5496 void
5497 ffeste_V022 (ffestpBeruStmt *info)
5499 ffeste_check_simple_ ();
5501 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5502 fputs ("+ UNLOCK (", dmpout);
5503 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
5504 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
5505 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
5506 fputs (")\n", dmpout);
5507 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5508 #else
5509 #error
5510 #endif
5513 /* ENCODE statement -- start. */
5515 void
5516 ffeste_V023_start (ffestpVxtcodeStmt *info)
5518 ffeste_check_start_ ();
5520 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5521 fputs ("+ ENCODE (", dmpout);
5522 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5523 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5524 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5525 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5526 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5527 fputs (") ", dmpout);
5528 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5529 #else
5530 #error
5531 #endif
5534 /* ENCODE statement -- I/O item. */
5536 void
5537 ffeste_V023_item (ffebld expr)
5539 ffeste_check_item_ ();
5541 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5542 ffebld_dump (expr);
5543 fputc (',', dmpout);
5544 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5545 #else
5546 #error
5547 #endif
5550 /* ENCODE statement -- end. */
5552 void
5553 ffeste_V023_finish ()
5555 ffeste_check_finish_ ();
5557 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5558 fputc ('\n', dmpout);
5559 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5560 #else
5561 #error
5562 #endif
5565 /* DECODE statement -- start. */
5567 void
5568 ffeste_V024_start (ffestpVxtcodeStmt *info)
5570 ffeste_check_start_ ();
5572 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5573 fputs ("+ DECODE (", dmpout);
5574 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5575 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5576 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5577 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5578 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5579 fputs (") ", dmpout);
5580 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5581 #else
5582 #error
5583 #endif
5586 /* DECODE statement -- I/O item. */
5588 void
5589 ffeste_V024_item (ffebld expr)
5591 ffeste_check_item_ ();
5593 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5594 ffebld_dump (expr);
5595 fputc (',', dmpout);
5596 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5597 #else
5598 #error
5599 #endif
5602 /* DECODE statement -- end. */
5604 void
5605 ffeste_V024_finish ()
5607 ffeste_check_finish_ ();
5609 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5610 fputc ('\n', dmpout);
5611 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5612 #else
5613 #error
5614 #endif
5617 /* DEFINEFILE statement -- start. */
5619 void
5620 ffeste_V025_start ()
5622 ffeste_check_start_ ();
5624 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5625 fputs ("+ DEFINE_FILE ", dmpout);
5626 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5627 #else
5628 #error
5629 #endif
5632 /* DEFINE FILE statement -- item. */
5634 void
5635 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
5637 ffeste_check_item_ ();
5639 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5640 ffebld_dump (u);
5641 fputc ('(', dmpout);
5642 ffebld_dump (m);
5643 fputc (',', dmpout);
5644 ffebld_dump (n);
5645 fputs (",U,", dmpout);
5646 ffebld_dump (asv);
5647 fputs ("),", dmpout);
5648 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5649 #else
5650 #error
5651 #endif
5654 /* DEFINE FILE statement -- end. */
5656 void
5657 ffeste_V025_finish ()
5659 ffeste_check_finish_ ();
5661 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5662 fputc ('\n', dmpout);
5663 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5664 #else
5665 #error
5666 #endif
5669 /* FIND statement. */
5671 void
5672 ffeste_V026 (ffestpFindStmt *info)
5674 ffeste_check_simple_ ();
5676 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5677 fputs ("+ FIND (", dmpout);
5678 ffeste_subr_file_ ("UNIT", &info->find_spec[FFESTP_findixUNIT]);
5679 ffeste_subr_file_ ("REC", &info->find_spec[FFESTP_findixREC]);
5680 ffeste_subr_file_ ("ERR", &info->find_spec[FFESTP_findixERR]);
5681 ffeste_subr_file_ ("IOSTAT", &info->find_spec[FFESTP_findixIOSTAT]);
5682 fputs (")\n", dmpout);
5683 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5684 #else
5685 #error
5686 #endif
5689 #endif
5691 #ifdef ENABLE_CHECKING
5692 void
5693 ffeste_terminate_2 (void)
5695 assert (! ffeste_top_block_);
5697 #endif