blob: a5e9757cca397b92b05575d2b5467922da48a0e5 [file] [log] [blame]
/* ste.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
This file is part of GNU Fortran.
GNU Fortran is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Fortran is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Fortran; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
Related Modules:
ste.c
Description:
Implements the various statements and such like.
Modifications:
*/
/* As of 0.5.4, any statement that calls on ffecom to transform an
expression might need to be wrapped in ffecom_push_calltemps ()
and ffecom_pop_calltemps () as are some other cases. That is
the case when the transformation might involve generation of
a temporary that must be auto-popped, the specific case being
when a COMPLEX operation requiring a call to libf2c being
generated, whereby a temp is needed to hold the result since
libf2c doesn't return COMPLEX results directly. Cases where it
is known that ffecom_expr () won't need to do this, such as
the CALL statement (where it's the transformation of the
call expr itself that does the wrapping), don't need to bother
with this wrapping. Forgetting to do the wrapping currently
means a crash at an assertion when the wrapping would be helpful
to keep temporaries from being wasted -- see ffecom_push_tempvar. */
/* Include files. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
#include "config.j"
#include "rtl.j"
#endif
#include "proj.h"
#include "ste.h"
#include "bld.h"
#include "com.h"
#include "expr.h"
#include "lab.h"
#include "lex.h"
#include "sta.h"
#include "stp.h"
#include "str.h"
#include "sts.h"
#include "stt.h"
#include "stv.h"
#include "stw.h"
#include "symbol.h"
/* Externals defined here. */
/* Simple definitions and enumerations. */
typedef enum
{
FFESTE_stateletSIMPLE_, /* Expecting simple/start. */
FFESTE_stateletATTRIB_, /* Expecting attrib/item/itemstart. */
FFESTE_stateletITEM_, /* Expecting item/itemstart/finish. */
FFESTE_stateletITEMVALS_, /* Expecting itemvalue/itemendvals. */
FFESTE_
} ffesteStatelet_;
/* Internal typedefs. */
/* Private include files. */
/* Internal structure definitions. */
/* Static objects accessed by functions in this module. */
static ffesteStatelet_ ffeste_statelet_ = FFESTE_stateletSIMPLE_;
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static ffelab ffeste_label_formatdef_ = NULL;
static tree (*ffeste_io_driver_) (ffebld expr); /* do?io. */
static ffecomGfrt ffeste_io_endgfrt_; /* end function to call. */
static tree ffeste_io_abort_; /* abort-io label or NULL_TREE. */
static bool ffeste_io_abort_is_temp_; /* abort-io label is a temp. */
static tree ffeste_io_end_; /* END= label or NULL_TREE. */
static tree ffeste_io_err_; /* ERR= label or NULL_TREE. */
static tree ffeste_io_iostat_; /* IOSTAT= var or NULL_TREE. */
static bool ffeste_io_iostat_is_temp_; /* IOSTAT= var is a temp. */
#endif
/* Static functions (internal). */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
tree *xitersvar, ffebld var,
ffebld start, ffelexToken start_token,
ffebld end, ffelexToken end_token,
ffebld incr, ffelexToken incr_token,
char *msg);
static void ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar);
static void ffeste_io_call_ (tree call, bool do_check);
static tree ffeste_io_dofio_ (ffebld expr);
static tree ffeste_io_dolio_ (ffebld expr);
static tree ffeste_io_douio_ (ffebld expr);
static tree ffeste_io_ialist_ (bool have_err, ffestvUnit unit,
ffebld unit_expr, int unit_dflt);
static tree ffeste_io_cilist_ (bool have_err, ffestvUnit unit,
ffebld unit_expr, int unit_dflt,
bool have_end, ffestvFormat format,
ffestpFile *format_spec, bool rec,
ffebld rec_expr);
static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
ffestpFile *stat_spec);
static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
bool have_end, ffestvFormat format,
ffestpFile *format_spec);
static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
ffestpFile *file_spec,
ffestpFile *stat_spec,
ffestpFile *access_spec,
ffestpFile *form_spec,
ffestpFile *recl_spec,
ffestpFile *blank_spec);
static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
#elif FFECOM_targetCURRENT == FFECOM_targetFFE
static void ffeste_subr_file_ (char *kw, ffestpFile *spec);
#else
#error
#endif
/* Internal macros. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
#define ffeste_emit_line_note_() \
emit_line_note (input_filename, lineno)
#endif
#define ffeste_check_simple_() \
assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_)
#define ffeste_check_start_() \
assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_); \
ffeste_statelet_ = FFESTE_stateletATTRIB_
#define ffeste_check_attrib_() \
assert(ffeste_statelet_ == FFESTE_stateletATTRIB_)
#define ffeste_check_item_() \
assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
|| ffeste_statelet_ == FFESTE_stateletITEM_); \
ffeste_statelet_ = FFESTE_stateletITEM_
#define ffeste_check_item_startvals_() \
assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
|| ffeste_statelet_ == FFESTE_stateletITEM_); \
ffeste_statelet_ = FFESTE_stateletITEMVALS_
#define ffeste_check_item_value_() \
assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_)
#define ffeste_check_item_endvals_() \
assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_); \
ffeste_statelet_ = FFESTE_stateletITEM_
#define ffeste_check_finish_() \
assert(ffeste_statelet_ == FFESTE_stateletATTRIB_ \
|| ffeste_statelet_ == FFESTE_stateletITEM_); \
ffeste_statelet_ = FFESTE_stateletSIMPLE_
#define ffeste_f2c_charnolenspec_(Spec,Exp,Init) \
do \
{ \
if (Spec->kw_or_val_present) \
Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&ignore); \
else \
Exp = null_pointer_node; \
if (TREE_CONSTANT(Exp)) \
{ \
Init = Exp; \
Exp = NULL_TREE; \
} \
else \
{ \
Init = null_pointer_node; \
constantp = FALSE; \
} \
} while(0)
#define ffeste_f2c_charspec_(Spec,Exp,Init,Lenexp,Leninit) \
do \
{ \
if (Spec->kw_or_val_present) \
Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&Lenexp); \
else \
{ \
Exp = null_pointer_node; \
Lenexp = ffecom_f2c_ftnlen_zero_node; \
} \
if (TREE_CONSTANT(Exp)) \
{ \
Init = Exp; \
Exp = NULL_TREE; \
} \
else \
{ \
Init = null_pointer_node; \
constantp = FALSE; \
} \
if ((Lenexp != NULL_TREE) && TREE_CONSTANT(Lenexp)) \
{ \
Leninit = Lenexp; \
Lenexp = NULL_TREE; \
} \
else \
{ \
Leninit = ffecom_f2c_ftnlen_zero_node; \
constantp = FALSE; \
} \
} while(0)
#define ffeste_f2c_exp_(Field,Exp) \
do \
{ \
if (Exp != NULL_TREE) \
{ \
Exp = ffecom_modify(void_type_node,ffecom_2(COMPONENT_REF, \
TREE_TYPE(Field),t,Field),Exp); \
expand_expr_stmt(Exp); \
} \
} while(0)
#define ffeste_f2c_init_(Init) \
do \
{ \
TREE_CHAIN(initn) = build_tree_list((field = TREE_CHAIN(field)),Init); \
initn = TREE_CHAIN(initn); \
} while(0)
#define ffeste_f2c_flagspec_(Flag,Init) \
do { Init = convert (ffecom_f2c_flag_type_node, \
Flag ? integer_one_node : integer_zero_node); } \
while(0)
#define ffeste_f2c_intspec_(Spec,Exp,Init) \
do \
{ \
if (Spec->kw_or_val_present) \
Exp = ffecom_expr(Spec->u.expr); \
else \
Exp = ffecom_integer_zero_node; \
if (TREE_CONSTANT(Exp)) \
{ \
Init = Exp; \
Exp = NULL_TREE; \
} \
else \
{ \
Init = ffecom_integer_zero_node; \
constantp = FALSE; \
} \
} while(0)
#define ffeste_f2c_ptrtointspec_(Spec,Exp,Init) \
do \
{ \
if (Spec->kw_or_val_present) \
Exp = ffecom_ptr_to_expr(Spec->u.expr); \
else \
Exp = null_pointer_node; \
if (TREE_CONSTANT(Exp)) \
{ \
Init = Exp; \
Exp = NULL_TREE; \
} \
else \
{ \
Init = null_pointer_node; \
constantp = FALSE; \
} \
} while(0)
/* Begin an iterative DO loop. Pass the block to start if applicable.
NOTE: Does _two_ push_momentary () calls, which the caller must
undo (by calling ffeste_end_iterdo_). */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
tree *xitersvar, ffebld var,
ffebld start, ffelexToken start_token,
ffebld end, ffelexToken end_token,
ffebld incr, ffelexToken incr_token,
char *msg)
{
tree tvar;
tree expr;
tree tstart;
tree tend;
tree tincr;
tree tincr_saved;
tree niters;
push_momentary (); /* Want to save these throughout the loop. */
tvar = ffecom_expr_rw (var);
tincr = ffecom_expr (incr);
/* Check whether incr is known to be zero, complain and fix. */
if (integer_zerop (tincr) || real_zerop (tincr))
{
ffebad_start (FFEBAD_DO_STEP_ZERO);
ffebad_here (0, ffelex_token_where_line (incr_token),
ffelex_token_where_column (incr_token));
ffebad_string (msg);
ffebad_finish ();
tincr = convert (TREE_TYPE (tvar), integer_one_node);
}
tincr_saved = ffecom_save_tree (tincr);
push_momentary (); /* Want to discard the rest after the loop. */
tstart = ffecom_expr (start);
tend = ffecom_expr (end);
{ /* For warnings only, nothing else
happens here. */
tree try;
if (!ffe_is_onetrip ())
{
try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
tend,
tstart);
try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
try,
tincr);
if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
tincr);
else
try = convert (integer_type_node,
ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
try,
tincr));
/* Warn if loop never executed, since we've done the evaluation
of the unofficial iteration count already. */
try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
try,
convert (TREE_TYPE (tvar),
integer_zero_node)));
if (integer_onep (try))
{
ffebad_start (FFEBAD_DO_NULL);
ffebad_here (0, ffelex_token_where_line (start_token),
ffelex_token_where_column (start_token));
ffebad_string (msg);
ffebad_finish ();
}
}
/* Warn if end plus incr would overflow. */
try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
tend,
tincr);
if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
&& TREE_CONSTANT_OVERFLOW (try))
{
ffebad_start (FFEBAD_DO_END_OVERFLOW);
ffebad_here (0, ffelex_token_where_line (end_token),
ffelex_token_where_column (end_token));
ffebad_string (msg);
ffebad_finish ();
}
}
/* Do the initial assignment into the DO var. */
expr = ffecom_modify (void_type_node, tvar, tstart);
expand_expr_stmt (expr);
expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
tend,
TREE_CONSTANT (tstart) ? tstart : tvar);
if (!ffe_is_onetrip ())
{
expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
expr,
convert (TREE_TYPE (expr), tincr_saved));
}
if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
expr,
tincr_saved);
else
expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
expr,
tincr_saved);
#if 1 /* New, F90-approved approach: convert to default INTEGER. */
if (TREE_TYPE (tvar) != error_mark_node)
expr = convert (ffecom_integer_type_node, expr);
#else /* Old approach; convert to INTEGER unless that's a narrowing. */
if ((TREE_TYPE (tvar) != error_mark_node)
&& ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
|| ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
&& ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
!= INTEGER_CST)
|| (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
<= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
/* Convert unless promoting INTEGER type of any kind downward to
default INTEGER; else leave as, say, INTEGER*8 (long long int). */
expr = convert (ffecom_integer_type_node, expr);
#endif
niters = ffecom_push_tempvar (TREE_TYPE (expr),
FFETARGET_charactersizeNONE, -1, FALSE);
expr = ffecom_modify (void_type_node, niters, expr);
expand_expr_stmt (expr);
if (block == NULL)
expand_start_loop_continue_elsewhere (0);
else
ffestw_set_do_hook (block,
expand_start_loop_continue_elsewhere (1));
if (!ffe_is_onetrip ())
{
expr = ffecom_truth_value
(ffecom_2 (GE_EXPR, integer_type_node,
ffecom_2 (PREDECREMENT_EXPR,
TREE_TYPE (niters),
niters,
convert (TREE_TYPE (niters),
ffecom_integer_one_node)),
convert (TREE_TYPE (niters),
ffecom_integer_zero_node)));
expand_exit_loop_if_false (0, expr);
}
clear_momentary (); /* Discard the above now that we're done with
DO stmt. */
if (block == NULL)
{
*xtvar = tvar;
*xtincr = tincr_saved;
*xitersvar = niters;
}
else
{
ffestw_set_do_tvar (block, tvar);
ffestw_set_do_incr_saved (block, tincr_saved);
ffestw_set_do_count_var (block, niters);
}
}
#endif
/* End an iterative DO loop. Pass the same iteration variable and increment
value trees that were generated in the paired _begin_ call. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar)
{
tree expr;
tree niters = itersvar;
expand_loop_continue_here ();
if (ffe_is_onetrip ())
{
expr = ffecom_truth_value
(ffecom_2 (GE_EXPR, integer_type_node,
ffecom_2 (PREDECREMENT_EXPR,
TREE_TYPE (niters),
niters,
convert (TREE_TYPE (niters),
ffecom_integer_one_node)),
convert (TREE_TYPE (niters),
ffecom_integer_zero_node)));
expand_exit_loop_if_false (0, expr);
}
expr = ffecom_modify (void_type_node, tvar,
ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
tvar,
tincr));
expand_expr_stmt (expr);
expand_end_loop ();
ffecom_pop_tempvar (itersvar); /* Free #iters var. */
clear_momentary ();
pop_momentary (); /* Lose the stuff we just built. */
clear_momentary ();
pop_momentary (); /* Lose the tvar and incr_saved trees. */
}
#endif
/* ffeste_io_call_ -- Generate call to run-time I/O routine
tree callexpr = build(CALL_EXPR,...);
ffeste_io_call_(callexpr,TRUE);
Sets TREE_SIDE_EFFECTS(callexpr) = 1. If ffeste_io_iostat_ is not
NULL_TREE, replaces callexpr with "iostat = callexpr;". Expands the
result. If ffeste_io_abort_ is not NULL_TREE and the second argument
is TRUE, generates "if (iostat != 0) goto ffeste_io_abort_;". */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
ffeste_io_call_ (tree call, bool do_check)
{
/* Generate the call and optional assignment into iostat var. */
TREE_SIDE_EFFECTS (call) = 1;
if (ffeste_io_iostat_ != NULL_TREE)
{
call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
ffeste_io_iostat_, call);
}
expand_expr_stmt (call);
if (!do_check
|| (ffeste_io_abort_ == NULL_TREE)
|| (TREE_CODE (ffeste_io_abort_) == ERROR_MARK))
return;
/* Generate optional test. */
expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
expand_goto (ffeste_io_abort_);
expand_end_cond ();
}
#endif
/* ffeste_io_dofio_ -- Generate call to do_fio for formatted I/O item
ffebld expr;
tree call;
call = ffeste_io_dofio_(expr);
Returns a tree for a CALL_EXPR to the do_fio function, which handles
a formatted I/O list item, along with the appropriate arguments for
the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
for the CALL_EXPR, expand (emit) the expression, emit any assignment
of the result to an IOSTAT= variable, and emit any checking of the
result for errors. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_dofio_ (ffebld expr)
{
tree num_elements;
tree variable;
tree size;
tree arglist;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
bool is_complex;
bt = ffeinfo_basictype (ffebld_info (expr));
kt = ffeinfo_kindtype (ffebld_info (expr));
if ((bt == FFEINFO_basictypeANY)
|| (kt == FFEINFO_kindtypeANY))
return error_mark_node;
if (bt == FFEINFO_basictypeCOMPLEX)
{
is_complex = TRUE;
bt = FFEINFO_basictypeREAL;
}
else
is_complex = FALSE;
ffecom_push_calltemps ();
variable = ffecom_arg_ptr_to_expr (expr, &size);
if ((variable == error_mark_node)
|| (size == error_mark_node))
{
ffecom_pop_calltemps ();
return error_mark_node;
}
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
size = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (ffecom_tree_type[bt][kt]),
size_int (TYPE_PRECISION (char_type_node)));
#if 0 /* Assume that while it is possible that char * is wider than
ftnlen, no object in Fortran space can get big enough for its
size to be wider than ftnlen. I really hope nobody wastes
time debugging a case where it can! */
assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
>= TYPE_PRECISION (TREE_TYPE (size)));
#endif
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
if ((ffeinfo_rank (ffebld_info (expr)) == 0)
|| (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
: ffecom_f2c_ftnlen_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
size_int (TYPE_PRECISION
(char_type_node)));
num_elements = convert (ffecom_f2c_ftnlen_type_node,
num_elements);
}
num_elements
= ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
num_elements);
variable = convert (string_type_node, variable);
arglist = build_tree_list (NULL_TREE, num_elements);
TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
ffecom_pop_calltemps ();
return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist);
}
#endif
/* ffeste_io_dolio_ -- Generate call to do_lio for list-directed I/O item
ffebld expr;
tree call;
call = ffeste_io_dolio_(expr);
Returns a tree for a CALL_EXPR to the do_lio function, which handles
a list-directed I/O list item, along with the appropriate arguments for
the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
for the CALL_EXPR, expand (emit) the expression, emit any assignment
of the result to an IOSTAT= variable, and emit any checking of the
result for errors. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_dolio_ (ffebld expr)
{
tree type_id;
tree num_elements;
tree variable;
tree size;
tree arglist;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
int tc;
bt = ffeinfo_basictype (ffebld_info (expr));
kt = ffeinfo_kindtype (ffebld_info (expr));
if ((bt == FFEINFO_basictypeANY)
|| (kt == FFEINFO_kindtypeANY))
return error_mark_node;
ffecom_push_calltemps ();
tc = ffecom_f2c_typecode (bt, kt);
assert (tc != -1);
type_id = build_int_2 (tc, 0);
type_id
= ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
convert (ffecom_f2c_ftnint_type_node,
type_id));
variable = ffecom_arg_ptr_to_expr (expr, &size);
if ((type_id == error_mark_node)
|| (variable == error_mark_node)
|| (size == error_mark_node))
{
ffecom_pop_calltemps ();
return error_mark_node;
}
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
size = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (ffecom_tree_type[bt][kt]),
size_int (TYPE_PRECISION (char_type_node)));
#if 0 /* Assume that while it is possible that char * is wider than
ftnlen, no object in Fortran space can get big enough for its
size to be wider than ftnlen. I really hope nobody wastes
time debugging a case where it can! */
assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
>= TYPE_PRECISION (TREE_TYPE (size)));
#endif
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
if ((ffeinfo_rank (ffebld_info (expr)) == 0)
|| (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
num_elements = ffecom_integer_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
num_elements = size_binop (CEIL_DIV_EXPR,
num_elements, size_int (TYPE_PRECISION
(char_type_node)));
num_elements = convert (ffecom_f2c_ftnlen_type_node,
num_elements);
}
num_elements
= ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
num_elements);
variable = convert (string_type_node, variable);
arglist = build_tree_list (NULL_TREE, type_id);
TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
= build_tree_list (NULL_TREE, size);
ffecom_pop_calltemps ();
return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist);
}
#endif
/* ffeste_io_douio_ -- Generate call to do_uio for unformatted I/O item
ffebld expr;
tree call;
call = ffeste_io_douio_(expr);
Returns a tree for a CALL_EXPR to the do_uio function, which handles
an unformatted I/O list item, along with the appropriate arguments for
the function. It is up to the caller to set the TREE_SIDE_EFFECTS flag
for the CALL_EXPR, expand (emit) the expression, emit any assignment
of the result to an IOSTAT= variable, and emit any checking of the
result for errors. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_douio_ (ffebld expr)
{
tree num_elements;
tree variable;
tree size;
tree arglist;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
bool is_complex;
bt = ffeinfo_basictype (ffebld_info (expr));
kt = ffeinfo_kindtype (ffebld_info (expr));
if ((bt == FFEINFO_basictypeANY)
|| (kt == FFEINFO_kindtypeANY))
return error_mark_node;
if (bt == FFEINFO_basictypeCOMPLEX)
{
is_complex = TRUE;
bt = FFEINFO_basictypeREAL;
}
else
is_complex = FALSE;
ffecom_push_calltemps ();
variable = ffecom_arg_ptr_to_expr (expr, &size);
if ((variable == error_mark_node)
|| (size == error_mark_node))
{
ffecom_pop_calltemps ();
return error_mark_node;
}
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
size = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (ffecom_tree_type[bt][kt]),
size_int (TYPE_PRECISION (char_type_node)));
#if 0 /* Assume that while it is possible that char * is wider than
ftnlen, no object in Fortran space can get big enough for its
size to be wider than ftnlen. I really hope nobody wastes
time debugging a case where it can! */
assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
>= TYPE_PRECISION (TREE_TYPE (size)));
#endif
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
if ((ffeinfo_rank (ffebld_info (expr)) == 0)
|| (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
: ffecom_f2c_ftnlen_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
size_int (TYPE_PRECISION
(char_type_node)));
num_elements = convert (ffecom_f2c_ftnlen_type_node,
num_elements);
}
num_elements
= ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
num_elements);
variable = convert (string_type_node, variable);
arglist = build_tree_list (NULL_TREE, num_elements);
TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
ffecom_pop_calltemps ();
return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist);
}
#endif
/* ffeste_io_ialist_ -- Make arglist with ptr to B/E/R control list
tree arglist;
arglist = ffeste_io_ialist_(...);
Returns a tree suitable as an argument list containing a pointer to
a BACKSPACE/ENDFILE/REWIND control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_ialist_ (bool have_err,
ffestvUnit unit,
ffebld unit_expr,
int unit_dflt)
{
static tree f2c_alist_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
bool constantp = TRUE;
static tree errfield, unitfield;
tree errinit, unitinit;
tree unitexp;
static int mynumber = 0;
if (f2c_alist_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
ffecom_f2c_ftnint_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_alist_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
switch (unit)
{
case FFESTV_unitNONE:
case FFESTV_unitASTERISK:
unitinit = build_int_2 (unit_dflt, 0);
unitexp = NULL_TREE;
break;
case FFESTV_unitINTEXPR:
unitexp = ffecom_expr (unit_expr);
if (TREE_CONSTANT (unitexp))
{
unitinit = unitexp;
unitexp = NULL_TREE;
}
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
break;
default:
assert ("bad unit spec" == NULL);
unitexp = NULL_TREE;
unitinit = ffecom_integer_zero_node;
break;
}
inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_alist_%d", NULL,
mynumber++),
f2c_alist_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_io_cilist_ -- Make arglist with ptr to external I/O control list
tree arglist;
arglist = ffeste_io_cilist_(...);
Returns a tree suitable as an argument list containing a pointer to
an external-file I/O control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_cilist_ (bool have_err,
ffestvUnit unit,
ffebld unit_expr,
int unit_dflt,
bool have_end,
ffestvFormat format,
ffestpFile *format_spec,
bool rec,
ffebld rec_expr)
{
static tree f2c_cilist_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
tree ignore; /* We ignore the length of format! */
bool constantp = TRUE;
static tree errfield, unitfield, endfield, formatfield, recfield;
tree errinit, unitinit, endinit, formatinit, recinit;
tree unitexp, formatexp, recexp;
static int mynumber = 0;
if (f2c_cilist_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
ffecom_f2c_ftnint_type_node);
endfield = ffecom_decl_field (ref, unitfield, "end",
ffecom_f2c_flag_type_node);
formatfield = ffecom_decl_field (ref, endfield, "format",
string_type_node);
recfield = ffecom_decl_field (ref, formatfield, "rec",
ffecom_f2c_ftnint_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_cilist_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
switch (unit)
{
case FFESTV_unitNONE:
case FFESTV_unitASTERISK:
unitinit = build_int_2 (unit_dflt, 0);
unitexp = NULL_TREE;
break;
case FFESTV_unitINTEXPR:
unitexp = ffecom_expr (unit_expr);
if (TREE_CONSTANT (unitexp))
{
unitinit = unitexp;
unitexp = NULL_TREE;
}
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
break;
default:
assert ("bad unit spec" == NULL);
unitexp = NULL_TREE;
unitinit = ffecom_integer_zero_node;
break;
}
switch (format)
{
case FFESTV_formatNONE:
formatinit = null_pointer_node;
formatexp = NULL_TREE;
break;
case FFESTV_formatLABEL:
formatexp = NULL_TREE;
formatinit = ffecom_lookup_label (format_spec->u.label);
if ((formatinit == NULL_TREE)
|| (TREE_CODE (formatinit) == ERROR_MARK))
break;
formatinit = ffecom_1 (ADDR_EXPR,
build_pointer_type (void_type_node),
formatinit);
TREE_CONSTANT (formatinit) = 1;
break;
case FFESTV_formatCHAREXPR:
formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, &ignore);
if (TREE_CONSTANT (formatexp))
{
formatinit = formatexp;
formatexp = NULL_TREE;
}
else
{
formatinit = null_pointer_node;
constantp = FALSE;
}
break;
case FFESTV_formatASTERISK:
formatinit = null_pointer_node;
formatexp = NULL_TREE;
break;
case FFESTV_formatINTEXPR:
formatinit = null_pointer_node;
formatexp = ffecom_expr_assign (format_spec->u.expr);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
error ("ASSIGNed FORMAT specifier is too small");
formatexp = convert (string_type_node, formatexp);
break;
case FFESTV_formatNAMELIST:
formatinit = ffecom_expr (format_spec->u.expr);
formatexp = NULL_TREE;
break;
default:
assert ("bad format spec" == NULL);
formatexp = NULL_TREE;
formatinit = integer_zero_node;
break;
}
ffeste_f2c_flagspec_ (have_end, endinit);
if (rec)
recexp = ffecom_expr (rec_expr);
else
recexp = ffecom_integer_zero_node;
if (TREE_CONSTANT (recexp))
{
recinit = recexp;
recexp = NULL_TREE;
}
else
{
recinit = ffecom_integer_zero_node;
constantp = FALSE;
}
inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
ffeste_f2c_init_ (endinit);
ffeste_f2c_init_ (formatinit);
ffeste_f2c_init_ (recinit);
inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_cilist_%d", NULL,
mynumber++),
f2c_cilist_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ffeste_f2c_exp_ (formatfield, formatexp);
ffeste_f2c_exp_ (recfield, recexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_io_cllist_ -- Make arglist with ptr to CLOSE control list
tree arglist;
arglist = ffeste_io_cllist_(...);
Returns a tree suitable as an argument list containing a pointer to
a CLOSE-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_cllist_ (bool have_err,
ffebld unit_expr,
ffestpFile *stat_spec)
{
static tree f2c_close_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
tree ignore; /* Ignore length info for certain fields. */
bool constantp = TRUE;
static tree errfield, unitfield, statfield;
tree errinit, unitinit, statinit;
tree unitexp, statexp;
static int mynumber = 0;
if (f2c_close_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
ffecom_f2c_ftnint_type_node);
statfield = ffecom_decl_field (ref, unitfield, "stat",
string_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_close_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
unitexp = ffecom_expr (unit_expr);
if (TREE_CONSTANT (unitexp))
{
unitinit = unitexp;
unitexp = NULL_TREE;
}
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
ffeste_f2c_init_ (statinit);
inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_cllist_%d", NULL,
mynumber++),
f2c_close_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ffeste_f2c_exp_ (statfield, statexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_io_icilist_ -- Make arglist with ptr to internal I/O control list
tree arglist;
arglist = ffeste_io_icilist_(...);
Returns a tree suitable as an argument list containing a pointer to
an internal-file I/O control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_icilist_ (bool have_err,
ffebld unit_expr,
bool have_end,
ffestvFormat format,
ffestpFile *format_spec)
{
static tree f2c_icilist_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
tree ignore; /* We ignore the length of format! */
bool constantp = TRUE;
static tree errfield, unitfield, endfield, formatfield, unitlenfield,
unitnumfield;
tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
tree unitexp, formatexp, unitlenexp, unitnumexp;
static int mynumber = 0;
if (f2c_icilist_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
string_type_node);
endfield = ffecom_decl_field (ref, unitfield, "end",
ffecom_f2c_flag_type_node);
formatfield = ffecom_decl_field (ref, endfield, "format",
string_type_node);
unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
ffecom_f2c_ftnint_type_node);
unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
ffecom_f2c_ftnint_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_icilist_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
if ((ffeinfo_rank (ffebld_info (unit_expr)) == 0)
|| (TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
unitnumexp = ffecom_integer_one_node;
else
{
unitnumexp = size_binop (CEIL_DIV_EXPR,
TYPE_SIZE (TREE_TYPE (TREE_TYPE (unitexp))), unitlenexp);
unitnumexp = size_binop (CEIL_DIV_EXPR,
unitnumexp, size_int (TYPE_PRECISION
(char_type_node)));
}
if (TREE_CONSTANT (unitexp))
{
unitinit = unitexp;
unitexp = NULL_TREE;
}
else
{
unitinit = null_pointer_node;
constantp = FALSE;
}
if ((unitlenexp != NULL_TREE) && TREE_CONSTANT (unitlenexp))
{
unitleninit = unitlenexp;
unitlenexp = NULL_TREE;
}
else
{
unitleninit = ffecom_integer_zero_node;
constantp = FALSE;
}
if (TREE_CONSTANT (unitnumexp))
{
unitnuminit = unitnumexp;
unitnumexp = NULL_TREE;
}
else
{
unitnuminit = ffecom_integer_zero_node;
constantp = FALSE;
}
switch (format)
{
case FFESTV_formatNONE:
formatinit = null_pointer_node;
formatexp = NULL_TREE;
break;
case FFESTV_formatLABEL:
formatexp = NULL_TREE;
formatinit = ffecom_lookup_label (format_spec->u.label);
if ((formatinit == NULL_TREE)
|| (TREE_CODE (formatinit) == ERROR_MARK))
break;
formatinit = ffecom_1 (ADDR_EXPR,
build_pointer_type (void_type_node),
formatinit);
TREE_CONSTANT (formatinit) = 1;
break;
case FFESTV_formatCHAREXPR:
formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, &ignore);
if (TREE_CONSTANT (formatexp))
{
formatinit = formatexp;
formatexp = NULL_TREE;
}
else
{
formatinit = null_pointer_node;
constantp = FALSE;
}
break;
case FFESTV_formatASTERISK:
formatinit = null_pointer_node;
formatexp = NULL_TREE;
break;
case FFESTV_formatINTEXPR:
formatinit = null_pointer_node;
formatexp = ffecom_expr_assign (format_spec->u.expr);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
error ("ASSIGNed FORMAT specifier is too small");
formatexp = convert (string_type_node, formatexp);
break;
default:
assert ("bad format spec" == NULL);
formatexp = NULL_TREE;
formatinit = ffecom_integer_zero_node;
break;
}
ffeste_f2c_flagspec_ (have_end, endinit);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
ffeste_f2c_init_ (endinit);
ffeste_f2c_init_ (formatinit);
ffeste_f2c_init_ (unitleninit);
ffeste_f2c_init_ (unitnuminit);
inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_icilist_%d", NULL,
mynumber++),
f2c_icilist_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ffeste_f2c_exp_ (formatfield, formatexp);
ffeste_f2c_exp_ (unitlenfield, unitlenexp);
ffeste_f2c_exp_ (unitnumfield, unitnumexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_io_impdo_ -- Handle implied-DO in I/O list
ffebld expr;
ffeste_io_impdo_(expr);
Expands code to start up the DO loop. Then for each item in the
DO loop, handles appropriately (possibly including recursively calling
itself). Then expands code to end the DO loop. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
{
ffebld var = ffebld_head (ffebld_right (impdo));
ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
ffebld end = ffebld_head (ffebld_trail (ffebld_trail
(ffebld_right (impdo))));
ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
(ffebld_trail (ffebld_right (impdo)))));
ffebld list; /* Used for list of items in left part of
impdo. */
ffebld item; /* I/O item from head of given list. */
tree tvar;
tree tincr;
tree titervar;
if (incr == NULL)
{
incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
ffebld_set_info (incr, ffeinfo_new
(FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
}
/* Start the DO loop. */
start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
FFEEXPR_contextLET);
end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
FFEEXPR_contextLET);
incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
FFEEXPR_contextLET);
ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
start, impdo_token,
end, impdo_token,
incr, impdo_token,
"Implied DO loop");
/* Handle the list of items. */
for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
{
item = ffebld_head (list);
if (item == NULL)
continue;
while (ffebld_op (item) == FFEBLD_opPAREN)
item = ffebld_left (item);
if (ffebld_op (item) == FFEBLD_opANY)
continue;
if (ffebld_op (item) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (item, impdo_token);
else
ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
clear_momentary ();
}
/* Generate end of implied-do construct. */
ffeste_end_iterdo_ (tvar, tincr, titervar);
}
#endif
/* ffeste_io_inlist_ -- Make arglist with ptr to INQUIRE control list
tree arglist;
arglist = ffeste_io_inlist_(...);
Returns a tree suitable as an argument list containing a pointer to
an INQUIRE-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_inlist_ (bool have_err,
ffestpFile *unit_spec,
ffestpFile *file_spec,
ffestpFile *exist_spec,
ffestpFile *open_spec,
ffestpFile *number_spec,
ffestpFile *named_spec,
ffestpFile *name_spec,
ffestpFile *access_spec,
ffestpFile *sequential_spec,
ffestpFile *direct_spec,
ffestpFile *form_spec,
ffestpFile *formatted_spec,
ffestpFile *unformatted_spec,
ffestpFile *recl_spec,
ffestpFile *nextrec_spec,
ffestpFile *blank_spec)
{
static tree f2c_inquire_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
bool constantp = TRUE;
static tree errfield, unitfield, filefield, filelenfield, existfield,
openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
sequentialleninit, directinit, directleninit, forminit, formleninit,
formattedinit, formattedleninit, unformattedinit, unformattedleninit,
reclinit, nextrecinit, blankinit, blankleninit;
tree
unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
static int mynumber = 0;
if (f2c_inquire_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
ffecom_f2c_ftnint_type_node);
filefield = ffecom_decl_field (ref, unitfield, "file",
string_type_node);
filelenfield = ffecom_decl_field (ref, filefield, "filelen",
ffecom_f2c_ftnlen_type_node);
existfield = ffecom_decl_field (ref, filelenfield, "exist",
ffecom_f2c_ptr_to_ftnint_type_node);
openfield = ffecom_decl_field (ref, existfield, "open",
ffecom_f2c_ptr_to_ftnint_type_node);
numberfield = ffecom_decl_field (ref, openfield, "number",
ffecom_f2c_ptr_to_ftnint_type_node);
namedfield = ffecom_decl_field (ref, numberfield, "named",
ffecom_f2c_ptr_to_ftnint_type_node);
namefield = ffecom_decl_field (ref, namedfield, "name",
string_type_node);
namelenfield = ffecom_decl_field (ref, namefield, "namelen",
ffecom_f2c_ftnlen_type_node);
accessfield = ffecom_decl_field (ref, namelenfield, "access",
string_type_node);
accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
ffecom_f2c_ftnlen_type_node);
sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
string_type_node);
sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
"sequentiallen",
ffecom_f2c_ftnlen_type_node);
directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
string_type_node);
directlenfield = ffecom_decl_field (ref, directfield, "directlen",
ffecom_f2c_ftnlen_type_node);
formfield = ffecom_decl_field (ref, directlenfield, "form",
string_type_node);
formlenfield = ffecom_decl_field (ref, formfield, "formlen",
ffecom_f2c_ftnlen_type_node);
formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
string_type_node);
formattedlenfield = ffecom_decl_field (ref, formattedfield,
"formattedlen",
ffecom_f2c_ftnlen_type_node);
unformattedfield = ffecom_decl_field (ref, formattedlenfield,
"unformatted",
string_type_node);
unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
"unformattedlen",
ffecom_f2c_ftnlen_type_node);
reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
ffecom_f2c_ptr_to_ftnint_type_node);
nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
ffecom_f2c_ptr_to_ftnint_type_node);
blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
string_type_node);
blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
ffecom_f2c_ftnlen_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_inquire_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
ffeste_f2c_intspec_ (unit_spec, unitexp, unitinit);
ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
ffeste_f2c_ptrtointspec_ (exist_spec, existexp, existinit);
ffeste_f2c_ptrtointspec_ (open_spec, openexp, openinit);
ffeste_f2c_ptrtointspec_ (number_spec, numberexp, numberinit);
ffeste_f2c_ptrtointspec_ (named_spec, namedexp, namedinit);
ffeste_f2c_charspec_ (name_spec, nameexp, nameinit, namelenexp, nameleninit);
ffeste_f2c_charspec_ (access_spec, accessexp, accessinit, accesslenexp,
accessleninit);
ffeste_f2c_charspec_ (sequential_spec, sequentialexp, sequentialinit,
sequentiallenexp, sequentialleninit);
ffeste_f2c_charspec_ (direct_spec, directexp, directinit, directlenexp,
directleninit);
ffeste_f2c_charspec_ (form_spec, formexp, forminit, formlenexp, formleninit);
ffeste_f2c_charspec_ (formatted_spec, formattedexp, formattedinit,
formattedlenexp, formattedleninit);
ffeste_f2c_charspec_ (unformatted_spec, unformattedexp, unformattedinit,
unformattedlenexp, unformattedleninit);
ffeste_f2c_ptrtointspec_ (recl_spec, reclexp, reclinit);
ffeste_f2c_ptrtointspec_ (nextrec_spec, nextrecexp, nextrecinit);
ffeste_f2c_charspec_ (blank_spec, blankexp, blankinit, blanklenexp,
blankleninit);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
ffeste_f2c_init_ (fileinit);
ffeste_f2c_init_ (fileleninit);
ffeste_f2c_init_ (existinit);
ffeste_f2c_init_ (openinit);
ffeste_f2c_init_ (numberinit);
ffeste_f2c_init_ (namedinit);
ffeste_f2c_init_ (nameinit);
ffeste_f2c_init_ (nameleninit);
ffeste_f2c_init_ (accessinit);
ffeste_f2c_init_ (accessleninit);
ffeste_f2c_init_ (sequentialinit);
ffeste_f2c_init_ (sequentialleninit);
ffeste_f2c_init_ (directinit);
ffeste_f2c_init_ (directleninit);
ffeste_f2c_init_ (forminit);
ffeste_f2c_init_ (formleninit);
ffeste_f2c_init_ (formattedinit);
ffeste_f2c_init_ (formattedleninit);
ffeste_f2c_init_ (unformattedinit);
ffeste_f2c_init_ (unformattedleninit);
ffeste_f2c_init_ (reclinit);
ffeste_f2c_init_ (nextrecinit);
ffeste_f2c_init_ (blankinit);
ffeste_f2c_init_ (blankleninit);
inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_inlist_%d", NULL,
mynumber++),
f2c_inquire_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ffeste_f2c_exp_ (filefield, fileexp);
ffeste_f2c_exp_ (filelenfield, filelenexp);
ffeste_f2c_exp_ (existfield, existexp);
ffeste_f2c_exp_ (openfield, openexp);
ffeste_f2c_exp_ (numberfield, numberexp);
ffeste_f2c_exp_ (namedfield, namedexp);
ffeste_f2c_exp_ (namefield, nameexp);
ffeste_f2c_exp_ (namelenfield, namelenexp);
ffeste_f2c_exp_ (accessfield, accessexp);
ffeste_f2c_exp_ (accesslenfield, accesslenexp);
ffeste_f2c_exp_ (sequentialfield, sequentialexp);
ffeste_f2c_exp_ (sequentiallenfield, sequentiallenexp);
ffeste_f2c_exp_ (directfield, directexp);
ffeste_f2c_exp_ (directlenfield, directlenexp);
ffeste_f2c_exp_ (formfield, formexp);
ffeste_f2c_exp_ (formlenfield, formlenexp);
ffeste_f2c_exp_ (formattedfield, formattedexp);
ffeste_f2c_exp_ (formattedlenfield, formattedlenexp);
ffeste_f2c_exp_ (unformattedfield, unformattedexp);
ffeste_f2c_exp_ (unformattedlenfield, unformattedlenexp);
ffeste_f2c_exp_ (reclfield, reclexp);
ffeste_f2c_exp_ (nextrecfield, nextrecexp);
ffeste_f2c_exp_ (blankfield, blankexp);
ffeste_f2c_exp_ (blanklenfield, blanklenexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_io_olist_ -- Make arglist with ptr to OPEN control list
tree arglist;
arglist = ffeste_io_olist_(...);
Returns a tree suitable as an argument list containing a pointer to
an OPEN-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
that are needed as specified by the arguments to this function. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffeste_io_olist_ (bool have_err,
ffebld unit_expr,
ffestpFile *file_spec,
ffestpFile *stat_spec,
ffestpFile *access_spec,
ffestpFile *form_spec,
ffestpFile *recl_spec,
ffestpFile *blank_spec)
{
static tree f2c_open_struct = NULL_TREE;
tree t;
tree ttype;
int yes;
tree field;
tree inits, initn;
tree ignore; /* Ignore length info for certain fields. */
bool constantp = TRUE;
static tree errfield, unitfield, filefield, filelenfield, statfield,
accessfield, formfield, reclfield, blankfield;
tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
forminit, reclinit, blankinit;
tree
unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
blankexp;
static int mynumber = 0;
if (f2c_open_struct == NULL_TREE)
{
tree ref;
push_obstacks_nochange ();
end_temporary_allocation ();
ref = make_node (RECORD_TYPE);
errfield = ffecom_decl_field (ref, NULL_TREE, "err",
ffecom_f2c_flag_type_node);
unitfield = ffecom_decl_field (ref, errfield, "unit",
ffecom_f2c_ftnint_type_node);
filefield = ffecom_decl_field (ref, unitfield, "file",
string_type_node);
filelenfield = ffecom_decl_field (ref, filefield, "filelen",
ffecom_f2c_ftnlen_type_node);
statfield = ffecom_decl_field (ref, filelenfield, "stat",
string_type_node);
accessfield = ffecom_decl_field (ref, statfield, "access",
string_type_node);
formfield = ffecom_decl_field (ref, accessfield, "form",
string_type_node);
reclfield = ffecom_decl_field (ref, formfield, "recl",
ffecom_f2c_ftnint_type_node);
blankfield = ffecom_decl_field (ref, reclfield, "blank",
string_type_node);
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
resume_temporary_allocation ();
pop_obstacks ();
f2c_open_struct = ref;
}
ffeste_f2c_flagspec_ (have_err, errinit);
unitexp = ffecom_expr (unit_expr);
if (TREE_CONSTANT (unitexp))
{
unitinit = unitexp;
unitexp = NULL_TREE;
}
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
ffeste_f2c_charnolenspec_ (access_spec, accessexp, accessinit);
ffeste_f2c_charnolenspec_ (form_spec, formexp, forminit);
ffeste_f2c_intspec_ (recl_spec, reclexp, reclinit);
ffeste_f2c_charnolenspec_ (blank_spec, blankexp, blankinit);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
initn = inits;
ffeste_f2c_init_ (unitinit);
ffeste_f2c_init_ (fileinit);
ffeste_f2c_init_ (fileleninit);
ffeste_f2c_init_ (statinit);
ffeste_f2c_init_ (accessinit);
ffeste_f2c_init_ (forminit);
ffeste_f2c_init_ (reclinit);
ffeste_f2c_init_ (blankinit);
inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
TREE_STATIC (inits) = 1;
yes = suspend_momentary ();
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_olist_%d", NULL,
mynumber++),
f2c_open_struct);
TREE_STATIC (t) = 1;
t = ffecom_start_decl (t, 1);
ffecom_finish_decl (t, inits, 0);
resume_momentary (yes);
ffeste_f2c_exp_ (unitfield, unitexp);
ffeste_f2c_exp_ (filefield, fileexp);
ffeste_f2c_exp_ (filelenfield, filelenexp);
ffeste_f2c_exp_ (statfield, statexp);
ffeste_f2c_exp_ (accessfield, accessexp);
ffeste_f2c_exp_ (formfield, formexp);
ffeste_f2c_exp_ (reclfield, reclexp);
ffeste_f2c_exp_ (blankfield, blankexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
t = build_tree_list (NULL_TREE, t);
return t;
}
#endif
/* ffeste_subr_file_ -- Display file-statement specifier
ffeste_subr_file_(&specifier); */
#if FFECOM_targetCURRENT == FFECOM_targetFFE
static void
ffeste_subr_file_ (char *kw, ffestpFile *spec)
{
if (!spec->kw_or_val_present)
return;
fputs (kw, dmpout);
if (spec->value_present)
{
fputc ('=', dmpout);
if (spec->value_is_label)
{
assert (spec->value_is_label == 2); /* Temporary checking only. */
fprintf (dmpout, "%" ffelabValue_f "u",
ffelab_value (spec->u.label));
}
else
ffebld_dump (spec->u.expr);
}
fputc (',', dmpout);
}
#endif
/* ffeste_subr_beru_ -- Generate code for BACKSPACE/ENDFILE/REWIND
ffeste_subr_beru_(FFECOM_gfrtFBACK); */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
{
tree alist;
bool iostat;
bool errl;
#define specified(something) (info->beru_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
/* Do the real work. */
iostat = specified (FFESTP_beruixIOSTAT);
errl = specified (FFESTP_beruixERR);
/* ~~For now, we assume the unit number is specified and is not ASTERISK,
because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
without any unit specifier. f2c, however, supports the former
construct. When it is time to add this feature to the FFE, which
probably is fairly easy, ffestc_R919 and company will want to pass an
ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
ffeste_R919 and company, and they will want to pass that same value to
this function, and that argument will replace the constant _unitINTEXPR_
in the call below. Right now, the default unit number, 6, is ignored. */
ffecom_push_calltemps ();
alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
if (errl)
{ /* ERR= */
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
(info->beru_spec[FFESTP_beruixERR].u.label);
ffeste_io_abort_is_temp_ = FALSE;
}
else
{ /* no ERR= */
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, or ERR= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (rt, alist),
!ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
assert (ffeste_io_err_ == NULL_TREE);
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
#undef specified
clear_momentary ();
}
#endif
/* ffeste_do -- End of statement following DO-term-stmt etc
ffeste_do(TRUE);
Also invoked by _labeldef_branch_finish_ (or, in cases
of errors, other _labeldef_ functions) when the label definition is
for a DO-target (LOOPEND) label, once per matching/outstanding DO
block on the stack. These cases invoke this function with ok==TRUE, so
only forced stack popping (via ffeste_eof_()) invokes it with ok==FALSE. */
void
ffeste_do (ffestw block)
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_DO\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
if (ffestw_do_tvar (block) == 0)
expand_end_loop (); /* DO WHILE and just DO. */
else
ffeste_end_iterdo_ (ffestw_do_tvar (block),
ffestw_do_incr_saved (block),
ffestw_do_count_var (block));
clear_momentary ();
#else
#error
#endif
}
/* ffeste_end_R807 -- End of statement following logical IF
ffeste_end_R807(TRUE);
Applies ONLY to logical IF, not to IF-THEN. For example, does not
ffelex_token_kill the construct name for an IF-THEN block (the name
field is invalid for logical IF). ok==TRUE iff statement following
logical IF (substatement) is valid; else, statement is invalid or
stack forcibly popped due to ffeste_eof_(). */
void
ffeste_end_R807 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_IF\n", dmpout); /* Also see ffeste_R806. */
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
expand_end_cond ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_labeldef_branch -- Generate "code" for branch label def
ffeste_labeldef_branch(label); */
void
ffeste_labeldef_branch (ffelab label)
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ label %lu\n", ffelab_value (label));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree glabel;
glabel = ffecom_lookup_label (label);
assert (glabel != NULL_TREE);
if (TREE_CODE (glabel) == ERROR_MARK)
return;
assert (DECL_INITIAL (glabel) == NULL_TREE);
DECL_INITIAL (glabel) = error_mark_node;
DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
emit_nop ();
expand_label (glabel);
}
#else
#error
#endif
}
/* ffeste_labeldef_format -- Generate "code" for FORMAT label def
ffeste_labeldef_format(label); */
void
ffeste_labeldef_format (ffelab label)
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "$ label %lu\n", ffelab_value (label));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_label_formatdef_ = label;
#else
#error
#endif
}
/* ffeste_R737A -- Assignment statement outside of WHERE
ffeste_R737A(dest_expr,source_expr); */
void
ffeste_R737A (ffebld dest, ffebld source)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ let ", dmpout);
ffebld_dump (dest);
fputs ("=", dmpout);
ffebld_dump (source);
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
ffecom_expand_let_stmt (dest, source);
ffecom_pop_calltemps ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R803 -- Block IF (IF-THEN) statement
ffeste_R803(construct_name,expr,expr_token);
Make sure statement is valid here; implement. */
void
ffeste_R803 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ IF_block (", dmpout);
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
ffecom_pop_calltemps ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R804 -- ELSE IF statement
ffeste_R804(expr,expr_token,name_token);
Make sure ffeste_kind_ identifies an IF block. If not
NULL, make sure name_token gives the correct name. Implement the else
of the IF block. */
void
ffeste_R804 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ ELSE_IF (", dmpout);
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
expand_start_elseif (ffecom_truth_value (ffecom_expr (expr)));
ffecom_pop_calltemps ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R805 -- ELSE statement
ffeste_R805(name_token);
Make sure ffeste_kind_ identifies an IF block. If not
NULL, make sure name_token gives the correct name. Implement the ELSE
of the IF block. */
void
ffeste_R805 ()
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ ELSE\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
expand_start_else ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R806 -- End an IF-THEN
ffeste_R806(TRUE); */
void
ffeste_R806 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_IF_then\n", dmpout); /* Also see ffeste_shriek_if_. */
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
expand_end_cond ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R807 -- Logical IF statement
ffeste_R807(expr,expr_token);
Make sure statement is valid here; implement. */
void
ffeste_R807 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ IF_logical (", dmpout);
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
ffecom_pop_calltemps ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R809 -- SELECT CASE statement
ffeste_R809(construct_name,expr,expr_token);
Make sure statement is valid here; implement. */
void
ffeste_R809 (ffestw block, ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ SELECT_CASE (", dmpout);
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffecom_push_calltemps ();
{
tree texpr;
ffeste_emit_line_note_ ();
if ((expr == NULL)
|| (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeANY))
{
ffestw_set_select_texpr (block, error_mark_node);
clear_momentary ();
}
else
{
texpr = ffecom_expr (expr);
if (ffeinfo_basictype (ffebld_info (expr))
!= FFEINFO_basictypeCHARACTER)
{
expand_start_case (1, texpr, TREE_TYPE (texpr),
"SELECT CASE statement");
ffestw_set_select_texpr (block, texpr);
ffestw_set_select_break (block, FALSE);
push_momentary ();
}
else
{
ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
FFEBAD_severityFATAL);
ffebad_here (0, ffestw_line (block), ffestw_col (block));
ffebad_finish ();
ffestw_set_select_texpr (block, error_mark_node);
}
}
}
ffecom_pop_calltemps ();
#else
#error
#endif
}
/* ffeste_R810 -- CASE statement
ffeste_R810(case_value_range_list,name);
If casenum is 0, it's CASE DEFAULT. Else it's the case ranges at
the start of the first_stmt list in the select object at the top of
the stack that match casenum. */
void
ffeste_R810 (ffestw block, unsigned long casenum)
{
ffestwSelect s = ffestw_select (block);
ffestwCase c;
ffeste_check_simple_ ();
if (s->first_stmt == (ffestwCase) &s->first_rel)
c = NULL;
else
c = s->first_stmt;
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if ((c == NULL) || (casenum != c->casenum))
{
if (casenum == 0) /* Intentional CASE DEFAULT. */
fputs ("+ CASE_DEFAULT", dmpout);
}
else
{
bool comma = FALSE;
fputs ("+ CASE (", dmpout);
do
{
if (comma)
fputc (',', dmpout);
else
comma = TRUE;
if (c->low != NULL)
ffebld_constant_dump (c->low);
if (c->low != c->high)
{
fputc (':', dmpout);
if (c->high != NULL)
ffebld_constant_dump (c->high);
}
c = c->next_stmt;
/* Unlink prev. */
c->previous_stmt->previous_stmt->next_stmt = c;
c->previous_stmt = c->previous_stmt->previous_stmt;
}
while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
fputc (')', dmpout);
}
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree texprlow;
tree texprhigh;
tree tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
int pushok;
tree duplicate;
ffeste_emit_line_note_ ();
if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
{
clear_momentary ();
return;
}
if (ffestw_select_break (block))
expand_exit_something ();
else
ffestw_set_select_break (block, TRUE);
if ((c == NULL) || (casenum != c->casenum))
{
if (casenum == 0) /* Intentional CASE DEFAULT. */
{
pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
assert (pushok == 0);
}
}
else
do
{
texprlow = (c->low == NULL) ? NULL_TREE
: ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
if (c->low != c->high)
{
texprhigh = (c->high == NULL) ? NULL_TREE
: ffecom_constantunion (&ffebld_constant_union (c->high),
s->type, s->kindtype, ffecom_tree_type[s->type][s->kindtype]);
pushok = pushcase_range (texprlow, texprhigh, convert,
tlabel, &duplicate);
}
else
pushok = pushcase (texprlow, convert, tlabel, &duplicate);
assert (pushok == 0);
c = c->next_stmt;
/* Unlink prev. */
c->previous_stmt->previous_stmt->next_stmt = c;
c->previous_stmt = c->previous_stmt->previous_stmt;
}
while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
clear_momentary ();
} /* ~~~handle character, character*1 */
#else
#error
#endif
}
/* ffeste_R811 -- End a SELECT
ffeste_R811(TRUE); */
void
ffeste_R811 (ffestw block)
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_SELECT\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
{
clear_momentary ();
return;
}
expand_end_case (ffestw_select_texpr (block));
pop_momentary ();
clear_momentary (); /* ~~~handle character and character*1 */
#else
#error
#endif
}
/* Iterative DO statement. */
void
ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
ffebld start, ffelexToken start_token,
ffebld end, ffelexToken end_token,
ffebld incr, ffelexToken incr_token)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if ((ffebld_op (incr) == FFEBLD_opCONTER)
&& (ffebld_constant_is_zero (ffebld_conter (incr))))
{
ffebad_start (FFEBAD_DO_STEP_ZERO);
ffebad_here (0, ffelex_token_where_line (incr_token),
ffelex_token_where_column (incr_token));
ffebad_string ("Iterative DO loop");
ffebad_finish ();
/* Don't bother replacing it with 1 yet. */
}
if (label == NULL)
fputs ("+ DO_iterative_nonlabeled (", dmpout);
else
fprintf (dmpout, "+ DO_iterative_labeled %lu (", ffelab_value (label));
ffebld_dump (var);
fputc ('=', dmpout);
ffebld_dump (start);
fputc (',', dmpout);
ffebld_dump (end);
fputc (',', dmpout);
ffebld_dump (incr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
/* Start the DO loop. */
ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
var,
start, start_token,
end, end_token,
incr, incr_token,
"Iterative DO loop");
ffecom_pop_calltemps ();
}
#else
#error
#endif
}
/* ffeste_R819B -- DO WHILE statement
ffeste_R819B(construct_name,label_token,expr,expr_token);
Make sure statement is valid here; implement. */
void
ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if (label == NULL)
fputs ("+ DO_WHILE_nonlabeled (", dmpout);
else
fprintf (dmpout, "+ DO_WHILE_labeled %lu (", ffelab_value (label));
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
ffestw_set_do_hook (block, expand_start_loop (1));
ffestw_set_do_tvar (block, 0); /* Means DO WHILE vs. iter DO. */
if (expr != NULL)
expand_exit_loop_if_false (0, ffecom_truth_value (ffecom_expr (expr)));
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R825 -- END DO statement
ffeste_R825(name_token);
Make sure ffeste_kind_ identifies a DO block. If not
NULL, make sure name_token gives the correct name. Do whatever
is specific to seeing END DO with a DO-target label definition on it,
where the END DO is really treated as a CONTINUE (i.e. generate th
same code you would for CONTINUE). ffeste_do handles the actual
generation of end-loop code. */
void
ffeste_R825 ()
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_DO_sugar\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
emit_nop ();
#else
#error
#endif
}
/* ffeste_R834 -- CYCLE statement
ffeste_R834(name_token);
Handle a CYCLE within a loop. */
void
ffeste_R834 (ffestw block)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ CYCLE block #%lu\n", ffestw_blocknum (block));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
expand_continue_loop (ffestw_do_hook (block));
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R835 -- EXIT statement
ffeste_R835(name_token);
Handle a EXIT within a loop. */
void
ffeste_R835 (ffestw block)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ EXIT block #%lu\n", ffestw_blocknum (block));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
expand_exit_loop (ffestw_do_hook (block));
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R836 -- GOTO statement
ffeste_R836(label);
Make sure label_token identifies a valid label for a GOTO. Update
that label's info to indicate it is the target of a GOTO. */
void
ffeste_R836 (ffelab label)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ GOTO %lu\n", ffelab_value (label));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree glabel;
ffeste_emit_line_note_ ();
glabel = ffecom_lookup_label (label);
if ((glabel != NULL_TREE)
&& (TREE_CODE (glabel) != ERROR_MARK))
{
TREE_USED (glabel) = 1;
expand_goto (glabel);
clear_momentary ();
}
}
#else
#error
#endif
}
/* ffeste_R837 -- Computed GOTO statement
ffeste_R837(labels,count,expr);
Make sure label_list identifies valid labels for a GOTO. Update
each label's info to indicate it is the target of a GOTO. */
void
ffeste_R837 (ffelab *labels, int count, ffebld expr)
{
int i;
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ CGOTO (", dmpout);
for (i = 0; i < count; ++i)
{
if (i != 0)
fputc (',', dmpout);
fprintf (dmpout, "%" ffelabValue_f "u", ffelab_value (labels[i]));
}
fputs ("),", dmpout);
ffebld_dump (expr);
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree texpr;
tree value;
tree tlabel;
int pushok;
tree duplicate;
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
texpr = ffecom_expr (expr);
expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
push_momentary (); /* In case of lots of labels, keep clearing
them out. */
for (i = 0; i < count; ++i)
{
value = build_int_2 (i + 1, 0);
tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
pushok = pushcase (value, convert, tlabel, &duplicate);
assert (pushok == 0);
tlabel = ffecom_lookup_label (labels[i]);
if ((tlabel == NULL_TREE)
|| (TREE_CODE (tlabel) == ERROR_MARK))
continue;
TREE_USED (tlabel) = 1;
expand_goto (tlabel);
clear_momentary ();
}
pop_momentary ();
expand_end_case (texpr);
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R838 -- ASSIGN statement
ffeste_R838(label_token,target_variable,target_token);
Make sure label_token identifies a valid label for an assignment. Update
that label's info to indicate it is the source of an assignment. Update
target_variable's info to indicate it is the target the assignment of that
label. */
void
ffeste_R838 (ffelab label, ffebld target)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ ASSIGN %lu TO ", ffelab_value (label));
ffebld_dump (target);
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree expr_tree;
tree label_tree;
tree target_tree;
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
label_tree = ffecom_lookup_label (label);
if ((label_tree != NULL_TREE)
&& (TREE_CODE (label_tree) != ERROR_MARK))
{
label_tree = ffecom_1 (ADDR_EXPR,
build_pointer_type (void_type_node),
label_tree);
TREE_CONSTANT (label_tree) = 1;
target_tree = ffecom_expr_assign_w (target);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
error ("ASSIGN to variable that is too small");
label_tree = convert (TREE_TYPE (target_tree), label_tree);
expr_tree = ffecom_modify (void_type_node,
target_tree,
label_tree);
expand_expr_stmt (expr_tree);
clear_momentary ();
}
ffecom_pop_calltemps ();
}
#else
#error
#endif
}
/* ffeste_R839 -- Assigned GOTO statement
ffeste_R839(target,target_token,label_list);
Make sure label_list identifies valid labels for a GOTO. Update
each label's info to indicate it is the target of a GOTO. */
void
ffeste_R839 (ffebld target)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ AGOTO ", dmpout);
ffebld_dump (target);
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree t;
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
t = ffecom_expr_assign (target);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
error ("ASSIGNed GOTO target variable is too small");
expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R840 -- Arithmetic IF statement
ffeste_R840(expr,expr_token,neg,zero,pos);
Make sure the labels are valid; implement. */
void
ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ IF_arithmetic (", dmpout);
ffebld_dump (expr);
fprintf (dmpout, ") %" ffelabValue_f "u,%" ffelabValue_f "u,%" ffelabValue_f "u\n",
ffelab_value (neg), ffelab_value (zero), ffelab_value (pos));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree gneg = ffecom_lookup_label (neg);
tree gzero = ffecom_lookup_label (zero);
tree gpos = ffecom_lookup_label (pos);
tree texpr;
if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
return;
if ((TREE_CODE (gneg) == ERROR_MARK)
|| (TREE_CODE (gzero) == ERROR_MARK)
|| (TREE_CODE (gpos) == ERROR_MARK))
return;
ffecom_push_calltemps ();
if (neg == zero)
if (neg == pos)
expand_goto (gzero);
else
{ /* IF (expr.LE.0) THEN GOTO neg/zero ELSE
GOTO pos. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (LE_EXPR, integer_type_node,
texpr,
convert (TREE_TYPE (texpr),
integer_zero_node));
expand_start_cond (ffecom_truth_value (texpr), 0);
expand_goto (gzero);
expand_start_else ();
expand_goto (gpos);
expand_end_cond ();
}
else if (neg == pos)
{ /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO
zero. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (NE_EXPR, integer_type_node,
texpr,
convert (TREE_TYPE (texpr),
integer_zero_node));
expand_start_cond (ffecom_truth_value (texpr), 0);
expand_goto (gneg);
expand_start_else ();
expand_goto (gzero);
expand_end_cond ();
}
else if (zero == pos)
{ /* IF (expr.GE.0) THEN GOTO zero/pos ELSE
GOTO neg. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (GE_EXPR, integer_type_node,
texpr,
convert (TREE_TYPE (texpr),
integer_zero_node));
expand_start_cond (ffecom_truth_value (texpr), 0);
expand_goto (gzero);
expand_start_else ();
expand_goto (gneg);
expand_end_cond ();
}
else
{ /* Use a SAVE_EXPR in combo with:
IF (expr.LT.0) THEN GOTO neg
ELSEIF (expr.GT.0) THEN GOTO pos
ELSE GOTO zero. */
tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
texpr = ffecom_2 (LT_EXPR, integer_type_node,
expr_saved,
convert (TREE_TYPE (expr_saved),
integer_zero_node));
expand_start_cond (ffecom_truth_value (texpr), 0);
expand_goto (gneg);
texpr = ffecom_2 (GT_EXPR, integer_type_node,
expr_saved,
convert (TREE_TYPE (expr_saved),
integer_zero_node));
expand_start_elseif (ffecom_truth_value (texpr));
expand_goto (gpos);
expand_start_else ();
expand_goto (gzero);
expand_end_cond ();
}
ffeste_emit_line_note_ ();
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R841 -- CONTINUE statement
ffeste_R841(); */
void
ffeste_R841 ()
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ CONTINUE\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
emit_nop ();
#else
#error
#endif
}
/* ffeste_R842 -- STOP statement
ffeste_R842(expr); */
void
ffeste_R842 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if (expr == NULL)
{
fputs ("+ STOP\n", dmpout);
}
else
{
fputs ("+ STOP_coded ", dmpout);
ffebld_dump (expr);
fputc ('\n', dmpout);
}
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree callit;
ffelexToken msg;
ffeste_emit_line_note_ ();
if ((expr == NULL)
|| (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeANY))
{
msg = ffelex_token_new_character ("", ffelex_token_where_line
(ffesta_tokens[0]), ffelex_token_where_column
(ffesta_tokens[0]));
expr = ffebld_new_conter (ffebld_constant_new_characterdefault
(msg));
ffelex_token_kill (msg);
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, 0));
}
else if (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeINTEGER)
{
char num[50];
assert (ffebld_op (expr) == FFEBLD_opCONTER);
assert (ffeinfo_kindtype (ffebld_info (expr))
== FFEINFO_kindtypeINTEGERDEFAULT);
sprintf (num, "%" ffetargetIntegerDefault_f "d",
ffebld_constant_integer1 (ffebld_conter (expr)));
msg = ffelex_token_new_character (num, ffelex_token_where_line
(ffesta_tokens[0]), ffelex_token_where_column
(ffesta_tokens[0]));
expr = ffebld_new_conter (ffebld_constant_new_characterdefault
(msg));
ffelex_token_kill (msg);
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, 0));
}
else
{
assert (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeCHARACTER);
assert (ffebld_op (expr) == FFEBLD_opCONTER);
assert (ffeinfo_kindtype (ffebld_info (expr))
== FFEINFO_kindtypeCHARACTERDEFAULT);
}
ffecom_push_calltemps ();
callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
ffecom_pop_calltemps ();
TREE_SIDE_EFFECTS (callit) = 1;
expand_expr_stmt (callit);
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R843 -- PAUSE statement
ffeste_R843(expr,expr_token);
Make sure statement is valid here; implement. expr and expr_token are
both NULL if there was no expression. */
void
ffeste_R843 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if (expr == NULL)
{
fputs ("+ PAUSE\n", dmpout);
}
else
{
fputs ("+ PAUSE_coded ", dmpout);
ffebld_dump (expr);
fputc ('\n', dmpout);
}
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree callit;
ffelexToken msg;
ffeste_emit_line_note_ ();
if ((expr == NULL)
|| (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeANY))
{
msg = ffelex_token_new_character ("", ffelex_token_where_line
(ffesta_tokens[0]), ffelex_token_where_column
(ffesta_tokens[0]));
expr = ffebld_new_conter (ffebld_constant_new_characterdefault
(msg));
ffelex_token_kill (msg);
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, 0));
}
else if (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeINTEGER)
{
char num[50];
assert (ffebld_op (expr) == FFEBLD_opCONTER);
assert (ffeinfo_kindtype (ffebld_info (expr))
== FFEINFO_kindtypeINTEGERDEFAULT);
sprintf (num, "%" ffetargetIntegerDefault_f "d",
ffebld_constant_integer1 (ffebld_conter (expr)));
msg = ffelex_token_new_character (num, ffelex_token_where_line
(ffesta_tokens[0]), ffelex_token_where_column
(ffesta_tokens[0]));
expr = ffebld_new_conter (ffebld_constant_new_characterdefault
(msg));
ffelex_token_kill (msg);
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
FFEINFO_kindtypeCHARACTERDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, 0));
}
else
{
assert (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeCHARACTER);
assert (ffebld_op (expr) == FFEBLD_opCONTER);
assert (ffeinfo_kindtype (ffebld_info (expr))
== FFEINFO_kindtypeCHARACTERDEFAULT);
}
ffecom_push_calltemps ();
callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
ffecom_pop_calltemps ();
TREE_SIDE_EFFECTS (callit) = 1;
expand_expr_stmt (callit);
clear_momentary ();
}
#if 0 /* Old approach for phantom g77 run-time
library. */
{
tree callit;
ffeste_emit_line_note_ ();
if (expr == NULL)
callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE);
else if (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeINTEGER)
{
ffecom_push_calltemps ();
callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
ffecom_pop_calltemps ();
}
else
{
if (ffeinfo_basictype (ffebld_info (expr))
!= FFEINFO_basictypeCHARACTER)
break;
ffecom_push_calltemps ();
callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
ffecom_pop_calltemps ();
}
TREE_SIDE_EFFECTS (callit) = 1;
expand_expr_stmt (callit);
clear_momentary ();
}
#endif
#else
#error
#endif
}
/* ffeste_R904 -- OPEN statement
ffeste_R904();
Make sure an OPEN is valid in the current context, and implement it. */
void
ffeste_R904 (ffestpOpenStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ OPEN (", dmpout);
ffeste_subr_file_ ("UNIT", &info->open_spec[FFESTP_openixUNIT]);
ffeste_subr_file_ ("ACCESS", &info->open_spec[FFESTP_openixACCESS]);
ffeste_subr_file_ ("ACTION", &info->open_spec[FFESTP_openixACTION]);
ffeste_subr_file_ ("ASSOCIATEVARIABLE", &info->open_spec[FFESTP_openixASSOCIATEVARIABLE]);
ffeste_subr_file_ ("BLANK", &info->open_spec[FFESTP_openixBLANK]);
ffeste_subr_file_ ("BLOCKSIZE", &info->open_spec[FFESTP_openixBLOCKSIZE]);
ffeste_subr_file_ ("BUFFERCOUNT", &info->open_spec[FFESTP_openixBUFFERCOUNT]);
ffeste_subr_file_ ("CARRIAGECONTROL", &info->open_spec[FFESTP_openixCARRIAGECONTROL]);
ffeste_subr_file_ ("DEFAULTFILE", &info->open_spec[FFESTP_openixDEFAULTFILE]);
ffeste_subr_file_ ("DELIM", &info->open_spec[FFESTP_openixDELIM]);
ffeste_subr_file_ ("DISPOSE", &info->open_spec[FFESTP_openixDISPOSE]);
ffeste_subr_file_ ("ERR", &info->open_spec[FFESTP_openixERR]);
ffeste_subr_file_ ("EXTENDSIZE", &info->open_spec[FFESTP_openixEXTENDSIZE]);
ffeste_subr_file_ ("FILE", &info->open_spec[FFESTP_openixFILE]);
ffeste_subr_file_ ("FORM", &info->open_spec[FFESTP_openixFORM]);
ffeste_subr_file_ ("INITIALSIZE", &info->open_spec[FFESTP_openixINITIALSIZE]);
ffeste_subr_file_ ("IOSTAT", &info->open_spec[FFESTP_openixIOSTAT]);
ffeste_subr_file_ ("KEY", &info->open_spec[FFESTP_openixKEY]);
ffeste_subr_file_ ("MAXREC", &info->open_spec[FFESTP_openixMAXREC]);
ffeste_subr_file_ ("NOSPANBLOCKS", &info->open_spec[FFESTP_openixNOSPANBLOCKS]);
ffeste_subr_file_ ("ORGANIZATION", &info->open_spec[FFESTP_openixORGANIZATION]);
ffeste_subr_file_ ("PAD", &info->open_spec[FFESTP_openixPAD]);
ffeste_subr_file_ ("POSITION", &info->open_spec[FFESTP_openixPOSITION]);
ffeste_subr_file_ ("READONLY", &info->open_spec[FFESTP_openixREADONLY]);
ffeste_subr_file_ ("RECL", &info->open_spec[FFESTP_openixRECL]);
ffeste_subr_file_ ("RECORDTYPE", &info->open_spec[FFESTP_openixRECORDTYPE]);
ffeste_subr_file_ ("SHARED", &info->open_spec[FFESTP_openixSHARED]);
ffeste_subr_file_ ("STATUS", &info->open_spec[FFESTP_openixSTATUS]);
ffeste_subr_file_ ("USEROPEN", &info->open_spec[FFESTP_openixUSEROPEN]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree args;
bool iostat;
bool errl;
#define specified(something) (info->open_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
iostat = specified (FFESTP_openixIOSTAT);
errl = specified (FFESTP_openixERR);
ffecom_push_calltemps ();
args = ffeste_io_olist_ (errl || iostat,
info->open_spec[FFESTP_openixUNIT].u.expr,
&info->open_spec[FFESTP_openixFILE],
&info->open_spec[FFESTP_openixSTATUS],
&info->open_spec[FFESTP_openixACCESS],
&info->open_spec[FFESTP_openixFORM],
&info->open_spec[FFESTP_openixRECL],
&info->open_spec[FFESTP_openixBLANK]);
if (errl)
{
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
(info->open_spec[FFESTP_openixERR].u.label);
ffeste_io_abort_is_temp_ = FALSE;
}
else
{
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->open_spec[FFESTP_openixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, or ERR= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args),
!ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
assert (ffeste_io_err_ == NULL_TREE);
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
#undef specified
}
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R907 -- CLOSE statement
ffeste_R907();
Make sure a CLOSE is valid in the current context, and implement it. */
void
ffeste_R907 (ffestpCloseStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ CLOSE (", dmpout);
ffeste_subr_file_ ("UNIT", &info->close_spec[FFESTP_closeixUNIT]);
ffeste_subr_file_ ("ERR", &info->close_spec[FFESTP_closeixERR]);
ffeste_subr_file_ ("IOSTAT", &info->close_spec[FFESTP_closeixIOSTAT]);
ffeste_subr_file_ ("STATUS", &info->close_spec[FFESTP_closeixSTATUS]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree args;
bool iostat;
bool errl;
#define specified(something) (info->close_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
iostat = specified (FFESTP_closeixIOSTAT);
errl = specified (FFESTP_closeixERR);
ffecom_push_calltemps ();
args = ffeste_io_cllist_ (errl || iostat,
info->close_spec[FFESTP_closeixUNIT].u.expr,
&info->close_spec[FFESTP_closeixSTATUS]);
if (errl)
{
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
(info->close_spec[FFESTP_closeixERR].u.label);
ffeste_io_abort_is_temp_ = FALSE;
}
else
{
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->close_spec[FFESTP_closeixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, or ERR= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args),
!ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
assert (ffeste_io_err_ == NULL_TREE);
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
#undef specified
}
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R909_start -- READ(...) statement list begin
ffeste_R909_start(FALSE);
Verify that READ is valid here, and begin accepting items in the
list. */
void
ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
ffestvUnit unit, ffestvFormat format, bool rec,
bool key UNUSED)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatNONE:
if (rec)
fputs ("+ READ_ufdac", dmpout);
else if (key)
fputs ("+ READ_ufidx", dmpout);
else
fputs ("+ READ_ufseq", dmpout);
break;
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
if (rec)
fputs ("+ READ_fmdac", dmpout);
else if (key)
fputs ("+ READ_fmidx", dmpout);
else if (unit == FFESTV_unitCHAREXPR)
fputs ("+ READ_fmint", dmpout);
else
fputs ("+ READ_fmseq", dmpout);
break;
case FFESTV_formatASTERISK:
if (unit == FFESTV_unitCHAREXPR)
fputs ("+ READ_lsint", dmpout);
else
fputs ("+ READ_lsseq", dmpout);
break;
case FFESTV_formatNAMELIST:
fputs ("+ READ_nlseq", dmpout);
break;
default:
assert ("Unexpected kind of format item in R909 READ" == NULL);
}
if (only_format)
{
fputc (' ', dmpout);
ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
fputc (' ', dmpout);
return;
}
fputs (" (", dmpout);
ffeste_subr_file_ ("UNIT", &info->read_spec[FFESTP_readixUNIT]);
ffeste_subr_file_ ("FORMAT", &info->read_spec[FFESTP_readixFORMAT]);
ffeste_subr_file_ ("ADVANCE", &info->read_spec[FFESTP_readixADVANCE]);
ffeste_subr_file_ ("EOR", &info->read_spec[FFESTP_readixEOR]);
ffeste_subr_file_ ("ERR", &info->read_spec[FFESTP_readixERR]);
ffeste_subr_file_ ("END", &info->read_spec[FFESTP_readixEND]);
ffeste_subr_file_ ("IOSTAT", &info->read_spec[FFESTP_readixIOSTAT]);
ffeste_subr_file_ ("KEYEQ", &info->read_spec[FFESTP_readixKEYEQ]);
ffeste_subr_file_ ("KEYGE", &info->read_spec[FFESTP_readixKEYGE]);
ffeste_subr_file_ ("KEYGT", &info->read_spec[FFESTP_readixKEYGT]);
ffeste_subr_file_ ("KEYID", &info->read_spec[FFESTP_readixKEYID]);
ffeste_subr_file_ ("NULLS", &info->read_spec[FFESTP_readixNULLS]);
ffeste_subr_file_ ("REC", &info->read_spec[FFESTP_readixREC]);
ffeste_subr_file_ ("SIZE", &info->read_spec[FFESTP_readixSIZE]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#define specified(something) (info->read_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
/* Do the real work. */
{
ffecomGfrt start;
ffecomGfrt end;
tree cilist;
bool iostat;
bool errl;
bool endl;
/* First determine the start, per-item, and end run-time functions to
call. The per-item function is picked by choosing an ffeste functio
to call to handle a given item; it knows how to generate a call to the
appropriate run-time function, and is called an "io driver". It
handles the implied-DO construct, for example. */
switch (format)
{
case FFESTV_formatNONE: /* no FMT= */
ffeste_io_driver_ = ffeste_io_douio_;
if (rec)
start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
#if 0
else if (key)
start = FFECOM_gfrtSRIUE, end = FFECOM_gfrtERIUE;
#endif
else
start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
break;
case FFESTV_formatLABEL: /* FMT=10 */
case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
ffeste_io_driver_ = ffeste_io_dofio_;
if (rec)
start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
#if 0
else if (key)
start = FFECOM_gfrtSRIFE, end = FFECOM_gfrtERIFE;
#endif
else if (unit == FFESTV_unitCHAREXPR)
start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
else
start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
break;
case FFESTV_formatASTERISK: /* FMT=* */
ffeste_io_driver_ = ffeste_io_dolio_;
if (unit == FFESTV_unitCHAREXPR)
start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
else
start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
break;
case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
/FOO/] */
ffeste_io_driver_ = NULL; /* No start or driver function. */
start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
break;
default:
assert ("Weird stuff" == NULL);
start = FFECOM_gfrt, end = FFECOM_gfrt;
break;
}
ffeste_io_endgfrt_ = end;
iostat = specified (FFESTP_readixIOSTAT);
errl = specified (FFESTP_readixERR);
endl = specified (FFESTP_readixEND);
ffecom_push_calltemps ();
if (unit == FFESTV_unitCHAREXPR)
{
cilist = ffeste_io_icilist_ (errl || iostat,
info->read_spec[FFESTP_readixUNIT].u.expr,
endl || iostat, format,
&info->read_spec[FFESTP_readixFORMAT]);
}
else
{
cilist = ffeste_io_cilist_ (errl || iostat, unit,
info->read_spec[FFESTP_readixUNIT].u.expr,
5, endl || iostat, format,
&info->read_spec[FFESTP_readixFORMAT],
rec,
info->read_spec[FFESTP_readixREC].u.expr);
}
if (errl)
{ /* ERR= */
ffeste_io_err_
= ffecom_lookup_label
(info->read_spec[FFESTP_readixERR].u.label);
if (endl)
{ /* ERR= END= */
ffeste_io_end_
= ffecom_lookup_label
(info->read_spec[FFESTP_readixEND].u.label);
ffeste_io_abort_is_temp_ = TRUE;
ffeste_io_abort_ = ffecom_temp_label ();
}
else
{ /* ERR= but no END= */
ffeste_io_end_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = ffeste_io_err_;
}
}
else
{ /* no ERR= */
ffeste_io_err_ = NULL_TREE;
if (endl)
{ /* END= but no ERR= */
ffeste_io_end_
= ffecom_lookup_label
(info->read_spec[FFESTP_readixEND].u.label);
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = ffeste_io_end_;
}
else
{ /* no ERR= or END= */
ffeste_io_end_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->read_spec[FFESTP_readixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= or END= or both */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, ERR=, or END= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
!ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
}
#undef specified
push_momentary ();
#else
#error
#endif
}
/* ffeste_R909_item -- READ statement i/o item
ffeste_R909_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_R909_item (ffebld expr, ffelexToken expr_token)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
while (ffebld_op (expr) == FFEBLD_opPAREN)
expr = ffebld_left (expr); /* "READ *,(A)" -- really a bug in the user's
code, but I've been told lots of code does
this (blech)! */
if (ffebld_op (expr) == FFEBLD_opANY)
return;
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R909_finish -- READ statement list complete
ffeste_R909_finish();
Just wrap up any local activities. */
void
ffeste_R909_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
{
if (ffeste_io_endgfrt_ != FFECOM_gfrt)
ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
!ffeste_io_abort_is_temp_);
clear_momentary ();
pop_momentary ();
/* If we've got a temp label, generate its code here and have it fan out
to the END= or ERR= label as appropriate. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
/* if (iostat<0) goto end_label; */
if ((ffeste_io_end_ != NULL_TREE)
&& (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
{
expand_start_cond (ffecom_truth_value
(ffecom_2 (LT_EXPR, integer_type_node,
ffeste_io_iostat_,
ffecom_integer_zero_node)),
0);
expand_goto (ffeste_io_end_);
expand_end_cond ();
}
/* if (iostat>0) goto err_label; */
if ((ffeste_io_err_ != NULL_TREE)
&& (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
{
expand_start_cond (ffecom_truth_value
(ffecom_2 (GT_EXPR, integer_type_node,
ffeste_io_iostat_,
ffecom_integer_zero_node)),
0);
expand_goto (ffeste_io_err_);
expand_end_cond ();
}
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R910_start -- WRITE(...) statement list begin
ffeste_R910_start();
Verify that WRITE is valid here, and begin accepting items in the
list. */
void
ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
ffestvFormat format, bool rec)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatNONE:
if (rec)
fputs ("+ WRITE_ufdac (", dmpout);
else
fputs ("+ WRITE_ufseq_or_idx (", dmpout);
break;
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
if (rec)
fputs ("+ WRITE_fmdac (", dmpout);
else if (unit == FFESTV_unitCHAREXPR)
fputs ("+ WRITE_fmint (", dmpout);
else
fputs ("+ WRITE_fmseq_or_idx (", dmpout);
break;
case FFESTV_formatASTERISK:
if (unit == FFESTV_unitCHAREXPR)
fputs ("+ WRITE_lsint (", dmpout);
else
fputs ("+ WRITE_lsseq (", dmpout);
break;
case FFESTV_formatNAMELIST:
fputs ("+ WRITE_nlseq (", dmpout);
break;
default:
assert ("Unexpected kind of format item in R910 WRITE" == NULL);
}
ffeste_subr_file_ ("UNIT", &info->write_spec[FFESTP_writeixUNIT]);
ffeste_subr_file_ ("FORMAT", &info->write_spec[FFESTP_writeixFORMAT]);
ffeste_subr_file_ ("ADVANCE", &info->write_spec[FFESTP_writeixADVANCE]);
ffeste_subr_file_ ("EOR", &info->write_spec[FFESTP_writeixEOR]);
ffeste_subr_file_ ("ERR", &info->write_spec[FFESTP_writeixERR]);
ffeste_subr_file_ ("IOSTAT", &info->write_spec[FFESTP_writeixIOSTAT]);
ffeste_subr_file_ ("REC", &info->write_spec[FFESTP_writeixREC]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#define specified(something) (info->write_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
/* Do the real work. */
{
ffecomGfrt start;
ffecomGfrt end;
tree cilist;
bool iostat;
bool errl;
/* First determine the start, per-item, and end run-time functions to
call. The per-item function is picked by choosing an ffeste functio
to call to handle a given item; it knows how to generate a call to the
appropriate run-time function, and is called an "io driver". It
handles the implied-DO construct, for example. */
switch (format)
{
case FFESTV_formatNONE: /* no FMT= */
ffeste_io_driver_ = ffeste_io_douio_;
if (rec)
start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
else
start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
break;
case FFESTV_formatLABEL: /* FMT=10 */
case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
ffeste_io_driver_ = ffeste_io_dofio_;
if (rec)
start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
else if (unit == FFESTV_unitCHAREXPR)
start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
else
start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
break;
case FFESTV_formatASTERISK: /* FMT=* */
ffeste_io_driver_ = ffeste_io_dolio_;
if (unit == FFESTV_unitCHAREXPR)
start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
else
start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
break;
case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
/FOO/] */
ffeste_io_driver_ = NULL; /* No start or driver function. */
start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
break;
default:
assert ("Weird stuff" == NULL);
start = FFECOM_gfrt, end = FFECOM_gfrt;
break;
}
ffeste_io_endgfrt_ = end;
iostat = specified (FFESTP_writeixIOSTAT);
errl = specified (FFESTP_writeixERR);
ffecom_push_calltemps ();
if (unit == FFESTV_unitCHAREXPR)
{
cilist = ffeste_io_icilist_ (errl || iostat,
info->write_spec[FFESTP_writeixUNIT].u.expr,
FALSE, format,
&info->write_spec[FFESTP_writeixFORMAT]);
}
else
{
cilist = ffeste_io_cilist_ (errl || iostat, unit,
info->write_spec[FFESTP_writeixUNIT].u.expr,
6, FALSE, format,
&info->write_spec[FFESTP_writeixFORMAT],
rec,
info->write_spec[FFESTP_writeixREC].u.expr);
}
ffeste_io_end_ = NULL_TREE;
if (errl)
{ /* ERR= */
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
(info->write_spec[FFESTP_writeixERR].u.label);
ffeste_io_abort_is_temp_ = FALSE;
}
else
{ /* no ERR= */
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->write_spec[FFESTP_writeixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, or ERR= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
!ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
}
#undef specified
push_momentary ();
#else
#error
#endif
}
/* ffeste_R910_item -- WRITE statement i/o item
ffeste_R910_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_R910_item (ffebld expr, ffelexToken expr_token)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
if (ffebld_op (expr) == FFEBLD_opANY)
return;
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R910_finish -- WRITE statement list complete
ffeste_R910_finish();
Just wrap up any local activities. */
void
ffeste_R910_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
{
if (ffeste_io_endgfrt_ != FFECOM_gfrt)
ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
!ffeste_io_abort_is_temp_);
clear_momentary ();
pop_momentary ();
/* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
assert (ffeste_io_err_ == NULL_TREE);
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R911_start -- PRINT statement list begin
ffeste_R911_start();
Verify that PRINT is valid here, and begin accepting items in the
list. */
void
ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
fputs ("+ PRINT_fm ", dmpout);
break;
case FFESTV_formatASTERISK:
fputs ("+ PRINT_ls ", dmpout);
break;
case FFESTV_formatNAMELIST:
fputs ("+ PRINT_nl ", dmpout);
break;
default:
assert ("Unexpected kind of format item in R911 PRINT" == NULL);
}
ffeste_subr_file_ ("FORMAT", &info->print_spec[FFESTP_printixFORMAT]);
fputc (' ', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
/* Do the real work. */
{
ffecomGfrt start;
ffecomGfrt end;
tree cilist;
/* First determine the start, per-item, and end run-time functions to
call. The per-item function is picked by choosing an ffeste functio
to call to handle a given item; it knows how to generate a call to the
appropriate run-time function, and is called an "io driver". It
handles the implied-DO construct, for example. */
switch (format)
{
case FFESTV_formatLABEL: /* FMT=10 */
case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
case FFESTV_formatINTEXPR: /* FMT=I [after ASSIGN 10 TO I] */
ffeste_io_driver_ = ffeste_io_dofio_;
start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
break;
case FFESTV_formatASTERISK: /* FMT=* */
ffeste_io_driver_ = ffeste_io_dolio_;
start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
break;
case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
/FOO/] */
ffeste_io_driver_ = NULL; /* No start or driver function. */
start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
break;
default:
assert ("Weird stuff" == NULL);
start = FFECOM_gfrt, end = FFECOM_gfrt;
break;
}
ffeste_io_endgfrt_ = end;
ffecom_push_calltemps ();
cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
&info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
ffeste_io_end_ = NULL_TREE;
ffeste_io_err_ = NULL_TREE;
ffeste_io_abort_ = NULL_TREE;
ffeste_io_abort_is_temp_ = FALSE;
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
!ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
}
push_momentary ();
#else
#error
#endif
}
/* ffeste_R911_item -- PRINT statement i/o item
ffeste_R911_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_R911_item (ffebld expr, ffelexToken expr_token)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
if (ffebld_op (expr) == FFEBLD_opANY)
return;
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
ffeste_io_call_ ((*ffeste_io_driver_) (expr), FALSE);
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R911_finish -- PRINT statement list complete
ffeste_R911_finish();
Just wrap up any local activities. */
void
ffeste_R911_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
if (ffeste_io_endgfrt_ != FFECOM_gfrt)
ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
FALSE);
ffecom_pop_calltemps ();
clear_momentary ();
pop_momentary ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R919 -- BACKSPACE statement
ffeste_R919();
Make sure a BACKSPACE is valid in the current context, and implement it. */
void
ffeste_R919 (ffestpBeruStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ BACKSPACE (", dmpout);
ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
#else
#error
#endif
}
/* ffeste_R920 -- ENDFILE statement
ffeste_R920();
Make sure a ENDFILE is valid in the current context, and implement it. */
void
ffeste_R920 (ffestpBeruStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ ENDFILE (", dmpout);
ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
#else
#error
#endif
}
/* ffeste_R921 -- REWIND statement
ffeste_R921();
Make sure a REWIND is valid in the current context, and implement it. */
void
ffeste_R921 (ffestpBeruStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ REWIND (", dmpout);
ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
#else
#error
#endif
}
/* ffeste_R923A -- INQUIRE statement (non-IOLENGTH version)
ffeste_R923A(bool by_file);
Make sure an INQUIRE is valid in the current context, and implement it. */
void
ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if (by_file)
{
fputs ("+ INQUIRE_file (", dmpout);
ffeste_subr_file_ ("FILE", &info->inquire_spec[FFESTP_inquireixFILE]);
}
else
{
fputs ("+ INQUIRE_unit (", dmpout);
ffeste_subr_file_ ("UNIT", &info->inquire_spec[FFESTP_inquireixUNIT]);
}
ffeste_subr_file_ ("ACCESS", &info->inquire_spec[FFESTP_inquireixACCESS]);
ffeste_subr_file_ ("ACTION", &info->inquire_spec[FFESTP_inquireixACTION]);
ffeste_subr_file_ ("BLANK", &info->inquire_spec[FFESTP_inquireixBLANK]);
ffeste_subr_file_ ("CARRIAGECONTROL", &info->inquire_spec[FFESTP_inquireixCARRIAGECONTROL]);
ffeste_subr_file_ ("DEFAULTFILE", &info->inquire_spec[FFESTP_inquireixDEFAULTFILE]);
ffeste_subr_file_ ("DELIM", &info->inquire_spec[FFESTP_inquireixDELIM]);
ffeste_subr_file_ ("DIRECT", &info->inquire_spec[FFESTP_inquireixDIRECT]);
ffeste_subr_file_ ("ERR", &info->inquire_spec[FFESTP_inquireixERR]);
ffeste_subr_file_ ("EXIST", &info->inquire_spec[FFESTP_inquireixEXIST]);
ffeste_subr_file_ ("FORM", &info->inquire_spec[FFESTP_inquireixFORM]);
ffeste_subr_file_ ("FORMATTED", &info->inquire_spec[FFESTP_inquireixFORMATTED]);
ffeste_subr_file_ ("IOSTAT", &info->inquire_spec[FFESTP_inquireixIOSTAT]);
ffeste_subr_file_ ("KEYED", &info->inquire_spec[FFESTP_inquireixKEYED]);
ffeste_subr_file_ ("NAME", &info->inquire_spec[FFESTP_inquireixNAME]);
ffeste_subr_file_ ("NAMED", &info->inquire_spec[FFESTP_inquireixNAMED]);
ffeste_subr_file_ ("NEXTREC", &info->inquire_spec[FFESTP_inquireixNEXTREC]);
ffeste_subr_file_ ("NUMBER", &info->inquire_spec[FFESTP_inquireixNUMBER]);
ffeste_subr_file_ ("OPENED", &info->inquire_spec[FFESTP_inquireixOPENED]);
ffeste_subr_file_ ("ORGANIZATION", &info->inquire_spec[FFESTP_inquireixORGANIZATION]);
ffeste_subr_file_ ("PAD", &info->inquire_spec[FFESTP_inquireixPAD]);
ffeste_subr_file_ ("POSITION", &info->inquire_spec[FFESTP_inquireixPOSITION]);
ffeste_subr_file_ ("READ", &info->inquire_spec[FFESTP_inquireixREAD]);
ffeste_subr_file_ ("READWRITE", &info->inquire_spec[FFESTP_inquireixREADWRITE]);
ffeste_subr_file_ ("RECL", &info->inquire_spec[FFESTP_inquireixRECL]);
ffeste_subr_file_ ("RECORDTYPE", &info->inquire_spec[FFESTP_inquireixRECORDTYPE]);
ffeste_subr_file_ ("SEQUENTIAL", &info->inquire_spec[FFESTP_inquireixSEQUENTIAL]);
ffeste_subr_file_ ("UNFORMATTED", &info->inquire_spec[FFESTP_inquireixUNFORMATTED]);
ffeste_subr_file_ ("WRITE", &info->inquire_spec[FFESTP_inquireixWRITE]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree args;
bool iostat;
bool errl;
#define specified(something) (info->inquire_spec[something].kw_or_val_present)
ffeste_emit_line_note_ ();
iostat = specified (FFESTP_inquireixIOSTAT);
errl = specified (FFESTP_inquireixERR);
ffecom_push_calltemps ();
args = ffeste_io_inlist_ (errl || iostat,
&info->inquire_spec[FFESTP_inquireixUNIT],
&info->inquire_spec[FFESTP_inquireixFILE],
&info->inquire_spec[FFESTP_inquireixEXIST],
&info->inquire_spec[FFESTP_inquireixOPENED],
&info->inquire_spec[FFESTP_inquireixNUMBER],
&info->inquire_spec[FFESTP_inquireixNAMED],
&info->inquire_spec[FFESTP_inquireixNAME],
&info->inquire_spec[FFESTP_inquireixACCESS],
&info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
&info->inquire_spec[FFESTP_inquireixDIRECT],
&info->inquire_spec[FFESTP_inquireixFORM],
&info->inquire_spec[FFESTP_inquireixFORMATTED],
&info->inquire_spec[FFESTP_inquireixUNFORMATTED],
&info->inquire_spec[FFESTP_inquireixRECL],
&info->inquire_spec[FFESTP_inquireixNEXTREC],
&info->inquire_spec[FFESTP_inquireixBLANK]);
if (errl)
{
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
(info->inquire_spec[FFESTP_inquireixERR].u.label);
ffeste_io_abort_is_temp_ = FALSE;
}
else
{
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = NULL_TREE;
}
if (iostat)
{ /* IOSTAT= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
{ /* no IOSTAT= but ERR= */
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
= ffecom_push_tempvar (ffecom_integer_type_node,
FFETARGET_charactersizeNONE, -1, FALSE);
}
else
{ /* no IOSTAT=, or ERR= */
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args),
!ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
emit_nop ();
expand_label (ffeste_io_abort_);
assert (ffeste_io_err_ == NULL_TREE);
}
/* If we've got a temp iostat, pop the temp. */
if (ffeste_io_iostat_is_temp_)
ffecom_pop_tempvar (ffeste_io_iostat_);
ffecom_pop_calltemps ();
#undef specified
}
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R923B_start -- INQUIRE(IOLENGTH=expr) statement list begin
ffeste_R923B_start();
Verify that INQUIRE is valid here, and begin accepting items in the
list. */
void
ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ INQUIRE (", dmpout);
ffeste_subr_file_ ("IOLENGTH", &info->inquire_spec[FFESTP_inquireixIOLENGTH]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
ffeste_emit_line_note_ ();
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R923B_item -- INQUIRE statement i/o item
ffeste_R923B_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_R923B_item (ffebld expr UNUSED)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R923B_finish -- INQUIRE statement list complete
ffeste_R923B_finish();
Just wrap up any local activities. */
void
ffeste_R923B_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
clear_momentary ();
#else
#error
#endif
}
/* ffeste_R1001 -- FORMAT statement
ffeste_R1001(format_list); */
void
ffeste_R1001 (ffests s)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "$ FORMAT %.*s\n", (int) ffests_length (s), ffests_text (s));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree t;
tree ttype;
tree maxindex;
tree var;
assert (ffeste_label_formatdef_ != NULL);
ffeste_emit_line_note_ ();
t = build_string (ffests_length (s), ffests_text (s));
TREE_TYPE (t)
= build_type_variant (build_array_type
(char_type_node,
build_range_type (integer_type_node,
integer_one_node,
build_int_2 (ffests_length (s),
0))),
1, 0);
TREE_CONSTANT (t) = 1;
TREE_STATIC (t) = 1;
push_obstacks_nochange ();
end_temporary_allocation ();
var = ffecom_lookup_label (ffeste_label_formatdef_);
if ((var != NULL_TREE)
&& (TREE_CODE (var) == VAR_DECL))
{
DECL_INITIAL (var) = t;
maxindex = build_int_2 (ffests_length (s) - 1, 0);
ttype = TREE_TYPE (var);
TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
integer_zero_node,
maxindex);
if (!TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
layout_type (ttype);
rest_of_decl_compilation (var, NULL, 1, 0);
expand_decl (var);
expand_decl_init (var);
}
resume_temporary_allocation ();
pop_obstacks ();
ffeste_label_formatdef_ = NULL;
}
#else
#error
#endif
}
/* ffeste_R1103 -- End a PROGRAM
ffeste_R1103(); */
void
ffeste_R1103 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_PROGRAM\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_R1112 -- End a BLOCK DATA
ffeste_R1112(TRUE); */
void
ffeste_R1112 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("* END_BLOCK_DATA\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_R1212 -- CALL statement
ffeste_R1212(expr,expr_token);
Make sure statement is valid here; implement. */
void
ffeste_R1212 (ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ CALL ", dmpout);
ffebld_dump (expr);
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
ffebld args = ffebld_right (expr);
ffebld arg;
ffebld labels = NULL; /* First in list of LABTERs. */
ffebld prevlabels = NULL;
ffebld prevargs = NULL;
ffeste_emit_line_note_ ();
/* Here we split the list at ffebld_right(expr) into two lists: one at
ffebld_right(expr) consisting of all items that are not LABTERs, the
other at labels consisting of all items that are LABTERs. Then, if
the latter list is NULL, we have an ordinary call, else we have a call
with alternate returns. */
for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
{
if (((arg = ffebld_head (args)) == NULL)
|| (ffebld_op (arg) != FFEBLD_opLABTER))
{
if (prevargs == NULL)
{
prevargs = args;
ffebld_set_right (expr, args);
}
else
{
ffebld_set_trail (prevargs, args);
prevargs = args;
}
}
else
{
if (prevlabels == NULL)
{
prevlabels = labels = args;
}
else
{
ffebld_set_trail (prevlabels, args);
prevlabels = args;
}
}
}
if (prevlabels == NULL)
labels = NULL;
else
ffebld_set_trail (prevlabels, NULL);
if (prevargs == NULL)
ffebld_set_right (expr, NULL);
else
ffebld_set_trail (prevargs, NULL);
if (labels == NULL)
expand_expr_stmt (ffecom_expr (expr));
else
{
tree texpr;
tree value;
tree tlabel;
int caseno;
int pushok;
tree duplicate;
texpr = ffecom_expr (expr);
expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
push_momentary (); /* In case of many labels, keep 'em cleared
out. */
for (caseno = 1;
labels != NULL;
++caseno, labels = ffebld_trail (labels))
{
value = build_int_2 (caseno, 0);
tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
pushok = pushcase (value, convert, tlabel, &duplicate);
assert (pushok == 0);
tlabel
= ffecom_lookup_label (ffebld_labter (ffebld_head (labels)));
if ((tlabel == NULL_TREE)
|| (TREE_CODE (tlabel) == ERROR_MARK))
continue;
TREE_USED (tlabel) = 1;
expand_goto (tlabel);
clear_momentary ();
}
pop_momentary ();
expand_end_case (texpr);
}
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R1221 -- End a FUNCTION
ffeste_R1221(TRUE); */
void
ffeste_R1221 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_FUNCTION\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_R1225 -- End a SUBROUTINE
ffeste_R1225(TRUE); */
void
ffeste_R1225 ()
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ END_SUBROUTINE\n");
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_R1226 -- ENTRY statement
ffeste_R1226(entryname,arglist,ending_token);
Make sure we're in a SUBROUTINE or FUNCTION, register arguments for the
entry point name, and so on. */
void
ffeste_R1226 (ffesymbol entry)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fprintf (dmpout, "+ ENTRY %s", ffesymbol_text (entry));
if (ffesymbol_dummyargs (entry) != NULL)
{
ffebld argh;
fputc ('(', dmpout);
for (argh = ffesymbol_dummyargs (entry);
argh != NULL;
argh = ffebld_trail (argh))
{
assert (ffebld_head (argh) != NULL);
switch (ffebld_op (ffebld_head (argh)))
{
case FFEBLD_opSYMTER:
fputs (ffesymbol_text (ffebld_symter (ffebld_head (argh))),
dmpout);
break;
case FFEBLD_opSTAR:
fputc ('*', dmpout);
break;
default:
fputc ('?', dmpout);
ffebld_dump (ffebld_head (argh));
fputc ('?', dmpout);
break;
}
if (ffebld_trail (argh) != NULL)
fputc (',', dmpout);
}
fputc (')', dmpout);
}
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree label = ffesymbol_hook (entry).length_tree;
ffeste_emit_line_note_ ();
DECL_INITIAL (label) = error_mark_node;
emit_nop ();
expand_label (label);
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_R1227 -- RETURN statement
ffeste_R1227(expr);
Make sure statement is valid here; implement. expr and expr_token are
both NULL if there was no expression. */
void
ffeste_R1227 (ffestw block UNUSED, ffebld expr)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
if (expr == NULL)
{
fputs ("+ RETURN\n", dmpout);
}
else
{
fputs ("+ RETURN_alternate ", dmpout);
ffebld_dump (expr);
fputc ('\n', dmpout);
}
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
tree rtn;
ffeste_emit_line_note_ ();
ffecom_push_calltemps ();
rtn = ffecom_return_expr (expr);
if ((rtn == NULL_TREE)
|| (rtn == error_mark_node))
expand_null_return ();
else
{
tree result = DECL_RESULT (current_function_decl);
if ((result != error_mark_node)
&& (TREE_TYPE (result) != error_mark_node))
expand_return (ffecom_modify (NULL_TREE,
result,
convert (TREE_TYPE (result),
rtn)));
else
expand_null_return ();
}
ffecom_pop_calltemps ();
clear_momentary ();
}
#else
#error
#endif
}
/* ffeste_V018_start -- REWRITE(...) statement list begin
ffeste_V018_start();
Verify that REWRITE is valid here, and begin accepting items in the
list. */
#if FFESTR_VXT
void
ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatNONE:
fputs ("+ REWRITE_uf (", dmpout);
break;
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
fputs ("+ REWRITE_fm (", dmpout);
break;
default:
assert ("Unexpected kind of format item in V018 REWRITE" == NULL);
}
ffeste_subr_file_ ("UNIT", &info->rewrite_spec[FFESTP_rewriteixUNIT]);
ffeste_subr_file_ ("FMT", &info->rewrite_spec[FFESTP_rewriteixFMT]);
ffeste_subr_file_ ("ERR", &info->rewrite_spec[FFESTP_rewriteixERR]);
ffeste_subr_file_ ("IOSTAT", &info->rewrite_spec[FFESTP_rewriteixIOSTAT]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V018_item -- REWRITE statement i/o item
ffeste_V018_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_V018_item (ffebld expr)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V018_finish -- REWRITE statement list complete
ffeste_V018_finish();
Just wrap up any local activities. */
void
ffeste_V018_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V019_start -- ACCEPT statement list begin
ffeste_V019_start();
Verify that ACCEPT is valid here, and begin accepting items in the
list. */
void
ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
fputs ("+ ACCEPT_fm ", dmpout);
break;
case FFESTV_formatASTERISK:
fputs ("+ ACCEPT_ls ", dmpout);
break;
case FFESTV_formatNAMELIST:
fputs ("+ ACCEPT_nl ", dmpout);
break;
default:
assert ("Unexpected kind of format item in V019 ACCEPT" == NULL);
}
ffeste_subr_file_ ("FORMAT", &info->accept_spec[FFESTP_acceptixFORMAT]);
fputc (' ', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V019_item -- ACCEPT statement i/o item
ffeste_V019_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_V019_item (ffebld expr)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V019_finish -- ACCEPT statement list complete
ffeste_V019_finish();
Just wrap up any local activities. */
void
ffeste_V019_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
#endif
/* ffeste_V020_start -- TYPE statement list begin
ffeste_V020_start();
Verify that TYPE is valid here, and begin accepting items in the
list. */
void
ffeste_V020_start (ffestpTypeStmt *info UNUSED,
ffestvFormat format UNUSED)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
switch (format)
{
case FFESTV_formatLABEL:
case FFESTV_formatCHAREXPR:
case FFESTV_formatINTEXPR:
fputs ("+ TYPE_fm ", dmpout);
break;
case FFESTV_formatASTERISK:
fputs ("+ TYPE_ls ", dmpout);
break;
case FFESTV_formatNAMELIST:
fputs ("* TYPE_nl ", dmpout);
break;
default:
assert ("Unexpected kind of format item in V020 TYPE" == NULL);
}
ffeste_subr_file_ ("FORMAT", &info->type_spec[FFESTP_typeixFORMAT]);
fputc (' ', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V020_item -- TYPE statement i/o item
ffeste_V020_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_V020_item (ffebld expr UNUSED)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V020_finish -- TYPE statement list complete
ffeste_V020_finish();
Just wrap up any local activities. */
void
ffeste_V020_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V021 -- DELETE statement
ffeste_V021();
Make sure a DELETE is valid in the current context, and implement it. */
#if FFESTR_VXT
void
ffeste_V021 (ffestpDeleteStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ DELETE (", dmpout);
ffeste_subr_file_ ("UNIT", &info->delete_spec[FFESTP_deleteixUNIT]);
ffeste_subr_file_ ("REC", &info->delete_spec[FFESTP_deleteixREC]);
ffeste_subr_file_ ("ERR", &info->delete_spec[FFESTP_deleteixERR]);
ffeste_subr_file_ ("IOSTAT", &info->delete_spec[FFESTP_deleteixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V022 -- UNLOCK statement
ffeste_V022();
Make sure a UNLOCK is valid in the current context, and implement it. */
void
ffeste_V022 (ffestpBeruStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ UNLOCK (", dmpout);
ffeste_subr_file_ ("UNIT", &info->beru_spec[FFESTP_beruixUNIT]);
ffeste_subr_file_ ("ERR", &info->beru_spec[FFESTP_beruixERR]);
ffeste_subr_file_ ("IOSTAT", &info->beru_spec[FFESTP_beruixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V023_start -- ENCODE(...) statement list begin
ffeste_V023_start();
Verify that ENCODE is valid here, and begin accepting items in the
list. */
void
ffeste_V023_start (ffestpVxtcodeStmt *info)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ ENCODE (", dmpout);
ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V023_item -- ENCODE statement i/o item
ffeste_V023_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_V023_item (ffebld expr)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V023_finish -- ENCODE statement list complete
ffeste_V023_finish();
Just wrap up any local activities. */
void
ffeste_V023_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V024_start -- DECODE(...) statement list begin
ffeste_V024_start();
Verify that DECODE is valid here, and begin accepting items in the
list. */
void
ffeste_V024_start (ffestpVxtcodeStmt *info)
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ DECODE (", dmpout);
ffeste_subr_file_ ("C", &info->vxtcode_spec[FFESTP_vxtcodeixC]);
ffeste_subr_file_ ("F", &info->vxtcode_spec[FFESTP_vxtcodeixF]);
ffeste_subr_file_ ("B", &info->vxtcode_spec[FFESTP_vxtcodeixB]);
ffeste_subr_file_ ("ERR", &info->vxtcode_spec[FFESTP_vxtcodeixERR]);
ffeste_subr_file_ ("IOSTAT", &info->vxtcode_spec[FFESTP_vxtcodeixIOSTAT]);
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V024_item -- DECODE statement i/o item
ffeste_V024_item(expr,expr_token);
Implement output-list expression. */
void
ffeste_V024_item (ffebld expr)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V024_finish -- DECODE statement list complete
ffeste_V024_finish();
Just wrap up any local activities. */
void
ffeste_V024_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V025_start -- DEFINEFILE statement list begin
ffeste_V025_start();
Verify that DEFINEFILE is valid here, and begin accepting items in the
list. */
void
ffeste_V025_start ()
{
ffeste_check_start_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ DEFINE_FILE ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V025_item -- DEFINE FILE statement item
ffeste_V025_item(u,ut,m,mt,n,nt,asv,asvt);
Implement item. */
void
ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
{
ffeste_check_item_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
ffebld_dump (u);
fputc ('(', dmpout);
ffebld_dump (m);
fputc (',', dmpout);
ffebld_dump (n);
fputs (",U,", dmpout);
ffebld_dump (asv);
fputs ("),", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V025_finish -- DEFINE FILE statement list complete
ffeste_V025_finish();
Just wrap up any local activities. */
void
ffeste_V025_finish ()
{
ffeste_check_finish_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
/* ffeste_V026 -- FIND statement
ffeste_V026();
Make sure a FIND is valid in the current context, and implement it. */
void
ffeste_V026 (ffestpFindStmt *info)
{
ffeste_check_simple_ ();
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ FIND (", dmpout);
ffeste_subr_file_ ("UNIT", &info->find_spec[FFESTP_findixUNIT]);
ffeste_subr_file_ ("REC", &info->find_spec[FFESTP_findixREC]);
ffeste_subr_file_ ("ERR", &info->find_spec[FFESTP_findixERR]);
ffeste_subr_file_ ("IOSTAT", &info->find_spec[FFESTP_findixIOSTAT]);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
#else
#error
#endif
}
#endif