Undo June 11th change
[official-gcc.git] / gcc / f / ste.c
blobaddafc4083d0443352913b924145980032affcc8
1 /* ste.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.org).
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 /* As of 0.5.4, any statement that calls on ffecom to transform an
32 expression might need to be wrapped in ffecom_push_calltemps ()
33 and ffecom_pop_calltemps () as are some other cases. That is
34 the case when the transformation might involve generation of
35 a temporary that must be auto-popped, the specific case being
36 when a COMPLEX operation requiring a call to libf2c being
37 generated, whereby a temp is needed to hold the result since
38 libf2c doesn't return COMPLEX results directly. Cases where it
39 is known that ffecom_expr () won't need to do this, such as
40 the CALL statement (where it's the transformation of the
41 call expr itself that does the wrapping), don't need to bother
42 with this wrapping. Forgetting to do the wrapping currently
43 means a crash at an assertion when the wrapping would be helpful
44 to keep temporaries from being wasted -- see ffecom_push_tempvar. */
46 /* Include files. */
48 #include "proj.h"
50 #if FFECOM_targetCURRENT == FFECOM_targetGCC
51 #include "config.j"
52 #include "rtl.j"
53 #endif
55 #include "ste.h"
56 #include "bld.h"
57 #include "com.h"
58 #include "expr.h"
59 #include "lab.h"
60 #include "lex.h"
61 #include "sta.h"
62 #include "stp.h"
63 #include "str.h"
64 #include "sts.h"
65 #include "stt.h"
66 #include "stv.h"
67 #include "stw.h"
68 #include "symbol.h"
70 /* Externals defined here. */
73 /* Simple definitions and enumerations. */
75 typedef enum
77 FFESTE_stateletSIMPLE_, /* Expecting simple/start. */
78 FFESTE_stateletATTRIB_, /* Expecting attrib/item/itemstart. */
79 FFESTE_stateletITEM_, /* Expecting item/itemstart/finish. */
80 FFESTE_stateletITEMVALS_, /* Expecting itemvalue/itemendvals. */
81 FFESTE_
82 } ffesteStatelet_;
84 /* Internal typedefs. */
87 /* Private include files. */
90 /* Internal structure definitions. */
93 /* Static objects accessed by functions in this module. */
95 static ffesteStatelet_ ffeste_statelet_ = FFESTE_stateletSIMPLE_;
96 #if FFECOM_targetCURRENT == FFECOM_targetGCC
97 static ffelab ffeste_label_formatdef_ = NULL;
98 static tree (*ffeste_io_driver_) (ffebld expr); /* do?io. */
99 static ffecomGfrt ffeste_io_endgfrt_; /* end function to call. */
100 static tree ffeste_io_abort_; /* abort-io label or NULL_TREE. */
101 static bool ffeste_io_abort_is_temp_; /* abort-io label is a temp. */
102 static tree ffeste_io_end_; /* END= label or NULL_TREE. */
103 static tree ffeste_io_err_; /* ERR= label or NULL_TREE. */
104 static tree ffeste_io_iostat_; /* IOSTAT= var or NULL_TREE. */
105 static bool ffeste_io_iostat_is_temp_; /* IOSTAT= var is a temp. */
106 #endif
108 /* Static functions (internal). */
110 #if FFECOM_targetCURRENT == FFECOM_targetGCC
111 static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
112 tree *xitersvar, ffebld var,
113 ffebld start, ffelexToken start_token,
114 ffebld end, ffelexToken end_token,
115 ffebld incr, ffelexToken incr_token,
116 char *msg);
117 static void ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar);
118 static void ffeste_io_call_ (tree call, bool do_check);
119 static tree ffeste_io_dofio_ (ffebld expr);
120 static tree ffeste_io_dolio_ (ffebld expr);
121 static tree ffeste_io_douio_ (ffebld expr);
122 static tree ffeste_io_ialist_ (bool have_err, ffestvUnit unit,
123 ffebld unit_expr, int unit_dflt);
124 static tree ffeste_io_cilist_ (bool have_err, ffestvUnit unit,
125 ffebld unit_expr, int unit_dflt,
126 bool have_end, ffestvFormat format,
127 ffestpFile *format_spec, bool rec,
128 ffebld rec_expr);
129 static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
130 ffestpFile *stat_spec);
131 static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
132 bool have_end, ffestvFormat format,
133 ffestpFile *format_spec);
134 static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
135 static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
136 ffestpFile *file_spec,
137 ffestpFile *stat_spec,
138 ffestpFile *access_spec,
139 ffestpFile *form_spec,
140 ffestpFile *recl_spec,
141 ffestpFile *blank_spec);
142 static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
143 #elif FFECOM_targetCURRENT == FFECOM_targetFFE
144 static void ffeste_subr_file_ (char *kw, ffestpFile *spec);
145 #else
146 #error
147 #endif
149 /* Internal macros. */
151 #if FFECOM_targetCURRENT == FFECOM_targetGCC
152 #define ffeste_emit_line_note_() \
153 emit_line_note (input_filename, lineno)
154 #endif
155 #define ffeste_check_simple_() \
156 assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_)
157 #define ffeste_check_start_() \
158 assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_); \
159 ffeste_statelet_ = FFESTE_stateletATTRIB_
160 #define ffeste_check_attrib_() \
161 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_)
162 #define ffeste_check_item_() \
163 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
164 || ffeste_statelet_ == FFESTE_stateletITEM_); \
165 ffeste_statelet_ = FFESTE_stateletITEM_
166 #define ffeste_check_item_startvals_() \
167 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
168 || ffeste_statelet_ == FFESTE_stateletITEM_); \
169 ffeste_statelet_ = FFESTE_stateletITEMVALS_
170 #define ffeste_check_item_value_() \
171 assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_)
172 #define ffeste_check_item_endvals_() \
173 assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_); \
174 ffeste_statelet_ = FFESTE_stateletITEM_
175 #define ffeste_check_finish_() \
176 assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
177 || ffeste_statelet_ == FFESTE_stateletITEM_); \
178 ffeste_statelet_ = FFESTE_stateletSIMPLE_
180 #define ffeste_f2c_charnolenspec_(Spec,Exp,Init) \
181 do \
183 if (Spec->kw_or_val_present) \
184 Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&ignore); \
185 else \
186 Exp = null_pointer_node; \
187 if (TREE_CONSTANT(Exp)) \
189 Init = Exp; \
190 Exp = NULL_TREE; \
192 else \
194 Init = null_pointer_node; \
195 constantp = FALSE; \
197 } while(0)
199 #define ffeste_f2c_charspec_(Spec,Exp,Init,Lenexp,Leninit) \
200 do \
202 if (Spec->kw_or_val_present) \
203 Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&Lenexp); \
204 else \
206 Exp = null_pointer_node; \
207 Lenexp = ffecom_f2c_ftnlen_zero_node; \
209 if (TREE_CONSTANT(Exp)) \
211 Init = Exp; \
212 Exp = NULL_TREE; \
214 else \
216 Init = null_pointer_node; \
217 constantp = FALSE; \
219 if ((Lenexp != NULL_TREE) && TREE_CONSTANT(Lenexp)) \
221 Leninit = Lenexp; \
222 Lenexp = NULL_TREE; \
224 else \
226 Leninit = ffecom_f2c_ftnlen_zero_node; \
227 constantp = FALSE; \
229 } while(0)
231 #define ffeste_f2c_exp_(Field,Exp) \
232 do \
234 if (Exp != NULL_TREE) \
236 Exp = ffecom_modify(void_type_node,ffecom_2(COMPONENT_REF, \
237 TREE_TYPE(Field),t,Field),Exp); \
238 expand_expr_stmt(Exp); \
240 } while(0)
242 #define ffeste_f2c_init_(Init) \
243 do \
245 TREE_CHAIN(initn) = build_tree_list((field = TREE_CHAIN(field)),Init); \
246 initn = TREE_CHAIN(initn); \
247 } while(0)
249 #define ffeste_f2c_flagspec_(Flag,Init) \
250 do { Init = convert (ffecom_f2c_flag_type_node, \
251 Flag ? integer_one_node : integer_zero_node); } \
252 while(0)
254 #define ffeste_f2c_intspec_(Spec,Exp,Init) \
255 do \
257 if (Spec->kw_or_val_present) \
258 Exp = ffecom_expr(Spec->u.expr); \
259 else \
260 Exp = ffecom_integer_zero_node; \
261 if (TREE_CONSTANT(Exp)) \
263 Init = Exp; \
264 Exp = NULL_TREE; \
266 else \
268 Init = ffecom_integer_zero_node; \
269 constantp = FALSE; \
271 } while(0)
273 #define ffeste_f2c_ptrtointspec_(Spec,Exp,Init) \
274 do \
276 if (Spec->kw_or_val_present) \
277 Exp = ffecom_ptr_to_expr(Spec->u.expr); \
278 else \
279 Exp = null_pointer_node; \
280 if (TREE_CONSTANT(Exp)) \
282 Init = Exp; \
283 Exp = NULL_TREE; \
285 else \
287 Init = null_pointer_node; \
288 constantp = FALSE; \
290 } while(0)
293 /* Begin an iterative DO loop. Pass the block to start if applicable.
295 NOTE: Does _two_ push_momentary () calls, which the caller must
296 undo (by calling ffeste_end_iterdo_). */
298 #if FFECOM_targetCURRENT == FFECOM_targetGCC
299 static void
300 ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
301 tree *xitersvar, ffebld var,
302 ffebld start, ffelexToken start_token,
303 ffebld end, ffelexToken end_token,
304 ffebld incr, ffelexToken incr_token,
305 char *msg)
307 tree tvar;
308 tree expr;
309 tree tstart;
310 tree tend;
311 tree tincr;
312 tree tincr_saved;
313 tree niters;
315 push_momentary (); /* Want to save these throughout the loop. */
317 tvar = ffecom_expr_rw (var);
318 tincr = ffecom_expr (incr);
320 /* Check whether incr is known to be zero, complain and fix. */
322 if (integer_zerop (tincr) || real_zerop (tincr))
324 ffebad_start (FFEBAD_DO_STEP_ZERO);
325 ffebad_here (0, ffelex_token_where_line (incr_token),
326 ffelex_token_where_column (incr_token));
327 ffebad_string (msg);
328 ffebad_finish ();
329 tincr = convert (TREE_TYPE (tvar), integer_one_node);
332 tincr_saved = ffecom_save_tree (tincr);
334 push_momentary (); /* Want to discard the rest after the loop. */
336 tstart = ffecom_expr (start);
337 tend = ffecom_expr (end);
339 { /* For warnings only, nothing else
340 happens here. */
341 tree try;
343 if (!ffe_is_onetrip ())
345 try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
346 tend,
347 tstart);
349 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
350 try,
351 tincr);
353 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
354 try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
355 tincr);
356 else
357 try = convert (integer_type_node,
358 ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
359 try,
360 tincr));
362 /* Warn if loop never executed, since we've done the evaluation
363 of the unofficial iteration count already. */
365 try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
366 try,
367 convert (TREE_TYPE (tvar),
368 integer_zero_node)));
370 if (integer_onep (try))
372 ffebad_start (FFEBAD_DO_NULL);
373 ffebad_here (0, ffelex_token_where_line (start_token),
374 ffelex_token_where_column (start_token));
375 ffebad_string (msg);
376 ffebad_finish ();
380 /* Warn if end plus incr would overflow. */
382 try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
383 tend,
384 tincr);
386 if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
387 && TREE_CONSTANT_OVERFLOW (try))
389 ffebad_start (FFEBAD_DO_END_OVERFLOW);
390 ffebad_here (0, ffelex_token_where_line (end_token),
391 ffelex_token_where_column (end_token));
392 ffebad_string (msg);
393 ffebad_finish ();
397 /* Do the initial assignment into the DO var. */
399 tstart = ffecom_save_tree (tstart);
401 expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
402 tend,
403 tstart);
405 if (!ffe_is_onetrip ())
407 expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
408 expr,
409 convert (TREE_TYPE (expr), tincr_saved));
412 if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
413 expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
414 expr,
415 tincr_saved);
416 else
417 expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
418 expr,
419 tincr_saved);
421 #if 1 /* New, F90-approved approach: convert to default INTEGER. */
422 if (TREE_TYPE (tvar) != error_mark_node)
423 expr = convert (ffecom_integer_type_node, expr);
424 #else /* Old approach; convert to INTEGER unless that's a narrowing. */
425 if ((TREE_TYPE (tvar) != error_mark_node)
426 && ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
427 || ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
428 && ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
429 != INTEGER_CST)
430 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
431 <= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
432 /* Convert unless promoting INTEGER type of any kind downward to
433 default INTEGER; else leave as, say, INTEGER*8 (long long int). */
434 expr = convert (ffecom_integer_type_node, expr);
435 #endif
437 niters = ffecom_push_tempvar (TREE_TYPE (expr),
438 FFETARGET_charactersizeNONE, -1, FALSE);
439 expr = ffecom_modify (void_type_node, niters, expr);
440 expand_expr_stmt (expr);
442 expr = ffecom_modify (void_type_node, tvar, tstart);
443 expand_expr_stmt (expr);
445 if (block == NULL)
446 expand_start_loop_continue_elsewhere (0);
447 else
448 ffestw_set_do_hook (block,
449 expand_start_loop_continue_elsewhere (1));
451 if (!ffe_is_onetrip ())
453 expr = ffecom_truth_value
454 (ffecom_2 (GE_EXPR, integer_type_node,
455 ffecom_2 (PREDECREMENT_EXPR,
456 TREE_TYPE (niters),
457 niters,
458 convert (TREE_TYPE (niters),
459 ffecom_integer_one_node)),
460 convert (TREE_TYPE (niters),
461 ffecom_integer_zero_node)));
463 expand_exit_loop_if_false (0, expr);
466 clear_momentary (); /* Discard the above now that we're done with
467 DO stmt. */
469 if (block == NULL)
471 *xtvar = tvar;
472 *xtincr = tincr_saved;
473 *xitersvar = niters;
475 else
477 ffestw_set_do_tvar (block, tvar);
478 ffestw_set_do_incr_saved (block, tincr_saved);
479 ffestw_set_do_count_var (block, niters);
483 #endif
485 /* End an iterative DO loop. Pass the same iteration variable and increment
486 value trees that were generated in the paired _begin_ call. */
488 #if FFECOM_targetCURRENT == FFECOM_targetGCC
489 static void
490 ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar)
492 tree expr;
493 tree niters = itersvar;
495 expand_loop_continue_here ();
497 if (ffe_is_onetrip ())
499 expr = ffecom_truth_value
500 (ffecom_2 (GE_EXPR, integer_type_node,
501 ffecom_2 (PREDECREMENT_EXPR,
502 TREE_TYPE (niters),
503 niters,
504 convert (TREE_TYPE (niters),
505 ffecom_integer_one_node)),
506 convert (TREE_TYPE (niters),
507 ffecom_integer_zero_node)));
509 expand_exit_loop_if_false (0, expr);
512 expr = ffecom_modify (void_type_node, tvar,
513 ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
514 tvar,
515 tincr));
516 expand_expr_stmt (expr);
517 expand_end_loop ();
519 ffecom_pop_tempvar (itersvar); /* Free #iters var. */
521 clear_momentary ();
522 pop_momentary (); /* Lose the stuff we just built. */
524 clear_momentary ();
525 pop_momentary (); /* Lose the tvar and incr_saved trees. */
528 #endif
529 /* ffeste_io_call_ -- Generate call to run-time I/O routine
531 tree callexpr = build(CALL_EXPR,...);
532 ffeste_io_call_(callexpr,TRUE);
534 Sets TREE_SIDE_EFFECTS(callexpr) = 1. If ffeste_io_iostat_ is not
535 NULL_TREE, replaces callexpr with "iostat = callexpr;". Expands the
536 result. If ffeste_io_abort_ is not NULL_TREE and the second argument
537 is TRUE, generates "if (iostat != 0) goto ffeste_io_abort_;". */
539 #if FFECOM_targetCURRENT == FFECOM_targetGCC
540 static void
541 ffeste_io_call_ (tree call, bool do_check)
543 /* Generate the call and optional assignment into iostat var. */
545 TREE_SIDE_EFFECTS (call) = 1;
546 if (ffeste_io_iostat_ != NULL_TREE)
548 call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
549 ffeste_io_iostat_, call);
551 expand_expr_stmt (call);
553 if (!do_check
554 || (ffeste_io_abort_ == NULL_TREE)
555 || (TREE_CODE (ffeste_io_abort_) == ERROR_MARK))
556 return;
558 /* Generate optional test. */
560 expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
561 expand_goto (ffeste_io_abort_);
562 expand_end_cond ();
565 #endif
566 /* ffeste_io_dofio_ -- Generate call to do_fio for formatted I/O item
568 ffebld expr;
569 tree call;
570 call = ffeste_io_dofio_(expr);
572 Returns a tree for a CALL_EXPR to the do_fio function, which handles
573 a formatted I/O list item, along with the appropriate arguments for
574 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
575 for the CALL_EXPR, expand (emit) the expression, emit any assignment
576 of the result to an IOSTAT= variable, and emit any checking of the
577 result for errors. */
579 #if FFECOM_targetCURRENT == FFECOM_targetGCC
580 static tree
581 ffeste_io_dofio_ (ffebld expr)
583 tree num_elements;
584 tree variable;
585 tree size;
586 tree arglist;
587 ffeinfoBasictype bt;
588 ffeinfoKindtype kt;
589 bool is_complex;
591 bt = ffeinfo_basictype (ffebld_info (expr));
592 kt = ffeinfo_kindtype (ffebld_info (expr));
594 if ((bt == FFEINFO_basictypeANY)
595 || (kt == FFEINFO_kindtypeANY))
596 return error_mark_node;
598 if (bt == FFEINFO_basictypeCOMPLEX)
600 is_complex = TRUE;
601 bt = FFEINFO_basictypeREAL;
603 else
604 is_complex = FALSE;
606 ffecom_push_calltemps ();
608 variable = ffecom_arg_ptr_to_expr (expr, &size);
610 if ((variable == error_mark_node)
611 || (size == error_mark_node))
613 ffecom_pop_calltemps ();
614 return error_mark_node;
617 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
618 { /* "(ftnlen) sizeof(type)" */
619 size = size_binop (CEIL_DIV_EXPR,
620 TYPE_SIZE (ffecom_tree_type[bt][kt]),
621 size_int (TYPE_PRECISION (char_type_node)));
622 #if 0 /* Assume that while it is possible that char * is wider than
623 ftnlen, no object in Fortran space can get big enough for its
624 size to be wider than ftnlen. I really hope nobody wastes
625 time debugging a case where it can! */
626 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
627 >= TYPE_PRECISION (TREE_TYPE (size)));
628 #endif
629 size = convert (ffecom_f2c_ftnlen_type_node, size);
632 if ((ffeinfo_rank (ffebld_info (expr)) == 0)
633 || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
634 num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
635 : ffecom_f2c_ftnlen_one_node;
636 else
638 num_elements = size_binop (CEIL_DIV_EXPR,
639 TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
640 num_elements = size_binop (CEIL_DIV_EXPR,
641 num_elements,
642 size_int (TYPE_PRECISION
643 (char_type_node)));
644 num_elements = convert (ffecom_f2c_ftnlen_type_node,
645 num_elements);
648 num_elements
649 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
650 num_elements);
652 variable = convert (string_type_node, variable);
654 arglist = build_tree_list (NULL_TREE, num_elements);
655 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
656 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
658 ffecom_pop_calltemps ();
660 return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist);
663 #endif
664 /* ffeste_io_dolio_ -- Generate call to do_lio for list-directed I/O item
666 ffebld expr;
667 tree call;
668 call = ffeste_io_dolio_(expr);
670 Returns a tree for a CALL_EXPR to the do_lio function, which handles
671 a list-directed I/O list item, along with the appropriate arguments for
672 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
673 for the CALL_EXPR, expand (emit) the expression, emit any assignment
674 of the result to an IOSTAT= variable, and emit any checking of the
675 result for errors. */
677 #if FFECOM_targetCURRENT == FFECOM_targetGCC
678 static tree
679 ffeste_io_dolio_ (ffebld expr)
681 tree type_id;
682 tree num_elements;
683 tree variable;
684 tree size;
685 tree arglist;
686 ffeinfoBasictype bt;
687 ffeinfoKindtype kt;
688 int tc;
690 bt = ffeinfo_basictype (ffebld_info (expr));
691 kt = ffeinfo_kindtype (ffebld_info (expr));
693 if ((bt == FFEINFO_basictypeANY)
694 || (kt == FFEINFO_kindtypeANY))
695 return error_mark_node;
697 ffecom_push_calltemps ();
699 tc = ffecom_f2c_typecode (bt, kt);
700 assert (tc != -1);
701 type_id = build_int_2 (tc, 0);
703 type_id
704 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
705 convert (ffecom_f2c_ftnint_type_node,
706 type_id));
708 variable = ffecom_arg_ptr_to_expr (expr, &size);
710 if ((type_id == error_mark_node)
711 || (variable == error_mark_node)
712 || (size == error_mark_node))
714 ffecom_pop_calltemps ();
715 return error_mark_node;
718 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
719 { /* "(ftnlen) sizeof(type)" */
720 size = size_binop (CEIL_DIV_EXPR,
721 TYPE_SIZE (ffecom_tree_type[bt][kt]),
722 size_int (TYPE_PRECISION (char_type_node)));
723 #if 0 /* Assume that while it is possible that char * is wider than
724 ftnlen, no object in Fortran space can get big enough for its
725 size to be wider than ftnlen. I really hope nobody wastes
726 time debugging a case where it can! */
727 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
728 >= TYPE_PRECISION (TREE_TYPE (size)));
729 #endif
730 size = convert (ffecom_f2c_ftnlen_type_node, size);
733 if ((ffeinfo_rank (ffebld_info (expr)) == 0)
734 || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
735 num_elements = ffecom_integer_one_node;
736 else
738 num_elements = size_binop (CEIL_DIV_EXPR,
739 TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
740 num_elements = size_binop (CEIL_DIV_EXPR,
741 num_elements,
742 size_int (TYPE_PRECISION
743 (char_type_node)));
744 num_elements = convert (ffecom_f2c_ftnlen_type_node,
745 num_elements);
748 num_elements
749 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
750 num_elements);
752 variable = convert (string_type_node, variable);
754 arglist = build_tree_list (NULL_TREE, type_id);
755 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
756 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
757 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
758 = build_tree_list (NULL_TREE, size);
760 ffecom_pop_calltemps ();
762 return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist);
765 #endif
766 /* ffeste_io_douio_ -- Generate call to do_uio for unformatted I/O item
768 ffebld expr;
769 tree call;
770 call = ffeste_io_douio_(expr);
772 Returns a tree for a CALL_EXPR to the do_uio function, which handles
773 an unformatted I/O list item, along with the appropriate arguments for
774 the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
775 for the CALL_EXPR, expand (emit) the expression, emit any assignment
776 of the result to an IOSTAT= variable, and emit any checking of the
777 result for errors. */
779 #if FFECOM_targetCURRENT == FFECOM_targetGCC
780 static tree
781 ffeste_io_douio_ (ffebld expr)
783 tree num_elements;
784 tree variable;
785 tree size;
786 tree arglist;
787 ffeinfoBasictype bt;
788 ffeinfoKindtype kt;
789 bool is_complex;
791 bt = ffeinfo_basictype (ffebld_info (expr));
792 kt = ffeinfo_kindtype (ffebld_info (expr));
794 if ((bt == FFEINFO_basictypeANY)
795 || (kt == FFEINFO_kindtypeANY))
796 return error_mark_node;
798 if (bt == FFEINFO_basictypeCOMPLEX)
800 is_complex = TRUE;
801 bt = FFEINFO_basictypeREAL;
803 else
804 is_complex = FALSE;
806 ffecom_push_calltemps ();
808 variable = ffecom_arg_ptr_to_expr (expr, &size);
810 if ((variable == error_mark_node)
811 || (size == error_mark_node))
813 ffecom_pop_calltemps ();
814 return error_mark_node;
817 if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
818 { /* "(ftnlen) sizeof(type)" */
819 size = size_binop (CEIL_DIV_EXPR,
820 TYPE_SIZE (ffecom_tree_type[bt][kt]),
821 size_int (TYPE_PRECISION (char_type_node)));
822 #if 0 /* Assume that while it is possible that char * is wider than
823 ftnlen, no object in Fortran space can get big enough for its
824 size to be wider than ftnlen. I really hope nobody wastes
825 time debugging a case where it can! */
826 assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
827 >= TYPE_PRECISION (TREE_TYPE (size)));
828 #endif
829 size = convert (ffecom_f2c_ftnlen_type_node, size);
832 if ((ffeinfo_rank (ffebld_info (expr)) == 0)
833 || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
834 num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
835 : ffecom_f2c_ftnlen_one_node;
836 else
838 num_elements = size_binop (CEIL_DIV_EXPR,
839 TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
840 num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
841 size_int (TYPE_PRECISION
842 (char_type_node)));
843 num_elements = convert (ffecom_f2c_ftnlen_type_node,
844 num_elements);
847 num_elements
848 = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
849 num_elements);
851 variable = convert (string_type_node, variable);
853 arglist = build_tree_list (NULL_TREE, num_elements);
854 TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
855 TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
857 ffecom_pop_calltemps ();
859 return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist);
862 #endif
863 /* ffeste_io_ialist_ -- Make arglist with ptr to B/E/R control list
865 tree arglist;
866 arglist = ffeste_io_ialist_(...);
868 Returns a tree suitable as an argument list containing a pointer to
869 a BACKSPACE/ENDFILE/REWIND control list. First, generates that control
870 list, if necessary, along with any static and run-time initializations
871 that are needed as specified by the arguments to this function. */
873 #if FFECOM_targetCURRENT == FFECOM_targetGCC
874 static tree
875 ffeste_io_ialist_ (bool have_err,
876 ffestvUnit unit,
877 ffebld unit_expr,
878 int unit_dflt)
880 static tree f2c_alist_struct = NULL_TREE;
881 tree t;
882 tree ttype;
883 int yes;
884 tree field;
885 tree inits, initn;
886 bool constantp = TRUE;
887 static tree errfield, unitfield;
888 tree errinit, unitinit;
889 tree unitexp;
890 static int mynumber = 0;
892 if (f2c_alist_struct == NULL_TREE)
894 tree ref;
896 push_obstacks_nochange ();
897 end_temporary_allocation ();
899 ref = make_node (RECORD_TYPE);
901 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
902 ffecom_f2c_flag_type_node);
903 unitfield = ffecom_decl_field (ref, errfield, "unit",
904 ffecom_f2c_ftnint_type_node);
906 TYPE_FIELDS (ref) = errfield;
907 layout_type (ref);
909 resume_temporary_allocation ();
910 pop_obstacks ();
912 f2c_alist_struct = ref;
915 ffeste_f2c_flagspec_ (have_err, errinit);
917 switch (unit)
919 case FFESTV_unitNONE:
920 case FFESTV_unitASTERISK:
921 unitinit = build_int_2 (unit_dflt, 0);
922 unitexp = NULL_TREE;
923 break;
925 case FFESTV_unitINTEXPR:
926 unitexp = ffecom_expr (unit_expr);
927 if (TREE_CONSTANT (unitexp))
929 unitinit = unitexp;
930 unitexp = NULL_TREE;
932 else
934 unitinit = ffecom_integer_zero_node;
935 constantp = FALSE;
937 break;
939 default:
940 assert ("bad unit spec" == NULL);
941 unitexp = NULL_TREE;
942 unitinit = ffecom_integer_zero_node;
943 break;
946 inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
947 initn = inits;
948 ffeste_f2c_init_ (unitinit);
950 inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
951 TREE_CONSTANT (inits) = constantp ? 1 : 0;
952 TREE_STATIC (inits) = 1;
954 yes = suspend_momentary ();
956 t = build_decl (VAR_DECL,
957 ffecom_get_invented_identifier ("__g77_alist_%d", NULL,
958 mynumber++),
959 f2c_alist_struct);
960 TREE_STATIC (t) = 1;
961 t = ffecom_start_decl (t, 1);
962 ffecom_finish_decl (t, inits, 0);
964 resume_momentary (yes);
966 ffeste_f2c_exp_ (unitfield, unitexp);
968 ttype = build_pointer_type (TREE_TYPE (t));
969 t = ffecom_1 (ADDR_EXPR, ttype, t);
971 t = build_tree_list (NULL_TREE, t);
973 return t;
976 #endif
977 /* ffeste_io_cilist_ -- Make arglist with ptr to external I/O control list
979 tree arglist;
980 arglist = ffeste_io_cilist_(...);
982 Returns a tree suitable as an argument list containing a pointer to
983 an external-file I/O control list. First, generates that control
984 list, if necessary, along with any static and run-time initializations
985 that are needed as specified by the arguments to this function. */
987 #if FFECOM_targetCURRENT == FFECOM_targetGCC
988 static tree
989 ffeste_io_cilist_ (bool have_err,
990 ffestvUnit unit,
991 ffebld unit_expr,
992 int unit_dflt,
993 bool have_end,
994 ffestvFormat format,
995 ffestpFile *format_spec,
996 bool rec,
997 ffebld rec_expr)
999 static tree f2c_cilist_struct = NULL_TREE;
1000 tree t;
1001 tree ttype;
1002 int yes;
1003 tree field;
1004 tree inits, initn;
1005 bool constantp = TRUE;
1006 static tree errfield, unitfield, endfield, formatfield, recfield;
1007 tree errinit, unitinit, endinit, formatinit, recinit;
1008 tree unitexp, formatexp, recexp;
1009 static int mynumber = 0;
1011 if (f2c_cilist_struct == NULL_TREE)
1013 tree ref;
1015 push_obstacks_nochange ();
1016 end_temporary_allocation ();
1018 ref = make_node (RECORD_TYPE);
1020 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1021 ffecom_f2c_flag_type_node);
1022 unitfield = ffecom_decl_field (ref, errfield, "unit",
1023 ffecom_f2c_ftnint_type_node);
1024 endfield = ffecom_decl_field (ref, unitfield, "end",
1025 ffecom_f2c_flag_type_node);
1026 formatfield = ffecom_decl_field (ref, endfield, "format",
1027 string_type_node);
1028 recfield = ffecom_decl_field (ref, formatfield, "rec",
1029 ffecom_f2c_ftnint_type_node);
1031 TYPE_FIELDS (ref) = errfield;
1032 layout_type (ref);
1034 resume_temporary_allocation ();
1035 pop_obstacks ();
1037 f2c_cilist_struct = ref;
1040 ffeste_f2c_flagspec_ (have_err, errinit);
1042 switch (unit)
1044 case FFESTV_unitNONE:
1045 case FFESTV_unitASTERISK:
1046 unitinit = build_int_2 (unit_dflt, 0);
1047 unitexp = NULL_TREE;
1048 break;
1050 case FFESTV_unitINTEXPR:
1051 unitexp = ffecom_expr (unit_expr);
1052 if (TREE_CONSTANT (unitexp))
1054 unitinit = unitexp;
1055 unitexp = NULL_TREE;
1057 else
1059 unitinit = ffecom_integer_zero_node;
1060 constantp = FALSE;
1062 break;
1064 default:
1065 assert ("bad unit spec" == NULL);
1066 unitexp = NULL_TREE;
1067 unitinit = ffecom_integer_zero_node;
1068 break;
1071 switch (format)
1073 case FFESTV_formatNONE:
1074 formatinit = null_pointer_node;
1075 formatexp = NULL_TREE;
1076 break;
1078 case FFESTV_formatLABEL:
1079 formatexp = NULL_TREE;
1080 formatinit = ffecom_lookup_label (format_spec->u.label);
1081 if ((formatinit == NULL_TREE)
1082 || (TREE_CODE (formatinit) == ERROR_MARK))
1083 break;
1084 formatinit = ffecom_1 (ADDR_EXPR,
1085 build_pointer_type (void_type_node),
1086 formatinit);
1087 TREE_CONSTANT (formatinit) = 1;
1088 break;
1090 case FFESTV_formatCHAREXPR:
1091 formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1092 if (TREE_CONSTANT (formatexp))
1094 formatinit = formatexp;
1095 formatexp = NULL_TREE;
1097 else
1099 formatinit = null_pointer_node;
1100 constantp = FALSE;
1102 break;
1104 case FFESTV_formatASTERISK:
1105 formatinit = null_pointer_node;
1106 formatexp = NULL_TREE;
1107 break;
1109 case FFESTV_formatINTEXPR:
1110 formatinit = null_pointer_node;
1111 formatexp = ffecom_expr_assign (format_spec->u.expr);
1112 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1113 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1114 error ("ASSIGNed FORMAT specifier is too small");
1115 formatexp = convert (string_type_node, formatexp);
1116 break;
1118 case FFESTV_formatNAMELIST:
1119 formatinit = ffecom_expr (format_spec->u.expr);
1120 formatexp = NULL_TREE;
1121 break;
1123 default:
1124 assert ("bad format spec" == NULL);
1125 formatexp = NULL_TREE;
1126 formatinit = integer_zero_node;
1127 break;
1130 ffeste_f2c_flagspec_ (have_end, endinit);
1132 if (rec)
1133 recexp = ffecom_expr (rec_expr);
1134 else
1135 recexp = ffecom_integer_zero_node;
1136 if (TREE_CONSTANT (recexp))
1138 recinit = recexp;
1139 recexp = NULL_TREE;
1141 else
1143 recinit = ffecom_integer_zero_node;
1144 constantp = FALSE;
1147 inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
1148 initn = inits;
1149 ffeste_f2c_init_ (unitinit);
1150 ffeste_f2c_init_ (endinit);
1151 ffeste_f2c_init_ (formatinit);
1152 ffeste_f2c_init_ (recinit);
1154 inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1155 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1156 TREE_STATIC (inits) = 1;
1158 yes = suspend_momentary ();
1160 t = build_decl (VAR_DECL,
1161 ffecom_get_invented_identifier ("__g77_cilist_%d", NULL,
1162 mynumber++),
1163 f2c_cilist_struct);
1164 TREE_STATIC (t) = 1;
1165 t = ffecom_start_decl (t, 1);
1166 ffecom_finish_decl (t, inits, 0);
1168 resume_momentary (yes);
1170 ffeste_f2c_exp_ (unitfield, unitexp);
1171 ffeste_f2c_exp_ (formatfield, formatexp);
1172 ffeste_f2c_exp_ (recfield, recexp);
1174 ttype = build_pointer_type (TREE_TYPE (t));
1175 t = ffecom_1 (ADDR_EXPR, ttype, t);
1177 t = build_tree_list (NULL_TREE, t);
1179 return t;
1182 #endif
1183 /* ffeste_io_cllist_ -- Make arglist with ptr to CLOSE control list
1185 tree arglist;
1186 arglist = ffeste_io_cllist_(...);
1188 Returns a tree suitable as an argument list containing a pointer to
1189 a CLOSE-statement control list. First, generates that control
1190 list, if necessary, along with any static and run-time initializations
1191 that are needed as specified by the arguments to this function. */
1193 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1194 static tree
1195 ffeste_io_cllist_ (bool have_err,
1196 ffebld unit_expr,
1197 ffestpFile *stat_spec)
1199 static tree f2c_close_struct = NULL_TREE;
1200 tree t;
1201 tree ttype;
1202 int yes;
1203 tree field;
1204 tree inits, initn;
1205 tree ignore; /* Ignore length info for certain fields. */
1206 bool constantp = TRUE;
1207 static tree errfield, unitfield, statfield;
1208 tree errinit, unitinit, statinit;
1209 tree unitexp, statexp;
1210 static int mynumber = 0;
1212 if (f2c_close_struct == NULL_TREE)
1214 tree ref;
1216 push_obstacks_nochange ();
1217 end_temporary_allocation ();
1219 ref = make_node (RECORD_TYPE);
1221 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1222 ffecom_f2c_flag_type_node);
1223 unitfield = ffecom_decl_field (ref, errfield, "unit",
1224 ffecom_f2c_ftnint_type_node);
1225 statfield = ffecom_decl_field (ref, unitfield, "stat",
1226 string_type_node);
1228 TYPE_FIELDS (ref) = errfield;
1229 layout_type (ref);
1231 resume_temporary_allocation ();
1232 pop_obstacks ();
1234 f2c_close_struct = ref;
1237 ffeste_f2c_flagspec_ (have_err, errinit);
1239 unitexp = ffecom_expr (unit_expr);
1240 if (TREE_CONSTANT (unitexp))
1242 unitinit = unitexp;
1243 unitexp = NULL_TREE;
1245 else
1247 unitinit = ffecom_integer_zero_node;
1248 constantp = FALSE;
1251 ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
1253 inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
1254 initn = inits;
1255 ffeste_f2c_init_ (unitinit);
1256 ffeste_f2c_init_ (statinit);
1258 inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1259 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1260 TREE_STATIC (inits) = 1;
1262 yes = suspend_momentary ();
1264 t = build_decl (VAR_DECL,
1265 ffecom_get_invented_identifier ("__g77_cllist_%d", NULL,
1266 mynumber++),
1267 f2c_close_struct);
1268 TREE_STATIC (t) = 1;
1269 t = ffecom_start_decl (t, 1);
1270 ffecom_finish_decl (t, inits, 0);
1272 resume_momentary (yes);
1274 ffeste_f2c_exp_ (unitfield, unitexp);
1275 ffeste_f2c_exp_ (statfield, statexp);
1277 ttype = build_pointer_type (TREE_TYPE (t));
1278 t = ffecom_1 (ADDR_EXPR, ttype, t);
1280 t = build_tree_list (NULL_TREE, t);
1282 return t;
1285 #endif
1286 /* ffeste_io_icilist_ -- Make arglist with ptr to internal I/O control list
1288 tree arglist;
1289 arglist = ffeste_io_icilist_(...);
1291 Returns a tree suitable as an argument list containing a pointer to
1292 an internal-file I/O control list. First, generates that control
1293 list, if necessary, along with any static and run-time initializations
1294 that are needed as specified by the arguments to this function. */
1296 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1297 static tree
1298 ffeste_io_icilist_ (bool have_err,
1299 ffebld unit_expr,
1300 bool have_end,
1301 ffestvFormat format,
1302 ffestpFile *format_spec)
1304 static tree f2c_icilist_struct = NULL_TREE;
1305 tree t;
1306 tree ttype;
1307 int yes;
1308 tree field;
1309 tree inits, initn;
1310 bool constantp = TRUE;
1311 static tree errfield, unitfield, endfield, formatfield, unitlenfield,
1312 unitnumfield;
1313 tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
1314 tree unitexp, formatexp, unitlenexp, unitnumexp;
1315 static int mynumber = 0;
1317 if (f2c_icilist_struct == NULL_TREE)
1319 tree ref;
1321 push_obstacks_nochange ();
1322 end_temporary_allocation ();
1324 ref = make_node (RECORD_TYPE);
1326 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1327 ffecom_f2c_flag_type_node);
1328 unitfield = ffecom_decl_field (ref, errfield, "unit",
1329 string_type_node);
1330 endfield = ffecom_decl_field (ref, unitfield, "end",
1331 ffecom_f2c_flag_type_node);
1332 formatfield = ffecom_decl_field (ref, endfield, "format",
1333 string_type_node);
1334 unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
1335 ffecom_f2c_ftnint_type_node);
1336 unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
1337 ffecom_f2c_ftnint_type_node);
1339 TYPE_FIELDS (ref) = errfield;
1340 layout_type (ref);
1342 resume_temporary_allocation ();
1343 pop_obstacks ();
1345 f2c_icilist_struct = ref;
1348 ffeste_f2c_flagspec_ (have_err, errinit);
1350 unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
1351 if ((ffeinfo_rank (ffebld_info (unit_expr)) == 0)
1352 || (TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
1353 unitnumexp = ffecom_integer_one_node;
1354 else
1356 unitnumexp = size_binop (CEIL_DIV_EXPR,
1357 TYPE_SIZE (TREE_TYPE (TREE_TYPE (unitexp))), unitlenexp);
1358 unitnumexp = size_binop (CEIL_DIV_EXPR,
1359 unitnumexp, size_int (TYPE_PRECISION
1360 (char_type_node)));
1362 if (TREE_CONSTANT (unitexp))
1364 unitinit = unitexp;
1365 unitexp = NULL_TREE;
1367 else
1369 unitinit = null_pointer_node;
1370 constantp = FALSE;
1372 if ((unitlenexp != NULL_TREE) && TREE_CONSTANT (unitlenexp))
1374 unitleninit = unitlenexp;
1375 unitlenexp = NULL_TREE;
1377 else
1379 unitleninit = ffecom_integer_zero_node;
1380 constantp = FALSE;
1382 if (TREE_CONSTANT (unitnumexp))
1384 unitnuminit = unitnumexp;
1385 unitnumexp = NULL_TREE;
1387 else
1389 unitnuminit = ffecom_integer_zero_node;
1390 constantp = FALSE;
1393 switch (format)
1395 case FFESTV_formatNONE:
1396 formatinit = null_pointer_node;
1397 formatexp = NULL_TREE;
1398 break;
1400 case FFESTV_formatLABEL:
1401 formatexp = NULL_TREE;
1402 formatinit = ffecom_lookup_label (format_spec->u.label);
1403 if ((formatinit == NULL_TREE)
1404 || (TREE_CODE (formatinit) == ERROR_MARK))
1405 break;
1406 formatinit = ffecom_1 (ADDR_EXPR,
1407 build_pointer_type (void_type_node),
1408 formatinit);
1409 TREE_CONSTANT (formatinit) = 1;
1410 break;
1412 case FFESTV_formatCHAREXPR:
1413 formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1414 if (TREE_CONSTANT (formatexp))
1416 formatinit = formatexp;
1417 formatexp = NULL_TREE;
1419 else
1421 formatinit = null_pointer_node;
1422 constantp = FALSE;
1424 break;
1426 case FFESTV_formatASTERISK:
1427 formatinit = null_pointer_node;
1428 formatexp = NULL_TREE;
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 default:
1441 assert ("bad format spec" == NULL);
1442 formatexp = NULL_TREE;
1443 formatinit = ffecom_integer_zero_node;
1444 break;
1447 ffeste_f2c_flagspec_ (have_end, endinit);
1449 inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
1450 errinit);
1451 initn = inits;
1452 ffeste_f2c_init_ (unitinit);
1453 ffeste_f2c_init_ (endinit);
1454 ffeste_f2c_init_ (formatinit);
1455 ffeste_f2c_init_ (unitleninit);
1456 ffeste_f2c_init_ (unitnuminit);
1458 inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1459 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1460 TREE_STATIC (inits) = 1;
1462 yes = suspend_momentary ();
1464 t = build_decl (VAR_DECL,
1465 ffecom_get_invented_identifier ("__g77_icilist_%d", NULL,
1466 mynumber++),
1467 f2c_icilist_struct);
1468 TREE_STATIC (t) = 1;
1469 t = ffecom_start_decl (t, 1);
1470 ffecom_finish_decl (t, inits, 0);
1472 resume_momentary (yes);
1474 ffeste_f2c_exp_ (unitfield, unitexp);
1475 ffeste_f2c_exp_ (formatfield, formatexp);
1476 ffeste_f2c_exp_ (unitlenfield, unitlenexp);
1477 ffeste_f2c_exp_ (unitnumfield, unitnumexp);
1479 ttype = build_pointer_type (TREE_TYPE (t));
1480 t = ffecom_1 (ADDR_EXPR, ttype, t);
1482 t = build_tree_list (NULL_TREE, t);
1484 return t;
1487 #endif
1488 /* ffeste_io_impdo_ -- Handle implied-DO in I/O list
1490 ffebld expr;
1491 ffeste_io_impdo_(expr);
1493 Expands code to start up the DO loop. Then for each item in the
1494 DO loop, handles appropriately (possibly including recursively calling
1495 itself). Then expands code to end the DO loop. */
1497 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1498 static void
1499 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
1501 ffebld var = ffebld_head (ffebld_right (impdo));
1502 ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
1503 ffebld end = ffebld_head (ffebld_trail (ffebld_trail
1504 (ffebld_right (impdo))));
1505 ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
1506 (ffebld_trail (ffebld_right (impdo)))));
1507 ffebld list; /* Used for list of items in left part of
1508 impdo. */
1509 ffebld item; /* I/O item from head of given list. */
1510 tree tvar;
1511 tree tincr;
1512 tree titervar;
1514 if (incr == NULL)
1516 incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
1517 ffebld_set_info (incr, ffeinfo_new
1518 (FFEINFO_basictypeINTEGER,
1519 FFEINFO_kindtypeINTEGERDEFAULT,
1521 FFEINFO_kindENTITY,
1522 FFEINFO_whereCONSTANT,
1523 FFETARGET_charactersizeNONE));
1526 /* Start the DO loop. */
1528 start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
1529 FFEEXPR_contextLET);
1530 end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
1531 FFEEXPR_contextLET);
1532 incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
1533 FFEEXPR_contextLET);
1535 ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
1536 start, impdo_token,
1537 end, impdo_token,
1538 incr, impdo_token,
1539 "Implied DO loop");
1541 /* Handle the list of items. */
1543 for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
1545 item = ffebld_head (list);
1546 if (item == NULL)
1547 continue;
1548 while (ffebld_op (item) == FFEBLD_opPAREN)
1549 item = ffebld_left (item);
1550 if (ffebld_op (item) == FFEBLD_opANY)
1551 continue;
1552 if (ffebld_op (item) == FFEBLD_opIMPDO)
1553 ffeste_io_impdo_ (item, impdo_token);
1554 else
1555 ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
1556 clear_momentary ();
1559 /* Generate end of implied-do construct. */
1561 ffeste_end_iterdo_ (tvar, tincr, titervar);
1564 #endif
1565 /* ffeste_io_inlist_ -- Make arglist with ptr to INQUIRE control list
1567 tree arglist;
1568 arglist = ffeste_io_inlist_(...);
1570 Returns a tree suitable as an argument list containing a pointer to
1571 an INQUIRE-statement control list. First, generates that control
1572 list, if necessary, along with any static and run-time initializations
1573 that are needed as specified by the arguments to this function. */
1575 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1576 static tree
1577 ffeste_io_inlist_ (bool have_err,
1578 ffestpFile *unit_spec,
1579 ffestpFile *file_spec,
1580 ffestpFile *exist_spec,
1581 ffestpFile *open_spec,
1582 ffestpFile *number_spec,
1583 ffestpFile *named_spec,
1584 ffestpFile *name_spec,
1585 ffestpFile *access_spec,
1586 ffestpFile *sequential_spec,
1587 ffestpFile *direct_spec,
1588 ffestpFile *form_spec,
1589 ffestpFile *formatted_spec,
1590 ffestpFile *unformatted_spec,
1591 ffestpFile *recl_spec,
1592 ffestpFile *nextrec_spec,
1593 ffestpFile *blank_spec)
1595 static tree f2c_inquire_struct = NULL_TREE;
1596 tree t;
1597 tree ttype;
1598 int yes;
1599 tree field;
1600 tree inits, initn;
1601 bool constantp = TRUE;
1602 static tree errfield, unitfield, filefield, filelenfield, existfield,
1603 openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
1604 accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
1605 formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
1606 unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
1607 tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
1608 namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
1609 sequentialleninit, directinit, directleninit, forminit, formleninit,
1610 formattedinit, formattedleninit, unformattedinit, unformattedleninit,
1611 reclinit, nextrecinit, blankinit, blankleninit;
1612 tree
1613 unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
1614 nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
1615 directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
1616 unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
1617 static int mynumber = 0;
1619 if (f2c_inquire_struct == NULL_TREE)
1621 tree ref;
1623 push_obstacks_nochange ();
1624 end_temporary_allocation ();
1626 ref = make_node (RECORD_TYPE);
1628 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1629 ffecom_f2c_flag_type_node);
1630 unitfield = ffecom_decl_field (ref, errfield, "unit",
1631 ffecom_f2c_ftnint_type_node);
1632 filefield = ffecom_decl_field (ref, unitfield, "file",
1633 string_type_node);
1634 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1635 ffecom_f2c_ftnlen_type_node);
1636 existfield = ffecom_decl_field (ref, filelenfield, "exist",
1637 ffecom_f2c_ptr_to_ftnint_type_node);
1638 openfield = ffecom_decl_field (ref, existfield, "open",
1639 ffecom_f2c_ptr_to_ftnint_type_node);
1640 numberfield = ffecom_decl_field (ref, openfield, "number",
1641 ffecom_f2c_ptr_to_ftnint_type_node);
1642 namedfield = ffecom_decl_field (ref, numberfield, "named",
1643 ffecom_f2c_ptr_to_ftnint_type_node);
1644 namefield = ffecom_decl_field (ref, namedfield, "name",
1645 string_type_node);
1646 namelenfield = ffecom_decl_field (ref, namefield, "namelen",
1647 ffecom_f2c_ftnlen_type_node);
1648 accessfield = ffecom_decl_field (ref, namelenfield, "access",
1649 string_type_node);
1650 accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
1651 ffecom_f2c_ftnlen_type_node);
1652 sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
1653 string_type_node);
1654 sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
1655 "sequentiallen",
1656 ffecom_f2c_ftnlen_type_node);
1657 directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
1658 string_type_node);
1659 directlenfield = ffecom_decl_field (ref, directfield, "directlen",
1660 ffecom_f2c_ftnlen_type_node);
1661 formfield = ffecom_decl_field (ref, directlenfield, "form",
1662 string_type_node);
1663 formlenfield = ffecom_decl_field (ref, formfield, "formlen",
1664 ffecom_f2c_ftnlen_type_node);
1665 formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
1666 string_type_node);
1667 formattedlenfield = ffecom_decl_field (ref, formattedfield,
1668 "formattedlen",
1669 ffecom_f2c_ftnlen_type_node);
1670 unformattedfield = ffecom_decl_field (ref, formattedlenfield,
1671 "unformatted",
1672 string_type_node);
1673 unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
1674 "unformattedlen",
1675 ffecom_f2c_ftnlen_type_node);
1676 reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
1677 ffecom_f2c_ptr_to_ftnint_type_node);
1678 nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
1679 ffecom_f2c_ptr_to_ftnint_type_node);
1680 blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
1681 string_type_node);
1682 blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
1683 ffecom_f2c_ftnlen_type_node);
1685 TYPE_FIELDS (ref) = errfield;
1686 layout_type (ref);
1688 resume_temporary_allocation ();
1689 pop_obstacks ();
1691 f2c_inquire_struct = ref;
1694 ffeste_f2c_flagspec_ (have_err, errinit);
1695 ffeste_f2c_intspec_ (unit_spec, unitexp, unitinit);
1696 ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
1697 ffeste_f2c_ptrtointspec_ (exist_spec, existexp, existinit);
1698 ffeste_f2c_ptrtointspec_ (open_spec, openexp, openinit);
1699 ffeste_f2c_ptrtointspec_ (number_spec, numberexp, numberinit);
1700 ffeste_f2c_ptrtointspec_ (named_spec, namedexp, namedinit);
1701 ffeste_f2c_charspec_ (name_spec, nameexp, nameinit, namelenexp, nameleninit);
1702 ffeste_f2c_charspec_ (access_spec, accessexp, accessinit, accesslenexp,
1703 accessleninit);
1704 ffeste_f2c_charspec_ (sequential_spec, sequentialexp, sequentialinit,
1705 sequentiallenexp, sequentialleninit);
1706 ffeste_f2c_charspec_ (direct_spec, directexp, directinit, directlenexp,
1707 directleninit);
1708 ffeste_f2c_charspec_ (form_spec, formexp, forminit, formlenexp, formleninit);
1709 ffeste_f2c_charspec_ (formatted_spec, formattedexp, formattedinit,
1710 formattedlenexp, formattedleninit);
1711 ffeste_f2c_charspec_ (unformatted_spec, unformattedexp, unformattedinit,
1712 unformattedlenexp, unformattedleninit);
1713 ffeste_f2c_ptrtointspec_ (recl_spec, reclexp, reclinit);
1714 ffeste_f2c_ptrtointspec_ (nextrec_spec, nextrecexp, nextrecinit);
1715 ffeste_f2c_charspec_ (blank_spec, blankexp, blankinit, blanklenexp,
1716 blankleninit);
1718 inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
1719 errinit);
1720 initn = inits;
1721 ffeste_f2c_init_ (unitinit);
1722 ffeste_f2c_init_ (fileinit);
1723 ffeste_f2c_init_ (fileleninit);
1724 ffeste_f2c_init_ (existinit);
1725 ffeste_f2c_init_ (openinit);
1726 ffeste_f2c_init_ (numberinit);
1727 ffeste_f2c_init_ (namedinit);
1728 ffeste_f2c_init_ (nameinit);
1729 ffeste_f2c_init_ (nameleninit);
1730 ffeste_f2c_init_ (accessinit);
1731 ffeste_f2c_init_ (accessleninit);
1732 ffeste_f2c_init_ (sequentialinit);
1733 ffeste_f2c_init_ (sequentialleninit);
1734 ffeste_f2c_init_ (directinit);
1735 ffeste_f2c_init_ (directleninit);
1736 ffeste_f2c_init_ (forminit);
1737 ffeste_f2c_init_ (formleninit);
1738 ffeste_f2c_init_ (formattedinit);
1739 ffeste_f2c_init_ (formattedleninit);
1740 ffeste_f2c_init_ (unformattedinit);
1741 ffeste_f2c_init_ (unformattedleninit);
1742 ffeste_f2c_init_ (reclinit);
1743 ffeste_f2c_init_ (nextrecinit);
1744 ffeste_f2c_init_ (blankinit);
1745 ffeste_f2c_init_ (blankleninit);
1747 inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
1748 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1749 TREE_STATIC (inits) = 1;
1751 yes = suspend_momentary ();
1753 t = build_decl (VAR_DECL,
1754 ffecom_get_invented_identifier ("__g77_inlist_%d", NULL,
1755 mynumber++),
1756 f2c_inquire_struct);
1757 TREE_STATIC (t) = 1;
1758 t = ffecom_start_decl (t, 1);
1759 ffecom_finish_decl (t, inits, 0);
1761 resume_momentary (yes);
1763 ffeste_f2c_exp_ (unitfield, unitexp);
1764 ffeste_f2c_exp_ (filefield, fileexp);
1765 ffeste_f2c_exp_ (filelenfield, filelenexp);
1766 ffeste_f2c_exp_ (existfield, existexp);
1767 ffeste_f2c_exp_ (openfield, openexp);
1768 ffeste_f2c_exp_ (numberfield, numberexp);
1769 ffeste_f2c_exp_ (namedfield, namedexp);
1770 ffeste_f2c_exp_ (namefield, nameexp);
1771 ffeste_f2c_exp_ (namelenfield, namelenexp);
1772 ffeste_f2c_exp_ (accessfield, accessexp);
1773 ffeste_f2c_exp_ (accesslenfield, accesslenexp);
1774 ffeste_f2c_exp_ (sequentialfield, sequentialexp);
1775 ffeste_f2c_exp_ (sequentiallenfield, sequentiallenexp);
1776 ffeste_f2c_exp_ (directfield, directexp);
1777 ffeste_f2c_exp_ (directlenfield, directlenexp);
1778 ffeste_f2c_exp_ (formfield, formexp);
1779 ffeste_f2c_exp_ (formlenfield, formlenexp);
1780 ffeste_f2c_exp_ (formattedfield, formattedexp);
1781 ffeste_f2c_exp_ (formattedlenfield, formattedlenexp);
1782 ffeste_f2c_exp_ (unformattedfield, unformattedexp);
1783 ffeste_f2c_exp_ (unformattedlenfield, unformattedlenexp);
1784 ffeste_f2c_exp_ (reclfield, reclexp);
1785 ffeste_f2c_exp_ (nextrecfield, nextrecexp);
1786 ffeste_f2c_exp_ (blankfield, blankexp);
1787 ffeste_f2c_exp_ (blanklenfield, blanklenexp);
1789 ttype = build_pointer_type (TREE_TYPE (t));
1790 t = ffecom_1 (ADDR_EXPR, ttype, t);
1792 t = build_tree_list (NULL_TREE, t);
1794 return t;
1797 #endif
1798 /* ffeste_io_olist_ -- Make arglist with ptr to OPEN control list
1800 tree arglist;
1801 arglist = ffeste_io_olist_(...);
1803 Returns a tree suitable as an argument list containing a pointer to
1804 an OPEN-statement control list. First, generates that control
1805 list, if necessary, along with any static and run-time initializations
1806 that are needed as specified by the arguments to this function. */
1808 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1809 static tree
1810 ffeste_io_olist_ (bool have_err,
1811 ffebld unit_expr,
1812 ffestpFile *file_spec,
1813 ffestpFile *stat_spec,
1814 ffestpFile *access_spec,
1815 ffestpFile *form_spec,
1816 ffestpFile *recl_spec,
1817 ffestpFile *blank_spec)
1819 static tree f2c_open_struct = NULL_TREE;
1820 tree t;
1821 tree ttype;
1822 int yes;
1823 tree field;
1824 tree inits, initn;
1825 tree ignore; /* Ignore length info for certain fields. */
1826 bool constantp = TRUE;
1827 static tree errfield, unitfield, filefield, filelenfield, statfield,
1828 accessfield, formfield, reclfield, blankfield;
1829 tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
1830 forminit, reclinit, blankinit;
1831 tree
1832 unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
1833 blankexp;
1834 static int mynumber = 0;
1836 if (f2c_open_struct == NULL_TREE)
1838 tree ref;
1840 push_obstacks_nochange ();
1841 end_temporary_allocation ();
1843 ref = make_node (RECORD_TYPE);
1845 errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1846 ffecom_f2c_flag_type_node);
1847 unitfield = ffecom_decl_field (ref, errfield, "unit",
1848 ffecom_f2c_ftnint_type_node);
1849 filefield = ffecom_decl_field (ref, unitfield, "file",
1850 string_type_node);
1851 filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1852 ffecom_f2c_ftnlen_type_node);
1853 statfield = ffecom_decl_field (ref, filelenfield, "stat",
1854 string_type_node);
1855 accessfield = ffecom_decl_field (ref, statfield, "access",
1856 string_type_node);
1857 formfield = ffecom_decl_field (ref, accessfield, "form",
1858 string_type_node);
1859 reclfield = ffecom_decl_field (ref, formfield, "recl",
1860 ffecom_f2c_ftnint_type_node);
1861 blankfield = ffecom_decl_field (ref, reclfield, "blank",
1862 string_type_node);
1864 TYPE_FIELDS (ref) = errfield;
1865 layout_type (ref);
1867 resume_temporary_allocation ();
1868 pop_obstacks ();
1870 f2c_open_struct = ref;
1873 ffeste_f2c_flagspec_ (have_err, errinit);
1875 unitexp = ffecom_expr (unit_expr);
1876 if (TREE_CONSTANT (unitexp))
1878 unitinit = unitexp;
1879 unitexp = NULL_TREE;
1881 else
1883 unitinit = ffecom_integer_zero_node;
1884 constantp = FALSE;
1887 ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
1888 ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
1889 ffeste_f2c_charnolenspec_ (access_spec, accessexp, accessinit);
1890 ffeste_f2c_charnolenspec_ (form_spec, formexp, forminit);
1891 ffeste_f2c_intspec_ (recl_spec, reclexp, reclinit);
1892 ffeste_f2c_charnolenspec_ (blank_spec, blankexp, blankinit);
1894 inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
1895 initn = inits;
1896 ffeste_f2c_init_ (unitinit);
1897 ffeste_f2c_init_ (fileinit);
1898 ffeste_f2c_init_ (fileleninit);
1899 ffeste_f2c_init_ (statinit);
1900 ffeste_f2c_init_ (accessinit);
1901 ffeste_f2c_init_ (forminit);
1902 ffeste_f2c_init_ (reclinit);
1903 ffeste_f2c_init_ (blankinit);
1905 inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
1906 TREE_CONSTANT (inits) = constantp ? 1 : 0;
1907 TREE_STATIC (inits) = 1;
1909 yes = suspend_momentary ();
1911 t = build_decl (VAR_DECL,
1912 ffecom_get_invented_identifier ("__g77_olist_%d", NULL,
1913 mynumber++),
1914 f2c_open_struct);
1915 TREE_STATIC (t) = 1;
1916 t = ffecom_start_decl (t, 1);
1917 ffecom_finish_decl (t, inits, 0);
1919 resume_momentary (yes);
1921 ffeste_f2c_exp_ (unitfield, unitexp);
1922 ffeste_f2c_exp_ (filefield, fileexp);
1923 ffeste_f2c_exp_ (filelenfield, filelenexp);
1924 ffeste_f2c_exp_ (statfield, statexp);
1925 ffeste_f2c_exp_ (accessfield, accessexp);
1926 ffeste_f2c_exp_ (formfield, formexp);
1927 ffeste_f2c_exp_ (reclfield, reclexp);
1928 ffeste_f2c_exp_ (blankfield, blankexp);
1930 ttype = build_pointer_type (TREE_TYPE (t));
1931 t = ffecom_1 (ADDR_EXPR, ttype, t);
1933 t = build_tree_list (NULL_TREE, t);
1935 return t;
1938 #endif
1939 /* ffeste_subr_file_ -- Display file-statement specifier
1941 ffeste_subr_file_(&specifier); */
1943 #if FFECOM_targetCURRENT == FFECOM_targetFFE
1944 static void
1945 ffeste_subr_file_ (char *kw, ffestpFile *spec)
1947 if (!spec->kw_or_val_present)
1948 return;
1949 fputs (kw, dmpout);
1950 if (spec->value_present)
1952 fputc ('=', dmpout);
1953 if (spec->value_is_label)
1955 assert (spec->value_is_label == 2); /* Temporary checking only. */
1956 fprintf (dmpout, "%" ffelabValue_f "u",
1957 ffelab_value (spec->u.label));
1959 else
1960 ffebld_dump (spec->u.expr);
1962 fputc (',', dmpout);
1964 #endif
1966 /* ffeste_subr_beru_ -- Generate code for BACKSPACE/ENDFILE/REWIND
1968 ffeste_subr_beru_(FFECOM_gfrtFBACK); */
1970 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1971 static void
1972 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
1974 tree alist;
1975 bool iostat;
1976 bool errl;
1978 #define specified(something) (info->beru_spec[something].kw_or_val_present)
1980 ffeste_emit_line_note_ ();
1982 /* Do the real work. */
1984 iostat = specified (FFESTP_beruixIOSTAT);
1985 errl = specified (FFESTP_beruixERR);
1987 /* ~~For now, we assume the unit number is specified and is not ASTERISK,
1988 because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
1989 without any unit specifier. f2c, however, supports the former
1990 construct. When it is time to add this feature to the FFE, which
1991 probably is fairly easy, ffestc_R919 and company will want to pass an
1992 ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
1993 ffeste_R919 and company, and they will want to pass that same value to
1994 this function, and that argument will replace the constant _unitINTEXPR_
1995 in the call below. Right now, the default unit number, 6, is ignored. */
1997 ffecom_push_calltemps ();
1999 alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2000 info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
2002 if (errl)
2003 { /* ERR= */
2004 ffeste_io_err_
2005 = ffeste_io_abort_
2006 = ffecom_lookup_label
2007 (info->beru_spec[FFESTP_beruixERR].u.label);
2008 ffeste_io_abort_is_temp_ = FALSE;
2010 else
2011 { /* no ERR= */
2012 ffeste_io_err_ = NULL_TREE;
2014 if ((ffeste_io_abort_is_temp_ = iostat))
2015 ffeste_io_abort_ = ffecom_temp_label ();
2016 else
2017 ffeste_io_abort_ = NULL_TREE;
2020 if (iostat)
2021 { /* IOSTAT= */
2022 ffeste_io_iostat_is_temp_ = FALSE;
2023 ffeste_io_iostat_ = ffecom_expr
2024 (info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2026 else if (ffeste_io_abort_ != NULL_TREE)
2027 { /* no IOSTAT= but ERR= */
2028 ffeste_io_iostat_is_temp_ = TRUE;
2029 ffeste_io_iostat_
2030 = ffecom_push_tempvar (ffecom_integer_type_node,
2031 FFETARGET_charactersizeNONE, -1, FALSE);
2033 else
2034 { /* no IOSTAT=, or ERR= */
2035 ffeste_io_iostat_is_temp_ = FALSE;
2036 ffeste_io_iostat_ = NULL_TREE;
2039 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
2040 label, since we're gonna fall through to there anyway. */
2042 ffeste_io_call_ (ffecom_call_gfrt (rt, alist),
2043 !ffeste_io_abort_is_temp_);
2045 /* If we've got a temp label, generate its code here. */
2047 if (ffeste_io_abort_is_temp_)
2049 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2050 emit_nop ();
2051 expand_label (ffeste_io_abort_);
2053 assert (ffeste_io_err_ == NULL_TREE);
2056 /* If we've got a temp iostat, pop the temp. */
2058 if (ffeste_io_iostat_is_temp_)
2059 ffecom_pop_tempvar (ffeste_io_iostat_);
2061 ffecom_pop_calltemps ();
2063 #undef specified
2065 clear_momentary ();
2068 #endif
2069 /* ffeste_do -- End of statement following DO-term-stmt etc
2071 ffeste_do(TRUE);
2073 Also invoked by _labeldef_branch_finish_ (or, in cases
2074 of errors, other _labeldef_ functions) when the label definition is
2075 for a DO-target (LOOPEND) label, once per matching/outstanding DO
2076 block on the stack. These cases invoke this function with ok==TRUE, so
2077 only forced stack popping (via ffeste_eof_()) invokes it with ok==FALSE. */
2079 void
2080 ffeste_do (ffestw block)
2082 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2083 fputs ("+ END_DO\n", dmpout);
2084 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2085 ffeste_emit_line_note_ ();
2086 if (ffestw_do_tvar (block) == 0)
2087 expand_end_loop (); /* DO WHILE and just DO. */
2088 else
2089 ffeste_end_iterdo_ (ffestw_do_tvar (block),
2090 ffestw_do_incr_saved (block),
2091 ffestw_do_count_var (block));
2093 clear_momentary ();
2094 #else
2095 #error
2096 #endif
2099 /* ffeste_end_R807 -- End of statement following logical IF
2101 ffeste_end_R807(TRUE);
2103 Applies ONLY to logical IF, not to IF-THEN. For example, does not
2104 ffelex_token_kill the construct name for an IF-THEN block (the name
2105 field is invalid for logical IF). ok==TRUE iff statement following
2106 logical IF (substatement) is valid; else, statement is invalid or
2107 stack forcibly popped due to ffeste_eof_(). */
2109 void
2110 ffeste_end_R807 ()
2112 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2113 fputs ("+ END_IF\n", dmpout); /* Also see ffeste_R806. */
2114 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2115 ffeste_emit_line_note_ ();
2116 expand_end_cond ();
2117 clear_momentary ();
2118 #else
2119 #error
2120 #endif
2123 /* ffeste_labeldef_branch -- Generate "code" for branch label def
2125 ffeste_labeldef_branch(label); */
2127 void
2128 ffeste_labeldef_branch (ffelab label)
2130 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2131 fprintf (dmpout, "+ label %lu\n", ffelab_value (label));
2132 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2134 tree glabel;
2136 glabel = ffecom_lookup_label (label);
2137 assert (glabel != NULL_TREE);
2138 if (TREE_CODE (glabel) == ERROR_MARK)
2139 return;
2140 assert (DECL_INITIAL (glabel) == NULL_TREE);
2141 DECL_INITIAL (glabel) = error_mark_node;
2142 DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
2143 DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
2144 emit_nop ();
2145 expand_label (glabel);
2147 #else
2148 #error
2149 #endif
2152 /* ffeste_labeldef_format -- Generate "code" for FORMAT label def
2154 ffeste_labeldef_format(label); */
2156 void
2157 ffeste_labeldef_format (ffelab label)
2159 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2160 fprintf (dmpout, "$ label %lu\n", ffelab_value (label));
2161 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2162 ffeste_label_formatdef_ = label;
2163 #else
2164 #error
2165 #endif
2168 /* ffeste_R737A -- Assignment statement outside of WHERE
2170 ffeste_R737A(dest_expr,source_expr); */
2172 void
2173 ffeste_R737A (ffebld dest, ffebld source)
2175 ffeste_check_simple_ ();
2177 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2178 fputs ("+ let ", dmpout);
2179 ffebld_dump (dest);
2180 fputs ("=", dmpout);
2181 ffebld_dump (source);
2182 fputc ('\n', dmpout);
2183 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2184 ffeste_emit_line_note_ ();
2185 ffecom_push_calltemps ();
2187 ffecom_expand_let_stmt (dest, source);
2189 ffecom_pop_calltemps ();
2190 clear_momentary ();
2191 #else
2192 #error
2193 #endif
2196 /* ffeste_R803 -- Block IF (IF-THEN) statement
2198 ffeste_R803(construct_name,expr,expr_token);
2200 Make sure statement is valid here; implement. */
2202 void
2203 ffeste_R803 (ffebld expr)
2205 ffeste_check_simple_ ();
2207 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2208 fputs ("+ IF_block (", dmpout);
2209 ffebld_dump (expr);
2210 fputs (")\n", dmpout);
2211 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2212 ffeste_emit_line_note_ ();
2213 ffecom_push_calltemps ();
2215 expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
2217 ffecom_pop_calltemps ();
2218 clear_momentary ();
2219 #else
2220 #error
2221 #endif
2224 /* ffeste_R804 -- ELSE IF statement
2226 ffeste_R804(expr,expr_token,name_token);
2228 Make sure ffeste_kind_ identifies an IF block. If not
2229 NULL, make sure name_token gives the correct name. Implement the else
2230 of the IF block. */
2232 void
2233 ffeste_R804 (ffebld expr)
2235 ffeste_check_simple_ ();
2237 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2238 fputs ("+ ELSE_IF (", dmpout);
2239 ffebld_dump (expr);
2240 fputs (")\n", dmpout);
2241 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2242 ffeste_emit_line_note_ ();
2243 ffecom_push_calltemps ();
2245 expand_start_elseif (ffecom_truth_value (ffecom_expr (expr)));
2247 ffecom_pop_calltemps ();
2248 clear_momentary ();
2249 #else
2250 #error
2251 #endif
2254 /* ffeste_R805 -- ELSE statement
2256 ffeste_R805(name_token);
2258 Make sure ffeste_kind_ identifies an IF block. If not
2259 NULL, make sure name_token gives the correct name. Implement the ELSE
2260 of the IF block. */
2262 void
2263 ffeste_R805 ()
2265 ffeste_check_simple_ ();
2267 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2268 fputs ("+ ELSE\n", dmpout);
2269 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2270 ffeste_emit_line_note_ ();
2271 expand_start_else ();
2272 clear_momentary ();
2273 #else
2274 #error
2275 #endif
2278 /* ffeste_R806 -- End an IF-THEN
2280 ffeste_R806(TRUE); */
2282 void
2283 ffeste_R806 ()
2285 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2286 fputs ("+ END_IF_then\n", dmpout); /* Also see ffeste_shriek_if_. */
2287 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2288 ffeste_emit_line_note_ ();
2289 expand_end_cond ();
2290 clear_momentary ();
2291 #else
2292 #error
2293 #endif
2296 /* ffeste_R807 -- Logical IF statement
2298 ffeste_R807(expr,expr_token);
2300 Make sure statement is valid here; implement. */
2302 void
2303 ffeste_R807 (ffebld expr)
2305 ffeste_check_simple_ ();
2307 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2308 fputs ("+ IF_logical (", dmpout);
2309 ffebld_dump (expr);
2310 fputs (")\n", dmpout);
2311 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2312 ffeste_emit_line_note_ ();
2313 ffecom_push_calltemps ();
2315 expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
2317 ffecom_pop_calltemps ();
2318 clear_momentary ();
2319 #else
2320 #error
2321 #endif
2324 /* ffeste_R809 -- SELECT CASE statement
2326 ffeste_R809(construct_name,expr,expr_token);
2328 Make sure statement is valid here; implement. */
2330 void
2331 ffeste_R809 (ffestw block, ffebld expr)
2333 ffeste_check_simple_ ();
2335 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2336 fputs ("+ SELECT_CASE (", dmpout);
2337 ffebld_dump (expr);
2338 fputs (")\n", dmpout);
2339 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2340 ffecom_push_calltemps ();
2343 tree texpr;
2345 ffeste_emit_line_note_ ();
2347 if ((expr == NULL)
2348 || (ffeinfo_basictype (ffebld_info (expr))
2349 == FFEINFO_basictypeANY))
2351 ffestw_set_select_texpr (block, error_mark_node);
2352 clear_momentary ();
2354 else
2356 texpr = ffecom_expr (expr);
2357 if (ffeinfo_basictype (ffebld_info (expr))
2358 != FFEINFO_basictypeCHARACTER)
2360 expand_start_case (1, texpr, TREE_TYPE (texpr),
2361 "SELECT CASE statement");
2362 ffestw_set_select_texpr (block, texpr);
2363 ffestw_set_select_break (block, FALSE);
2364 push_momentary ();
2366 else
2368 ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
2369 FFEBAD_severityFATAL);
2370 ffebad_here (0, ffestw_line (block), ffestw_col (block));
2371 ffebad_finish ();
2372 ffestw_set_select_texpr (block, error_mark_node);
2377 ffecom_pop_calltemps ();
2378 #else
2379 #error
2380 #endif
2383 /* ffeste_R810 -- CASE statement
2385 ffeste_R810(case_value_range_list,name);
2387 If casenum is 0, it's CASE DEFAULT. Else it's the case ranges at
2388 the start of the first_stmt list in the select object at the top of
2389 the stack that match casenum. */
2391 void
2392 ffeste_R810 (ffestw block, unsigned long casenum)
2394 ffestwSelect s = ffestw_select (block);
2395 ffestwCase c;
2397 ffeste_check_simple_ ();
2399 if (s->first_stmt == (ffestwCase) &s->first_rel)
2400 c = NULL;
2401 else
2402 c = s->first_stmt;
2404 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2405 if ((c == NULL) || (casenum != c->casenum))
2407 if (casenum == 0) /* Intentional CASE DEFAULT. */
2408 fputs ("+ CASE_DEFAULT", dmpout);
2410 else
2412 bool comma = FALSE;
2414 fputs ("+ CASE (", dmpout);
2417 if (comma)
2418 fputc (',', dmpout);
2419 else
2420 comma = TRUE;
2421 if (c->low != NULL)
2422 ffebld_constant_dump (c->low);
2423 if (c->low != c->high)
2425 fputc (':', dmpout);
2426 if (c->high != NULL)
2427 ffebld_constant_dump (c->high);
2429 c = c->next_stmt;
2430 /* Unlink prev. */
2431 c->previous_stmt->previous_stmt->next_stmt = c;
2432 c->previous_stmt = c->previous_stmt->previous_stmt;
2434 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2435 fputc (')', dmpout);
2438 fputc ('\n', dmpout);
2439 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2441 tree texprlow;
2442 tree texprhigh;
2443 tree tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2444 int pushok;
2445 tree duplicate;
2447 ffeste_emit_line_note_ ();
2449 if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
2451 clear_momentary ();
2452 return;
2455 if (ffestw_select_break (block))
2456 expand_exit_something ();
2457 else
2458 ffestw_set_select_break (block, TRUE);
2460 if ((c == NULL) || (casenum != c->casenum))
2462 if (casenum == 0) /* Intentional CASE DEFAULT. */
2464 pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2465 assert (pushok == 0);
2468 else
2471 texprlow = (c->low == NULL) ? NULL_TREE
2472 : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
2473 s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2474 if (c->low != c->high)
2476 texprhigh = (c->high == NULL) ? NULL_TREE
2477 : ffecom_constantunion (&ffebld_constant_union (c->high),
2478 s->type, s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
2479 pushok = pushcase_range (texprlow, texprhigh, convert,
2480 tlabel, &duplicate);
2482 else
2483 pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2484 assert (pushok == 0);
2485 c = c->next_stmt;
2486 /* Unlink prev. */
2487 c->previous_stmt->previous_stmt->next_stmt = c;
2488 c->previous_stmt = c->previous_stmt->previous_stmt;
2490 while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2492 clear_momentary ();
2493 } /* ~~~handle character, character*1 */
2494 #else
2495 #error
2496 #endif
2499 /* ffeste_R811 -- End a SELECT
2501 ffeste_R811(TRUE); */
2503 void
2504 ffeste_R811 (ffestw block)
2506 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2507 fputs ("+ END_SELECT\n", dmpout);
2508 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2509 ffeste_emit_line_note_ ();
2511 if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
2513 clear_momentary ();
2514 return;
2517 expand_end_case (ffestw_select_texpr (block));
2518 pop_momentary ();
2519 clear_momentary (); /* ~~~handle character and character*1 */
2520 #else
2521 #error
2522 #endif
2525 /* Iterative DO statement. */
2527 void
2528 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
2529 ffebld start, ffelexToken start_token,
2530 ffebld end, ffelexToken end_token,
2531 ffebld incr, ffelexToken incr_token)
2533 ffeste_check_simple_ ();
2535 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2536 if ((ffebld_op (incr) == FFEBLD_opCONTER)
2537 && (ffebld_constant_is_zero (ffebld_conter (incr))))
2539 ffebad_start (FFEBAD_DO_STEP_ZERO);
2540 ffebad_here (0, ffelex_token_where_line (incr_token),
2541 ffelex_token_where_column (incr_token));
2542 ffebad_string ("Iterative DO loop");
2543 ffebad_finish ();
2544 /* Don't bother replacing it with 1 yet. */
2547 if (label == NULL)
2548 fputs ("+ DO_iterative_nonlabeled (", dmpout);
2549 else
2550 fprintf (dmpout, "+ DO_iterative_labeled %lu (", ffelab_value (label));
2551 ffebld_dump (var);
2552 fputc ('=', dmpout);
2553 ffebld_dump (start);
2554 fputc (',', dmpout);
2555 ffebld_dump (end);
2556 fputc (',', dmpout);
2557 ffebld_dump (incr);
2558 fputs (")\n", dmpout);
2559 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2561 ffeste_emit_line_note_ ();
2562 ffecom_push_calltemps ();
2564 /* Start the DO loop. */
2566 ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
2567 var,
2568 start, start_token,
2569 end, end_token,
2570 incr, incr_token,
2571 "Iterative DO loop");
2573 ffecom_pop_calltemps ();
2575 #else
2576 #error
2577 #endif
2580 /* ffeste_R819B -- DO WHILE statement
2582 ffeste_R819B(construct_name,label_token,expr,expr_token);
2584 Make sure statement is valid here; implement. */
2586 void
2587 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
2589 ffeste_check_simple_ ();
2591 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2592 if (label == NULL)
2593 fputs ("+ DO_WHILE_nonlabeled (", dmpout);
2594 else
2595 fprintf (dmpout, "+ DO_WHILE_labeled %lu (", ffelab_value (label));
2596 ffebld_dump (expr);
2597 fputs (")\n", dmpout);
2598 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2600 ffeste_emit_line_note_ ();
2601 ffecom_push_calltemps ();
2603 ffestw_set_do_hook (block, expand_start_loop (1));
2604 ffestw_set_do_tvar (block, 0); /* Means DO WHILE vs. iter DO. */
2605 if (expr != NULL)
2606 expand_exit_loop_if_false (0, ffecom_truth_value (ffecom_expr (expr)));
2608 ffecom_pop_calltemps ();
2609 clear_momentary ();
2611 #else
2612 #error
2613 #endif
2616 /* ffeste_R825 -- END DO statement
2618 ffeste_R825(name_token);
2620 Make sure ffeste_kind_ identifies a DO block. If not
2621 NULL, make sure name_token gives the correct name. Do whatever
2622 is specific to seeing END DO with a DO-target label definition on it,
2623 where the END DO is really treated as a CONTINUE (i.e. generate th
2624 same code you would for CONTINUE). ffeste_do handles the actual
2625 generation of end-loop code. */
2627 void
2628 ffeste_R825 ()
2630 ffeste_check_simple_ ();
2632 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2633 fputs ("+ END_DO_sugar\n", dmpout);
2634 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2635 ffeste_emit_line_note_ ();
2636 emit_nop ();
2637 #else
2638 #error
2639 #endif
2642 /* ffeste_R834 -- CYCLE statement
2644 ffeste_R834(name_token);
2646 Handle a CYCLE within a loop. */
2648 void
2649 ffeste_R834 (ffestw block)
2651 ffeste_check_simple_ ();
2653 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2654 fprintf (dmpout, "+ CYCLE block #%lu\n", ffestw_blocknum (block));
2655 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2656 ffeste_emit_line_note_ ();
2657 expand_continue_loop (ffestw_do_hook (block));
2658 clear_momentary ();
2659 #else
2660 #error
2661 #endif
2664 /* ffeste_R835 -- EXIT statement
2666 ffeste_R835(name_token);
2668 Handle a EXIT within a loop. */
2670 void
2671 ffeste_R835 (ffestw block)
2673 ffeste_check_simple_ ();
2675 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2676 fprintf (dmpout, "+ EXIT block #%lu\n", ffestw_blocknum (block));
2677 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2678 ffeste_emit_line_note_ ();
2679 expand_exit_loop (ffestw_do_hook (block));
2680 clear_momentary ();
2681 #else
2682 #error
2683 #endif
2686 /* ffeste_R836 -- GOTO statement
2688 ffeste_R836(label);
2690 Make sure label_token identifies a valid label for a GOTO. Update
2691 that label's info to indicate it is the target of a GOTO. */
2693 void
2694 ffeste_R836 (ffelab label)
2696 ffeste_check_simple_ ();
2698 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2699 fprintf (dmpout, "+ GOTO %lu\n", ffelab_value (label));
2700 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2702 tree glabel;
2704 ffeste_emit_line_note_ ();
2705 glabel = ffecom_lookup_label (label);
2706 if ((glabel != NULL_TREE)
2707 && (TREE_CODE (glabel) != ERROR_MARK))
2709 TREE_USED (glabel) = 1;
2710 expand_goto (glabel);
2711 clear_momentary ();
2714 #else
2715 #error
2716 #endif
2719 /* ffeste_R837 -- Computed GOTO statement
2721 ffeste_R837(labels,count,expr);
2723 Make sure label_list identifies valid labels for a GOTO. Update
2724 each label's info to indicate it is the target of a GOTO. */
2726 void
2727 ffeste_R837 (ffelab *labels, int count, ffebld expr)
2729 int i;
2731 ffeste_check_simple_ ();
2733 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2734 fputs ("+ CGOTO (", dmpout);
2735 for (i = 0; i < count; ++i)
2737 if (i != 0)
2738 fputc (',', dmpout);
2739 fprintf (dmpout, "%" ffelabValue_f "u", ffelab_value (labels[i]));
2741 fputs ("),", dmpout);
2742 ffebld_dump (expr);
2743 fputc ('\n', dmpout);
2744 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2746 tree texpr;
2747 tree value;
2748 tree tlabel;
2749 int pushok;
2750 tree duplicate;
2752 ffeste_emit_line_note_ ();
2753 ffecom_push_calltemps ();
2755 texpr = ffecom_expr (expr);
2756 expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
2757 push_momentary (); /* In case of lots of labels, keep clearing
2758 them out. */
2759 for (i = 0; i < count; ++i)
2761 value = build_int_2 (i + 1, 0);
2762 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2764 pushok = pushcase (value, convert, tlabel, &duplicate);
2765 assert (pushok == 0);
2766 tlabel = ffecom_lookup_label (labels[i]);
2767 if ((tlabel == NULL_TREE)
2768 || (TREE_CODE (tlabel) == ERROR_MARK))
2769 continue;
2770 TREE_USED (tlabel) = 1;
2771 expand_goto (tlabel);
2772 clear_momentary ();
2774 pop_momentary ();
2775 expand_end_case (texpr);
2777 ffecom_pop_calltemps ();
2778 clear_momentary ();
2780 #else
2781 #error
2782 #endif
2785 /* ffeste_R838 -- ASSIGN statement
2787 ffeste_R838(label_token,target_variable,target_token);
2789 Make sure label_token identifies a valid label for an assignment. Update
2790 that label's info to indicate it is the source of an assignment. Update
2791 target_variable's info to indicate it is the target the assignment of that
2792 label. */
2794 void
2795 ffeste_R838 (ffelab label, ffebld target)
2797 ffeste_check_simple_ ();
2799 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2800 fprintf (dmpout, "+ ASSIGN %lu TO ", ffelab_value (label));
2801 ffebld_dump (target);
2802 fputc ('\n', dmpout);
2803 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2805 tree expr_tree;
2806 tree label_tree;
2807 tree target_tree;
2809 ffeste_emit_line_note_ ();
2810 ffecom_push_calltemps ();
2812 label_tree = ffecom_lookup_label (label);
2813 if ((label_tree != NULL_TREE)
2814 && (TREE_CODE (label_tree) != ERROR_MARK))
2816 label_tree = ffecom_1 (ADDR_EXPR,
2817 build_pointer_type (void_type_node),
2818 label_tree);
2819 TREE_CONSTANT (label_tree) = 1;
2820 target_tree = ffecom_expr_assign_w (target);
2821 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
2822 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
2823 error ("ASSIGN to variable that is too small");
2824 label_tree = convert (TREE_TYPE (target_tree), label_tree);
2825 expr_tree = ffecom_modify (void_type_node,
2826 target_tree,
2827 label_tree);
2828 expand_expr_stmt (expr_tree);
2829 clear_momentary ();
2832 ffecom_pop_calltemps ();
2834 #else
2835 #error
2836 #endif
2839 /* ffeste_R839 -- Assigned GOTO statement
2841 ffeste_R839(target,target_token,label_list);
2843 Make sure label_list identifies valid labels for a GOTO. Update
2844 each label's info to indicate it is the target of a GOTO. */
2846 void
2847 ffeste_R839 (ffebld target)
2849 ffeste_check_simple_ ();
2851 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2852 fputs ("+ AGOTO ", dmpout);
2853 ffebld_dump (target);
2854 fputc ('\n', dmpout);
2855 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2857 tree t;
2859 ffeste_emit_line_note_ ();
2860 ffecom_push_calltemps ();
2862 t = ffecom_expr_assign (target);
2863 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2864 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2865 error ("ASSIGNed GOTO target variable is too small");
2866 expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
2868 ffecom_pop_calltemps ();
2869 clear_momentary ();
2871 #else
2872 #error
2873 #endif
2876 /* ffeste_R840 -- Arithmetic IF statement
2878 ffeste_R840(expr,expr_token,neg,zero,pos);
2880 Make sure the labels are valid; implement. */
2882 void
2883 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
2885 ffeste_check_simple_ ();
2887 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2888 fputs ("+ IF_arithmetic (", dmpout);
2889 ffebld_dump (expr);
2890 fprintf (dmpout, ") %" ffelabValue_f "u,%" ffelabValue_f "u,%" ffelabValue_f "u\n",
2891 ffelab_value (neg), ffelab_value (zero), ffelab_value (pos));
2892 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
2894 tree gneg = ffecom_lookup_label (neg);
2895 tree gzero = ffecom_lookup_label (zero);
2896 tree gpos = ffecom_lookup_label (pos);
2897 tree texpr;
2899 if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
2900 return;
2901 if ((TREE_CODE (gneg) == ERROR_MARK)
2902 || (TREE_CODE (gzero) == ERROR_MARK)
2903 || (TREE_CODE (gpos) == ERROR_MARK))
2904 return;
2906 ffecom_push_calltemps ();
2908 if (neg == zero)
2910 if (neg == pos)
2911 expand_goto (gzero);
2912 else
2913 { /* IF (expr.LE.0) THEN GOTO neg/zero ELSE
2914 GOTO pos. */
2915 texpr = ffecom_expr (expr);
2916 texpr = ffecom_2 (LE_EXPR, integer_type_node,
2917 texpr,
2918 convert (TREE_TYPE (texpr),
2919 integer_zero_node));
2920 expand_start_cond (ffecom_truth_value (texpr), 0);
2921 expand_goto (gzero);
2922 expand_start_else ();
2923 expand_goto (gpos);
2924 expand_end_cond ();
2927 else if (neg == pos)
2928 { /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO
2929 zero. */
2930 texpr = ffecom_expr (expr);
2931 texpr = ffecom_2 (NE_EXPR, integer_type_node,
2932 texpr,
2933 convert (TREE_TYPE (texpr),
2934 integer_zero_node));
2935 expand_start_cond (ffecom_truth_value (texpr), 0);
2936 expand_goto (gneg);
2937 expand_start_else ();
2938 expand_goto (gzero);
2939 expand_end_cond ();
2941 else if (zero == pos)
2942 { /* IF (expr.GE.0) THEN GOTO zero/pos ELSE
2943 GOTO neg. */
2944 texpr = ffecom_expr (expr);
2945 texpr = ffecom_2 (GE_EXPR, integer_type_node,
2946 texpr,
2947 convert (TREE_TYPE (texpr),
2948 integer_zero_node));
2949 expand_start_cond (ffecom_truth_value (texpr), 0);
2950 expand_goto (gzero);
2951 expand_start_else ();
2952 expand_goto (gneg);
2953 expand_end_cond ();
2955 else
2956 { /* Use a SAVE_EXPR in combo with:
2957 IF (expr.LT.0) THEN GOTO neg
2958 ELSEIF (expr.GT.0) THEN GOTO pos
2959 ELSE GOTO zero. */
2960 tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
2962 texpr = ffecom_2 (LT_EXPR, integer_type_node,
2963 expr_saved,
2964 convert (TREE_TYPE (expr_saved),
2965 integer_zero_node));
2966 expand_start_cond (ffecom_truth_value (texpr), 0);
2967 expand_goto (gneg);
2968 texpr = ffecom_2 (GT_EXPR, integer_type_node,
2969 expr_saved,
2970 convert (TREE_TYPE (expr_saved),
2971 integer_zero_node));
2972 expand_start_elseif (ffecom_truth_value (texpr));
2973 expand_goto (gpos);
2974 expand_start_else ();
2975 expand_goto (gzero);
2976 expand_end_cond ();
2978 ffeste_emit_line_note_ ();
2980 ffecom_pop_calltemps ();
2981 clear_momentary ();
2983 #else
2984 #error
2985 #endif
2988 /* ffeste_R841 -- CONTINUE statement
2990 ffeste_R841(); */
2992 void
2993 ffeste_R841 ()
2995 ffeste_check_simple_ ();
2997 #if FFECOM_targetCURRENT == FFECOM_targetFFE
2998 fputs ("+ CONTINUE\n", dmpout);
2999 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3000 ffeste_emit_line_note_ ();
3001 emit_nop ();
3002 #else
3003 #error
3004 #endif
3007 /* ffeste_R842 -- STOP statement
3009 ffeste_R842(expr); */
3011 void
3012 ffeste_R842 (ffebld expr)
3014 ffeste_check_simple_ ();
3016 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3017 if (expr == NULL)
3019 fputs ("+ STOP\n", dmpout);
3021 else
3023 fputs ("+ STOP_coded ", dmpout);
3024 ffebld_dump (expr);
3025 fputc ('\n', dmpout);
3027 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3029 tree callit;
3030 ffelexToken msg;
3032 ffeste_emit_line_note_ ();
3033 if ((expr == NULL)
3034 || (ffeinfo_basictype (ffebld_info (expr))
3035 == FFEINFO_basictypeANY))
3037 msg = ffelex_token_new_character ("", ffelex_token_where_line
3038 (ffesta_tokens[0]), ffelex_token_where_column
3039 (ffesta_tokens[0]));
3040 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3041 (msg));
3042 ffelex_token_kill (msg);
3043 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3044 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3045 FFEINFO_whereCONSTANT, 0));
3047 else if (ffeinfo_basictype (ffebld_info (expr))
3048 == FFEINFO_basictypeINTEGER)
3050 char num[50];
3052 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3053 assert (ffeinfo_kindtype (ffebld_info (expr))
3054 == FFEINFO_kindtypeINTEGERDEFAULT);
3055 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3056 ffebld_constant_integer1 (ffebld_conter (expr)));
3057 msg = ffelex_token_new_character (num, ffelex_token_where_line
3058 (ffesta_tokens[0]), ffelex_token_where_column
3059 (ffesta_tokens[0]));
3060 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3061 (msg));
3062 ffelex_token_kill (msg);
3063 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3064 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3065 FFEINFO_whereCONSTANT, 0));
3067 else
3069 assert (ffeinfo_basictype (ffebld_info (expr))
3070 == FFEINFO_basictypeCHARACTER);
3071 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3072 assert (ffeinfo_kindtype (ffebld_info (expr))
3073 == FFEINFO_kindtypeCHARACTERDEFAULT);
3076 ffecom_push_calltemps ();
3077 callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3078 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
3079 ffecom_pop_calltemps ();
3080 TREE_SIDE_EFFECTS (callit) = 1;
3081 expand_expr_stmt (callit);
3082 clear_momentary ();
3084 #else
3085 #error
3086 #endif
3089 /* ffeste_R843 -- PAUSE statement
3091 ffeste_R843(expr,expr_token);
3093 Make sure statement is valid here; implement. expr and expr_token are
3094 both NULL if there was no expression. */
3096 void
3097 ffeste_R843 (ffebld expr)
3099 ffeste_check_simple_ ();
3101 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3102 if (expr == NULL)
3104 fputs ("+ PAUSE\n", dmpout);
3106 else
3108 fputs ("+ PAUSE_coded ", dmpout);
3109 ffebld_dump (expr);
3110 fputc ('\n', dmpout);
3112 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3114 tree callit;
3115 ffelexToken msg;
3117 ffeste_emit_line_note_ ();
3118 if ((expr == NULL)
3119 || (ffeinfo_basictype (ffebld_info (expr))
3120 == FFEINFO_basictypeANY))
3122 msg = ffelex_token_new_character ("", ffelex_token_where_line
3123 (ffesta_tokens[0]), ffelex_token_where_column
3124 (ffesta_tokens[0]));
3125 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3126 (msg));
3127 ffelex_token_kill (msg);
3128 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3129 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3130 FFEINFO_whereCONSTANT, 0));
3132 else if (ffeinfo_basictype (ffebld_info (expr))
3133 == FFEINFO_basictypeINTEGER)
3135 char num[50];
3137 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3138 assert (ffeinfo_kindtype (ffebld_info (expr))
3139 == FFEINFO_kindtypeINTEGERDEFAULT);
3140 sprintf (num, "%" ffetargetIntegerDefault_f "d",
3141 ffebld_constant_integer1 (ffebld_conter (expr)));
3142 msg = ffelex_token_new_character (num, ffelex_token_where_line
3143 (ffesta_tokens[0]), ffelex_token_where_column
3144 (ffesta_tokens[0]));
3145 expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3146 (msg));
3147 ffelex_token_kill (msg);
3148 ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3149 FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
3150 FFEINFO_whereCONSTANT, 0));
3152 else
3154 assert (ffeinfo_basictype (ffebld_info (expr))
3155 == FFEINFO_basictypeCHARACTER);
3156 assert (ffebld_op (expr) == FFEBLD_opCONTER);
3157 assert (ffeinfo_kindtype (ffebld_info (expr))
3158 == FFEINFO_kindtypeCHARACTERDEFAULT);
3161 ffecom_push_calltemps ();
3162 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3163 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
3164 ffecom_pop_calltemps ();
3165 TREE_SIDE_EFFECTS (callit) = 1;
3166 expand_expr_stmt (callit);
3167 clear_momentary ();
3169 #if 0 /* Old approach for phantom g77 run-time
3170 library. */
3172 tree callit;
3174 ffeste_emit_line_note_ ();
3175 if (expr == NULL)
3176 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE);
3177 else if (ffeinfo_basictype (ffebld_info (expr))
3178 == FFEINFO_basictypeINTEGER)
3180 ffecom_push_calltemps ();
3181 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
3182 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
3183 ffecom_pop_calltemps ();
3185 else
3187 if (ffeinfo_basictype (ffebld_info (expr))
3188 != FFEINFO_basictypeCHARACTER)
3189 break;
3190 ffecom_push_calltemps ();
3191 callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
3192 ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
3193 ffecom_pop_calltemps ();
3195 TREE_SIDE_EFFECTS (callit) = 1;
3196 expand_expr_stmt (callit);
3197 clear_momentary ();
3199 #endif
3200 #else
3201 #error
3202 #endif
3205 /* ffeste_R904 -- OPEN statement
3207 ffeste_R904();
3209 Make sure an OPEN is valid in the current context, and implement it. */
3211 void
3212 ffeste_R904 (ffestpOpenStmt *info)
3214 ffeste_check_simple_ ();
3216 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3217 fputs ("+ OPEN (", dmpout);
3218 ffeste_subr_file_ ("UNIT", &info->open_spec[FFESTP_openixUNIT]);
3219 ffeste_subr_file_ ("ACCESS", &info->open_spec[FFESTP_openixACCESS]);
3220 ffeste_subr_file_ ("ACTION", &info->open_spec[FFESTP_openixACTION]);
3221 ffeste_subr_file_ ("ASSOCIATEVARIABLE", &info->open_spec[FFESTP_openixASSOCIATEVARIABLE]);
3222 ffeste_subr_file_ ("BLANK", &info->open_spec[FFESTP_openixBLANK]);
3223 ffeste_subr_file_ ("BLOCKSIZE", &info->open_spec[FFESTP_openixBLOCKSIZE]);
3224 ffeste_subr_file_ ("BUFFERCOUNT", &info->open_spec[FFESTP_openixBUFFERCOUNT]);
3225 ffeste_subr_file_ ("CARRIAGECONTROL", &info->open_spec[FFESTP_openixCARRIAGECONTROL]);
3226 ffeste_subr_file_ ("DEFAULTFILE", &info->open_spec[FFESTP_openixDEFAULTFILE]);
3227 ffeste_subr_file_ ("DELIM", &info->open_spec[FFESTP_openixDELIM]);
3228 ffeste_subr_file_ ("DISPOSE", &info->open_spec[FFESTP_openixDISPOSE]);
3229 ffeste_subr_file_ ("ERR", &info->open_spec[FFESTP_openixERR]);
3230 ffeste_subr_file_ ("EXTENDSIZE", &info->open_spec[FFESTP_openixEXTENDSIZE]);
3231 ffeste_subr_file_ ("FILE", &info->open_spec[FFESTP_openixFILE]);
3232 ffeste_subr_file_ ("FORM", &info->open_spec[FFESTP_openixFORM]);
3233 ffeste_subr_file_ ("INITIALSIZE", &info->open_spec[FFESTP_openixINITIALSIZE]);
3234 ffeste_subr_file_ ("IOSTAT", &info->open_spec[FFESTP_openixIOSTAT]);
3235 ffeste_subr_file_ ("KEY", &info->open_spec[FFESTP_openixKEY]);
3236 ffeste_subr_file_ ("MAXREC", &info->open_spec[FFESTP_openixMAXREC]);
3237 ffeste_subr_file_ ("NOSPANBLOCKS", &info->open_spec[FFESTP_openixNOSPANBLOCKS]);
3238 ffeste_subr_file_ ("ORGANIZATION", &info->open_spec[FFESTP_openixORGANIZATION]);
3239 ffeste_subr_file_ ("PAD", &info->open_spec[FFESTP_openixPAD]);
3240 ffeste_subr_file_ ("POSITION", &info->open_spec[FFESTP_openixPOSITION]);
3241 ffeste_subr_file_ ("READONLY", &info->open_spec[FFESTP_openixREADONLY]);
3242 ffeste_subr_file_ ("RECL", &info->open_spec[FFESTP_openixRECL]);
3243 ffeste_subr_file_ ("RECORDTYPE", &info->open_spec[FFESTP_openixRECORDTYPE]);
3244 ffeste_subr_file_ ("SHARED", &info->open_spec[FFESTP_openixSHARED]);
3245 ffeste_subr_file_ ("STATUS", &info->open_spec[FFESTP_openixSTATUS]);
3246 ffeste_subr_file_ ("USEROPEN", &info->open_spec[FFESTP_openixUSEROPEN]);
3247 fputs (")\n", dmpout);
3248 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3250 tree args;
3251 bool iostat;
3252 bool errl;
3254 #define specified(something) (info->open_spec[something].kw_or_val_present)
3256 ffeste_emit_line_note_ ();
3258 iostat = specified (FFESTP_openixIOSTAT);
3259 errl = specified (FFESTP_openixERR);
3261 ffecom_push_calltemps ();
3263 args = ffeste_io_olist_ (errl || iostat,
3264 info->open_spec[FFESTP_openixUNIT].u.expr,
3265 &info->open_spec[FFESTP_openixFILE],
3266 &info->open_spec[FFESTP_openixSTATUS],
3267 &info->open_spec[FFESTP_openixACCESS],
3268 &info->open_spec[FFESTP_openixFORM],
3269 &info->open_spec[FFESTP_openixRECL],
3270 &info->open_spec[FFESTP_openixBLANK]);
3272 if (errl)
3274 ffeste_io_err_
3275 = ffeste_io_abort_
3276 = ffecom_lookup_label
3277 (info->open_spec[FFESTP_openixERR].u.label);
3278 ffeste_io_abort_is_temp_ = FALSE;
3280 else
3282 ffeste_io_err_ = NULL_TREE;
3284 if ((ffeste_io_abort_is_temp_ = iostat))
3285 ffeste_io_abort_ = ffecom_temp_label ();
3286 else
3287 ffeste_io_abort_ = NULL_TREE;
3290 if (iostat)
3291 { /* IOSTAT= */
3292 ffeste_io_iostat_is_temp_ = FALSE;
3293 ffeste_io_iostat_ = ffecom_expr
3294 (info->open_spec[FFESTP_openixIOSTAT].u.expr);
3296 else if (ffeste_io_abort_ != NULL_TREE)
3297 { /* no IOSTAT= but ERR= */
3298 ffeste_io_iostat_is_temp_ = TRUE;
3299 ffeste_io_iostat_
3300 = ffecom_push_tempvar (ffecom_integer_type_node,
3301 FFETARGET_charactersizeNONE, -1, FALSE);
3303 else
3304 { /* no IOSTAT=, or ERR= */
3305 ffeste_io_iostat_is_temp_ = FALSE;
3306 ffeste_io_iostat_ = NULL_TREE;
3309 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3310 label, since we're gonna fall through to there anyway. */
3312 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args),
3313 !ffeste_io_abort_is_temp_);
3315 /* If we've got a temp label, generate its code here. */
3317 if (ffeste_io_abort_is_temp_)
3319 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3320 emit_nop ();
3321 expand_label (ffeste_io_abort_);
3323 assert (ffeste_io_err_ == NULL_TREE);
3326 /* If we've got a temp iostat, pop the temp. */
3328 if (ffeste_io_iostat_is_temp_)
3329 ffecom_pop_tempvar (ffeste_io_iostat_);
3331 ffecom_pop_calltemps ();
3333 #undef specified
3336 clear_momentary ();
3337 #else
3338 #error
3339 #endif
3342 /* ffeste_R907 -- CLOSE statement
3344 ffeste_R907();
3346 Make sure a CLOSE is valid in the current context, and implement it. */
3348 void
3349 ffeste_R907 (ffestpCloseStmt *info)
3351 ffeste_check_simple_ ();
3353 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3354 fputs ("+ CLOSE (", dmpout);
3355 ffeste_subr_file_ ("UNIT", &info->close_spec[FFESTP_closeixUNIT]);
3356 ffeste_subr_file_ ("ERR", &info->close_spec[FFESTP_closeixERR]);
3357 ffeste_subr_file_ ("IOSTAT", &info->close_spec[FFESTP_closeixIOSTAT]);
3358 ffeste_subr_file_ ("STATUS", &info->close_spec[FFESTP_closeixSTATUS]);
3359 fputs (")\n", dmpout);
3360 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3362 tree args;
3363 bool iostat;
3364 bool errl;
3366 #define specified(something) (info->close_spec[something].kw_or_val_present)
3368 ffeste_emit_line_note_ ();
3370 iostat = specified (FFESTP_closeixIOSTAT);
3371 errl = specified (FFESTP_closeixERR);
3373 ffecom_push_calltemps ();
3375 args = ffeste_io_cllist_ (errl || iostat,
3376 info->close_spec[FFESTP_closeixUNIT].u.expr,
3377 &info->close_spec[FFESTP_closeixSTATUS]);
3379 if (errl)
3381 ffeste_io_err_
3382 = ffeste_io_abort_
3383 = ffecom_lookup_label
3384 (info->close_spec[FFESTP_closeixERR].u.label);
3385 ffeste_io_abort_is_temp_ = FALSE;
3387 else
3389 ffeste_io_err_ = NULL_TREE;
3391 if ((ffeste_io_abort_is_temp_ = iostat))
3392 ffeste_io_abort_ = ffecom_temp_label ();
3393 else
3394 ffeste_io_abort_ = NULL_TREE;
3397 if (iostat)
3398 { /* IOSTAT= */
3399 ffeste_io_iostat_is_temp_ = FALSE;
3400 ffeste_io_iostat_ = ffecom_expr
3401 (info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3403 else if (ffeste_io_abort_ != NULL_TREE)
3404 { /* no IOSTAT= but ERR= */
3405 ffeste_io_iostat_is_temp_ = TRUE;
3406 ffeste_io_iostat_
3407 = ffecom_push_tempvar (ffecom_integer_type_node,
3408 FFETARGET_charactersizeNONE, -1, FALSE);
3410 else
3411 { /* no IOSTAT=, or ERR= */
3412 ffeste_io_iostat_is_temp_ = FALSE;
3413 ffeste_io_iostat_ = NULL_TREE;
3416 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3417 label, since we're gonna fall through to there anyway. */
3419 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args),
3420 !ffeste_io_abort_is_temp_);
3422 /* If we've got a temp label, generate its code here. */
3424 if (ffeste_io_abort_is_temp_)
3426 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3427 emit_nop ();
3428 expand_label (ffeste_io_abort_);
3430 assert (ffeste_io_err_ == NULL_TREE);
3433 /* If we've got a temp iostat, pop the temp. */
3435 if (ffeste_io_iostat_is_temp_)
3436 ffecom_pop_tempvar (ffeste_io_iostat_);
3438 ffecom_pop_calltemps ();
3440 #undef specified
3443 clear_momentary ();
3444 #else
3445 #error
3446 #endif
3449 /* ffeste_R909_start -- READ(...) statement list begin
3451 ffeste_R909_start(FALSE);
3453 Verify that READ is valid here, and begin accepting items in the
3454 list. */
3456 void
3457 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3458 ffestvUnit unit, ffestvFormat format, bool rec,
3459 bool key UNUSED)
3461 ffeste_check_start_ ();
3463 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3464 switch (format)
3466 case FFESTV_formatNONE:
3467 if (rec)
3468 fputs ("+ READ_ufdac", dmpout);
3469 else if (key)
3470 fputs ("+ READ_ufidx", dmpout);
3471 else
3472 fputs ("+ READ_ufseq", dmpout);
3473 break;
3475 case FFESTV_formatLABEL:
3476 case FFESTV_formatCHAREXPR:
3477 case FFESTV_formatINTEXPR:
3478 if (rec)
3479 fputs ("+ READ_fmdac", dmpout);
3480 else if (key)
3481 fputs ("+ READ_fmidx", dmpout);
3482 else if (unit == FFESTV_unitCHAREXPR)
3483 fputs ("+ READ_fmint", dmpout);
3484 else
3485 fputs ("+ READ_fmseq", dmpout);
3486 break;
3488 case FFESTV_formatASTERISK:
3489 if (unit == FFESTV_unitCHAREXPR)
3490 fputs ("+ READ_lsint", dmpout);
3491 else
3492 fputs ("+ READ_lsseq", dmpout);
3493 break;
3495 case FFESTV_formatNAMELIST:
3496 fputs ("+ READ_nlseq", dmpout);
3497 break;
3499 default:
3500 assert ("Unexpected kind of format item in R909 READ" == NULL);
3503 if (only_format)
3505 fputc (' ', dmpout);
3506 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3507 fputc (' ', dmpout);
3509 return;
3512 fputs (" (", dmpout);
3513 ffeste_subr_file_ ("UNIT", &info->read_spec[FFESTP_readixUNIT]);
3514 ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
3515 ffeste_subr_file_ ("ADVANCE", &info->read_spec[FFESTP_readixADVANCE]);
3516 ffeste_subr_file_ ("EOR", &info->read_spec[FFESTP_readixEOR]);
3517 ffeste_subr_file_ ("ERR", &info->read_spec[FFESTP_readixERR]);
3518 ffeste_subr_file_ ("END", &info->read_spec[FFESTP_readixEND]);
3519 ffeste_subr_file_ ("IOSTAT", &info->read_spec[FFESTP_readixIOSTAT]);
3520 ffeste_subr_file_ ("KEYEQ", &info->read_spec[FFESTP_readixKEYEQ]);
3521 ffeste_subr_file_ ("KEYGE", &info->read_spec[FFESTP_readixKEYGE]);
3522 ffeste_subr_file_ ("KEYGT", &info->read_spec[FFESTP_readixKEYGT]);
3523 ffeste_subr_file_ ("KEYID", &info->read_spec[FFESTP_readixKEYID]);
3524 ffeste_subr_file_ ("NULLS", &info->read_spec[FFESTP_readixNULLS]);
3525 ffeste_subr_file_ ("REC", &info->read_spec[FFESTP_readixREC]);
3526 ffeste_subr_file_ ("SIZE", &info->read_spec[FFESTP_readixSIZE]);
3527 fputs (") ", dmpout);
3528 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3530 #define specified(something) (info->read_spec[something].kw_or_val_present)
3532 ffeste_emit_line_note_ ();
3534 /* Do the real work. */
3537 ffecomGfrt start;
3538 ffecomGfrt end;
3539 tree cilist;
3540 bool iostat;
3541 bool errl;
3542 bool endl;
3544 /* First determine the start, per-item, and end run-time functions to
3545 call. The per-item function is picked by choosing an ffeste functio
3546 to call to handle a given item; it knows how to generate a call to the
3547 appropriate run-time function, and is called an "io driver". It
3548 handles the implied-DO construct, for example. */
3550 switch (format)
3552 case FFESTV_formatNONE: /* no FMT= */
3553 ffeste_io_driver_ = ffeste_io_douio_;
3554 if (rec)
3555 start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
3556 #if 0
3557 else if (key)
3558 start = FFECOM_gfrtSRIUE, end = FFECOM_gfrtERIUE;
3559 #endif
3560 else
3561 start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
3562 break;
3564 case FFESTV_formatLABEL: /* FMT=10 */
3565 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3566 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3567 ffeste_io_driver_ = ffeste_io_dofio_;
3568 if (rec)
3569 start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
3570 #if 0
3571 else if (key)
3572 start = FFECOM_gfrtSRIFE, end = FFECOM_gfrtERIFE;
3573 #endif
3574 else if (unit == FFESTV_unitCHAREXPR)
3575 start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
3576 else
3577 start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
3578 break;
3580 case FFESTV_formatASTERISK: /* FMT=* */
3581 ffeste_io_driver_ = ffeste_io_dolio_;
3582 if (unit == FFESTV_unitCHAREXPR)
3583 start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
3584 else
3585 start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
3586 break;
3588 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3589 /FOO/] */
3590 ffeste_io_driver_ = NULL; /* No start or driver function. */
3591 start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
3592 break;
3594 default:
3595 assert ("Weird stuff" == NULL);
3596 start = FFECOM_gfrt, end = FFECOM_gfrt;
3597 break;
3599 ffeste_io_endgfrt_ = end;
3601 iostat = specified (FFESTP_readixIOSTAT);
3602 errl = specified (FFESTP_readixERR);
3603 endl = specified (FFESTP_readixEND);
3605 ffecom_push_calltemps ();
3607 if (unit == FFESTV_unitCHAREXPR)
3609 cilist = ffeste_io_icilist_ (errl || iostat,
3610 info->read_spec[FFESTP_readixUNIT].u.expr,
3611 endl || iostat, format,
3612 &info->read_spec[FFESTP_readixFORMAT]);
3614 else
3616 cilist = ffeste_io_cilist_ (errl || iostat, unit,
3617 info->read_spec[FFESTP_readixUNIT].u.expr,
3618 5, endl || iostat, format,
3619 &info->read_spec[FFESTP_readixFORMAT],
3620 rec,
3621 info->read_spec[FFESTP_readixREC].u.expr);
3624 if (errl)
3625 { /* ERR= */
3626 ffeste_io_err_
3627 = ffecom_lookup_label
3628 (info->read_spec[FFESTP_readixERR].u.label);
3630 if (endl)
3631 { /* ERR= END= */
3632 ffeste_io_end_
3633 = ffecom_lookup_label
3634 (info->read_spec[FFESTP_readixEND].u.label);
3635 ffeste_io_abort_is_temp_ = TRUE;
3636 ffeste_io_abort_ = ffecom_temp_label ();
3638 else
3639 { /* ERR= but no END= */
3640 ffeste_io_end_ = NULL_TREE;
3641 if ((ffeste_io_abort_is_temp_ = iostat))
3642 ffeste_io_abort_ = ffecom_temp_label ();
3643 else
3644 ffeste_io_abort_ = ffeste_io_err_;
3647 else
3648 { /* no ERR= */
3649 ffeste_io_err_ = NULL_TREE;
3650 if (endl)
3651 { /* END= but no ERR= */
3652 ffeste_io_end_
3653 = ffecom_lookup_label
3654 (info->read_spec[FFESTP_readixEND].u.label);
3655 if ((ffeste_io_abort_is_temp_ = iostat))
3656 ffeste_io_abort_ = ffecom_temp_label ();
3657 else
3658 ffeste_io_abort_ = ffeste_io_end_;
3660 else
3661 { /* no ERR= or END= */
3662 ffeste_io_end_ = NULL_TREE;
3663 if ((ffeste_io_abort_is_temp_ = iostat))
3664 ffeste_io_abort_ = ffecom_temp_label ();
3665 else
3666 ffeste_io_abort_ = NULL_TREE;
3670 if (iostat)
3671 { /* IOSTAT= */
3672 ffeste_io_iostat_is_temp_ = FALSE;
3673 ffeste_io_iostat_ = ffecom_expr
3674 (info->read_spec[FFESTP_readixIOSTAT].u.expr);
3676 else if (ffeste_io_abort_ != NULL_TREE)
3677 { /* no IOSTAT= but ERR= or END= or both */
3678 ffeste_io_iostat_is_temp_ = TRUE;
3679 ffeste_io_iostat_
3680 = ffecom_push_tempvar (ffecom_integer_type_node,
3681 FFETARGET_charactersizeNONE, -1, FALSE);
3683 else
3684 { /* no IOSTAT=, ERR=, or END= */
3685 ffeste_io_iostat_is_temp_ = FALSE;
3686 ffeste_io_iostat_ = NULL_TREE;
3689 /* If there is no end function, then there are no item functions (i.e.
3690 it's a NAMELIST), and vice versa by the way. In this situation, don't
3691 generate the "if (iostat != 0) goto label;" if the label is temp abort
3692 label, since we're gonna fall through to there anyway. */
3694 ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
3695 !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
3698 #undef specified
3700 push_momentary ();
3701 #else
3702 #error
3703 #endif
3706 /* ffeste_R909_item -- READ statement i/o item
3708 ffeste_R909_item(expr,expr_token);
3710 Implement output-list expression. */
3712 void
3713 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
3715 ffeste_check_item_ ();
3717 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3718 ffebld_dump (expr);
3719 fputc (',', dmpout);
3720 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3721 if (expr == NULL)
3722 return;
3723 while (ffebld_op (expr) == FFEBLD_opPAREN)
3724 expr = ffebld_left (expr); /* "READ *,(A)" -- really a bug in the user's
3725 code, but I've been told lots of code does
3726 this (blech)! */
3727 if (ffebld_op (expr) == FFEBLD_opANY)
3728 return;
3729 if (ffebld_op (expr) == FFEBLD_opIMPDO)
3730 ffeste_io_impdo_ (expr, expr_token);
3731 else
3732 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3733 clear_momentary ();
3734 #else
3735 #error
3736 #endif
3739 /* ffeste_R909_finish -- READ statement list complete
3741 ffeste_R909_finish();
3743 Just wrap up any local activities. */
3745 void
3746 ffeste_R909_finish ()
3748 ffeste_check_finish_ ();
3750 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3751 fputc ('\n', dmpout);
3752 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3754 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3755 label, since we're gonna fall through to there anyway. */
3758 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3759 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
3760 !ffeste_io_abort_is_temp_);
3762 clear_momentary ();
3763 pop_momentary ();
3765 /* If we've got a temp label, generate its code here and have it fan out
3766 to the END= or ERR= label as appropriate. */
3768 if (ffeste_io_abort_is_temp_)
3770 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3771 emit_nop ();
3772 expand_label (ffeste_io_abort_);
3774 /* if (iostat<0) goto end_label; */
3776 if ((ffeste_io_end_ != NULL_TREE)
3777 && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
3779 expand_start_cond (ffecom_truth_value
3780 (ffecom_2 (LT_EXPR, integer_type_node,
3781 ffeste_io_iostat_,
3782 ffecom_integer_zero_node)),
3784 expand_goto (ffeste_io_end_);
3785 expand_end_cond ();
3788 /* if (iostat>0) goto err_label; */
3790 if ((ffeste_io_err_ != NULL_TREE)
3791 && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
3793 expand_start_cond (ffecom_truth_value
3794 (ffecom_2 (GT_EXPR, integer_type_node,
3795 ffeste_io_iostat_,
3796 ffecom_integer_zero_node)),
3798 expand_goto (ffeste_io_err_);
3799 expand_end_cond ();
3804 /* If we've got a temp iostat, pop the temp. */
3806 if (ffeste_io_iostat_is_temp_)
3807 ffecom_pop_tempvar (ffeste_io_iostat_);
3809 ffecom_pop_calltemps ();
3811 clear_momentary ();
3813 #else
3814 #error
3815 #endif
3818 /* ffeste_R910_start -- WRITE(...) statement list begin
3820 ffeste_R910_start();
3822 Verify that WRITE is valid here, and begin accepting items in the
3823 list. */
3825 void
3826 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
3827 ffestvFormat format, bool rec)
3829 ffeste_check_start_ ();
3831 #if FFECOM_targetCURRENT == FFECOM_targetFFE
3832 switch (format)
3834 case FFESTV_formatNONE:
3835 if (rec)
3836 fputs ("+ WRITE_ufdac (", dmpout);
3837 else
3838 fputs ("+ WRITE_ufseq_or_idx (", dmpout);
3839 break;
3841 case FFESTV_formatLABEL:
3842 case FFESTV_formatCHAREXPR:
3843 case FFESTV_formatINTEXPR:
3844 if (rec)
3845 fputs ("+ WRITE_fmdac (", dmpout);
3846 else if (unit == FFESTV_unitCHAREXPR)
3847 fputs ("+ WRITE_fmint (", dmpout);
3848 else
3849 fputs ("+ WRITE_fmseq_or_idx (", dmpout);
3850 break;
3852 case FFESTV_formatASTERISK:
3853 if (unit == FFESTV_unitCHAREXPR)
3854 fputs ("+ WRITE_lsint (", dmpout);
3855 else
3856 fputs ("+ WRITE_lsseq (", dmpout);
3857 break;
3859 case FFESTV_formatNAMELIST:
3860 fputs ("+ WRITE_nlseq (", dmpout);
3861 break;
3863 default:
3864 assert ("Unexpected kind of format item in R910 WRITE" == NULL);
3867 ffeste_subr_file_ ("UNIT", &info->write_spec[FFESTP_writeixUNIT]);
3868 ffeste_subr_file_ ("FORMAT", &info->write_spec[FFESTP_writeixFORMAT]);
3869 ffeste_subr_file_ ("ADVANCE", &info->write_spec[FFESTP_writeixADVANCE]);
3870 ffeste_subr_file_ ("EOR", &info->write_spec[FFESTP_writeixEOR]);
3871 ffeste_subr_file_ ("ERR", &info->write_spec[FFESTP_writeixERR]);
3872 ffeste_subr_file_ ("IOSTAT", &info->write_spec[FFESTP_writeixIOSTAT]);
3873 ffeste_subr_file_ ("REC", &info->write_spec[FFESTP_writeixREC]);
3874 fputs (") ", dmpout);
3875 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
3877 #define specified(something) (info->write_spec[something].kw_or_val_present)
3879 ffeste_emit_line_note_ ();
3881 /* Do the real work. */
3884 ffecomGfrt start;
3885 ffecomGfrt end;
3886 tree cilist;
3887 bool iostat;
3888 bool errl;
3890 /* First determine the start, per-item, and end run-time functions to
3891 call. The per-item function is picked by choosing an ffeste functio
3892 to call to handle a given item; it knows how to generate a call to the
3893 appropriate run-time function, and is called an "io driver". It
3894 handles the implied-DO construct, for example. */
3896 switch (format)
3898 case FFESTV_formatNONE: /* no FMT= */
3899 ffeste_io_driver_ = ffeste_io_douio_;
3900 if (rec)
3901 start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
3902 else
3903 start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
3904 break;
3906 case FFESTV_formatLABEL: /* FMT=10 */
3907 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3908 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
3909 ffeste_io_driver_ = ffeste_io_dofio_;
3910 if (rec)
3911 start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
3912 else if (unit == FFESTV_unitCHAREXPR)
3913 start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
3914 else
3915 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3916 break;
3918 case FFESTV_formatASTERISK: /* FMT=* */
3919 ffeste_io_driver_ = ffeste_io_dolio_;
3920 if (unit == FFESTV_unitCHAREXPR)
3921 start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
3922 else
3923 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3924 break;
3926 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3927 /FOO/] */
3928 ffeste_io_driver_ = NULL; /* No start or driver function. */
3929 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3930 break;
3932 default:
3933 assert ("Weird stuff" == NULL);
3934 start = FFECOM_gfrt, end = FFECOM_gfrt;
3935 break;
3937 ffeste_io_endgfrt_ = end;
3939 iostat = specified (FFESTP_writeixIOSTAT);
3940 errl = specified (FFESTP_writeixERR);
3942 ffecom_push_calltemps ();
3944 if (unit == FFESTV_unitCHAREXPR)
3946 cilist = ffeste_io_icilist_ (errl || iostat,
3947 info->write_spec[FFESTP_writeixUNIT].u.expr,
3948 FALSE, format,
3949 &info->write_spec[FFESTP_writeixFORMAT]);
3951 else
3953 cilist = ffeste_io_cilist_ (errl || iostat, unit,
3954 info->write_spec[FFESTP_writeixUNIT].u.expr,
3955 6, FALSE, format,
3956 &info->write_spec[FFESTP_writeixFORMAT],
3957 rec,
3958 info->write_spec[FFESTP_writeixREC].u.expr);
3961 ffeste_io_end_ = NULL_TREE;
3963 if (errl)
3964 { /* ERR= */
3965 ffeste_io_err_
3966 = ffeste_io_abort_
3967 = ffecom_lookup_label
3968 (info->write_spec[FFESTP_writeixERR].u.label);
3969 ffeste_io_abort_is_temp_ = FALSE;
3971 else
3972 { /* no ERR= */
3973 ffeste_io_err_ = NULL_TREE;
3975 if ((ffeste_io_abort_is_temp_ = iostat))
3976 ffeste_io_abort_ = ffecom_temp_label ();
3977 else
3978 ffeste_io_abort_ = NULL_TREE;
3981 if (iostat)
3982 { /* IOSTAT= */
3983 ffeste_io_iostat_is_temp_ = FALSE;
3984 ffeste_io_iostat_ = ffecom_expr
3985 (info->write_spec[FFESTP_writeixIOSTAT].u.expr);
3987 else if (ffeste_io_abort_ != NULL_TREE)
3988 { /* no IOSTAT= but ERR= */
3989 ffeste_io_iostat_is_temp_ = TRUE;
3990 ffeste_io_iostat_
3991 = ffecom_push_tempvar (ffecom_integer_type_node,
3992 FFETARGET_charactersizeNONE, -1, FALSE);
3994 else
3995 { /* no IOSTAT=, or ERR= */
3996 ffeste_io_iostat_is_temp_ = FALSE;
3997 ffeste_io_iostat_ = NULL_TREE;
4000 /* If there is no end function, then there are no item functions (i.e.
4001 it's a NAMELIST), and vice versa by the way. In this situation, don't
4002 generate the "if (iostat != 0) goto label;" if the label is temp abort
4003 label, since we're gonna fall through to there anyway. */
4005 ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
4006 !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
4009 #undef specified
4011 push_momentary ();
4012 #else
4013 #error
4014 #endif
4017 /* ffeste_R910_item -- WRITE statement i/o item
4019 ffeste_R910_item(expr,expr_token);
4021 Implement output-list expression. */
4023 void
4024 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
4026 ffeste_check_item_ ();
4028 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4029 ffebld_dump (expr);
4030 fputc (',', dmpout);
4031 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4032 if (expr == NULL)
4033 return;
4034 if (ffebld_op (expr) == FFEBLD_opANY)
4035 return;
4036 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4037 ffeste_io_impdo_ (expr, expr_token);
4038 else
4039 ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
4040 clear_momentary ();
4041 #else
4042 #error
4043 #endif
4046 /* ffeste_R910_finish -- WRITE statement list complete
4048 ffeste_R910_finish();
4050 Just wrap up any local activities. */
4052 void
4053 ffeste_R910_finish ()
4055 ffeste_check_finish_ ();
4057 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4058 fputc ('\n', dmpout);
4059 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4061 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4062 label, since we're gonna fall through to there anyway. */
4065 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4066 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
4067 !ffeste_io_abort_is_temp_);
4069 clear_momentary ();
4070 pop_momentary ();
4072 /* If we've got a temp label, generate its code here. */
4074 if (ffeste_io_abort_is_temp_)
4076 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4077 emit_nop ();
4078 expand_label (ffeste_io_abort_);
4080 assert (ffeste_io_err_ == NULL_TREE);
4083 /* If we've got a temp iostat, pop the temp. */
4085 if (ffeste_io_iostat_is_temp_)
4086 ffecom_pop_tempvar (ffeste_io_iostat_);
4088 ffecom_pop_calltemps ();
4090 clear_momentary ();
4092 #else
4093 #error
4094 #endif
4097 /* ffeste_R911_start -- PRINT statement list begin
4099 ffeste_R911_start();
4101 Verify that PRINT is valid here, and begin accepting items in the
4102 list. */
4104 void
4105 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
4107 ffeste_check_start_ ();
4109 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4110 switch (format)
4112 case FFESTV_formatLABEL:
4113 case FFESTV_formatCHAREXPR:
4114 case FFESTV_formatINTEXPR:
4115 fputs ("+ PRINT_fm ", dmpout);
4116 break;
4118 case FFESTV_formatASTERISK:
4119 fputs ("+ PRINT_ls ", dmpout);
4120 break;
4122 case FFESTV_formatNAMELIST:
4123 fputs ("+ PRINT_nl ", dmpout);
4124 break;
4126 default:
4127 assert ("Unexpected kind of format item in R911 PRINT" == NULL);
4129 ffeste_subr_file_ ("FORMAT", &info->print_spec[FFESTP_printixFORMAT]);
4130 fputc (' ', dmpout);
4131 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4133 ffeste_emit_line_note_ ();
4135 /* Do the real work. */
4138 ffecomGfrt start;
4139 ffecomGfrt end;
4140 tree cilist;
4142 /* First determine the start, per-item, and end run-time functions to
4143 call. The per-item function is picked by choosing an ffeste functio
4144 to call to handle a given item; it knows how to generate a call to the
4145 appropriate run-time function, and is called an "io driver". It
4146 handles the implied-DO construct, for example. */
4148 switch (format)
4150 case FFESTV_formatLABEL: /* FMT=10 */
4151 case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
4152 case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
4153 ffeste_io_driver_ = ffeste_io_dofio_;
4154 start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
4155 break;
4157 case FFESTV_formatASTERISK: /* FMT=* */
4158 ffeste_io_driver_ = ffeste_io_dolio_;
4159 start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
4160 break;
4162 case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
4163 /FOO/] */
4164 ffeste_io_driver_ = NULL; /* No start or driver function. */
4165 start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
4166 break;
4168 default:
4169 assert ("Weird stuff" == NULL);
4170 start = FFECOM_gfrt, end = FFECOM_gfrt;
4171 break;
4173 ffeste_io_endgfrt_ = end;
4175 ffecom_push_calltemps ();
4177 cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
4178 &info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
4180 ffeste_io_end_ = NULL_TREE;
4181 ffeste_io_err_ = NULL_TREE;
4182 ffeste_io_abort_ = NULL_TREE;
4183 ffeste_io_abort_is_temp_ = FALSE;
4184 ffeste_io_iostat_is_temp_ = FALSE;
4185 ffeste_io_iostat_ = NULL_TREE;
4187 /* If there is no end function, then there are no item functions (i.e.
4188 it's a NAMELIST), and vice versa by the way. In this situation, don't
4189 generate the "if (iostat != 0) goto label;" if the label is temp abort
4190 label, since we're gonna fall through to there anyway. */
4192 ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
4193 !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
4196 push_momentary ();
4197 #else
4198 #error
4199 #endif
4202 /* ffeste_R911_item -- PRINT statement i/o item
4204 ffeste_R911_item(expr,expr_token);
4206 Implement output-list expression. */
4208 void
4209 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
4211 ffeste_check_item_ ();
4213 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4214 ffebld_dump (expr);
4215 fputc (',', dmpout);
4216 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4217 if (expr == NULL)
4218 return;
4219 if (ffebld_op (expr) == FFEBLD_opANY)
4220 return;
4221 if (ffebld_op (expr) == FFEBLD_opIMPDO)
4222 ffeste_io_impdo_ (expr, expr_token);
4223 else
4224 ffeste_io_call_ ((*ffeste_io_driver_) (expr), FALSE);
4225 clear_momentary ();
4226 #else
4227 #error
4228 #endif
4231 /* ffeste_R911_finish -- PRINT statement list complete
4233 ffeste_R911_finish();
4235 Just wrap up any local activities. */
4237 void
4238 ffeste_R911_finish ()
4240 ffeste_check_finish_ ();
4242 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4243 fputc ('\n', dmpout);
4244 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4246 if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4247 ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
4248 FALSE);
4250 ffecom_pop_calltemps ();
4252 clear_momentary ();
4253 pop_momentary ();
4254 clear_momentary ();
4256 #else
4257 #error
4258 #endif
4261 /* ffeste_R919 -- BACKSPACE statement
4263 ffeste_R919();
4265 Make sure a BACKSPACE is valid in the current context, and implement it. */
4267 void
4268 ffeste_R919 (ffestpBeruStmt *info)
4270 ffeste_check_simple_ ();
4272 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4273 fputs ("+ BACKSPACE (", dmpout);
4274 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4275 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4276 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4277 fputs (")\n", dmpout);
4278 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4279 ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4280 #else
4281 #error
4282 #endif
4285 /* ffeste_R920 -- ENDFILE statement
4287 ffeste_R920();
4289 Make sure a ENDFILE is valid in the current context, and implement it. */
4291 void
4292 ffeste_R920 (ffestpBeruStmt *info)
4294 ffeste_check_simple_ ();
4296 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4297 fputs ("+ ENDFILE (", dmpout);
4298 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4299 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4300 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4301 fputs (")\n", dmpout);
4302 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4303 ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4304 #else
4305 #error
4306 #endif
4309 /* ffeste_R921 -- REWIND statement
4311 ffeste_R921();
4313 Make sure a REWIND is valid in the current context, and implement it. */
4315 void
4316 ffeste_R921 (ffestpBeruStmt *info)
4318 ffeste_check_simple_ ();
4320 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4321 fputs ("+ REWIND (", dmpout);
4322 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
4323 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
4324 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
4325 fputs (")\n", dmpout);
4326 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4327 ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4328 #else
4329 #error
4330 #endif
4333 /* ffeste_R923A -- INQUIRE statement (non-IOLENGTH version)
4335 ffeste_R923A(bool by_file);
4337 Make sure an INQUIRE is valid in the current context, and implement it. */
4339 void
4340 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4342 ffeste_check_simple_ ();
4344 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4345 if (by_file)
4347 fputs ("+ INQUIRE_file (", dmpout);
4348 ffeste_subr_file_ ("FILE", &info->inquire_spec[FFESTP_inquireixFILE]);
4350 else
4352 fputs ("+ INQUIRE_unit (", dmpout);
4353 ffeste_subr_file_ ("UNIT", &info->inquire_spec[FFESTP_inquireixUNIT]);
4355 ffeste_subr_file_ ("ACCESS", &info->inquire_spec[FFESTP_inquireixACCESS]);
4356 ffeste_subr_file_ ("ACTION", &info->inquire_spec[FFESTP_inquireixACTION]);
4357 ffeste_subr_file_ ("BLANK", &info->inquire_spec[FFESTP_inquireixBLANK]);
4358 ffeste_subr_file_ ("CARRIAGECONTROL", &info->inquire_spec[FFESTP_inquireixCARRIAGECONTROL]);
4359 ffeste_subr_file_ ("DEFAULTFILE", &info->inquire_spec[FFESTP_inquireixDEFAULTFILE]);
4360 ffeste_subr_file_ ("DELIM", &info->inquire_spec[FFESTP_inquireixDELIM]);
4361 ffeste_subr_file_ ("DIRECT", &info->inquire_spec[FFESTP_inquireixDIRECT]);
4362 ffeste_subr_file_ ("ERR", &info->inquire_spec[FFESTP_inquireixERR]);
4363 ffeste_subr_file_ ("EXIST", &info->inquire_spec[FFESTP_inquireixEXIST]);
4364 ffeste_subr_file_ ("FORM", &info->inquire_spec[FFESTP_inquireixFORM]);
4365 ffeste_subr_file_ ("FORMATTED", &info->inquire_spec[FFESTP_inquireixFORMATTED]);
4366 ffeste_subr_file_ ("IOSTAT", &info->inquire_spec[FFESTP_inquireixIOSTAT]);
4367 ffeste_subr_file_ ("KEYED", &info->inquire_spec[FFESTP_inquireixKEYED]);
4368 ffeste_subr_file_ ("NAME", &info->inquire_spec[FFESTP_inquireixNAME]);
4369 ffeste_subr_file_ ("NAMED", &info->inquire_spec[FFESTP_inquireixNAMED]);
4370 ffeste_subr_file_ ("NEXTREC", &info->inquire_spec[FFESTP_inquireixNEXTREC]);
4371 ffeste_subr_file_ ("NUMBER", &info->inquire_spec[FFESTP_inquireixNUMBER]);
4372 ffeste_subr_file_ ("OPENED", &info->inquire_spec[FFESTP_inquireixOPENED]);
4373 ffeste_subr_file_ ("ORGANIZATION", &info->inquire_spec[FFESTP_inquireixORGANIZATION]);
4374 ffeste_subr_file_ ("PAD", &info->inquire_spec[FFESTP_inquireixPAD]);
4375 ffeste_subr_file_ ("POSITION", &info->inquire_spec[FFESTP_inquireixPOSITION]);
4376 ffeste_subr_file_ ("READ", &info->inquire_spec[FFESTP_inquireixREAD]);
4377 ffeste_subr_file_ ("READWRITE", &info->inquire_spec[FFESTP_inquireixREADWRITE]);
4378 ffeste_subr_file_ ("RECL", &info->inquire_spec[FFESTP_inquireixRECL]);
4379 ffeste_subr_file_ ("RECORDTYPE", &info->inquire_spec[FFESTP_inquireixRECORDTYPE]);
4380 ffeste_subr_file_ ("SEQUENTIAL", &info->inquire_spec[FFESTP_inquireixSEQUENTIAL]);
4381 ffeste_subr_file_ ("UNFORMATTED", &info->inquire_spec[FFESTP_inquireixUNFORMATTED]);
4382 ffeste_subr_file_ ("WRITE", &info->inquire_spec[FFESTP_inquireixWRITE]);
4383 fputs (")\n", dmpout);
4384 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4386 tree args;
4387 bool iostat;
4388 bool errl;
4390 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4392 ffeste_emit_line_note_ ();
4394 iostat = specified (FFESTP_inquireixIOSTAT);
4395 errl = specified (FFESTP_inquireixERR);
4397 ffecom_push_calltemps ();
4399 args = ffeste_io_inlist_ (errl || iostat,
4400 &info->inquire_spec[FFESTP_inquireixUNIT],
4401 &info->inquire_spec[FFESTP_inquireixFILE],
4402 &info->inquire_spec[FFESTP_inquireixEXIST],
4403 &info->inquire_spec[FFESTP_inquireixOPENED],
4404 &info->inquire_spec[FFESTP_inquireixNUMBER],
4405 &info->inquire_spec[FFESTP_inquireixNAMED],
4406 &info->inquire_spec[FFESTP_inquireixNAME],
4407 &info->inquire_spec[FFESTP_inquireixACCESS],
4408 &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4409 &info->inquire_spec[FFESTP_inquireixDIRECT],
4410 &info->inquire_spec[FFESTP_inquireixFORM],
4411 &info->inquire_spec[FFESTP_inquireixFORMATTED],
4412 &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4413 &info->inquire_spec[FFESTP_inquireixRECL],
4414 &info->inquire_spec[FFESTP_inquireixNEXTREC],
4415 &info->inquire_spec[FFESTP_inquireixBLANK]);
4417 if (errl)
4419 ffeste_io_err_
4420 = ffeste_io_abort_
4421 = ffecom_lookup_label
4422 (info->inquire_spec[FFESTP_inquireixERR].u.label);
4423 ffeste_io_abort_is_temp_ = FALSE;
4425 else
4427 ffeste_io_err_ = NULL_TREE;
4429 if ((ffeste_io_abort_is_temp_ = iostat))
4430 ffeste_io_abort_ = ffecom_temp_label ();
4431 else
4432 ffeste_io_abort_ = NULL_TREE;
4435 if (iostat)
4436 { /* IOSTAT= */
4437 ffeste_io_iostat_is_temp_ = FALSE;
4438 ffeste_io_iostat_ = ffecom_expr
4439 (info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4441 else if (ffeste_io_abort_ != NULL_TREE)
4442 { /* no IOSTAT= but ERR= */
4443 ffeste_io_iostat_is_temp_ = TRUE;
4444 ffeste_io_iostat_
4445 = ffecom_push_tempvar (ffecom_integer_type_node,
4446 FFETARGET_charactersizeNONE, -1, FALSE);
4448 else
4449 { /* no IOSTAT=, or ERR= */
4450 ffeste_io_iostat_is_temp_ = FALSE;
4451 ffeste_io_iostat_ = NULL_TREE;
4454 /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4455 label, since we're gonna fall through to there anyway. */
4457 ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args),
4458 !ffeste_io_abort_is_temp_);
4460 /* If we've got a temp label, generate its code here. */
4462 if (ffeste_io_abort_is_temp_)
4464 DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4465 emit_nop ();
4466 expand_label (ffeste_io_abort_);
4468 assert (ffeste_io_err_ == NULL_TREE);
4471 /* If we've got a temp iostat, pop the temp. */
4473 if (ffeste_io_iostat_is_temp_)
4474 ffecom_pop_tempvar (ffeste_io_iostat_);
4476 ffecom_pop_calltemps ();
4478 #undef specified
4481 clear_momentary ();
4482 #else
4483 #error
4484 #endif
4487 /* ffeste_R923B_start -- INQUIRE(IOLENGTH=expr) statement list begin
4489 ffeste_R923B_start();
4491 Verify that INQUIRE is valid here, and begin accepting items in the
4492 list. */
4494 void
4495 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4497 ffeste_check_start_ ();
4499 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4500 fputs ("+ INQUIRE (", dmpout);
4501 ffeste_subr_file_ ("IOLENGTH", &info->inquire_spec[FFESTP_inquireixIOLENGTH]);
4502 fputs (") ", dmpout);
4503 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4504 assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4505 ffeste_emit_line_note_ ();
4506 clear_momentary ();
4507 #else
4508 #error
4509 #endif
4512 /* ffeste_R923B_item -- INQUIRE statement i/o item
4514 ffeste_R923B_item(expr,expr_token);
4516 Implement output-list expression. */
4518 void
4519 ffeste_R923B_item (ffebld expr UNUSED)
4521 ffeste_check_item_ ();
4523 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4524 ffebld_dump (expr);
4525 fputc (',', dmpout);
4526 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4527 clear_momentary ();
4528 #else
4529 #error
4530 #endif
4533 /* ffeste_R923B_finish -- INQUIRE statement list complete
4535 ffeste_R923B_finish();
4537 Just wrap up any local activities. */
4539 void
4540 ffeste_R923B_finish ()
4542 ffeste_check_finish_ ();
4544 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4545 fputc ('\n', dmpout);
4546 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4547 clear_momentary ();
4548 #else
4549 #error
4550 #endif
4553 /* ffeste_R1001 -- FORMAT statement
4555 ffeste_R1001(format_list); */
4557 void
4558 ffeste_R1001 (ffests s)
4560 ffeste_check_simple_ ();
4562 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4563 fprintf (dmpout, "$ FORMAT %.*s\n", (int) ffests_length (s), ffests_text (s));
4564 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4566 tree t;
4567 tree ttype;
4568 tree maxindex;
4569 tree var;
4571 assert (ffeste_label_formatdef_ != NULL);
4573 ffeste_emit_line_note_ ();
4575 t = build_string (ffests_length (s), ffests_text (s));
4577 TREE_TYPE (t)
4578 = build_type_variant (build_array_type
4579 (char_type_node,
4580 build_range_type (integer_type_node,
4581 integer_one_node,
4582 build_int_2 (ffests_length (s),
4583 0))),
4584 1, 0);
4585 TREE_CONSTANT (t) = 1;
4586 TREE_STATIC (t) = 1;
4588 push_obstacks_nochange ();
4589 end_temporary_allocation ();
4591 var = ffecom_lookup_label (ffeste_label_formatdef_);
4592 if ((var != NULL_TREE)
4593 && (TREE_CODE (var) == VAR_DECL))
4595 DECL_INITIAL (var) = t;
4596 maxindex = build_int_2 (ffests_length (s) - 1, 0);
4597 ttype = TREE_TYPE (var);
4598 TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
4599 integer_zero_node,
4600 maxindex);
4601 if (!TREE_TYPE (maxindex))
4602 TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
4603 layout_type (ttype);
4604 rest_of_decl_compilation (var, NULL, 1, 0);
4605 expand_decl (var);
4606 expand_decl_init (var);
4609 resume_temporary_allocation ();
4610 pop_obstacks ();
4612 ffeste_label_formatdef_ = NULL;
4614 #else
4615 #error
4616 #endif
4619 /* ffeste_R1103 -- End a PROGRAM
4621 ffeste_R1103(); */
4623 void
4624 ffeste_R1103 ()
4626 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4627 fputs ("+ END_PROGRAM\n", dmpout);
4628 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4629 #else
4630 #error
4631 #endif
4634 /* ffeste_R1112 -- End a BLOCK DATA
4636 ffeste_R1112(TRUE); */
4638 void
4639 ffeste_R1112 ()
4641 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4642 fputs ("* END_BLOCK_DATA\n", dmpout);
4643 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4644 #else
4645 #error
4646 #endif
4649 /* ffeste_R1212 -- CALL statement
4651 ffeste_R1212(expr,expr_token);
4653 Make sure statement is valid here; implement. */
4655 void
4656 ffeste_R1212 (ffebld expr)
4658 ffeste_check_simple_ ();
4660 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4661 fputs ("+ CALL ", dmpout);
4662 ffebld_dump (expr);
4663 fputc ('\n', dmpout);
4664 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4666 ffebld args = ffebld_right (expr);
4667 ffebld arg;
4668 ffebld labels = NULL; /* First in list of LABTERs. */
4669 ffebld prevlabels = NULL;
4670 ffebld prevargs = NULL;
4672 ffeste_emit_line_note_ ();
4674 /* Here we split the list at ffebld_right(expr) into two lists: one at
4675 ffebld_right(expr) consisting of all items that are not LABTERs, the
4676 other at labels consisting of all items that are LABTERs. Then, if
4677 the latter list is NULL, we have an ordinary call, else we have a call
4678 with alternate returns. */
4680 for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
4682 if (((arg = ffebld_head (args)) == NULL)
4683 || (ffebld_op (arg) != FFEBLD_opLABTER))
4685 if (prevargs == NULL)
4687 prevargs = args;
4688 ffebld_set_right (expr, args);
4690 else
4692 ffebld_set_trail (prevargs, args);
4693 prevargs = args;
4696 else
4698 if (prevlabels == NULL)
4700 prevlabels = labels = args;
4702 else
4704 ffebld_set_trail (prevlabels, args);
4705 prevlabels = args;
4709 if (prevlabels == NULL)
4710 labels = NULL;
4711 else
4712 ffebld_set_trail (prevlabels, NULL);
4713 if (prevargs == NULL)
4714 ffebld_set_right (expr, NULL);
4715 else
4716 ffebld_set_trail (prevargs, NULL);
4718 if (labels == NULL)
4719 expand_expr_stmt (ffecom_expr (expr));
4720 else
4722 tree texpr;
4723 tree value;
4724 tree tlabel;
4725 int caseno;
4726 int pushok;
4727 tree duplicate;
4729 texpr = ffecom_expr (expr);
4730 expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
4731 push_momentary (); /* In case of many labels, keep 'em cleared
4732 out. */
4733 for (caseno = 1;
4734 labels != NULL;
4735 ++caseno, labels = ffebld_trail (labels))
4737 value = build_int_2 (caseno, 0);
4738 tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
4740 pushok = pushcase (value, convert, tlabel, &duplicate);
4741 assert (pushok == 0);
4742 tlabel
4743 = ffecom_lookup_label (ffebld_labter (ffebld_head (labels)));
4744 if ((tlabel == NULL_TREE)
4745 || (TREE_CODE (tlabel) == ERROR_MARK))
4746 continue;
4747 TREE_USED (tlabel) = 1;
4748 expand_goto (tlabel);
4749 clear_momentary ();
4752 pop_momentary ();
4753 expand_end_case (texpr);
4755 clear_momentary ();
4757 #else
4758 #error
4759 #endif
4762 /* ffeste_R1221 -- End a FUNCTION
4764 ffeste_R1221(TRUE); */
4766 void
4767 ffeste_R1221 ()
4769 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4770 fputs ("+ END_FUNCTION\n", dmpout);
4771 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4772 #else
4773 #error
4774 #endif
4777 /* ffeste_R1225 -- End a SUBROUTINE
4779 ffeste_R1225(TRUE); */
4781 void
4782 ffeste_R1225 ()
4784 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4785 fprintf (dmpout, "+ END_SUBROUTINE\n");
4786 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4787 #else
4788 #error
4789 #endif
4792 /* ffeste_R1226 -- ENTRY statement
4794 ffeste_R1226(entryname,arglist,ending_token);
4796 Make sure we're in a SUBROUTINE or FUNCTION, register arguments for the
4797 entry point name, and so on. */
4799 void
4800 ffeste_R1226 (ffesymbol entry)
4802 ffeste_check_simple_ ();
4804 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4805 fprintf (dmpout, "+ ENTRY %s", ffesymbol_text (entry));
4806 if (ffesymbol_dummyargs (entry) != NULL)
4808 ffebld argh;
4810 fputc ('(', dmpout);
4811 for (argh = ffesymbol_dummyargs (entry);
4812 argh != NULL;
4813 argh = ffebld_trail (argh))
4815 assert (ffebld_head (argh) != NULL);
4816 switch (ffebld_op (ffebld_head (argh)))
4818 case FFEBLD_opSYMTER:
4819 fputs (ffesymbol_text (ffebld_symter (ffebld_head (argh))),
4820 dmpout);
4821 break;
4823 case FFEBLD_opSTAR:
4824 fputc ('*', dmpout);
4825 break;
4827 default:
4828 fputc ('?', dmpout);
4829 ffebld_dump (ffebld_head (argh));
4830 fputc ('?', dmpout);
4831 break;
4833 if (ffebld_trail (argh) != NULL)
4834 fputc (',', dmpout);
4836 fputc (')', dmpout);
4838 fputc ('\n', dmpout);
4839 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4841 tree label = ffesymbol_hook (entry).length_tree;
4843 ffeste_emit_line_note_ ();
4845 DECL_INITIAL (label) = error_mark_node;
4846 emit_nop ();
4847 expand_label (label);
4849 clear_momentary ();
4851 #else
4852 #error
4853 #endif
4856 /* ffeste_R1227 -- RETURN statement
4858 ffeste_R1227(expr);
4860 Make sure statement is valid here; implement. expr and expr_token are
4861 both NULL if there was no expression. */
4863 void
4864 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
4866 ffeste_check_simple_ ();
4868 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4869 if (expr == NULL)
4871 fputs ("+ RETURN\n", dmpout);
4873 else
4875 fputs ("+ RETURN_alternate ", dmpout);
4876 ffebld_dump (expr);
4877 fputc ('\n', dmpout);
4879 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4881 tree rtn;
4883 ffeste_emit_line_note_ ();
4884 ffecom_push_calltemps ();
4886 rtn = ffecom_return_expr (expr);
4888 if ((rtn == NULL_TREE)
4889 || (rtn == error_mark_node))
4890 expand_null_return ();
4891 else
4893 tree result = DECL_RESULT (current_function_decl);
4895 if ((result != error_mark_node)
4896 && (TREE_TYPE (result) != error_mark_node))
4897 expand_return (ffecom_modify (NULL_TREE,
4898 result,
4899 convert (TREE_TYPE (result),
4900 rtn)));
4901 else
4902 expand_null_return ();
4905 ffecom_pop_calltemps ();
4906 clear_momentary ();
4908 #else
4909 #error
4910 #endif
4913 /* ffeste_V018_start -- REWRITE(...) statement list begin
4915 ffeste_V018_start();
4917 Verify that REWRITE is valid here, and begin accepting items in the
4918 list. */
4920 #if FFESTR_VXT
4921 void
4922 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
4924 ffeste_check_start_ ();
4926 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4927 switch (format)
4929 case FFESTV_formatNONE:
4930 fputs ("+ REWRITE_uf (", dmpout);
4931 break;
4933 case FFESTV_formatLABEL:
4934 case FFESTV_formatCHAREXPR:
4935 case FFESTV_formatINTEXPR:
4936 fputs ("+ REWRITE_fm (", dmpout);
4937 break;
4939 default:
4940 assert ("Unexpected kind of format item in V018 REWRITE" == NULL);
4942 ffeste_subr_file_ ("UNIT", &info->rewrite_spec[FFESTP_rewriteixUNIT]);
4943 ffeste_subr_file_ ("FMT", &info->rewrite_spec[FFESTP_rewriteixFMT]);
4944 ffeste_subr_file_ ("ERR", &info->rewrite_spec[FFESTP_rewriteixERR]);
4945 ffeste_subr_file_ ("IOSTAT", &info->rewrite_spec[FFESTP_rewriteixIOSTAT]);
4946 fputs (") ", dmpout);
4947 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4948 #else
4949 #error
4950 #endif
4953 /* ffeste_V018_item -- REWRITE statement i/o item
4955 ffeste_V018_item(expr,expr_token);
4957 Implement output-list expression. */
4959 void
4960 ffeste_V018_item (ffebld expr)
4962 ffeste_check_item_ ();
4964 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4965 ffebld_dump (expr);
4966 fputc (',', dmpout);
4967 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4968 #else
4969 #error
4970 #endif
4973 /* ffeste_V018_finish -- REWRITE statement list complete
4975 ffeste_V018_finish();
4977 Just wrap up any local activities. */
4979 void
4980 ffeste_V018_finish ()
4982 ffeste_check_finish_ ();
4984 #if FFECOM_targetCURRENT == FFECOM_targetFFE
4985 fputc ('\n', dmpout);
4986 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
4987 #else
4988 #error
4989 #endif
4992 /* ffeste_V019_start -- ACCEPT statement list begin
4994 ffeste_V019_start();
4996 Verify that ACCEPT is valid here, and begin accepting items in the
4997 list. */
4999 void
5000 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
5002 ffeste_check_start_ ();
5004 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5005 switch (format)
5007 case FFESTV_formatLABEL:
5008 case FFESTV_formatCHAREXPR:
5009 case FFESTV_formatINTEXPR:
5010 fputs ("+ ACCEPT_fm ", dmpout);
5011 break;
5013 case FFESTV_formatASTERISK:
5014 fputs ("+ ACCEPT_ls ", dmpout);
5015 break;
5017 case FFESTV_formatNAMELIST:
5018 fputs ("+ ACCEPT_nl ", dmpout);
5019 break;
5021 default:
5022 assert ("Unexpected kind of format item in V019 ACCEPT" == NULL);
5024 ffeste_subr_file_ ("FORMAT", &info->accept_spec[FFESTP_acceptixFORMAT]);
5025 fputc (' ', dmpout);
5026 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5027 #else
5028 #error
5029 #endif
5032 /* ffeste_V019_item -- ACCEPT statement i/o item
5034 ffeste_V019_item(expr,expr_token);
5036 Implement output-list expression. */
5038 void
5039 ffeste_V019_item (ffebld expr)
5041 ffeste_check_item_ ();
5043 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5044 ffebld_dump (expr);
5045 fputc (',', dmpout);
5046 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5047 #else
5048 #error
5049 #endif
5052 /* ffeste_V019_finish -- ACCEPT statement list complete
5054 ffeste_V019_finish();
5056 Just wrap up any local activities. */
5058 void
5059 ffeste_V019_finish ()
5061 ffeste_check_finish_ ();
5063 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5064 fputc ('\n', dmpout);
5065 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5066 #else
5067 #error
5068 #endif
5071 #endif
5072 /* ffeste_V020_start -- TYPE statement list begin
5074 ffeste_V020_start();
5076 Verify that TYPE is valid here, and begin accepting items in the
5077 list. */
5079 void
5080 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
5081 ffestvFormat format UNUSED)
5083 ffeste_check_start_ ();
5085 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5086 switch (format)
5088 case FFESTV_formatLABEL:
5089 case FFESTV_formatCHAREXPR:
5090 case FFESTV_formatINTEXPR:
5091 fputs ("+ TYPE_fm ", dmpout);
5092 break;
5094 case FFESTV_formatASTERISK:
5095 fputs ("+ TYPE_ls ", dmpout);
5096 break;
5098 case FFESTV_formatNAMELIST:
5099 fputs ("* TYPE_nl ", dmpout);
5100 break;
5102 default:
5103 assert ("Unexpected kind of format item in V020 TYPE" == NULL);
5105 ffeste_subr_file_ ("FORMAT", &info->type_spec[FFESTP_typeixFORMAT]);
5106 fputc (' ', dmpout);
5107 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5108 #else
5109 #error
5110 #endif
5113 /* ffeste_V020_item -- TYPE statement i/o item
5115 ffeste_V020_item(expr,expr_token);
5117 Implement output-list expression. */
5119 void
5120 ffeste_V020_item (ffebld expr UNUSED)
5122 ffeste_check_item_ ();
5124 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5125 ffebld_dump (expr);
5126 fputc (',', dmpout);
5127 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5128 #else
5129 #error
5130 #endif
5133 /* ffeste_V020_finish -- TYPE statement list complete
5135 ffeste_V020_finish();
5137 Just wrap up any local activities. */
5139 void
5140 ffeste_V020_finish ()
5142 ffeste_check_finish_ ();
5144 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5145 fputc ('\n', dmpout);
5146 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5147 #else
5148 #error
5149 #endif
5152 /* ffeste_V021 -- DELETE statement
5154 ffeste_V021();
5156 Make sure a DELETE is valid in the current context, and implement it. */
5158 #if FFESTR_VXT
5159 void
5160 ffeste_V021 (ffestpDeleteStmt *info)
5162 ffeste_check_simple_ ();
5164 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5165 fputs ("+ DELETE (", dmpout);
5166 ffeste_subr_file_ ("UNIT", &info->delete_spec[FFESTP_deleteixUNIT]);
5167 ffeste_subr_file_ ("REC", &info->delete_spec[FFESTP_deleteixREC]);
5168 ffeste_subr_file_ ("ERR", &info->delete_spec[FFESTP_deleteixERR]);
5169 ffeste_subr_file_ ("IOSTAT", &info->delete_spec[FFESTP_deleteixIOSTAT]);
5170 fputs (")\n", dmpout);
5171 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5172 #else
5173 #error
5174 #endif
5177 /* ffeste_V022 -- UNLOCK statement
5179 ffeste_V022();
5181 Make sure a UNLOCK is valid in the current context, and implement it. */
5183 void
5184 ffeste_V022 (ffestpBeruStmt *info)
5186 ffeste_check_simple_ ();
5188 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5189 fputs ("+ UNLOCK (", dmpout);
5190 ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
5191 ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
5192 ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
5193 fputs (")\n", dmpout);
5194 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5195 #else
5196 #error
5197 #endif
5200 /* ffeste_V023_start -- ENCODE(...) statement list begin
5202 ffeste_V023_start();
5204 Verify that ENCODE is valid here, and begin accepting items in the
5205 list. */
5207 void
5208 ffeste_V023_start (ffestpVxtcodeStmt *info)
5210 ffeste_check_start_ ();
5212 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5213 fputs ("+ ENCODE (", dmpout);
5214 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5215 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5216 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5217 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5218 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5219 fputs (") ", dmpout);
5220 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5221 #else
5222 #error
5223 #endif
5226 /* ffeste_V023_item -- ENCODE statement i/o item
5228 ffeste_V023_item(expr,expr_token);
5230 Implement output-list expression. */
5232 void
5233 ffeste_V023_item (ffebld expr)
5235 ffeste_check_item_ ();
5237 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5238 ffebld_dump (expr);
5239 fputc (',', dmpout);
5240 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5241 #else
5242 #error
5243 #endif
5246 /* ffeste_V023_finish -- ENCODE statement list complete
5248 ffeste_V023_finish();
5250 Just wrap up any local activities. */
5252 void
5253 ffeste_V023_finish ()
5255 ffeste_check_finish_ ();
5257 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5258 fputc ('\n', dmpout);
5259 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5260 #else
5261 #error
5262 #endif
5265 /* ffeste_V024_start -- DECODE(...) statement list begin
5267 ffeste_V024_start();
5269 Verify that DECODE is valid here, and begin accepting items in the
5270 list. */
5272 void
5273 ffeste_V024_start (ffestpVxtcodeStmt *info)
5275 ffeste_check_start_ ();
5277 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5278 fputs ("+ DECODE (", dmpout);
5279 ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
5280 ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
5281 ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
5282 ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
5283 ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
5284 fputs (") ", dmpout);
5285 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5286 #else
5287 #error
5288 #endif
5291 /* ffeste_V024_item -- DECODE statement i/o item
5293 ffeste_V024_item(expr,expr_token);
5295 Implement output-list expression. */
5297 void
5298 ffeste_V024_item (ffebld expr)
5300 ffeste_check_item_ ();
5302 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5303 ffebld_dump (expr);
5304 fputc (',', dmpout);
5305 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5306 #else
5307 #error
5308 #endif
5311 /* ffeste_V024_finish -- DECODE statement list complete
5313 ffeste_V024_finish();
5315 Just wrap up any local activities. */
5317 void
5318 ffeste_V024_finish ()
5320 ffeste_check_finish_ ();
5322 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5323 fputc ('\n', dmpout);
5324 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5325 #else
5326 #error
5327 #endif
5330 /* ffeste_V025_start -- DEFINEFILE statement list begin
5332 ffeste_V025_start();
5334 Verify that DEFINEFILE is valid here, and begin accepting items in the
5335 list. */
5337 void
5338 ffeste_V025_start ()
5340 ffeste_check_start_ ();
5342 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5343 fputs ("+ DEFINE_FILE ", dmpout);
5344 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5345 #else
5346 #error
5347 #endif
5350 /* ffeste_V025_item -- DEFINE FILE statement item
5352 ffeste_V025_item(u,ut,m,mt,n,nt,asv,asvt);
5354 Implement item. */
5356 void
5357 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
5359 ffeste_check_item_ ();
5361 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5362 ffebld_dump (u);
5363 fputc ('(', dmpout);
5364 ffebld_dump (m);
5365 fputc (',', dmpout);
5366 ffebld_dump (n);
5367 fputs (",U,", dmpout);
5368 ffebld_dump (asv);
5369 fputs ("),", dmpout);
5370 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5371 #else
5372 #error
5373 #endif
5376 /* ffeste_V025_finish -- DEFINE FILE statement list complete
5378 ffeste_V025_finish();
5380 Just wrap up any local activities. */
5382 void
5383 ffeste_V025_finish ()
5385 ffeste_check_finish_ ();
5387 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5388 fputc ('\n', dmpout);
5389 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5390 #else
5391 #error
5392 #endif
5395 /* ffeste_V026 -- FIND statement
5397 ffeste_V026();
5399 Make sure a FIND is valid in the current context, and implement it. */
5401 void
5402 ffeste_V026 (ffestpFindStmt *info)
5404 ffeste_check_simple_ ();
5406 #if FFECOM_targetCURRENT == FFECOM_targetFFE
5407 fputs ("+ FIND (", dmpout);
5408 ffeste_subr_file_ ("UNIT", &info->find_spec[FFESTP_findixUNIT]);
5409 ffeste_subr_file_ ("REC", &info->find_spec[FFESTP_findixREC]);
5410 ffeste_subr_file_ ("ERR", &info->find_spec[FFESTP_findixERR]);
5411 ffeste_subr_file_ ("IOSTAT", &info->find_spec[FFESTP_findixIOSTAT]);
5412 fputs (")\n", dmpout);
5413 #elif FFECOM_targetCURRENT == FFECOM_targetGCC
5414 #else
5415 #error
5416 #endif
5419 #endif