freebsd-skq/contrib/gcc/f/expr.c

19428 lines
553 KiB
C
Raw Normal View History

1999-08-26 09:30:50 +00:00
/* expr.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
Contributed by James Craig Burley.
1999-08-26 09:30:50 +00:00
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:
None.
Description:
Handles syntactic and semantic analysis of Fortran expressions.
Modifications:
*/
/* Include files. */
#include "proj.h"
#include "expr.h"
#include "bad.h"
#include "bld.h"
#include "com.h"
#include "global.h"
#include "implic.h"
#include "intrin.h"
#include "info.h"
#include "lex.h"
#include "malloc.h"
#include "src.h"
#include "st.h"
#include "symbol.h"
#include "str.h"
#include "target.h"
#include "where.h"
/* Externals defined here. */
/* Simple definitions and enumerations. */
typedef enum
{
FFEEXPR_exprtypeUNKNOWN_,
FFEEXPR_exprtypeOPERAND_,
FFEEXPR_exprtypeUNARY_,
FFEEXPR_exprtypeBINARY_,
FFEEXPR_exprtype_
} ffeexprExprtype_;
typedef enum
{
FFEEXPR_operatorPOWER_,
FFEEXPR_operatorMULTIPLY_,
FFEEXPR_operatorDIVIDE_,
FFEEXPR_operatorADD_,
FFEEXPR_operatorSUBTRACT_,
FFEEXPR_operatorCONCATENATE_,
FFEEXPR_operatorLT_,
FFEEXPR_operatorLE_,
FFEEXPR_operatorEQ_,
FFEEXPR_operatorNE_,
FFEEXPR_operatorGT_,
FFEEXPR_operatorGE_,
FFEEXPR_operatorNOT_,
FFEEXPR_operatorAND_,
FFEEXPR_operatorOR_,
FFEEXPR_operatorXOR_,
FFEEXPR_operatorEQV_,
FFEEXPR_operatorNEQV_,
FFEEXPR_operator_
} ffeexprOperator_;
typedef enum
{
FFEEXPR_operatorprecedenceHIGHEST_ = 1,
FFEEXPR_operatorprecedencePOWER_ = 1,
FFEEXPR_operatorprecedenceMULTIPLY_ = 2,
FFEEXPR_operatorprecedenceDIVIDE_ = 2,
FFEEXPR_operatorprecedenceADD_ = 3,
FFEEXPR_operatorprecedenceSUBTRACT_ = 3,
FFEEXPR_operatorprecedenceLOWARITH_ = 3,
FFEEXPR_operatorprecedenceCONCATENATE_ = 3,
FFEEXPR_operatorprecedenceLT_ = 4,
FFEEXPR_operatorprecedenceLE_ = 4,
FFEEXPR_operatorprecedenceEQ_ = 4,
FFEEXPR_operatorprecedenceNE_ = 4,
FFEEXPR_operatorprecedenceGT_ = 4,
FFEEXPR_operatorprecedenceGE_ = 4,
FFEEXPR_operatorprecedenceNOT_ = 5,
FFEEXPR_operatorprecedenceAND_ = 6,
FFEEXPR_operatorprecedenceOR_ = 7,
FFEEXPR_operatorprecedenceXOR_ = 8,
FFEEXPR_operatorprecedenceEQV_ = 8,
FFEEXPR_operatorprecedenceNEQV_ = 8,
FFEEXPR_operatorprecedenceLOWEST_ = 8,
FFEEXPR_operatorprecedence_
} ffeexprOperatorPrecedence_;
#define FFEEXPR_operatorassociativityL2R_ TRUE
#define FFEEXPR_operatorassociativityR2L_ FALSE
#define FFEEXPR_operatorassociativityPOWER_ FFEEXPR_operatorassociativityR2L_
#define FFEEXPR_operatorassociativityMULTIPLY_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityDIVIDE_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityADD_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativitySUBTRACT_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityCONCATENATE_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityLT_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityLE_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityEQ_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityNE_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityGT_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityGE_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityNOT_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityAND_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityOR_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityXOR_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityEQV_ FFEEXPR_operatorassociativityL2R_
#define FFEEXPR_operatorassociativityNEQV_ FFEEXPR_operatorassociativityL2R_
typedef enum
{
FFEEXPR_parentypeFUNCTION_,
FFEEXPR_parentypeSUBROUTINE_,
FFEEXPR_parentypeARRAY_,
FFEEXPR_parentypeSUBSTRING_,
FFEEXPR_parentypeFUNSUBSTR_,/* Ambig: check for colon after first expr. */
FFEEXPR_parentypeEQUIVALENCE_, /* Ambig: ARRAY_ or SUBSTRING_. */
FFEEXPR_parentypeANY_, /* Allow basically anything. */
FFEEXPR_parentype_
} ffeexprParenType_;
typedef enum
{
FFEEXPR_percentNONE_,
FFEEXPR_percentLOC_,
FFEEXPR_percentVAL_,
FFEEXPR_percentREF_,
FFEEXPR_percentDESCR_,
FFEEXPR_percent_
} ffeexprPercent_;
/* Internal typedefs. */
typedef struct _ffeexpr_expr_ *ffeexprExpr_;
typedef bool ffeexprOperatorAssociativity_;
typedef struct _ffeexpr_stack_ *ffeexprStack_;
/* Private include files. */
/* Internal structure definitions. */
struct _ffeexpr_expr_
{
ffeexprExpr_ previous;
ffelexToken token;
ffeexprExprtype_ type;
union
{
struct
{
ffeexprOperator_ op;
ffeexprOperatorPrecedence_ prec;
ffeexprOperatorAssociativity_ as;
}
operator;
ffebld operand;
}
u;
};
struct _ffeexpr_stack_
{
ffeexprStack_ previous;
mallocPool pool;
ffeexprContext context;
ffeexprCallback callback;
ffelexToken first_token;
ffeexprExpr_ exprstack;
ffelexToken tokens[10]; /* Used in certain cases, like (unary)
open-paren. */
ffebld expr; /* For first of
complex/implied-do/substring/array-elements
/ actual-args expression. */
ffebld bound_list; /* For tracking dimension bounds list of
array. */
ffebldListBottom bottom; /* For building lists. */
ffeinfoRank rank; /* For elements in an array reference. */
bool constant; /* TRUE while elements seen so far are
constants. */
bool immediate; /* TRUE while elements seen so far are
immediate/constants. */
ffebld next_dummy; /* Next SFUNC dummy arg in arg list. */
ffebldListLength num_args; /* Number of dummy args expected in arg list. */
bool is_rhs; /* TRUE if rhs context, FALSE otherwise. */
ffeexprPercent_ percent; /* Current %FOO keyword. */
};
struct _ffeexpr_find_
{
ffelexToken t;
ffelexHandler after;
int level;
};
/* Static objects accessed by functions in this module. */
static ffeexprStack_ ffeexpr_stack_; /* Expression stack for semantic. */
static ffelexToken ffeexpr_tokens_[10]; /* Scratchpad tokens for syntactic. */
static ffestrOther ffeexpr_current_dotdot_; /* Current .FOO. keyword. */
static long ffeexpr_hollerith_count_; /* ffeexpr_token_number_ and caller. */
static int ffeexpr_level_; /* Level of DATA implied-DO construct. */
static bool ffeexpr_is_substr_ok_; /* If OPEN_PAREN as binary "op" ok. */
static struct _ffeexpr_find_ ffeexpr_find_;
/* Static functions (internal). */
static ffelexHandler ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_close_paren_ambig_ (ffelexToken ft,
ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t);
static ffelexHandler ffeexpr_cb_close_paren_c_ (ffelexToken ft,
ffebld expr, ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_close_paren_ci_ (ffelexToken ft,
ffebld expr, ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_ci_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_1_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_2_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_3_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_4_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_comma_i_5_ (ffelexToken t);
static ffelexHandler ffeexpr_cb_end_loc_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_end_notloc_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_cb_end_notloc_1_ (ffelexToken t);
static ffesymbol ffeexpr_check_impctrl_ (ffesymbol s);
static void ffeexpr_check_impdo_ (ffebld list, ffelexToken list_t,
ffebld dovar, ffelexToken dovar_t);
static void ffeexpr_update_impdo_ (ffebld expr, ffebld dovar);
static void ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar);
static ffeexprContext ffeexpr_context_outer_ (ffeexprStack_ s);
static ffeexprExpr_ ffeexpr_expr_new_ (void);
static void ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t);
static bool ffeexpr_isdigits_ (const char *p);
1999-08-26 09:30:50 +00:00
static ffelexHandler ffeexpr_token_first_lhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_lhs_1_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_1_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_2_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_3_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_4_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_5_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_6_ (ffelexToken t);
static ffelexHandler ffeexpr_token_namelist_ (ffelexToken t);
static void ffeexpr_expr_kill_ (ffeexprExpr_ e);
static void ffeexpr_exprstack_push_ (ffeexprExpr_ e);
static void ffeexpr_exprstack_push_binary_ (ffeexprExpr_ e);
static void ffeexpr_exprstack_push_operand_ (ffeexprExpr_ e);
static void ffeexpr_exprstack_push_unary_ (ffeexprExpr_ e);
static void ffeexpr_reduce_ (void);
static ffebld ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op,
ffeexprExpr_ r);
static ffebld ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_eqop2_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op,
ffeexprExpr_ r);
static ffebld ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op,
ffeexprExpr_ r);
static ffebld ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffebld ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l,
ffeexprExpr_ op, ffeexprExpr_ r);
static ffelexHandler ffeexpr_find_close_paren_ (ffelexToken t,
ffelexHandler after);
static ffelexHandler ffeexpr_nil_finished_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_rhs_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_period_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_end_period_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_swallow_period_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_real_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_real_exponent_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_real_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_exponent_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_period_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_per_exp_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_real_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_num_per_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_number_real_exp_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_num_real_exp_sn_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_binary_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_binary_period_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_binary_end_per_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_binary_sw_per_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_quote_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_apostrophe_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_apos_char_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_name_rhs_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_name_apos_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_name_apos_name_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_percent_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_percent_name_ (ffelexToken t);
static ffelexHandler ffeexpr_nil_substrp_ (ffelexToken t);
static ffelexHandler ffeexpr_finished_ (ffelexToken t);
static ffebld ffeexpr_finished_ambig_ (ffelexToken t, ffebld expr);
static ffelexHandler ffeexpr_token_lhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_rhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_binary_ (ffelexToken t);
static ffelexHandler ffeexpr_token_period_ (ffelexToken t);
static ffelexHandler ffeexpr_token_end_period_ (ffelexToken t);
static ffelexHandler ffeexpr_token_swallow_period_ (ffelexToken t);
static ffelexHandler ffeexpr_token_real_ (ffelexToken t);
static ffelexHandler ffeexpr_token_real_exponent_ (ffelexToken t);
static ffelexHandler ffeexpr_token_real_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_exponent_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_period_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_per_exp_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_real_ (ffelexToken t);
static ffelexHandler ffeexpr_token_num_per_exp_sign_ (ffelexToken t);
static ffelexHandler ffeexpr_token_number_real_exp_ (ffelexToken t);
static ffelexHandler ffeexpr_token_num_real_exp_sn_ (ffelexToken t);
static ffelexHandler ffeexpr_token_binary_period_ (ffelexToken t);
static ffelexHandler ffeexpr_token_binary_end_per_ (ffelexToken t);
static ffelexHandler ffeexpr_token_binary_sw_per_ (ffelexToken t);
static ffelexHandler ffeexpr_token_quote_ (ffelexToken t);
static ffelexHandler ffeexpr_token_apostrophe_ (ffelexToken t);
static ffelexHandler ffeexpr_token_apos_char_ (ffelexToken t);
static ffelexHandler ffeexpr_token_name_lhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_name_arg_ (ffelexToken t);
static ffelexHandler ffeexpr_token_name_rhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_name_apos_ (ffelexToken t);
static ffelexHandler ffeexpr_token_name_apos_name_ (ffelexToken t);
static ffelexHandler ffeexpr_token_percent_ (ffelexToken t);
static ffelexHandler ffeexpr_token_percent_name_ (ffelexToken t);
static ffelexHandler ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_elements_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_substring_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_substring_1_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_substrp_ (ffelexToken t);
static ffelexHandler ffeexpr_token_intrincheck_ (ffelexToken t);
static ffelexHandler ffeexpr_token_funsubstr_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static ffelexHandler ffeexpr_token_anything_ (ffelexToken ft, ffebld expr,
ffelexToken t);
static void ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer,
ffelexToken decimal, ffelexToken fraction, ffelexToken exponent,
ffelexToken exponent_sign, ffelexToken exponent_digits);
static ffesymbol ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin);
static ffesymbol ffeexpr_sym_impdoitem_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t);
static ffesymbol ffeexpr_declare_parenthesized_ (ffelexToken t,
bool maybe_intrin,
ffeexprParenType_ *paren_type);
static ffesymbol ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t);
/* Internal macros. */
#define ffeexpr_paren_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t)
#define ffeexpr_sym_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t)
/* ffeexpr_collapse_convert -- Collapse convert expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_convert(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
ffetargetCharacterSize sz;
ffetargetCharacterSize sz2;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
sz = FFETARGET_charactersizeNONE;
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_integer1_integer2
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_integer1_integer3
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_integer1_integer4
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER1/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer1_real1
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer1_real2
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer1_real3
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer1_real4
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER1/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer1_complex1
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer1_complex2
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer1_complex3
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer1_complex4
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER1/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_integer1_logical1
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_integer1_logical2
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_integer1_logical3
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_integer1_logical4
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER1/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_integer1_character1
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_integer1_hollerith
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_integer1_typeless
(ffebld_cu_ptr_integer1 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("INTEGER1 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_integer2_integer1
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_integer2_integer3
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_integer2_integer4
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER2/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer2_real1
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer2_real2
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer2_real3
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer2_real4
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER2/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer2_complex1
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer2_complex2
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer2_complex3
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer2_complex4
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER2/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_integer2_logical1
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_integer2_logical2
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_integer2_logical3
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_integer2_logical4
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER2/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_integer2_character1
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_integer2_hollerith
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_integer2_typeless
(ffebld_cu_ptr_integer2 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("INTEGER2 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_integer3_integer1
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_integer3_integer2
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_integer3_integer4
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER3/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer3_real1
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer3_real2
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer3_real3
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer3_real4
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER3/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer3_complex1
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer3_complex2
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer3_complex3
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer3_complex4
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER3/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_integer3_logical1
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_integer3_logical2
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_integer3_logical3
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_integer3_logical4
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER3/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_integer3_character1
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_integer3_hollerith
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_integer3_typeless
(ffebld_cu_ptr_integer3 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("INTEGER3 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_integer4_integer1
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_integer4_integer2
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_integer4_integer3
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER4/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer4_real1
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer4_real2
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer4_real3
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer4_real4
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER4/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_integer4_complex1
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_integer4_complex2
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_integer4_complex3
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_integer4_complex4
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER3/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_integer4_logical1
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_integer4_logical2
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_integer4_logical3
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_integer4_logical4
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("INTEGER4/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_integer4_character1
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_integer4_hollerith
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_integer4_typeless
(ffebld_cu_ptr_integer4 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("INTEGER4 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
sz = FFETARGET_charactersizeNONE;
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_logical1_logical2
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_logical1_logical3
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_logical1_logical4
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL1/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_logical1_integer1
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_logical1_integer2
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_logical1_integer3
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_logical1_integer4
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL1/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_logical1_character1
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_logical1_hollerith
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_logical1_typeless
(ffebld_cu_ptr_logical1 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("LOGICAL1 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_logical2_logical1
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_logical2_logical3
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_logical2_logical4
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL2/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_logical2_integer1
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_logical2_integer2
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_logical2_integer3
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_logical2_integer4
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL2/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_logical2_character1
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_logical2_hollerith
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_logical2_typeless
(ffebld_cu_ptr_logical2 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("LOGICAL2 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_logical3_logical1
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_logical3_logical2
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_convert_logical3_logical4
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL3/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_logical3_integer1
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_logical3_integer2
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_logical3_integer3
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_logical3_integer4
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL3/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_logical3_character1
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_logical3_hollerith
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_logical3_typeless
(ffebld_cu_ptr_logical3 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("LOGICAL3 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_convert_logical4_logical1
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_convert_logical4_logical2
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_convert_logical4_logical3
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical3 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL4/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_logical4_integer1
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_logical4_integer2
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_logical4_integer3
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_logical4_integer4
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("LOGICAL4/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_logical4_character1
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_logical4_hollerith
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_logical4_typeless
(ffebld_cu_ptr_logical4 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("LOGICAL4 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
sz = FFETARGET_charactersizeNONE;
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_real1_integer1
(ffebld_cu_ptr_real1 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_real1_integer2
(ffebld_cu_ptr_real1 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_real1_integer3
(ffebld_cu_ptr_real1 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_real1_integer4
(ffebld_cu_ptr_real1 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL1/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real1_real2
(ffebld_cu_ptr_real1 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real1_real3
(ffebld_cu_ptr_real1 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real1_real4
(ffebld_cu_ptr_real1 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL1/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real1_complex1
(ffebld_cu_ptr_real1 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real1_complex2
(ffebld_cu_ptr_real1 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real1_complex3
(ffebld_cu_ptr_real1 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real1_complex4
(ffebld_cu_ptr_real1 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL1/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_real1_character1
(ffebld_cu_ptr_real1 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_real1_hollerith
(ffebld_cu_ptr_real1 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_real1_typeless
(ffebld_cu_ptr_real1 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("REAL1 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_real2_integer1
(ffebld_cu_ptr_real2 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_real2_integer2
(ffebld_cu_ptr_real2 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_real2_integer3
(ffebld_cu_ptr_real2 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_real2_integer4
(ffebld_cu_ptr_real2 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL2/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real2_real1
(ffebld_cu_ptr_real2 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real2_real3
(ffebld_cu_ptr_real2 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real2_real4
(ffebld_cu_ptr_real2 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL2/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real2_complex1
(ffebld_cu_ptr_real2 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real2_complex2
(ffebld_cu_ptr_real2 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real2_complex3
(ffebld_cu_ptr_real2 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real2_complex4
(ffebld_cu_ptr_real2 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL2/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_real2_character1
(ffebld_cu_ptr_real2 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_real2_hollerith
(ffebld_cu_ptr_real2 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_real2_typeless
(ffebld_cu_ptr_real2 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("REAL2 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_real3_integer1
(ffebld_cu_ptr_real3 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_real3_integer2
(ffebld_cu_ptr_real3 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_real3_integer3
(ffebld_cu_ptr_real3 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_real3_integer4
(ffebld_cu_ptr_real3 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL3/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real3_real1
(ffebld_cu_ptr_real3 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real3_real2
(ffebld_cu_ptr_real3 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real3_real4
(ffebld_cu_ptr_real3 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL3/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real3_complex1
(ffebld_cu_ptr_real3 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real3_complex2
(ffebld_cu_ptr_real3 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real3_complex3
(ffebld_cu_ptr_real3 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real3_complex4
(ffebld_cu_ptr_real3 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL3/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_real3_character1
(ffebld_cu_ptr_real3 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_real3_hollerith
(ffebld_cu_ptr_real3 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_real3_typeless
(ffebld_cu_ptr_real3 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("REAL3 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_real4_integer1
(ffebld_cu_ptr_real4 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_real4_integer2
(ffebld_cu_ptr_real4 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_real4_integer3
(ffebld_cu_ptr_real4 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_real4_integer4
(ffebld_cu_ptr_real4 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL4/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real4_real1
(ffebld_cu_ptr_real4 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real4_real2
(ffebld_cu_ptr_real4 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real4_real3
(ffebld_cu_ptr_real4 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL4/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_real4_complex1
(ffebld_cu_ptr_real4 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_real4_complex2
(ffebld_cu_ptr_real4 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_real4_complex3
(ffebld_cu_ptr_real4 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_real4_complex4
(ffebld_cu_ptr_real4 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("REAL4/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_real4_character1
(ffebld_cu_ptr_real4 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_real4_hollerith
(ffebld_cu_ptr_real4 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_real4_typeless
(ffebld_cu_ptr_real4 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("REAL4 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
sz = FFETARGET_charactersizeNONE;
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_complex1_integer1
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_complex1_integer2
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_complex1_integer3
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_complex1_integer4
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX1/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex1_real1
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex1_real2
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex1_real3
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex1_real4
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX1/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex1_complex2
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex1_complex3
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex1_complex4
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX1/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_complex1_character1
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_complex1_hollerith
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_complex1_typeless
(ffebld_cu_ptr_complex1 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("COMPLEX1 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_complex2_integer1
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_complex2_integer2
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_complex2_integer3
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_complex2_integer4
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX2/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex2_real1
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex2_real2
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex2_real3
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex2_real4
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX2/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex2_complex1
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex2_complex3
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex2_complex4
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX2/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_complex2_character1
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_complex2_hollerith
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_complex2_typeless
(ffebld_cu_ptr_complex2 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("COMPLEX2 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_complex3_integer1
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_complex3_integer2
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_complex3_integer3
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_complex3_integer4
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX3/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex3_real1
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex3_real2
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex3_real3
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex3_real4
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX3/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex3_complex1
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex3_complex2
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex3_complex4
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX3/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_complex3_character1
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_complex3_hollerith
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_complex3_typeless
(ffebld_cu_ptr_complex3 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("COMPLEX3 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_convert_complex4_integer1
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_integer1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_convert_complex4_integer2
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_integer2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_convert_complex4_integer3
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_integer3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_convert_complex4_integer4
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_integer4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX4/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex4_real1
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_real1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex4_real2
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_real2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex4_real3
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_real3 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_convert_complex4_real4
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_real4 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX4/REAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_convert_complex4_complex1
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex1 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_convert_complex4_complex2
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex2 (ffebld_conter (l)));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_convert_complex4_complex3
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex3 (ffebld_conter (l)));
break;
#endif
default:
assert ("COMPLEX4/COMPLEX bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
error = ffetarget_convert_complex4_character1
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_character1 (ffebld_conter (l)));
break;
case FFEINFO_basictypeHOLLERITH:
error = ffetarget_convert_complex4_hollerith
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_hollerith (ffebld_conter (l)));
break;
case FFEINFO_basictypeTYPELESS:
error = ffetarget_convert_complex4_typeless
(ffebld_cu_ptr_complex4 (u),
ffebld_constant_typeless (ffebld_conter (l)));
break;
default:
assert ("COMPLEX4 bad type" == NULL);
break;
}
/* If conversion operation is not implemented, return original expr. */
if (error == FFEBAD_NOCANDO)
return expr;
1999-08-26 09:30:50 +00:00
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
if ((sz = ffebld_size (expr)) == FFETARGET_charactersizeNONE)
return expr;
kt = ffeinfo_kindtype (ffebld_info (expr));
switch (kt)
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
switch (ffeinfo_basictype (ffebld_info (l)))
{
case FFEINFO_basictypeCHARACTER:
if ((sz2 = ffebld_size (l)) == FFETARGET_charactersizeNONE)
return expr;
assert (kt == ffeinfo_kindtype (ffebld_info (l)));
assert (sz2 == ffetarget_length_character1
(ffebld_constant_character1
(ffebld_conter (l))));
error
= ffetarget_convert_character1_character1
(ffebld_cu_ptr_character1 (u), sz,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error
= ffetarget_convert_character1_integer1
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error
= ffetarget_convert_character1_integer2
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error
= ffetarget_convert_character1_integer3
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error
= ffetarget_convert_character1_integer4
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
default:
assert ("CHARACTER1/INTEGER bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (ffeinfo_kindtype (ffebld_info (l)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error
= ffetarget_convert_character1_logical1
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error
= ffetarget_convert_character1_logical2
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error
= ffetarget_convert_character1_logical3
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error
= ffetarget_convert_character1_logical4
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_pool ());
break;
#endif
default:
assert ("CHARACTER1/LOGICAL bad source kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeHOLLERITH:
error
= ffetarget_convert_character1_hollerith
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_hollerith (ffebld_conter (l)),
ffebld_constant_pool ());
break;
case FFEINFO_basictypeTYPELESS:
error
= ffetarget_convert_character1_typeless
(ffebld_cu_ptr_character1 (u),
sz,
ffebld_constant_typeless (ffebld_conter (l)),
ffebld_constant_pool ());
break;
default:
assert ("CHARACTER1 bad type" == NULL);
}
expr
= ffebld_new_conter_with_orig
(ffebld_constant_new_character1_val
(ffebld_cu_val_character1 (u)),
expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
sz));
if ((error != FFEBAD)
&& ffebad_start (error))
{
assert (t != NULL);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_paren -- Collapse paren expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_paren(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_paren (ffebld expr, ffelexToken t UNUSED)
{
ffebld r;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
ffetargetCharacterSize len;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
r = ffebld_left (expr);
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
bt = ffeinfo_basictype (ffebld_info (r));
kt = ffeinfo_kindtype (ffebld_info (r));
len = ffebld_size (r);
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
expr);
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
return expr;
}
/* ffeexpr_collapse_uplus -- Collapse uplus expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_uplus(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_uplus (ffebld expr, ffelexToken t UNUSED)
{
ffebld r;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
ffetargetCharacterSize len;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
r = ffebld_left (expr);
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
bt = ffeinfo_basictype (ffebld_info (r));
kt = ffeinfo_kindtype (ffebld_info (r));
len = ffebld_size (r);
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
expr);
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
return expr;
}
/* ffeexpr_collapse_uminus -- Collapse uminus expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_uminus(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_uminus (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
r = ffebld_left (expr);
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_uminus_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_uminus_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_uminus_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_uminus_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_uminus_real1 (ffebld_cu_ptr_real1 (u),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_uminus_real2 (ffebld_cu_ptr_real2 (u),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_uminus_real3 (ffebld_cu_ptr_real3 (u),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_uminus_real4 (ffebld_cu_ptr_real4 (u),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_uminus_complex1 (ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_uminus_complex2 (ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_uminus_complex3 (ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_uminus_complex4 (ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_not -- Collapse not expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_not(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_not (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
r = ffebld_left (expr);
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_not_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_not_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_not_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_not_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_not_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_not_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_not_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_not_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_add -- Collapse add expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_add(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_add (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_add_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_add_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_add_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_add_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_add_real1 (ffebld_cu_ptr_real1 (u),
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_add_real2 (ffebld_cu_ptr_real2 (u),
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_add_real3 (ffebld_cu_ptr_real3 (u),
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_add_real4 (ffebld_cu_ptr_real4 (u),
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_add_complex1 (ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_add_complex2 (ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_add_complex3 (ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_add_complex4 (ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_subtract -- Collapse subtract expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_subtract(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_subtract (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_subtract_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_subtract_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_subtract_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_subtract_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_subtract_real1 (ffebld_cu_ptr_real1 (u),
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_subtract_real2 (ffebld_cu_ptr_real2 (u),
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_subtract_real3 (ffebld_cu_ptr_real3 (u),
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_subtract_real4 (ffebld_cu_ptr_real4 (u),
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_subtract_complex1 (ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_subtract_complex2 (ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_subtract_complex3 (ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_subtract_complex4 (ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_multiply -- Collapse multiply expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_multiply(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_multiply (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_multiply_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_multiply_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_multiply_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_multiply_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_multiply_real1 (ffebld_cu_ptr_real1 (u),
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_multiply_real2 (ffebld_cu_ptr_real2 (u),
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_multiply_real3 (ffebld_cu_ptr_real3 (u),
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_multiply_real4 (ffebld_cu_ptr_real4 (u),
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_multiply_complex1 (ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_multiply_complex2 (ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_multiply_complex3 (ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_multiply_complex4 (ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_divide -- Collapse divide expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_divide(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_divide (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_divide_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_divide_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_divide_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_divide_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_divide_real1 (ffebld_cu_ptr_real1 (u),
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_divide_real2 (ffebld_cu_ptr_real2 (u),
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_divide_real3 (ffebld_cu_ptr_real3 (u),
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_divide_real4 (ffebld_cu_ptr_real4 (u),
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_divide_complex1 (ffebld_cu_ptr_complex1 (u),
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_divide_complex2 (ffebld_cu_ptr_complex2 (u),
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_divide_complex3 (ffebld_cu_ptr_complex3 (u),
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_divide_complex4 (ffebld_cu_ptr_complex4 (u),
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_power -- Collapse power expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_power(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_power (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
if ((ffeinfo_basictype (ffebld_info (r)) != FFEINFO_basictypeINTEGER)
|| (ffeinfo_kindtype (ffebld_info (r)) != FFEINFO_kindtypeINTEGERDEFAULT))
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
case FFEINFO_kindtypeINTEGERDEFAULT:
error = ffetarget_power_integerdefault_integerdefault
(ffebld_cu_ptr_integerdefault (u),
ffebld_constant_integerdefault (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integerdefault_val
(ffebld_cu_val_integerdefault (u)), expr);
break;
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
case FFEINFO_kindtypeREALDEFAULT:
error = ffetarget_power_realdefault_integerdefault
(ffebld_cu_ptr_realdefault (u),
ffebld_constant_realdefault (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_realdefault_val
(ffebld_cu_val_realdefault (u)), expr);
break;
case FFEINFO_kindtypeREALDOUBLE:
error = ffetarget_power_realdouble_integerdefault
(ffebld_cu_ptr_realdouble (u),
ffebld_constant_realdouble (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_realdouble_val
(ffebld_cu_val_realdouble (u)), expr);
break;
#if FFETARGET_okREALQUAD
case FFEINFO_kindtypeREALQUAD:
error = ffetarget_power_realquad_integerdefault
(ffebld_cu_ptr_realquad (u),
ffebld_constant_realquad (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_realquad_val
(ffebld_cu_val_realquad (u)), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
case FFEINFO_kindtypeREALDEFAULT:
error = ffetarget_power_complexdefault_integerdefault
(ffebld_cu_ptr_complexdefault (u),
ffebld_constant_complexdefault (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complexdefault_val
(ffebld_cu_val_complexdefault (u)), expr);
break;
#if FFETARGET_okCOMPLEXDOUBLE
case FFEINFO_kindtypeREALDOUBLE:
error = ffetarget_power_complexdouble_integerdefault
(ffebld_cu_ptr_complexdouble (u),
ffebld_constant_complexdouble (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complexdouble_val
(ffebld_cu_val_complexdouble (u)), expr);
break;
#endif
#if FFETARGET_okCOMPLEXQUAD
case FFEINFO_kindtypeREALQUAD:
error = ffetarget_power_complexquad_integerdefault
(ffebld_cu_ptr_complexquad (u),
ffebld_constant_complexquad (ffebld_conter (l)),
ffebld_constant_integerdefault (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complexquad_val
(ffebld_cu_val_complexquad (u)), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_concatenate -- Collapse concatenate expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_concatenate(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_concatenate (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoKindtype kt;
ffetargetCharacterSize len;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeCHARACTER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_concatenate_character1 (ffebld_cu_ptr_character1 (u),
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)),
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val
(ffebld_cu_val_character1 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_concatenate_character2 (ffebld_cu_ptr_character2 (u),
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)),
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val
(ffebld_cu_val_character2 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_concatenate_character3 (ffebld_cu_ptr_character3 (u),
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)),
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val
(ffebld_cu_val_character3 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_concatenate_character4 (ffebld_cu_ptr_character4 (u),
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)),
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val
(ffebld_cu_val_character4 (u)), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeCHARACTER,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_eq -- Collapse eq expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_eq(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_eq (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_eq_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_eq_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_eq_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_eq_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_eq_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_eq_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_eq_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_eq_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_eq_complex1 (&val,
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_eq_complex2 (&val,
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_eq_complex3 (&val,
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_eq_complex4 (&val,
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_eq_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_eq_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_eq_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_eq_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_ne -- Collapse ne expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_ne(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_ne (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_ne_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_ne_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_ne_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_ne_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_ne_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_ne_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_ne_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_ne_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCOMPLEX:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
error = ffetarget_ne_complex1 (&val,
ffebld_constant_complex1 (ffebld_conter (l)),
ffebld_constant_complex1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
error = ffetarget_ne_complex2 (&val,
ffebld_constant_complex2 (ffebld_conter (l)),
ffebld_constant_complex2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
error = ffetarget_ne_complex3 (&val,
ffebld_constant_complex3 (ffebld_conter (l)),
ffebld_constant_complex3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
error = ffetarget_ne_complex4 (&val,
ffebld_constant_complex4 (ffebld_conter (l)),
ffebld_constant_complex4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad complex kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_ne_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_ne_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_ne_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_ne_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_ge -- Collapse ge expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_ge(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_ge (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_ge_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_ge_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_ge_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_ge_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_ge_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_ge_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_ge_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_ge_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_ge_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_ge_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_ge_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_ge_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_gt -- Collapse gt expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_gt(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_gt (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_gt_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_gt_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_gt_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_gt_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_gt_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_gt_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_gt_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_gt_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_gt_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_gt_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_gt_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_gt_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_le -- Collapse le expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_le(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_le (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_le_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_le_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_le_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_le_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_le_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_le_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_le_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_le_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_le_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_le_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_le_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_le_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_lt -- Collapse lt expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_lt(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_lt (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
bool val;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_lt_integer1 (&val,
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_lt_integer2 (&val,
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_lt_integer3 (&val,
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_lt_integer4 (&val,
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeREAL:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okREAL1
case FFEINFO_kindtypeREAL1:
error = ffetarget_lt_real1 (&val,
ffebld_constant_real1 (ffebld_conter (l)),
ffebld_constant_real1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL2
case FFEINFO_kindtypeREAL2:
error = ffetarget_lt_real2 (&val,
ffebld_constant_real2 (ffebld_conter (l)),
ffebld_constant_real2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL3
case FFEINFO_kindtypeREAL3:
error = ffetarget_lt_real3 (&val,
ffebld_constant_real3 (ffebld_conter (l)),
ffebld_constant_real3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okREAL4
case FFEINFO_kindtypeREAL4:
error = ffetarget_lt_real4 (&val,
ffebld_constant_real4 (ffebld_conter (l)),
ffebld_constant_real4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad real kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeCHARACTER:
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_lt_character1 (&val,
ffebld_constant_character1 (ffebld_conter (l)),
ffebld_constant_character1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_lt_character2 (&val,
ffebld_constant_character2 (ffebld_conter (l)),
ffebld_constant_character2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_lt_character3 (&val,
ffebld_constant_character3 (ffebld_conter (l)),
ffebld_constant_character3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_lt_character4 (&val,
ffebld_constant_character4 (ffebld_conter (l)),
ffebld_constant_character4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logicaldefault (val), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_and -- Collapse and expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_and(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_and (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_and_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_and_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_and_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_and_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_and_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_and_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_and_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_and_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_or -- Collapse or expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_or(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_or (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_or_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_or_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_or_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_or_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_or_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_or_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_or_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_or_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_xor -- Collapse xor expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_xor(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_xor (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_xor_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_xor_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_xor_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_xor_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_xor_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_xor_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_xor_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_xor_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_eqv -- Collapse eqv expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_eqv(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_eqv (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_eqv_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_eqv_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_eqv_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_eqv_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_eqv_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_eqv_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_eqv_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_eqv_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_neqv -- Collapse neqv expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_neqv(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_neqv (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebldConstantUnion u;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr);
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
if (ffebld_op (r) != FFEBLD_opCONTER)
return expr;
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeINTEGER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okINTEGER1
case FFEINFO_kindtypeINTEGER1:
error = ffetarget_neqv_integer1 (ffebld_cu_ptr_integer1 (u),
ffebld_constant_integer1 (ffebld_conter (l)),
ffebld_constant_integer1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER2
case FFEINFO_kindtypeINTEGER2:
error = ffetarget_neqv_integer2 (ffebld_cu_ptr_integer2 (u),
ffebld_constant_integer2 (ffebld_conter (l)),
ffebld_constant_integer2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER3
case FFEINFO_kindtypeINTEGER3:
error = ffetarget_neqv_integer3 (ffebld_cu_ptr_integer3 (u),
ffebld_constant_integer3 (ffebld_conter (l)),
ffebld_constant_integer3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
break;
#endif
#if FFETARGET_okINTEGER4
case FFEINFO_kindtypeINTEGER4:
error = ffetarget_neqv_integer4 (ffebld_cu_ptr_integer4 (u),
ffebld_constant_integer4 (ffebld_conter (l)),
ffebld_constant_integer4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
break;
#endif
default:
assert ("bad integer kind type" == NULL);
break;
}
break;
case FFEINFO_basictypeLOGICAL:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okLOGICAL1
case FFEINFO_kindtypeLOGICAL1:
error = ffetarget_neqv_logical1 (ffebld_cu_ptr_logical1 (u),
ffebld_constant_logical1 (ffebld_conter (l)),
ffebld_constant_logical1 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL2
case FFEINFO_kindtypeLOGICAL2:
error = ffetarget_neqv_logical2 (ffebld_cu_ptr_logical2 (u),
ffebld_constant_logical2 (ffebld_conter (l)),
ffebld_constant_logical2 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL3
case FFEINFO_kindtypeLOGICAL3:
error = ffetarget_neqv_logical3 (ffebld_cu_ptr_logical3 (u),
ffebld_constant_logical3 (ffebld_conter (l)),
ffebld_constant_logical3 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
break;
#endif
#if FFETARGET_okLOGICAL4
case FFEINFO_kindtypeLOGICAL4:
error = ffetarget_neqv_logical4 (ffebld_cu_ptr_logical4 (u),
ffebld_constant_logical4 (ffebld_conter (l)),
ffebld_constant_logical4 (ffebld_conter (r)));
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
break;
#endif
default:
assert ("bad logical kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_collapse_symter -- Collapse symter expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_symter(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_symter (ffebld expr, ffelexToken t UNUSED)
{
ffebld r;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
ffetargetCharacterSize len;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
if ((r = ffesymbol_init (ffebld_symter (expr))) == NULL)
return expr; /* A PARAMETER lhs in progress. */
switch (ffebld_op (r))
{
case FFEBLD_opCONTER:
break;
case FFEBLD_opANY:
return r;
default:
return expr;
}
bt = ffeinfo_basictype (ffebld_info (r));
kt = ffeinfo_kindtype (ffebld_info (r));
len = ffebld_size (r);
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
expr);
ffebld_set_info (expr, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
return expr;
}
/* ffeexpr_collapse_funcref -- Collapse funcref expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_funcref(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_funcref (ffebld expr, ffelexToken t UNUSED)
{
return expr; /* ~~someday go ahead and collapse these,
though not required */
}
/* ffeexpr_collapse_arrayref -- Collapse arrayref expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_arrayref(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_arrayref (ffebld expr, ffelexToken t UNUSED)
{
return expr;
}
/* ffeexpr_collapse_substr -- Collapse substr expr
ffebld expr;
ffelexToken token;
expr = ffeexpr_collapse_substr(expr,token);
If the result of the expr is a constant, replaces the expr with the
computed constant. */
ffebld
ffeexpr_collapse_substr (ffebld expr, ffelexToken t)
{
ffebad error = FFEBAD;
ffebld l;
ffebld r;
ffebld start;
ffebld stop;
ffebldConstantUnion u;
ffeinfoKindtype kt;
ffetargetCharacterSize len;
ffetargetIntegerDefault first;
ffetargetIntegerDefault last;
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
return expr;
l = ffebld_left (expr);
r = ffebld_right (expr); /* opITEM. */
if (ffebld_op (l) != FFEBLD_opCONTER)
return expr;
kt = ffeinfo_kindtype (ffebld_info (l));
len = ffebld_size (l);
start = ffebld_head (r);
stop = ffebld_head (ffebld_trail (r));
if (start == NULL)
first = 1;
else
{
if ((ffebld_op (start) != FFEBLD_opCONTER)
|| (ffeinfo_basictype (ffebld_info (start)) != FFEINFO_basictypeINTEGER)
|| (ffeinfo_kindtype (ffebld_info (start))
!= FFEINFO_kindtypeINTEGERDEFAULT))
return expr;
first = ffebld_constant_integerdefault (ffebld_conter (start));
}
if (stop == NULL)
last = len;
else
{
if ((ffebld_op (stop) != FFEBLD_opCONTER)
|| (ffeinfo_basictype (ffebld_info (stop)) != FFEINFO_basictypeINTEGER)
|| (ffeinfo_kindtype (ffebld_info (stop))
!= FFEINFO_kindtypeINTEGERDEFAULT))
return expr;
last = ffebld_constant_integerdefault (ffebld_conter (stop));
}
/* Handle problems that should have already been diagnosed, but
left in the expression tree. */
if (first <= 0)
first = 1;
if (last < first)
last = first + len - 1;
if ((first == 1) && (last == len))
{ /* Same as original. */
expr = ffebld_new_conter_with_orig (ffebld_constant_copy
(ffebld_conter (l)), expr);
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeCHARACTER,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
return expr;
}
switch (ffeinfo_basictype (ffebld_info (expr)))
{
case FFEINFO_basictypeANY:
return expr;
case FFEINFO_basictypeCHARACTER:
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
{
#if FFETARGET_okCHARACTER1
case FFEINFO_kindtypeCHARACTER1:
error = ffetarget_substr_character1 (ffebld_cu_ptr_character1 (u),
ffebld_constant_character1 (ffebld_conter (l)), first, last,
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val
(ffebld_cu_val_character1 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER2
case FFEINFO_kindtypeCHARACTER2:
error = ffetarget_substr_character2 (ffebld_cu_ptr_character2 (u),
ffebld_constant_character2 (ffebld_conter (l)), first, last,
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val
(ffebld_cu_val_character2 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER3
case FFEINFO_kindtypeCHARACTER3:
error = ffetarget_substr_character3 (ffebld_cu_ptr_character3 (u),
ffebld_constant_character3 (ffebld_conter (l)), first, last,
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val
(ffebld_cu_val_character3 (u)), expr);
break;
#endif
#if FFETARGET_okCHARACTER4
case FFEINFO_kindtypeCHARACTER4:
error = ffetarget_substr_character4 (ffebld_cu_ptr_character4 (u),
ffebld_constant_character4 (ffebld_conter (l)), first, last,
ffebld_constant_pool (), &len);
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val
(ffebld_cu_val_character4 (u)), expr);
break;
#endif
default:
assert ("bad character kind type" == NULL);
break;
}
break;
default:
assert ("bad type" == NULL);
return expr;
}
ffebld_set_info (expr, ffeinfo_new
(FFEINFO_basictypeCHARACTER,
kt,
0,
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
len));
if ((error != FFEBAD)
&& ffebad_start (error))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return expr;
}
/* ffeexpr_convert -- Convert source expression to given type
ffebld source;
ffelexToken source_token;
ffelexToken dest_token; // Any appropriate token for "destination".
ffeinfoBasictype bt;
ffeinfoKindtype kt;
ffetargetCharactersize sz;
ffeexprContext context; // Mainly LET or DATA.
source = ffeexpr_convert(source,source_token,dest_token,bt,kt,sz,context);
If the expression conforms, returns the source expression. Otherwise
returns source wrapped in a convert node doing the conversion, or
ANY wrapped in convert if there is a conversion error (and issues an
error message). Be sensitive to the context for certain aspects of
the conversion. */
ffebld
ffeexpr_convert (ffebld source, ffelexToken source_token, ffelexToken dest_token,
ffeinfoBasictype bt, ffeinfoKindtype kt, ffeinfoRank rk,
ffetargetCharacterSize sz, ffeexprContext context)
{
bool bad;
ffeinfo info;
ffeinfoWhere wh;
info = ffebld_info (source);
if ((bt != ffeinfo_basictype (info))
|| (kt != ffeinfo_kindtype (info))
|| (rk != 0) /* Can't convert from or to arrays yet. */
|| (ffeinfo_rank (info) != 0)
|| (sz != ffebld_size_known (source)))
#if 0 /* Nobody seems to need this spurious CONVERT node. */
|| ((context != FFEEXPR_contextLET)
&& (bt == FFEINFO_basictypeCHARACTER)
&& (sz == FFETARGET_charactersizeNONE)))
#endif
{
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
switch (bt)
{
case FFEINFO_basictypeLOGICAL:
bad = FALSE;
break;
case FFEINFO_basictypeINTEGER:
bad = !ffe_is_ugly_logint ();
break;
case FFEINFO_basictypeCHARACTER:
bad = ffe_is_pedantic ()
|| !(ffe_is_ugly_init ()
&& (context == FFEEXPR_contextDATA));
break;
default:
bad = TRUE;
break;
}
break;
case FFEINFO_basictypeINTEGER:
switch (bt)
{
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
bad = FALSE;
break;
case FFEINFO_basictypeLOGICAL:
bad = !ffe_is_ugly_logint ();
break;
case FFEINFO_basictypeCHARACTER:
bad = ffe_is_pedantic ()
|| !(ffe_is_ugly_init ()
&& (context == FFEEXPR_contextDATA));
break;
default:
bad = TRUE;
break;
}
break;
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
switch (bt)
{
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
bad = FALSE;
break;
case FFEINFO_basictypeCHARACTER:
bad = TRUE;
break;
default:
bad = TRUE;
break;
}
break;
case FFEINFO_basictypeCHARACTER:
bad = (bt != FFEINFO_basictypeCHARACTER)
&& (ffe_is_pedantic ()
|| (bt != FFEINFO_basictypeINTEGER)
|| !(ffe_is_ugly_init ()
&& (context == FFEEXPR_contextDATA)));
break;
case FFEINFO_basictypeTYPELESS:
case FFEINFO_basictypeHOLLERITH:
bad = ffe_is_pedantic ()
|| !(ffe_is_ugly_init ()
&& ((context == FFEEXPR_contextDATA)
|| (context == FFEEXPR_contextLET)));
break;
default:
bad = TRUE;
break;
}
if (!bad && ((rk != 0) || (ffeinfo_rank (info) != 0)))
bad = TRUE;
if (bad && (bt != FFEINFO_basictypeANY) && (kt != FFEINFO_kindtypeANY)
&& (ffeinfo_basictype (info) != FFEINFO_basictypeANY)
&& (ffeinfo_kindtype (info) != FFEINFO_kindtypeANY)
&& (ffeinfo_where (info) != FFEINFO_whereANY))
{
if (ffebad_start (FFEBAD_BAD_TYPES))
{
if (dest_token == NULL)
ffebad_here (0, ffewhere_line_unknown (),
ffewhere_column_unknown ());
else
ffebad_here (0, ffelex_token_where_line (dest_token),
ffelex_token_where_column (dest_token));
assert (source_token != NULL);
ffebad_here (1, ffelex_token_where_line (source_token),
ffelex_token_where_column (source_token));
ffebad_finish ();
}
source = ffebld_new_any ();
ffebld_set_info (source, ffeinfo_new_any ());
}
else
{
switch (ffeinfo_where (info))
{
case FFEINFO_whereCONSTANT:
wh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
wh = FFEINFO_whereIMMEDIATE;
break;
default:
wh = FFEINFO_whereFLEETING;
break;
}
source = ffebld_new_convert (source);
ffebld_set_info (source, ffeinfo_new
(bt,
kt,
0,
FFEINFO_kindENTITY,
wh,
sz));
source = ffeexpr_collapse_convert (source, source_token);
}
}
return source;
}
/* ffeexpr_convert_expr -- Convert source expr to conform to dest expr
ffebld source;
ffebld dest;
ffelexToken source_token;
ffelexToken dest_token;
ffeexprContext context;
source = ffeexpr_convert_expr(source,source_token,dest,dest_token,context);
If the expressions conform, returns the source expression. Otherwise
returns source wrapped in a convert node doing the conversion, or
ANY wrapped in convert if there is a conversion error (and issues an
error message). Be sensitive to the context, such as LET or DATA. */
ffebld
ffeexpr_convert_expr (ffebld source, ffelexToken source_token, ffebld dest,
ffelexToken dest_token, ffeexprContext context)
{
ffeinfo info;
info = ffebld_info (dest);
return ffeexpr_convert (source, source_token, dest_token,
ffeinfo_basictype (info),
ffeinfo_kindtype (info),
ffeinfo_rank (info),
ffebld_size_known (dest),
context);
}
/* ffeexpr_convert_to_sym -- Convert source expression to conform to symbol
ffebld source;
ffesymbol dest;
ffelexToken source_token;
ffelexToken dest_token;
source = ffeexpr_convert_to_sym(source,source_token,dest,dest_token);
If the expressions conform, returns the source expression. Otherwise
returns source wrapped in a convert node doing the conversion, or
ANY wrapped in convert if there is a conversion error (and issues an
error message). */
ffebld
ffeexpr_convert_to_sym (ffebld source, ffelexToken source_token,
ffesymbol dest, ffelexToken dest_token)
{
return ffeexpr_convert (source, source_token, dest_token, ffesymbol_basictype (dest),
ffesymbol_kindtype (dest), ffesymbol_rank (dest), ffesymbol_size (dest),
FFEEXPR_contextLET);
}
/* Initializes the module. */
void
ffeexpr_init_2 ()
{
ffeexpr_stack_ = NULL;
ffeexpr_level_ = 0;
}
/* ffeexpr_lhs -- Begin processing left-hand-side-context expression
Prepares cluster for delivery of lexer tokens representing an expression
in a left-hand-side context (A in A=B, for example). ffebld is used
to build expressions in the given pool. The appropriate lexer-token
handling routine within ffeexpr is returned. When the end of the
expression is detected, mycallbackroutine is called with the resulting
single ffebld object specifying the entire expression and the first
lexer token that is not considered part of the expression. This caller-
supplied routine itself returns a lexer-token handling routine. Thus,
if necessary, ffeexpr can return several tokens as end-of-expression
tokens if it needs to scan forward more than one in any instance. */
ffelexHandler
ffeexpr_lhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback)
{
ffeexprStack_ s;
ffebld_pool_push (pool);
s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s));
s->previous = ffeexpr_stack_;
s->pool = pool;
s->context = context;
s->callback = callback;
s->first_token = NULL;
s->exprstack = NULL;
s->is_rhs = FALSE;
ffeexpr_stack_ = s;
return (ffelexHandler) ffeexpr_token_first_lhs_;
}
/* ffeexpr_rhs -- Begin processing right-hand-side-context expression
return ffeexpr_rhs(malloc_pool_image(),mycallbackroutine); // to lexer.
Prepares cluster for delivery of lexer tokens representing an expression
in a right-hand-side context (B in A=B, for example). ffebld is used
to build expressions in the given pool. The appropriate lexer-token
handling routine within ffeexpr is returned. When the end of the
expression is detected, mycallbackroutine is called with the resulting
single ffebld object specifying the entire expression and the first
lexer token that is not considered part of the expression. This caller-
supplied routine itself returns a lexer-token handling routine. Thus,
if necessary, ffeexpr can return several tokens as end-of-expression
tokens if it needs to scan forward more than one in any instance. */
ffelexHandler
ffeexpr_rhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback)
{
ffeexprStack_ s;
ffebld_pool_push (pool);
s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s));
s->previous = ffeexpr_stack_;
s->pool = pool;
s->context = context;
s->callback = callback;
s->first_token = NULL;
s->exprstack = NULL;
s->is_rhs = TRUE;
ffeexpr_stack_ = s;
return (ffelexHandler) ffeexpr_token_first_rhs_;
}
/* ffeexpr_cb_close_paren_ -- OPEN_PAREN expr
Pass it to ffeexpr_rhs as the callback routine.
Makes sure the end token is close-paren and swallows it, else issues
an error message and doesn't swallow the token (passing it along instead).
In either case wraps up subexpression construction by enclosing the
ffebld expression in a paren. */
static ffelexHandler
ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ e;
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
{
/* Oops, naughty user didn't specify the close paren! */
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
ffeexpr_exprstack_push_operand_ (e);
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_binary_);
}
if (expr->op == FFEBLD_opIMPDO)
{
if (ffest_ffebad_start (FFEBAD_IMPDO_PAREN))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
}
else
{
expr = ffebld_new_paren (expr);
ffebld_set_info (expr, ffeinfo_use (ffebld_info (ffebld_left (expr))));
}
/* Now push the (parenthesized) expression as an operand onto the
expression stack. */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand = expr;
e->u.operand = ffeexpr_collapse_paren (e->u.operand, ft);
e->token = ffeexpr_stack_->tokens[0];
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_cb_close_paren_ambig_ -- OPEN_PAREN expr
Pass it to ffeexpr_rhs as the callback routine.
We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)"
with the next token in t. If the next token is possibly a binary
operator, continue processing the outer expression. If the next
token is COMMA, then the expression is a unit specifier, and
parentheses should not be added to it because it surrounds the
I/O control list that starts with the unit specifier (and continues
on from here -- we haven't seen the CLOSE_PAREN that matches the
OPEN_PAREN, it is up to the callback function to expect to see it
at some point). In this case, we notify the callback function that
the COMMA is inside, not outside, the parens by wrapping the expression
in an opITEM (with a NULL trail) -- the callback function presumably
unwraps it after seeing this kludgey indicator.
If the next token is CLOSE_PAREN, then we go to the _1_ state to
decide what to do with the token after that.
15-Feb-91 JCB 1.1
Use an extra state for the CLOSE_PAREN case to make READ &co really
work right. */
static ffelexHandler
ffeexpr_cb_close_paren_ambig_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
{ /* Need to see the next token before we
decide anything. */
ffeexpr_stack_->expr = expr;
ffeexpr_tokens_[0] = ffelex_token_use (ft);
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_cb_close_paren_ambig_1_;
}
expr = ffeexpr_finished_ambig_ (ft, expr);
/* Let the callback function handle the case where t isn't COMMA. */
/* Here is a kludge whereby we tell the callback function the OPEN_PAREN
that preceded the expression starts a list of expressions, and the expr
hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN
node. The callback function should extract the real expr from the head
of this opITEM node after testing it. */
expr = ffebld_new_item (expr, NULL);
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ffelex_token_kill (ffeexpr_stack_->first_token);
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
return (ffelexHandler) (*callback) (ft, expr, t);
}
/* ffeexpr_cb_close_paren_ambig_1_ -- OPEN_PAREN expr CLOSE_PAREN
See ffeexpr_cb_close_paren_ambig_.
We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)"
with the next token in t. If the next token is possibly a binary
operator, continue processing the outer expression. If the next
token is COMMA, the expression is a parenthesized format specifier.
If the next token is not EOS or SEMICOLON, then because it is not a
binary operator (it is NAME, OPEN_PAREN, &c), the expression is
a unit specifier, and parentheses should not be added to it because
they surround the I/O control list that consists of only the unit
specifier. If the next token is EOS or SEMICOLON, the statement
must be disambiguated by looking at the type of the expression -- a
character expression is a parenthesized format specifier, while a
non-character expression is a unit specifier.
Another issue is how to do the callback so the recipient of the
next token knows how to handle it if it is a COMMA. In all other
cases, disambiguation is straightforward: the same approach as the
above is used.
EXTENSION: in COMMA case, if not pedantic, use same disambiguation
as for EOS/SEMICOLON case; f2c allows "READ (cilist) [[,]iolist]"
and apparently other compilers do, as well, and some code out there
uses this "feature".
19-Feb-91 JCB 1.1
Extend to allow COMMA as nondisambiguating by itself. Remember
to not try and check info field for opSTAR, since that expr doesn't
have a valid info field. */
static ffelexHandler
ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken orig_ft = ffeexpr_tokens_[0]; /* In case callback clobbers
these. */
ffelexToken orig_t = ffeexpr_tokens_[1];
ffebld expr = ffeexpr_stack_->expr;
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA: /* Subexpr is parenthesized format specifier. */
if (ffe_is_pedantic ())
goto pedantic_comma; /* :::::::::::::::::::: */
/* Fall through. */
case FFELEX_typeEOS: /* Ambiguous; use type of expr to
disambiguate. */
case FFELEX_typeSEMICOLON:
if ((expr == NULL) || (ffebld_op (expr) == FFEBLD_opANY)
|| (ffebld_op (expr) == FFEBLD_opSTAR)
|| (ffeinfo_basictype (ffebld_info (expr))
!= FFEINFO_basictypeCHARACTER))
break; /* Not a valid CHARACTER entity, can't be a
format spec. */
/* Fall through. */
default: /* Binary op (we assume; error otherwise);
format specifier. */
pedantic_comma: /* :::::::::::::::::::: */
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILENUMAMBIG:
ffeexpr_stack_->context = FFEEXPR_contextFILENUM;
break;
case FFEEXPR_contextFILEUNITAMBIG:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
break;
default:
assert ("bad context" == NULL);
break;
}
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
next = (ffelexHandler) ffeexpr_cb_close_paren_ (orig_ft, expr, orig_t);
ffelex_token_kill (orig_ft);
ffelex_token_kill (orig_t);
return (ffelexHandler) (*next) (t);
case FFELEX_typeOPEN_PAREN:/* Non-binary op; beginning of I/O list. */
case FFELEX_typeNAME:
break;
}
expr = ffeexpr_finished_ambig_ (orig_ft, expr);
/* Here is a kludge whereby we tell the callback function the OPEN_PAREN
that preceded the expression starts a list of expressions, and the expr
hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN
node. The callback function should extract the real expr from the head
of this opITEM node after testing it. */
expr = ffebld_new_item (expr, NULL);
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ffelex_token_kill (ffeexpr_stack_->first_token);
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (orig_ft, expr, orig_t);
ffelex_token_kill (orig_ft);
ffelex_token_kill (orig_t);
return (ffelexHandler) (*next) (t);
}
/* ffeexpr_cb_close_paren_c_ -- OPEN_PAREN expr (possible complex)
Pass it to ffeexpr_rhs as the callback routine.
Makes sure the end token is close-paren and swallows it, or a comma
and handles complex/implied-do possibilities, else issues
an error message and doesn't swallow the token (passing it along instead). */
static ffelexHandler
ffeexpr_cb_close_paren_c_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
/* First check to see if this is a possible complex entity. It is if the
token is a comma. */
if (ffelex_token_type (t) == FFELEX_typeCOMMA)
{
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
ffeexpr_stack_->expr = expr;
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextPAREN_, ffeexpr_cb_comma_c_);
}
return (ffelexHandler) ffeexpr_cb_close_paren_ (ft, expr, t);
}
/* ffeexpr_cb_comma_c_ -- OPEN_PAREN expr COMMA expr
Pass it to ffeexpr_rhs as the callback routine.
If this token is not a comma, we have a complex constant (or an attempt
at one), so handle it accordingly, displaying error messages if the token
is not a close-paren. */
static ffelexHandler
ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ e;
ffeinfoBasictype lty = (ffeexpr_stack_->expr == NULL)
? FFEINFO_basictypeNONE : ffeinfo_basictype (ffebld_info (ffeexpr_stack_->expr));
ffeinfoBasictype rty = (expr == NULL)
? FFEINFO_basictypeNONE : ffeinfo_basictype (ffebld_info (expr));
ffeinfoKindtype lkt;
ffeinfoKindtype rkt;
ffeinfoKindtype nkt;
bool ok = TRUE;
ffebld orig;
if ((ffeexpr_stack_->expr == NULL)
|| (ffebld_op (ffeexpr_stack_->expr) != FFEBLD_opCONTER)
|| (((orig = ffebld_conter_orig (ffeexpr_stack_->expr)) != NULL)
&& (((ffebld_op (orig) != FFEBLD_opUMINUS)
&& (ffebld_op (orig) != FFEBLD_opUPLUS))
|| (ffebld_conter_orig (ffebld_left (orig)) != NULL)))
|| ((lty != FFEINFO_basictypeINTEGER)
&& (lty != FFEINFO_basictypeREAL)))
{
if ((lty != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_INVALID_COMPLEX_PART))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
ffebad_string ("Real");
ffebad_finish ();
}
ok = FALSE;
}
if ((expr == NULL)
|| (ffebld_op (expr) != FFEBLD_opCONTER)
|| (((orig = ffebld_conter_orig (expr)) != NULL)
&& (((ffebld_op (orig) != FFEBLD_opUMINUS)
&& (ffebld_op (orig) != FFEBLD_opUPLUS))
|| (ffebld_conter_orig (ffebld_left (orig)) != NULL)))
|| ((rty != FFEINFO_basictypeINTEGER)
&& (rty != FFEINFO_basictypeREAL)))
{
if ((rty != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_INVALID_COMPLEX_PART))
{
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_string ("Imaginary");
ffebad_finish ();
}
ok = FALSE;
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
/* Push the (parenthesized) expression as an operand onto the expression
stack. */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_stack_->tokens[0];
if (ok)
{
if (lty == FFEINFO_basictypeINTEGER)
lkt = FFEINFO_kindtypeREALDEFAULT;
else
lkt = ffeinfo_kindtype (ffebld_info (ffeexpr_stack_->expr));
if (rty == FFEINFO_basictypeINTEGER)
rkt = FFEINFO_kindtypeREALDEFAULT;
else
rkt = ffeinfo_kindtype (ffebld_info (expr));
nkt = ffeinfo_kindtype_max (FFEINFO_basictypeCOMPLEX, lkt, rkt);
ffeexpr_stack_->expr = ffeexpr_convert (ffeexpr_stack_->expr,
ffeexpr_stack_->tokens[1], ffeexpr_stack_->tokens[0],
FFEINFO_basictypeREAL, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
expr = ffeexpr_convert (expr,
ffeexpr_stack_->tokens[1], ffeexpr_stack_->tokens[0],
FFEINFO_basictypeREAL, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
}
else
nkt = FFEINFO_kindtypeANY;
switch (nkt)
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex1
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
break;
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex2
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
break;
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex3
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
break;
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex4
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
break;
#endif
default:
if (ffebad_start ((nkt == FFEINFO_kindtypeREALDOUBLE)
? FFEBAD_BAD_DBLCMPLX : FFEBAD_BAD_COMPLEX))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
/* Fall through. */
case FFEINFO_kindtypeANY:
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
break;
}
ffeexpr_exprstack_push_operand_ (e);
/* Now, if the token is a close parenthese, we're in great shape so return
the next handler. */
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_token_binary_;
/* Oops, naughty user didn't specify the close paren! */
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_binary_);
}
/* ffeexpr_cb_close_paren_ci_ -- OPEN_PAREN expr (possible complex or
implied-DO construct)
Pass it to ffeexpr_rhs as the callback routine.
Makes sure the end token is close-paren and swallows it, or a comma
and handles complex/implied-do possibilities, else issues
an error message and doesn't swallow the token (passing it along instead). */
static ffelexHandler
ffeexpr_cb_close_paren_ci_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprContext ctx;
/* First check to see if this is a possible complex or implied-DO entity.
It is if the token is a comma. */
if (ffelex_token_type (t) == FFELEX_typeCOMMA)
{
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIMPDOITEM_:
ctx = FFEEXPR_contextIMPDOITEM_;
break;
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEMDF_:
ctx = FFEEXPR_contextIMPDOITEMDF_;
break;
default:
assert ("bad context" == NULL);
ctx = FFEEXPR_contextIMPDOITEM_;
break;
}
ffeexpr_stack_->tokens[0] = ffelex_token_use (ft);
ffeexpr_stack_->expr = expr;
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ctx, ffeexpr_cb_comma_ci_);
}
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
return (ffelexHandler) ffeexpr_cb_close_paren_ (ft, expr, t);
}
/* ffeexpr_cb_comma_ci_ -- OPEN_PAREN expr COMMA expr
Pass it to ffeexpr_rhs as the callback routine.
If this token is not a comma, we have a complex constant (or an attempt
at one), so handle it accordingly, displaying error messages if the token
is not a close-paren. If we have a comma here, it is an attempt at an
implied-DO, so start making a list accordingly. Oh, it might be an
equal sign also, meaning an implied-DO with only one item in its list. */
static ffelexHandler
ffeexpr_cb_comma_ci_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffebld fexpr;
/* First check to see if this is a possible complex constant. It is if the
token is not a comma or an equals sign, in which case it should be a
close-paren. */
if ((ffelex_token_type (t) != FFELEX_typeCOMMA)
&& (ffelex_token_type (t) != FFELEX_typeEQUALS))
{
ffeexpr_stack_->tokens[1] = ffeexpr_stack_->tokens[0];
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
return (ffelexHandler) ffeexpr_cb_comma_c_ (ft, expr, t);
}
/* Here we have either EQUALS or COMMA, meaning we are in an implied-DO
construct. Make a list and handle accordingly. */
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
fexpr = ffeexpr_stack_->expr;
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
ffebld_append_item (&ffeexpr_stack_->bottom, fexpr);
return (ffelexHandler) ffeexpr_cb_comma_i_1_ (ft, expr, t);
}
/* ffeexpr_cb_comma_i_ -- OPEN_PAREN expr
Pass it to ffeexpr_rhs as the callback routine.
Handle first item in an implied-DO construct. */
static ffelexHandler
ffeexpr_cb_comma_i_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
{
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffebld_end_list (&ffeexpr_stack_->bottom);
ffeexpr_stack_->expr = ffebld_new_any ();
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
}
return (ffelexHandler) ffeexpr_cb_comma_i_1_ (ft, expr, t);
}
/* ffeexpr_cb_comma_i_1_ -- OPEN_PAREN expr
Pass it to ffeexpr_rhs as the callback routine.
Handle first item in an implied-DO construct. */
static ffelexHandler
ffeexpr_cb_comma_i_1_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprContext ctxi;
ffeexprContext ctxc;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
case FFEEXPR_contextDATAIMPDOITEM_:
ctxi = FFEEXPR_contextDATAIMPDOITEM_;
ctxc = FFEEXPR_contextDATAIMPDOCTRL_;
break;
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIMPDOITEM_:
ctxi = FFEEXPR_contextIMPDOITEM_;
ctxc = FFEEXPR_contextIMPDOCTRL_;
break;
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEMDF_:
ctxi = FFEEXPR_contextIMPDOITEMDF_;
ctxc = FFEEXPR_contextIMPDOCTRL_;
break;
default:
assert ("bad context" == NULL);
ctxi = FFEEXPR_context;
ctxc = FFEEXPR_context;
break;
}
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
if (ffeexpr_stack_->is_rhs)
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ctxi, ffeexpr_cb_comma_i_1_);
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
ctxi, ffeexpr_cb_comma_i_1_);
case FFELEX_typeEQUALS:
ffebld_end_list (&ffeexpr_stack_->bottom);
/* Complain if implied-DO variable in list of items to be read. */
if ((ctxc == FFEEXPR_contextIMPDOCTRL_) && !ffeexpr_stack_->is_rhs)
ffeexpr_check_impdo_ (ffeexpr_stack_->expr,
ffeexpr_stack_->first_token, expr, ft);
/* Set doiter flag for all appropriate SYMTERs. */
ffeexpr_update_impdo_ (ffeexpr_stack_->expr, expr);
ffeexpr_stack_->expr = ffebld_new_impdo (ffeexpr_stack_->expr, NULL);
ffebld_set_info (ffeexpr_stack_->expr,
ffeinfo_new (FFEINFO_basictypeNONE,
FFEINFO_kindtypeNONE,
0,
FFEINFO_kindNONE,
FFEINFO_whereNONE,
FFETARGET_charactersizeNONE));
ffebld_init_list (&(ffebld_right (ffeexpr_stack_->expr)),
&ffeexpr_stack_->bottom);
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ctxc, ffeexpr_cb_comma_i_2_);
default:
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffebld_end_list (&ffeexpr_stack_->bottom);
ffeexpr_stack_->expr = ffebld_new_any ();
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
}
}
/* ffeexpr_cb_comma_i_2_ -- OPEN_PAREN expr-list EQUALS expr
Pass it to ffeexpr_rhs as the callback routine.
Handle start-value in an implied-DO construct. */
static ffelexHandler
ffeexpr_cb_comma_i_2_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
{
ffeexprContext ctx;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
case FFEEXPR_contextDATAIMPDOITEM_:
ctx = FFEEXPR_contextDATAIMPDOCTRL_;
break;
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
ctx = FFEEXPR_contextIMPDOCTRL_;
break;
default:
assert ("bad context" == NULL);
ctx = FFEEXPR_context;
break;
}
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ctx, ffeexpr_cb_comma_i_3_);
break;
default:
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffebld_end_list (&ffeexpr_stack_->bottom);
ffeexpr_stack_->expr = ffebld_new_any ();
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
}
}
/* ffeexpr_cb_comma_i_3_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
Pass it to ffeexpr_rhs as the callback routine.
Handle end-value in an implied-DO construct. */
static ffelexHandler
ffeexpr_cb_comma_i_3_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
{
ffeexprContext ctx;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
case FFEEXPR_contextDATAIMPDOITEM_:
ctx = FFEEXPR_contextDATAIMPDOCTRL_;
break;
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
ctx = FFEEXPR_contextIMPDOCTRL_;
break;
default:
assert ("bad context" == NULL);
ctx = FFEEXPR_context;
break;
}
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ctx, ffeexpr_cb_comma_i_4_);
break;
case FFELEX_typeCLOSE_PAREN:
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
return (ffelexHandler) ffeexpr_cb_comma_i_4_ (NULL, NULL, t);
break;
default:
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffebld_end_list (&ffeexpr_stack_->bottom);
ffeexpr_stack_->expr = ffebld_new_any ();
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
}
}
/* ffeexpr_cb_comma_i_4_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
[COMMA expr]
Pass it to ffeexpr_rhs as the callback routine.
Handle incr-value in an implied-DO construct. */
static ffelexHandler
ffeexpr_cb_comma_i_4_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeCLOSE_PAREN:
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
ffebld_end_list (&ffeexpr_stack_->bottom);
{
ffebld item;
for (item = ffebld_left (ffeexpr_stack_->expr);
item != NULL;
item = ffebld_trail (item))
if (ffebld_op (ffebld_head (item)) == FFEBLD_opANY)
goto replace_with_any; /* :::::::::::::::::::: */
for (item = ffebld_right (ffeexpr_stack_->expr);
item != NULL;
item = ffebld_trail (item))
if ((ffebld_head (item) != NULL) /* Increment may be NULL. */
&& (ffebld_op (ffebld_head (item)) == FFEBLD_opANY))
goto replace_with_any; /* :::::::::::::::::::: */
}
break;
default:
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffebld_end_list (&ffeexpr_stack_->bottom);
replace_with_any: /* :::::::::::::::::::: */
ffeexpr_stack_->expr = ffebld_new_any ();
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
break;
}
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
}
/* ffeexpr_cb_comma_i_5_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
[COMMA expr] CLOSE_PAREN
Pass it to ffeexpr_rhs as the callback routine.
Collects token following implied-DO construct for callback function. */
static ffelexHandler
ffeexpr_cb_comma_i_5_ (ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
ffebld expr;
bool terminate;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
case FFEEXPR_contextDATAIMPDOITEM_:
terminate = TRUE;
break;
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
terminate = FALSE;
break;
default:
assert ("bad context" == NULL);
terminate = FALSE;
break;
}
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
expr = ffeexpr_stack_->expr;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
if (terminate)
{
ffesymbol_drive_sfnames (ffeexpr_check_impctrl_);
--ffeexpr_level_;
if (ffeexpr_level_ == 0)
ffe_terminate_4 ();
}
return (ffelexHandler) next;
}
/* ffeexpr_cb_end_loc_ -- Handle end of %LOC subexpression
Makes sure the end token is close-paren and swallows it, else issues
an error message and doesn't swallow the token (passing it along instead).
In either case wraps up subexpression construction by enclosing the
ffebld expression in a %LOC. */
static ffelexHandler
ffeexpr_cb_end_loc_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
{
ffeexprExpr_ e;
/* First push the (%LOC) expression as an operand onto the expression
stack. */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_stack_->tokens[0];
e->u.operand = ffebld_new_percent_loc (expr);
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeINTEGER,
ffecom_pointer_kind (),
0,
FFEINFO_kindENTITY,
FFEINFO_whereFLEETING,
FFETARGET_charactersizeNONE));
#if 0 /* ~~ */
e->u.operand = ffeexpr_collapse_percent_loc (e->u.operand, ft);
#endif
ffeexpr_exprstack_push_operand_ (e);
/* Now, if the token is a close parenthese, we're in great shape so return
the next handler. */
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
{
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* Oops, naughty user didn't specify the close paren! */
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_binary_);
}
/* ffeexpr_cb_end_notloc_ -- PERCENT NAME(VAL,REF,DESCR) OPEN_PAREN expr
Should be CLOSE_PAREN, and make sure expr isn't a %(VAL,REF,DESCR). */
static ffelexHandler
ffeexpr_cb_end_notloc_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ e;
ffebldOp op;
/* If expression is itself a %(VAL,REF,DESCR), complain and strip off all
such things until the lowest-level expression is reached. */
op = ffebld_op (expr);
if ((op == FFEBLD_opPERCENT_VAL) || (op == FFEBLD_opPERCENT_REF)
|| (op == FFEBLD_opPERCENT_DESCR))
{
if (ffebad_start (FFEBAD_NESTED_PERCENT))
{
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
do
{
expr = ffebld_left (expr);
op = ffebld_op (expr);
}
while ((op == FFEBLD_opPERCENT_VAL) || (op == FFEBLD_opPERCENT_REF)
|| (op == FFEBLD_opPERCENT_DESCR));
}
/* Push the expression as an operand onto the expression stack. */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_stack_->tokens[0];
switch (ffeexpr_stack_->percent)
{
case FFEEXPR_percentVAL_:
e->u.operand = ffebld_new_percent_val (expr);
break;
case FFEEXPR_percentREF_:
e->u.operand = ffebld_new_percent_ref (expr);
break;
case FFEEXPR_percentDESCR_:
e->u.operand = ffebld_new_percent_descr (expr);
break;
default:
assert ("%lossage" == NULL);
e->u.operand = expr;
break;
}
ffebld_set_info (e->u.operand, ffebld_info (expr));
#if 0 /* ~~ */
e->u.operand = ffeexpr_collapse_percent_ ? ? ? (e->u.operand, ft);
#endif
ffeexpr_exprstack_push_operand_ (e);
/* Now, if the token is a close parenthese, we're in great shape so return
the next handler. */
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_cb_end_notloc_1_;
/* Oops, naughty user didn't specify the close paren! */
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
ffebad_finish ();
}
ffebld_set_op (e->u.operand, FFEBLD_opPERCENT_LOC);
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
assert ("bad context?!?!" == NULL);
break;
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_cb_end_notloc_1_);
}
/* ffeexpr_cb_end_notloc_1_ -- PERCENT NAME(VAL,REF,DESCR) OPEN_PAREN expr
CLOSE_PAREN
Should be COMMA or CLOSE_PAREN, else change back to %LOC. */
static ffelexHandler
ffeexpr_cb_end_notloc_1_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
case FFELEX_typeCLOSE_PAREN:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextSFUNCDEFACTUALARG_:
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
break;
default:
assert ("bad context?!?!" == NULL);
break;
}
break;
default:
if (ffebad_start (FFEBAD_INVALID_PERCENT))
{
ffebad_here (0,
ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_string (ffelex_token_text (ffeexpr_stack_->tokens[1]));
ffebad_finish ();
}
ffebld_set_op (ffeexpr_stack_->exprstack->u.operand,
FFEBLD_opPERCENT_LOC);
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
assert ("bad context?!?!" == NULL);
break;
}
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
return
(ffelexHandler) ffeexpr_token_binary_ (t);
}
/* Process DATA implied-DO iterator variables as this implied-DO level
terminates. At this point, ffeexpr_level_ == 1 when we see the
last right-paren in "DATA (A(I),I=1,10)/.../". */
static ffesymbol
ffeexpr_check_impctrl_ (ffesymbol s)
{
assert (s != NULL);
assert (ffesymbol_sfdummyparent (s) != NULL);
switch (ffesymbol_state (s))
{
case FFESYMBOL_stateNONE: /* Used as iterator already. Now let symbol
be used as iterator at any level at or
innermore than the outermost of the
current level and the symbol's current
level. */
if (ffeexpr_level_ < ffesymbol_maxentrynum (s))
{
ffesymbol_signal_change (s);
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
ffesymbol_signal_unreported (s);
}
break;
case FFESYMBOL_stateSEEN: /* Seen already in this or other implied-DO.
Error if at outermost level, else it can
still become an iterator. */
if ((ffeexpr_level_ == 1)
&& ffebad_start (FFEBAD_BAD_IMPDCL))
{
ffebad_string (ffesymbol_text (s));
ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
ffebad_finish ();
}
break;
case FFESYMBOL_stateUNCERTAIN: /* Iterator. */
assert (ffeexpr_level_ <= ffesymbol_maxentrynum (s));
ffesymbol_signal_change (s);
ffesymbol_set_state (s, FFESYMBOL_stateNONE);
ffesymbol_signal_unreported (s);
break;
case FFESYMBOL_stateUNDERSTOOD:
break; /* ANY. */
default:
assert ("Sasha Foo!!" == NULL);
break;
}
return s;
}
/* Issue diagnostic if implied-DO variable appears in list of lhs
expressions (as in "READ *, (I,I=1,10)"). */
static void
ffeexpr_check_impdo_ (ffebld list, ffelexToken list_t,
ffebld dovar, ffelexToken dovar_t)
{
ffebld item;
ffesymbol dovar_sym;
int itemnum;
if (ffebld_op (dovar) != FFEBLD_opSYMTER)
return; /* Presumably opANY. */
dovar_sym = ffebld_symter (dovar);
for (itemnum = 1; list != NULL; list = ffebld_trail (list), ++itemnum)
{
if (((item = ffebld_head (list)) != NULL)
&& (ffebld_op (item) == FFEBLD_opSYMTER)
&& (ffebld_symter (item) == dovar_sym))
{
char itemno[20];
sprintf (&itemno[0], "%d", itemnum);
if (ffebad_start (FFEBAD_DOITER_IMPDO))
{
ffebad_here (0, ffelex_token_where_line (list_t),
ffelex_token_where_column (list_t));
ffebad_here (1, ffelex_token_where_line (dovar_t),
ffelex_token_where_column (dovar_t));
ffebad_string (ffesymbol_text (dovar_sym));
ffebad_string (itemno);
ffebad_finish ();
}
}
}
}
/* Decorate any SYMTERs referencing the DO variable with the "doiter"
flag. */
static void
ffeexpr_update_impdo_ (ffebld list, ffebld dovar)
{
ffesymbol dovar_sym;
if (ffebld_op (dovar) != FFEBLD_opSYMTER)
return; /* Presumably opANY. */
dovar_sym = ffebld_symter (dovar);
ffeexpr_update_impdo_sym_ (list, dovar_sym); /* Recurse! */
}
/* Recursive function to update any expr so SYMTERs have "doiter" flag
if they refer to the given variable. */
static void
ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar)
{
tail_recurse: /* :::::::::::::::::::: */
if (expr == NULL)
return;
switch (ffebld_op (expr))
{
case FFEBLD_opSYMTER:
if (ffebld_symter (expr) == dovar)
ffebld_symter_set_is_doiter (expr, TRUE);
break;
case FFEBLD_opITEM:
ffeexpr_update_impdo_sym_ (ffebld_head (expr), dovar);
expr = ffebld_trail (expr);
goto tail_recurse; /* :::::::::::::::::::: */
default:
break;
}
switch (ffebld_arity (expr))
{
case 2:
ffeexpr_update_impdo_sym_ (ffebld_left (expr), dovar);
expr = ffebld_right (expr);
goto tail_recurse; /* :::::::::::::::::::: */
case 1:
expr = ffebld_left (expr);
goto tail_recurse; /* :::::::::::::::::::: */
default:
break;
}
return;
}
/* ffeexpr_context_outer_ -- Determine context of stack entry, skipping PARENs
if (ffeexpr_context_outer_(ffeexpr_stack_) == FFEEXPR_contextIF)
// After zero or more PAREN_ contexts, an IF context exists */
static ffeexprContext
ffeexpr_context_outer_ (ffeexprStack_ s)
{
assert (s != NULL);
for (;;)
{
switch (s->context)
{
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextPARENFILENUM_:
case FFEEXPR_contextPARENFILEUNIT_:
break;
default:
return s->context;
}
s = s->previous;
assert (s != NULL);
}
}
/* ffeexpr_percent_ -- Look up name in list of %FOO possibilities
ffeexprPercent_ p;
ffelexToken t;
p = ffeexpr_percent_(t);
Returns the identifier for the name, or the NONE identifier. */
static ffeexprPercent_
ffeexpr_percent_ (ffelexToken t)
{
const char *p;
1999-08-26 09:30:50 +00:00
switch (ffelex_token_length (t))
{
case 3:
switch (*(p = ffelex_token_text (t)))
{
case FFESRC_CASE_MATCH_INIT ('L', 'l', match_3l, no_match_3):
if ((ffesrc_char_match_noninit (*++p, 'O', 'o'))
&& (ffesrc_char_match_noninit (*++p, 'C', 'c')))
return FFEEXPR_percentLOC_;
return FFEEXPR_percentNONE_;
case FFESRC_CASE_MATCH_INIT ('R', 'r', match_3r, no_match_3):
if ((ffesrc_char_match_noninit (*++p, 'E', 'e'))
&& (ffesrc_char_match_noninit (*++p, 'F', 'f')))
return FFEEXPR_percentREF_;
return FFEEXPR_percentNONE_;
case FFESRC_CASE_MATCH_INIT ('V', 'v', match_3v, no_match_3):
if ((ffesrc_char_match_noninit (*++p, 'A', 'a'))
&& (ffesrc_char_match_noninit (*++p, 'L', 'l')))
return FFEEXPR_percentVAL_;
return FFEEXPR_percentNONE_;
default:
no_match_3: /* :::::::::::::::::::: */
return FFEEXPR_percentNONE_;
}
case 5:
if (ffesrc_strcmp_2c (ffe_case_match (), ffelex_token_text (t), "DESCR",
"descr", "Descr") == 0)
return FFEEXPR_percentDESCR_;
return FFEEXPR_percentNONE_;
default:
return FFEEXPR_percentNONE_;
}
}
/* ffeexpr_type_combine -- Binop combine types, check for mythical new COMPLEX
See prototype.
If combining the two basictype/kindtype pairs produces a COMPLEX with an
unsupported kind type, complain and use the default kind type for
COMPLEX. */
void
ffeexpr_type_combine (ffeinfoBasictype *xnbt, ffeinfoKindtype *xnkt,
ffeinfoBasictype lbt, ffeinfoKindtype lkt,
ffeinfoBasictype rbt, ffeinfoKindtype rkt,
ffelexToken t)
{
ffeinfoBasictype nbt;
ffeinfoKindtype nkt;
nbt = ffeinfo_basictype_combine (lbt, rbt);
if ((nbt == FFEINFO_basictypeCOMPLEX)
&& ((lbt == nbt) || (lbt == FFEINFO_basictypeREAL))
&& ((rbt == nbt) || (rbt == FFEINFO_basictypeREAL)))
{
nkt = ffeinfo_kindtype_max (nbt, lkt, rkt);
if (ffe_is_pedantic_not_90 () && (nkt == FFEINFO_kindtypeREALDOUBLE))
nkt = FFEINFO_kindtypeNONE; /* Force error. */
switch (nkt)
{
#if FFETARGET_okCOMPLEX1
case FFEINFO_kindtypeREAL1:
#endif
#if FFETARGET_okCOMPLEX2
case FFEINFO_kindtypeREAL2:
#endif
#if FFETARGET_okCOMPLEX3
case FFEINFO_kindtypeREAL3:
#endif
#if FFETARGET_okCOMPLEX4
case FFEINFO_kindtypeREAL4:
#endif
break; /* Fine and dandy. */
default:
if (t != NULL)
{
ffebad_start ((nkt == FFEINFO_kindtypeREALDOUBLE)
? FFEBAD_BAD_DBLCMPLX : FFEBAD_BAD_COMPLEX);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
nbt = FFEINFO_basictypeNONE;
nkt = FFEINFO_kindtypeNONE;
break;
case FFEINFO_kindtypeANY:
nkt = FFEINFO_kindtypeREALDEFAULT;
break;
}
}
else
{ /* The normal stuff. */
if (nbt == lbt)
{
if (nbt == rbt)
nkt = ffeinfo_kindtype_max (nbt, lkt, rkt);
else
nkt = lkt;
}
else if (nbt == rbt)
nkt = rkt;
else
{ /* Let the caller do the complaining. */
nbt = FFEINFO_basictypeNONE;
nkt = FFEINFO_kindtypeNONE;
}
}
/* Always a good idea to avoid aliasing problems. */
*xnbt = nbt;
*xnkt = nkt;
}
/* ffeexpr_token_first_lhs_ -- First state for lhs expression
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Record line and column of first token in expression, then invoke the
initial-state lhs handler. */
static ffelexHandler
ffeexpr_token_first_lhs_ (ffelexToken t)
{
ffeexpr_stack_->first_token = ffelex_token_use (t);
/* When changing the list of valid initial lhs tokens, check whether to
update a corresponding list in ffeexpr_cb_close_paren_ambig_1_ for the
READ (expr) <token> case -- it assumes it knows which tokens <token> can
be to indicate an lhs (or implied DO), which right now is the set
{NAME,OPEN_PAREN}.
This comment also appears in ffeexpr_token_lhs_. */
switch (ffelex_token_type (t))
{
case FFELEX_typeOPEN_PAREN:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
ffe_init_4 ();
ffeexpr_level_ = 1; /* Level of DATA implied-DO construct. */
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
FFEEXPR_contextDATAIMPDOITEM_, ffeexpr_cb_comma_i_);
case FFEEXPR_contextDATAIMPDOITEM_:
++ffeexpr_level_; /* Level of DATA implied-DO construct. */
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
FFEEXPR_contextDATAIMPDOITEM_, ffeexpr_cb_comma_i_);
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIMPDOITEM_:
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
FFEEXPR_contextIMPDOITEM_, ffeexpr_cb_comma_i_);
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEMDF_:
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
FFEEXPR_contextIMPDOITEMDF_, ffeexpr_cb_comma_i_);
case FFEEXPR_contextFILEEXTFUNC:
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
default:
break;
}
break;
case FFELEX_typeNAME:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILENAMELIST:
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_namelist_;
case FFEEXPR_contextFILEEXTFUNC:
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
default:
break;
}
break;
default:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILEEXTFUNC:
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
default:
break;
}
break;
}
return (ffelexHandler) ffeexpr_token_lhs_ (t);
}
/* ffeexpr_token_first_lhs_1_ -- NAME
return ffeexpr_token_first_lhs_1_; // to lexer
Handle NAME as an external function (USEROPEN= VXT extension to OPEN
statement). */
static ffelexHandler
ffeexpr_token_first_lhs_1_ (ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
ffesymbol sy = NULL;
ffebld expr;
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
s = ffeexpr_stack_->previous;
if ((ffelex_token_type (ft) != FFELEX_typeNAME)
|| (ffesymbol_attrs (sy = ffeexpr_declare_unadorned_ (ft, FALSE))
& FFESYMBOL_attrANY))
{
if ((ffelex_token_type (ft) != FFELEX_typeNAME)
|| !(ffesymbol_attrs (sy) & FFESYMBOL_attrsANY))
{
ffebad_start (FFEBAD_EXPR_WRONG);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
expr = ffebld_new_any ();
ffebld_set_info (expr, ffeinfo_new_any ());
}
else
{
expr = ffebld_new_symter (sy, FFEINTRIN_genNONE, FFEINTRIN_specNONE,
FFEINTRIN_impNONE);
ffebld_set_info (expr, ffesymbol_info (sy));
}
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_token_first_rhs_ -- First state for rhs expression
Record line and column of first token in expression, then invoke the
initial-state rhs handler.
19-Feb-91 JCB 1.1
Allow ASTERISK in PARENFILEUNIT_ case, but only on second level only
(i.e. only as in READ(*), not READ((*))). */
static ffelexHandler
ffeexpr_token_first_rhs_ (ffelexToken t)
{
ffesymbol s;
ffeexpr_stack_->first_token = ffelex_token_use (t);
switch (ffelex_token_type (t))
{
case FFELEX_typeASTERISK:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILEFORMATNML:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
/* Fall through. */
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextCHARACTERSIZE:
if (ffeexpr_stack_->previous != NULL)
break; /* Valid only on first level. */
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_rhs_1_;
case FFEEXPR_contextPARENFILEUNIT_:
if (ffeexpr_stack_->previous->previous != NULL)
break; /* Valid only on second level. */
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_rhs_1_;
case FFEEXPR_contextACTUALARG_:
if (ffeexpr_stack_->previous->context
!= FFEEXPR_contextSUBROUTINEREF)
{
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
}
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_rhs_3_;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
break;
}
break;
case FFELEX_typeOPEN_PAREN:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILENUMAMBIG:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextPARENFILENUM_,
ffeexpr_cb_close_paren_ambig_);
case FFEEXPR_contextFILEUNITAMBIG:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextPARENFILEUNIT_,
ffeexpr_cb_close_paren_ambig_);
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIMPDOITEM_:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextIMPDOITEM_,
ffeexpr_cb_close_paren_ci_);
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextIMPDOITEMDF_:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextIMPDOITEMDF_,
ffeexpr_cb_close_paren_ci_);
case FFEEXPR_contextFILEFORMATNML:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
break;
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
break;
}
break;
case FFELEX_typeNUMBER:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILEFORMATNML:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
/* Fall through. */
case FFEEXPR_contextFILEFORMAT:
if (ffeexpr_stack_->previous != NULL)
break; /* Valid only on first level. */
assert (ffeexpr_stack_->exprstack == NULL);
return (ffelexHandler) ffeexpr_token_first_rhs_2_;
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
break;
}
break;
case FFELEX_typeNAME:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILEFORMATNML:
assert (ffeexpr_stack_->exprstack == NULL);
s = ffesymbol_lookup_local (t);
if ((s != NULL) && (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
return (ffelexHandler) ffeexpr_token_namelist_;
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
break;
default:
break;
}
break;
case FFELEX_typePERCENT:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextINDEXORACTUALARG_:
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
return (ffelexHandler) ffeexpr_token_first_rhs_5_;
case FFEEXPR_contextFILEFORMATNML:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
break;
default:
break;
}
default:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextFILEFORMATNML:
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
break;
default:
break;
}
break;
}
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
/* ffeexpr_token_first_rhs_1_ -- ASTERISK
return ffeexpr_token_first_rhs_1_; // to lexer
Return STAR as expression. */
static ffelexHandler
ffeexpr_token_first_rhs_1_ (ffelexToken t)
{
ffebld expr;
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
expr = ffebld_new_star ();
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_token_first_rhs_2_ -- NUMBER
return ffeexpr_token_first_rhs_2_; // to lexer
Return NULL as expression; NUMBER as first (and only) token, unless the
current token is not a terminating token, in which case run normal
expression handling. */
static ffelexHandler
ffeexpr_token_first_rhs_2_ (ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
switch (ffelex_token_type (t))
{
case FFELEX_typeCLOSE_PAREN:
case FFELEX_typeCOMMA:
case FFELEX_typeEOS:
case FFELEX_typeSEMICOLON:
break;
default:
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
return (ffelexHandler) (*next) (t);
}
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, NULL, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_token_first_rhs_3_ -- ASTERISK
return ffeexpr_token_first_rhs_3_; // to lexer
Expect NUMBER, make LABTOK (with copy of token if not inhibited after
confirming, else NULL). */
static ffelexHandler
ffeexpr_token_first_rhs_3_ (ffelexToken t)
{
ffelexHandler next;
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{ /* An error, but let normal processing handle
it. */
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
return (ffelexHandler) (*next) (t);
}
/* Special case: when we see "*10" as an argument to a subroutine
reference, we confirm the current statement and, if not inhibited at
this point, put a copy of the token into a LABTOK node. We do this
instead of just resolving the label directly via ffelab and putting it
into a LABTER simply to improve error reporting and consistency in
ffestc. We put NULL in the LABTOK if we're still inhibited, so ffestb
doesn't have to worry about killing off any tokens when retracting. */
ffest_confirmed ();
if (ffest_is_inhibited ())
ffeexpr_stack_->expr = ffebld_new_labtok (NULL);
else
ffeexpr_stack_->expr = ffebld_new_labtok (ffelex_token_use (t));
ffebld_set_info (ffeexpr_stack_->expr,
ffeinfo_new (FFEINFO_basictypeNONE,
FFEINFO_kindtypeNONE,
0,
FFEINFO_kindNONE,
FFEINFO_whereNONE,
FFETARGET_charactersizeNONE));
return (ffelexHandler) ffeexpr_token_first_rhs_4_;
}
/* ffeexpr_token_first_rhs_4_ -- ASTERISK NUMBER
return ffeexpr_token_first_rhs_4_; // to lexer
Collect/flush appropriate stuff, send token to callback function. */
static ffelexHandler
ffeexpr_token_first_rhs_4_ (ffelexToken t)
{
ffebld expr;
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
expr = ffeexpr_stack_->expr;
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_token_first_rhs_5_ -- PERCENT
Should be NAME, or pass through original mechanism. If NAME is LOC,
pass through original mechanism, otherwise must be VAL, REF, or DESCR,
in which case handle the argument (in parentheses), etc. */
static ffelexHandler
ffeexpr_token_first_rhs_5_ (ffelexToken t)
{
ffelexHandler next;
if (ffelex_token_type (t) == FFELEX_typeNAME)
{
ffeexprPercent_ p = ffeexpr_percent_ (t);
switch (p)
{
case FFEEXPR_percentNONE_:
case FFEEXPR_percentLOC_:
break; /* Treat %LOC as any other expression. */
case FFEEXPR_percentVAL_:
case FFEEXPR_percentREF_:
case FFEEXPR_percentDESCR_:
ffeexpr_stack_->percent = p;
ffeexpr_stack_->tokens[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_first_rhs_6_;
default:
assert ("bad percent?!?" == NULL);
break;
}
}
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
assert ("bad context?!?!" == NULL);
break;
}
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
return (ffelexHandler) (*next) (t);
}
/* ffeexpr_token_first_rhs_6_ -- PERCENT NAME(VAL,REF,DESCR)
Should be OPEN_PAREN, or pass through original mechanism. */
static ffelexHandler
ffeexpr_token_first_rhs_6_ (ffelexToken t)
{
ffelexHandler next;
ffelexToken ft;
if (ffelex_token_type (t) == FFELEX_typeOPEN_PAREN)
{
ffeexpr_stack_->tokens[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
ffeexpr_stack_->context,
ffeexpr_cb_end_notloc_);
}
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
assert ("bad context?!?!" == NULL);
break;
}
ft = ffeexpr_stack_->tokens[0];
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
next = (ffelexHandler) (*next) (ft);
ffelex_token_kill (ft);
return (ffelexHandler) (*next) (t);
}
/* ffeexpr_token_namelist_ -- NAME
return ffeexpr_token_namelist_; // to lexer
Make sure NAME was a valid namelist object, wrap it in a SYMTER and
return. */
static ffelexHandler
ffeexpr_token_namelist_ (ffelexToken t)
{
ffeexprCallback callback;
ffeexprStack_ s;
ffelexHandler next;
ffelexToken ft;
ffesymbol sy;
ffebld expr;
ffebld_pool_pop ();
callback = ffeexpr_stack_->callback;
ft = ffeexpr_stack_->first_token;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
sy = ffesymbol_lookup_local (ft);
if ((sy == NULL) || (ffesymbol_kind (sy) != FFEINFO_kindNAMELIST))
{
ffebad_start (FFEBAD_EXPR_WRONG);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
expr = ffebld_new_any ();
ffebld_set_info (expr, ffeinfo_new_any ());
}
else
{
expr = ffebld_new_symter (sy, FFEINTRIN_genNONE, FFEINTRIN_specNONE,
FFEINTRIN_impNONE);
ffebld_set_info (expr, ffesymbol_info (sy));
}
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_expr_kill_ -- Kill an existing internal expression object
ffeexprExpr_ e;
ffeexpr_expr_kill_(e);
Kills the ffewhere info, if necessary, then kills the object. */
static void
ffeexpr_expr_kill_ (ffeexprExpr_ e)
{
if (e->token != NULL)
ffelex_token_kill (e->token);
malloc_kill_ks (ffe_pool_program_unit (), e, sizeof (*e));
}
/* ffeexpr_expr_new_ -- Make a new internal expression object
ffeexprExpr_ e;
e = ffeexpr_expr_new_();
Allocates and initializes a new expression object, returns it. */
static ffeexprExpr_
ffeexpr_expr_new_ ()
{
ffeexprExpr_ e;
e = (ffeexprExpr_) malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR expr",
sizeof (*e));
e->previous = NULL;
e->type = FFEEXPR_exprtypeUNKNOWN_;
e->token = NULL;
return e;
}
/* Verify that call to global is valid, and register whatever
new information about a global might be discoverable by looking
at the call. */
static void
ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t)
{
int n_args;
ffebld list;
ffebld item;
ffesymbol s;
assert ((ffebld_op (*expr) == FFEBLD_opSUBRREF)
|| (ffebld_op (*expr) == FFEBLD_opFUNCREF));
if (ffebld_op (ffebld_left (*expr)) != FFEBLD_opSYMTER)
return;
if (ffesymbol_retractable ())
return;
s = ffebld_symter (ffebld_left (*expr));
if (ffesymbol_global (s) == NULL)
return;
for (n_args = 0, list = ffebld_right (*expr);
list != NULL;
list = ffebld_trail (list), ++n_args)
;
if (ffeglobal_proc_ref_nargs (s, n_args, t))
{
ffeglobalArgSummary as;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
bool array;
bool fail = FALSE;
for (n_args = 0, list = ffebld_right (*expr);
list != NULL;
list = ffebld_trail (list), ++n_args)
{
item = ffebld_head (list);
if (item != NULL)
{
bt = ffeinfo_basictype (ffebld_info (item));
kt = ffeinfo_kindtype (ffebld_info (item));
array = (ffeinfo_rank (ffebld_info (item)) > 0);
switch (ffebld_op (item))
{
case FFEBLD_opLABTOK:
case FFEBLD_opLABTER:
as = FFEGLOBAL_argsummaryALTRTN;
break;
#if 0
/* No, %LOC(foo) is just like any INTEGER(KIND=7)
expression, so don't treat it specially. */
case FFEBLD_opPERCENT_LOC:
as = FFEGLOBAL_argsummaryPTR;
break;
#endif
case FFEBLD_opPERCENT_VAL:
as = FFEGLOBAL_argsummaryVAL;
break;
case FFEBLD_opPERCENT_REF:
as = FFEGLOBAL_argsummaryREF;
break;
case FFEBLD_opPERCENT_DESCR:
as = FFEGLOBAL_argsummaryDESCR;
break;
case FFEBLD_opFUNCREF:
#if 0
/* No, LOC(foo) is just like any INTEGER(KIND=7)
expression, so don't treat it specially. */
if ((ffebld_op (ffebld_left (item)) == FFEBLD_opSYMTER)
&& (ffesymbol_specific (ffebld_symter (ffebld_left (item)))
== FFEINTRIN_specLOC))
{
as = FFEGLOBAL_argsummaryPTR;
break;
}
#endif
/* Fall through. */
default:
if (ffebld_op (item) == FFEBLD_opSYMTER)
{
as = FFEGLOBAL_argsummaryNONE;
switch (ffeinfo_kind (ffebld_info (item)))
{
case FFEINFO_kindFUNCTION:
as = FFEGLOBAL_argsummaryFUNC;
break;
case FFEINFO_kindSUBROUTINE:
as = FFEGLOBAL_argsummarySUBR;
break;
case FFEINFO_kindNONE:
as = FFEGLOBAL_argsummaryPROC;
break;
default:
break;
}
if (as != FFEGLOBAL_argsummaryNONE)
break;
}
if (bt == FFEINFO_basictypeCHARACTER)
as = FFEGLOBAL_argsummaryDESCR;
else
as = FFEGLOBAL_argsummaryREF;
break;
}
}
else
{
array = FALSE;
as = FFEGLOBAL_argsummaryNONE;
bt = FFEINFO_basictypeNONE;
kt = FFEINFO_kindtypeNONE;
}
if (! ffeglobal_proc_ref_arg (s, n_args, as, bt, kt, array, t))
fail = TRUE;
}
if (! fail)
return;
}
*expr = ffebld_new_any ();
ffebld_set_info (*expr, ffeinfo_new_any ());
}
/* Check whether rest of string is all decimal digits. */
static bool
ffeexpr_isdigits_ (const char *p)
1999-08-26 09:30:50 +00:00
{
for (; *p != '\0'; ++p)
if (! ISDIGIT (*p))
return FALSE;
return TRUE;
}
/* ffeexpr_exprstack_push_ -- Push an arbitrary expression object onto the stack
ffeexprExpr_ e;
ffeexpr_exprstack_push_(e);
Pushes the expression onto the stack without any analysis of the existing
contents of the stack. */
static void
ffeexpr_exprstack_push_ (ffeexprExpr_ e)
{
e->previous = ffeexpr_stack_->exprstack;
ffeexpr_stack_->exprstack = e;
}
/* ffeexpr_exprstack_push_operand_ -- Push an operand onto the stack, reduce?
ffeexprExpr_ e;
ffeexpr_exprstack_push_operand_(e);
Pushes the expression already containing an operand (a constant, variable,
or more complicated expression that has already been fully resolved) after
analyzing the stack and checking for possible reduction (which will never
happen here since the highest precedence operator is ** and it has right-
to-left associativity). */
static void
ffeexpr_exprstack_push_operand_ (ffeexprExpr_ e)
{
ffeexpr_exprstack_push_ (e);
#ifdef WEIRD_NONFORTRAN_RULES
if ((ffeexpr_stack_->exprstack != NULL)
&& (ffeexpr_stack_->exprstack->expr->type == FFEEXPR_exprtypeBINARY_)
&& (ffeexpr_stack_->exprstack->expr->u.operator.prec
== FFEEXPR_operatorprecedenceHIGHEST_)
&& (ffeexpr_stack_->exprstack->expr->u.operator.as
== FFEEXPR_operatorassociativityL2R_))
ffeexpr_reduce_ ();
#endif
}
/* ffeexpr_exprstack_push_unary_ -- Push a unary operator onto the stack
ffeexprExpr_ e;
ffeexpr_exprstack_push_unary_(e);
Pushes the expression already containing a unary operator. Reduction can
never happen since unary operators are themselves always R-L; that is, the
top of the expression stack is not an operand, in that it is either empty,
has a binary operator at the top, or a unary operator at the top. In any
of these cases, reduction is impossible. */
static void
ffeexpr_exprstack_push_unary_ (ffeexprExpr_ e)
{
if ((ffe_is_pedantic ()
|| ffe_is_warn_surprising ())
&& (ffeexpr_stack_->exprstack != NULL)
&& (ffeexpr_stack_->exprstack->type != FFEEXPR_exprtypeOPERAND_)
&& (ffeexpr_stack_->exprstack->u.operator.prec
<= FFEEXPR_operatorprecedenceLOWARITH_)
&& (e->u.operator.prec <= FFEEXPR_operatorprecedenceLOWARITH_))
{
ffebad_start_msg ("Two arithmetic operators in a row at %0 and %1 -- use parentheses",
ffe_is_pedantic ()
? FFEBAD_severityPEDANTIC
: FFEBAD_severityWARNING);
ffebad_here (0,
ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
ffebad_here (1,
ffelex_token_where_line (e->token),
ffelex_token_where_column (e->token));
ffebad_finish ();
}
ffeexpr_exprstack_push_ (e);
}
/* ffeexpr_exprstack_push_binary_ -- Push a binary operator onto the stack, reduce?
ffeexprExpr_ e;
ffeexpr_exprstack_push_binary_(e);
Pushes the expression already containing a binary operator after checking
whether reduction is possible. If the stack is not empty, the top of the
stack must be an operand or syntactic analysis has failed somehow. If
the operand is preceded by a unary operator of higher (or equal and L-R
associativity) precedence than the new binary operator, then reduce that
preceding operator and its operand(s) before pushing the new binary
operator. */
static void
ffeexpr_exprstack_push_binary_ (ffeexprExpr_ e)
{
ffeexprExpr_ ce;
if (ffe_is_warn_surprising ()
/* These next two are always true (see assertions below). */
&& (ffeexpr_stack_->exprstack != NULL)
&& (ffeexpr_stack_->exprstack->type == FFEEXPR_exprtypeOPERAND_)
/* If the previous operator is a unary minus, and the binary op
is of higher precedence, might not do what user expects,
e.g. "-2**2" is "-(2**2)", i.e. "-4", not "(-2)**2", which would
yield "4". */
&& (ffeexpr_stack_->exprstack->previous != NULL)
&& (ffeexpr_stack_->exprstack->previous->type == FFEEXPR_exprtypeUNARY_)
&& (ffeexpr_stack_->exprstack->previous->u.operator.op
== FFEEXPR_operatorSUBTRACT_)
&& (e->u.operator.prec
< ffeexpr_stack_->exprstack->previous->u.operator.prec))
{
ffebad_start_msg ("Operator at %0 has lower precedence than that at %1 -- use parentheses", FFEBAD_severityWARNING);
ffebad_here (0,
ffelex_token_where_line (ffeexpr_stack_->exprstack->previous->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->previous->token));
ffebad_here (1,
ffelex_token_where_line (e->token),
ffelex_token_where_column (e->token));
ffebad_finish ();
}
again:
assert (ffeexpr_stack_->exprstack != NULL);
assert (ffeexpr_stack_->exprstack->type == FFEEXPR_exprtypeOPERAND_);
if ((ce = ffeexpr_stack_->exprstack->previous) != NULL)
{
assert (ce->type != FFEEXPR_exprtypeOPERAND_);
if ((ce->u.operator.prec < e->u.operator.prec)
|| ((ce->u.operator.prec == e->u.operator.prec)
&& (e->u.operator.as == FFEEXPR_operatorassociativityL2R_)))
{
ffeexpr_reduce_ ();
goto again; /* :::::::::::::::::::: */
}
}
ffeexpr_exprstack_push_ (e);
}
/* ffeexpr_reduce_ -- Reduce highest operator w/operands on stack
ffeexpr_reduce_();
Converts operand binop operand or unop operand at top of stack to a
single operand having the appropriate ffebld expression, and makes
sure that the expression is proper (like not trying to add two character
variables, not trying to concatenate two numbers). Also does the
requisite type-assignment. */
static void
ffeexpr_reduce_ ()
{
ffeexprExpr_ operand; /* This is B in -B or A+B. */
ffeexprExpr_ left_operand; /* When operator is binary, this is A in A+B. */
ffeexprExpr_ operator; /* This is + in A+B. */
ffebld reduced; /* This is +(A,B) in A+B or u-(B) in -B. */
ffebldConstant constnode; /* For checking magical numbers (where mag ==
-mag). */
ffebld expr;
ffebld left_expr;
bool submag = FALSE;
operand = ffeexpr_stack_->exprstack;
assert (operand != NULL);
assert (operand->type == FFEEXPR_exprtypeOPERAND_);
operator = operand->previous;
assert (operator != NULL);
assert (operator->type != FFEEXPR_exprtypeOPERAND_);
if (operator->type == FFEEXPR_exprtypeUNARY_)
{
expr = operand->u.operand;
switch (operator->u.operator.op)
{
case FFEEXPR_operatorADD_:
reduced = ffebld_new_uplus (expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand);
reduced = ffeexpr_reduced_math1_ (reduced, operator, operand);
reduced = ffeexpr_collapse_uplus (reduced, operator->token);
break;
case FFEEXPR_operatorSUBTRACT_:
submag = TRUE; /* Ok to negate a magic number. */
reduced = ffebld_new_uminus (expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand);
reduced = ffeexpr_reduced_math1_ (reduced, operator, operand);
reduced = ffeexpr_collapse_uminus (reduced, operator->token);
break;
case FFEEXPR_operatorNOT_:
reduced = ffebld_new_not (expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly1log_ (reduced, operator, operand);
reduced = ffeexpr_reduced_bool1_ (reduced, operator, operand);
reduced = ffeexpr_collapse_not (reduced, operator->token);
break;
default:
assert ("unexpected unary op" != NULL);
reduced = NULL;
break;
}
if (!submag
&& (ffebld_op (expr) == FFEBLD_opCONTER)
&& (ffebld_conter_orig (expr) == NULL)
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
{
ffetarget_integer_bad_magical (operand->token);
}
ffeexpr_stack_->exprstack = operator->previous; /* Pops unary-op operand
off stack. */
ffeexpr_expr_kill_ (operand);
operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but
save */
operator->u.operand = reduced; /* the line/column ffewhere info. */
ffeexpr_exprstack_push_operand_ (operator); /* Push it back on
stack. */
}
else
{
assert (operator->type == FFEEXPR_exprtypeBINARY_);
left_operand = operator->previous;
assert (left_operand != NULL);
assert (left_operand->type == FFEEXPR_exprtypeOPERAND_);
expr = operand->u.operand;
left_expr = left_operand->u.operand;
switch (operator->u.operator.op)
{
case FFEEXPR_operatorADD_:
reduced = ffebld_new_add (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_add (reduced, operator->token);
break;
case FFEEXPR_operatorSUBTRACT_:
submag = TRUE; /* Just to pick the right error if magic
number. */
reduced = ffebld_new_subtract (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_subtract (reduced, operator->token);
break;
case FFEEXPR_operatorMULTIPLY_:
reduced = ffebld_new_multiply (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_multiply (reduced, operator->token);
break;
case FFEEXPR_operatorDIVIDE_:
reduced = ffebld_new_divide (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_divide (reduced, operator->token);
break;
case FFEEXPR_operatorPOWER_:
reduced = ffebld_new_power (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_power_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_power (reduced, operator->token);
break;
case FFEEXPR_operatorCONCATENATE_:
reduced = ffebld_new_concatenate (left_expr, expr);
reduced = ffeexpr_reduced_concatenate_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_concatenate (reduced, operator->token);
break;
case FFEEXPR_operatorLT_:
reduced = ffebld_new_lt (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_lt (reduced, operator->token);
break;
case FFEEXPR_operatorLE_:
reduced = ffebld_new_le (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_le (reduced, operator->token);
break;
case FFEEXPR_operatorEQ_:
reduced = ffebld_new_eq (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_eq (reduced, operator->token);
break;
case FFEEXPR_operatorNE_:
reduced = ffebld_new_ne (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_ne (reduced, operator->token);
break;
case FFEEXPR_operatorGT_:
reduced = ffebld_new_gt (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_gt (reduced, operator->token);
break;
case FFEEXPR_operatorGE_:
reduced = ffebld_new_ge (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_ge (reduced, operator->token);
break;
case FFEEXPR_operatorAND_:
reduced = ffebld_new_and (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_and (reduced, operator->token);
break;
case FFEEXPR_operatorOR_:
reduced = ffebld_new_or (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_or (reduced, operator->token);
break;
case FFEEXPR_operatorXOR_:
reduced = ffebld_new_xor (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_xor (reduced, operator->token);
break;
case FFEEXPR_operatorEQV_:
reduced = ffebld_new_eqv (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_eqv (reduced, operator->token);
break;
case FFEEXPR_operatorNEQV_:
reduced = ffebld_new_neqv (left_expr, expr);
if (ffe_is_ugly_logint ())
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
operand);
reduced = ffeexpr_collapse_neqv (reduced, operator->token);
break;
default:
assert ("bad bin op" == NULL);
reduced = expr;
break;
}
if ((ffebld_op (left_expr) == FFEBLD_opCONTER)
&& (ffebld_conter_orig (expr) == NULL)
&& ffebld_constant_is_magical (constnode = ffebld_conter (left_expr)))
{
if ((left_operand->previous != NULL)
&& (left_operand->previous->type != FFEEXPR_exprtypeOPERAND_)
&& (left_operand->previous->u.operator.op
== FFEEXPR_operatorSUBTRACT_))
{
if (left_operand->previous->type == FFEEXPR_exprtypeUNARY_)
ffetarget_integer_bad_magical_precedence (left_operand->token,
left_operand->previous->token,
operator->token);
else
ffetarget_integer_bad_magical_precedence_binary
(left_operand->token,
left_operand->previous->token,
operator->token);
}
else
ffetarget_integer_bad_magical (left_operand->token);
}
if ((ffebld_op (expr) == FFEBLD_opCONTER)
&& (ffebld_conter_orig (expr) == NULL)
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
{
if (submag)
ffetarget_integer_bad_magical_binary (operand->token,
operator->token);
else
ffetarget_integer_bad_magical (operand->token);
}
ffeexpr_stack_->exprstack = left_operand->previous; /* Pops binary-op
operands off stack. */
ffeexpr_expr_kill_ (left_operand);
ffeexpr_expr_kill_ (operand);
operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but
save */
operator->u.operand = reduced; /* the line/column ffewhere info. */
ffeexpr_exprstack_push_operand_ (operator); /* Push it back on
stack. */
}
}
/* ffeexpr_reduced_bool1_ -- Wrap up reduction of NOT operator
reduced = ffeexpr_reduced_bool1_(reduced,op,r);
Makes sure the argument for reduced has basictype of
LOGICAL or (ugly) INTEGER. If
argument has where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
{
ffeinfo rinfo, ninfo;
ffeinfoBasictype rbt;
ffeinfoKindtype rkt;
ffeinfoRank rrk;
ffeinfoKind rkd;
ffeinfoWhere rwh, nwh;
rinfo = ffebld_info (ffebld_left (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if (((rbt == FFEINFO_basictypeLOGICAL)
|| (ffe_is_ugly_logint () && (rbt == FFEINFO_basictypeINTEGER)))
&& (rrk == 0))
{
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh,
FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
return reduced;
}
if ((rbt != FFEINFO_basictypeLOGICAL)
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_NOT_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_NOT_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_bool2_ -- Wrap up reduction of boolean operators
reduced = ffeexpr_reduced_bool2_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
LOGICAL or (ugly) INTEGER. Determine common basictype and
size for reduction (flag expression for combined hollerith/typeless
situations for later determination of effective basictype). If both left
and right arguments have where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING. Create CONVERT ops for args where
needed. Convert typeless
constants to the desired type/size explicitly.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh, nwh;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
if (((nbt == FFEINFO_basictypeLOGICAL)
|| (ffe_is_ugly_logint () && (nbt == FFEINFO_basictypeINTEGER)))
&& (lrk == 0) && (rrk == 0))
{
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
return reduced;
}
if ((lbt != FFEINFO_basictypeLOGICAL)
&& (!ffe_is_ugly_logint () || (lbt != FFEINFO_basictypeINTEGER)))
{
if ((rbt != FFEINFO_basictypeLOGICAL)
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_BOOL_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_BOOL_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
}
else if ((rbt != FFEINFO_basictypeLOGICAL)
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_BOOL_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lrk != 0)
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_BOOL_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_BOOL_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_concatenate_ -- Wrap up reduction of concatenate operator
reduced = ffeexpr_reduced_concatenate_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
CHARACTER and kind of SCALAR, FUNCTION, or STATEMENT FUNCTION. Assign
basictype of CHARACTER and kind of SCALAR to reduced. Calculate effective
size of concatenation and assign that size to reduced. If both left and
right arguments have where of CONSTANT, assign where CONSTANT to reduced,
else assign where FLEETING.
If these requirements cannot be met, generate error message using the
info in l, op, and r arguments and assign basictype, size, kind, and where
of ANY. */
static ffebld
ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd, nkd;
ffeinfoWhere lwh, rwh, nwh;
ffetargetCharacterSize lszm, lszk, rszm, rszk, nszk;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
lszk = ffeinfo_size (linfo); /* Known size. */
lszm = ffebld_size_max (ffebld_left (reduced));
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
rszk = ffeinfo_size (rinfo); /* Known size. */
rszm = ffebld_size_max (ffebld_right (reduced));
if ((lbt == FFEINFO_basictypeCHARACTER) && (rbt == FFEINFO_basictypeCHARACTER)
&& (lkt == rkt) && (lrk == 0) && (rrk == 0)
&& (((lszm != FFETARGET_charactersizeNONE)
&& (rszm != FFETARGET_charactersizeNONE))
|| (ffeexpr_context_outer_ (ffeexpr_stack_)
== FFEEXPR_contextLET)
|| (ffeexpr_context_outer_ (ffeexpr_stack_)
== FFEEXPR_contextSFUNCDEF)))
{
nbt = FFEINFO_basictypeCHARACTER;
nkd = FFEINFO_kindENTITY;
if ((lszk == FFETARGET_charactersizeNONE)
|| (rszk == FFETARGET_charactersizeNONE))
nszk = FFETARGET_charactersizeNONE; /* Ok only in rhs of LET
stmt. */
else
nszk = lszk + rszk;
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
nkt = lkt;
ninfo = ffeinfo_new (nbt, nkt, 0, nkd, nwh, nszk);
ffebld_set_info (reduced, ninfo);
return reduced;
}
if ((lbt != FFEINFO_basictypeCHARACTER) && (rbt != FFEINFO_basictypeCHARACTER))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_CONCAT_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lbt != FFEINFO_basictypeCHARACTER)
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_CONCAT_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
else if (rbt != FFEINFO_basictypeCHARACTER)
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_CONCAT_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if ((lrk != 0) || (lszm == FFETARGET_charactersizeNONE))
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_CONCAT_ARG_KIND))
{
const char *what;
1999-08-26 09:30:50 +00:00
if (lrk != 0)
what = "an array";
else
what = "of indeterminate length";
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string (what);
ffebad_finish ();
}
}
else
{
if (ffebad_start (FFEBAD_CONCAT_ARG_KIND))
{
const char *what;
1999-08-26 09:30:50 +00:00
if (rrk != 0)
what = "an array";
else
what = "of indeterminate length";
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string (what);
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_eqop2_ -- Wrap up reduction of EQ and NE operators
reduced = ffeexpr_reduced_eqop2_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
INTEGER, REAL, COMPLEX, or CHARACTER. Determine common basictype and
size for reduction. If both left
and right arguments have where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING. Create CONVERT ops for args where
needed. Convert typeless
constants to the desired type/size explicitly.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_eqop2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh, nwh;
ffetargetCharacterSize lsz, rsz;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
lsz = ffebld_size_known (ffebld_left (reduced));
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
rsz = ffebld_size_known (ffebld_right (reduced));
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|| (nbt == FFEINFO_basictypeCOMPLEX) || (nbt == FFEINFO_basictypeCHARACTER))
&& (lrk == 0) && (rrk == 0))
{
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
if ((lsz != FFETARGET_charactersizeNONE)
&& (rsz != FFETARGET_charactersizeNONE))
lsz = rsz = (lsz > rsz) ? lsz : rsz;
ninfo = ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
0, FFEINFO_kindENTITY, nwh, FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, nbt, nkt, 0, lsz,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, nbt, nkt, 0, rsz,
FFEEXPR_contextLET));
return reduced;
}
if ((lbt == FFEINFO_basictypeLOGICAL)
&& (rbt == FFEINFO_basictypeLOGICAL))
{
if (ffebad_start_msg ("Use .EQV./.NEQV. instead of .EQ./.NE. at %0 for LOGICAL operands at %1 and %2",
FFEBAD_severityFATAL))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
&& (lbt != FFEINFO_basictypeCOMPLEX) && (lbt != FFEINFO_basictypeCHARACTER))
{
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_EQOP_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_EQOP_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
}
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_EQOP_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lrk != 0)
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_EQOP_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_EQOP_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_math1_ -- Wrap up reduction of + - unary operators
reduced = ffeexpr_reduced_math1_(reduced,op,r);
Makes sure the argument for reduced has basictype of
INTEGER, REAL, or COMPLEX. If the argument has where of CONSTANT,
assign where CONSTANT to
reduced, else assign where FLEETING.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
{
ffeinfo rinfo, ninfo;
ffeinfoBasictype rbt;
ffeinfoKindtype rkt;
ffeinfoRank rrk;
ffeinfoKind rkd;
ffeinfoWhere rwh, nwh;
rinfo = ffebld_info (ffebld_left (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if (((rbt == FFEINFO_basictypeINTEGER) || (rbt == FFEINFO_basictypeREAL)
|| (rbt == FFEINFO_basictypeCOMPLEX)) && (rrk == 0))
{
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh,
FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
return reduced;
}
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCOMPLEX))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_math2_ -- Wrap up reduction of + - * / operators
reduced = ffeexpr_reduced_math2_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
INTEGER, REAL, or COMPLEX. Determine common basictype and
size for reduction (flag expression for combined hollerith/typeless
situations for later determination of effective basictype). If both left
and right arguments have where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING. Create CONVERT ops for args where
needed. Convert typeless
constants to the desired type/size explicitly.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh, nwh;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|| (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0))
{
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
return reduced;
}
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
&& (lbt != FFEINFO_basictypeCOMPLEX))
{
if ((rbt != FFEINFO_basictypeINTEGER)
&& (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
}
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCOMPLEX))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lrk != 0)
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_power_ -- Wrap up reduction of ** operator
reduced = ffeexpr_reduced_power_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
INTEGER, REAL, or COMPLEX. Determine common basictype and
size for reduction (flag expression for combined hollerith/typeless
situations for later determination of effective basictype). If both left
and right arguments have where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING. Create CONVERT ops for args where
needed. Note that real**int or complex**int
comes out as int = real**int etc with no conversions.
If these requirements cannot be met, generate error message using the
info in l, op, and r arguments and assign basictype, size, kind, and where
of ANY. */
static ffebld
ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh, nwh;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if ((rbt == FFEINFO_basictypeINTEGER)
&& ((lbt == FFEINFO_basictypeREAL)
|| (lbt == FFEINFO_basictypeCOMPLEX)))
{
nbt = lbt;
nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDEFAULT);
if (nkt != FFEINFO_kindtypeREALDEFAULT)
{
nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDOUBLE);
if (nkt != FFEINFO_kindtypeREALDOUBLE)
nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */
}
if (rkt == FFEINFO_kindtypeINTEGER4)
{
ffebad_start_msg ("Unsupported operand for ** at %1 -- converting to default INTEGER",
FFEBAD_severityWARNING);
ffebad_here (0, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
if (rkt != FFEINFO_kindtypeINTEGERDEFAULT)
{
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token,
FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
rkt = FFEINFO_kindtypeINTEGERDEFAULT;
}
}
else
{
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
#if 0 /* INTEGER4**INTEGER4 works now. */
if ((nbt == FFEINFO_basictypeINTEGER)
&& (nkt != FFEINFO_kindtypeINTEGERDEFAULT))
nkt = FFEINFO_kindtypeINTEGERDEFAULT; /* Highest kt we can power! */
#endif
if (((nbt == FFEINFO_basictypeREAL)
|| (nbt == FFEINFO_basictypeCOMPLEX))
&& (nkt != FFEINFO_kindtypeREALDEFAULT))
{
nkt = ffeinfo_kindtype_max (nbt, nkt, FFEINFO_kindtypeREALDOUBLE);
if (nkt != FFEINFO_kindtypeREALDOUBLE)
nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */
}
/* else Gonna turn into an error below. */
}
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|| (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0))
{
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
if (rbt != FFEINFO_basictypeINTEGER)
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
return reduced;
}
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
&& (lbt != FFEINFO_basictypeCOMPLEX))
{
if ((rbt != FFEINFO_basictypeINTEGER)
&& (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
}
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCOMPLEX))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lrk != 0)
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_relop2_ -- Wrap up reduction of LT, LE, GE, and GT operators
reduced = ffeexpr_reduced_relop2_(reduced,l,op,r);
Makes sure the left and right arguments for reduced have basictype of
INTEGER, REAL, or CHARACTER. Determine common basictype and
size for reduction. If both left
and right arguments have where of CONSTANT, assign where CONSTANT to
reduced, else assign where FLEETING. Create CONVERT ops for args where
needed. Convert typeless
constants to the desired type/size explicitly.
If these requirements cannot be met, generate error message. */
static ffebld
ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo, ninfo;
ffeinfoBasictype lbt, rbt, nbt;
ffeinfoKindtype lkt, rkt, nkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh, nwh;
ffetargetCharacterSize lsz, rsz;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
lsz = ffebld_size_known (ffebld_left (reduced));
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
rsz = ffebld_size_known (ffebld_right (reduced));
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|| (nbt == FFEINFO_basictypeCHARACTER))
&& (lrk == 0) && (rrk == 0))
{
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
nwh = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
nwh = FFEINFO_whereIMMEDIATE;
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
break;
default:
nwh = FFEINFO_whereFLEETING;
break;
}
if ((lsz != FFETARGET_charactersizeNONE)
&& (rsz != FFETARGET_charactersizeNONE))
lsz = rsz = (lsz > rsz) ? lsz : rsz;
ninfo = ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
0, FFEINFO_kindENTITY, nwh, FFETARGET_charactersizeNONE);
ffebld_set_info (reduced, ninfo);
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, nbt, nkt, 0, lsz,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, nbt, nkt, 0, rsz,
FFEEXPR_contextLET));
return reduced;
}
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
&& (lbt != FFEINFO_basictypeCHARACTER))
{
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCHARACTER))
{
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_RELOP_ARGS_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else
{
if ((lbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_RELOP_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_finish ();
}
}
}
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
&& (rbt != FFEINFO_basictypeCHARACTER))
{
if ((rbt != FFEINFO_basictypeANY)
&& ffebad_start (FFEBAD_RELOP_ARG_TYPE))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_finish ();
}
}
else if (lrk != 0)
{
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_RELOP_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
else
{
if ((rkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_RELOP_ARG_KIND))
{
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
ffebad_string ("an array");
ffebad_finish ();
}
}
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
return reduced;
}
/* ffeexpr_reduced_ugly1_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL
reduced = ffeexpr_reduced_ugly1_(reduced,op,r);
Sigh. */
static ffebld
ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
{
ffeinfo rinfo;
ffeinfoBasictype rbt;
ffeinfoKindtype rkt;
ffeinfoRank rrk;
ffeinfoKind rkd;
ffeinfoWhere rwh;
rinfo = ffebld_info (ffebld_left (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
r->token, op->token, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
rinfo = ffebld_info (ffebld_left (reduced));
rbt = FFEINFO_basictypeINTEGER;
rkt = FFEINFO_kindtypeINTEGERDEFAULT;
rrk = 0;
rkd = FFEINFO_kindENTITY;
rwh = ffeinfo_where (rinfo);
}
if (rbt == FFEINFO_basictypeLOGICAL)
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
r->token, op->token, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
}
return reduced;
}
/* ffeexpr_reduced_ugly1log_ -- Deal with TYPELESS and HOLLERITH
reduced = ffeexpr_reduced_ugly1log_(reduced,op,r);
Sigh. */
static ffebld
ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
{
ffeinfo rinfo;
ffeinfoBasictype rbt;
ffeinfoKindtype rkt;
ffeinfoRank rrk;
ffeinfoKind rkd;
ffeinfoWhere rwh;
rinfo = ffebld_info (ffebld_left (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
r->token, op->token, FFEINFO_basictypeLOGICAL, 0,
FFEINFO_kindtypeLOGICALDEFAULT,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
rinfo = ffebld_info (ffebld_left (reduced));
rbt = FFEINFO_basictypeLOGICAL;
rkt = FFEINFO_kindtypeLOGICALDEFAULT;
rrk = 0;
rkd = FFEINFO_kindENTITY;
rwh = ffeinfo_where (rinfo);
}
return reduced;
}
/* ffeexpr_reduced_ugly2_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL
reduced = ffeexpr_reduced_ugly2_(reduced,l,op,r);
Sigh. */
static ffebld
ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo;
ffeinfoBasictype lbt, rbt;
ffeinfoKindtype lkt, rkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if ((lbt == FFEINFO_basictypeTYPELESS)
|| (lbt == FFEINFO_basictypeHOLLERITH))
{
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, FFEINFO_basictypeINTEGER, 0,
FFEINFO_kindtypeINTEGERDEFAULT,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
linfo = ffebld_info (ffebld_left (reduced));
rinfo = ffebld_info (ffebld_right (reduced));
lbt = rbt = FFEINFO_basictypeINTEGER;
lkt = rkt = FFEINFO_kindtypeINTEGERDEFAULT;
lrk = rrk = 0;
lkd = rkd = FFEINFO_kindENTITY;
lwh = ffeinfo_where (linfo);
rwh = ffeinfo_where (rinfo);
}
else
{
ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced),
l->token, ffebld_right (reduced), r->token,
FFEEXPR_contextLET));
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
}
}
else
{
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced),
r->token, ffebld_left (reduced), l->token,
FFEEXPR_contextLET));
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
}
/* else Leave it alone. */
}
if (lbt == FFEINFO_basictypeLOGICAL)
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
}
if (rbt == FFEINFO_basictypeLOGICAL)
{
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
}
return reduced;
}
/* ffeexpr_reduced_ugly2log_ -- Deal with TYPELESS and HOLLERITH
reduced = ffeexpr_reduced_ugly2log_(reduced,l,op,r);
Sigh. */
static ffebld
ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
ffeexprExpr_ r)
{
ffeinfo linfo, rinfo;
ffeinfoBasictype lbt, rbt;
ffeinfoKindtype lkt, rkt;
ffeinfoRank lrk, rrk;
ffeinfoKind lkd, rkd;
ffeinfoWhere lwh, rwh;
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
if ((lbt == FFEINFO_basictypeTYPELESS)
|| (lbt == FFEINFO_basictypeHOLLERITH))
{
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
l->token, op->token, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
r->token, op->token, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET));
linfo = ffebld_info (ffebld_left (reduced));
rinfo = ffebld_info (ffebld_right (reduced));
lbt = rbt = FFEINFO_basictypeLOGICAL;
lkt = rkt = FFEINFO_kindtypeLOGICALDEFAULT;
lrk = rrk = 0;
lkd = rkd = FFEINFO_kindENTITY;
lwh = ffeinfo_where (linfo);
rwh = ffeinfo_where (rinfo);
}
else
{
ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced),
l->token, ffebld_right (reduced), r->token,
FFEEXPR_contextLET));
linfo = ffebld_info (ffebld_left (reduced));
lbt = ffeinfo_basictype (linfo);
lkt = ffeinfo_kindtype (linfo);
lrk = ffeinfo_rank (linfo);
lkd = ffeinfo_kind (linfo);
lwh = ffeinfo_where (linfo);
}
}
else
{
if ((rbt == FFEINFO_basictypeTYPELESS)
|| (rbt == FFEINFO_basictypeHOLLERITH))
{
ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced),
r->token, ffebld_left (reduced), l->token,
FFEEXPR_contextLET));
rinfo = ffebld_info (ffebld_right (reduced));
rbt = ffeinfo_basictype (rinfo);
rkt = ffeinfo_kindtype (rinfo);
rrk = ffeinfo_rank (rinfo);
rkd = ffeinfo_kind (rinfo);
rwh = ffeinfo_where (rinfo);
}
/* else Leave it alone. */
}
return reduced;
}
/* Fumble through tokens until a nonmatching CLOSE_PAREN, EOS, or SEMICOLON
is found.
The idea is to process the tokens as they would be done by normal
expression processing, with the key things being telling the lexer
when hollerith/character constants are about to happen, until the
true closing token is found. */
static ffelexHandler
ffeexpr_find_close_paren_ (ffelexToken t,
ffelexHandler after)
{
ffeexpr_find_.after = after;
ffeexpr_find_.level = 1;
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
}
static ffelexHandler
ffeexpr_nil_finished_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeCLOSE_PAREN:
if (--ffeexpr_find_.level == 0)
return (ffelexHandler) ffeexpr_find_.after;
return (ffelexHandler) ffeexpr_nil_binary_;
case FFELEX_typeCOMMA:
case FFELEX_typeCOLON:
case FFELEX_typeEQUALS:
case FFELEX_typePOINTS:
return (ffelexHandler) ffeexpr_nil_rhs_;
default:
if (--ffeexpr_find_.level == 0)
return (ffelexHandler) ffeexpr_find_.after (t);
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
}
}
static ffelexHandler
ffeexpr_nil_rhs_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeQUOTE:
if (ffe_is_vxt ())
return (ffelexHandler) ffeexpr_nil_quote_;
ffelex_set_expecting_hollerith (-1, '\"',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
return (ffelexHandler) ffeexpr_nil_apostrophe_;
case FFELEX_typeAPOSTROPHE:
ffelex_set_expecting_hollerith (-1, '\'',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
return (ffelexHandler) ffeexpr_nil_apostrophe_;
case FFELEX_typePERCENT:
return (ffelexHandler) ffeexpr_nil_percent_;
case FFELEX_typeOPEN_PAREN:
++ffeexpr_find_.level;
return (ffelexHandler) ffeexpr_nil_rhs_;
case FFELEX_typePLUS:
case FFELEX_typeMINUS:
return (ffelexHandler) ffeexpr_nil_rhs_;
case FFELEX_typePERIOD:
return (ffelexHandler) ffeexpr_nil_period_;
case FFELEX_typeNUMBER:
ffeexpr_hollerith_count_ = atol (ffelex_token_text (t));
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_,
'\0',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
return (ffelexHandler) ffeexpr_nil_number_;
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
return (ffelexHandler) ffeexpr_nil_name_rhs_;
case FFELEX_typeASTERISK:
case FFELEX_typeSLASH:
case FFELEX_typePOWER:
case FFELEX_typeCONCAT:
case FFELEX_typeREL_EQ:
case FFELEX_typeREL_NE:
case FFELEX_typeREL_LE:
case FFELEX_typeREL_GE:
return (ffelexHandler) ffeexpr_nil_rhs_;
default:
return (ffelexHandler) ffeexpr_nil_finished_ (t);
}
}
static ffelexHandler
ffeexpr_nil_period_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_current_dotdot_ = ffestr_other (t);
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherNone:
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
case FFESTR_otherTRUE:
case FFESTR_otherFALSE:
case FFESTR_otherNOT:
return (ffelexHandler) ffeexpr_nil_end_period_;
default:
return (ffelexHandler) ffeexpr_nil_swallow_period_;
}
break; /* Nothing really reaches here. */
case FFELEX_typeNUMBER:
return (ffelexHandler) ffeexpr_nil_real_;
default:
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
}
}
static ffelexHandler
ffeexpr_nil_end_period_ (ffelexToken t)
{
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherNOT:
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
return (ffelexHandler) ffeexpr_nil_rhs_;
case FFESTR_otherTRUE:
case FFESTR_otherFALSE:
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
default:
assert ("Bad [nil] unary dotdot in ffeexpr_current_dotdot_" == NULL);
exit (0);
return NULL;
}
}
static ffelexHandler
ffeexpr_nil_swallow_period_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
return (ffelexHandler) ffeexpr_nil_rhs_;
}
static ffelexHandler
ffeexpr_nil_real_ (ffelexToken t)
{
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q')))
&& ffeexpr_isdigits_ (++p)))
return (ffelexHandler) ffeexpr_nil_binary_ (t);
if (*p == '\0')
return (ffelexHandler) ffeexpr_nil_real_exponent_;
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_real_exponent_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_real_exp_sign_;
}
static ffelexHandler
ffeexpr_nil_real_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_number_ (ffelexToken t)
{
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (0, '\0',
ffewhere_line_unknown (),
ffewhere_column_unknown ());
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q'))
&& ffeexpr_isdigits_ (++p))
{
if (*p == '\0')
{
ffeexpr_find_.t = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_nil_number_exponent_;
}
return (ffelexHandler) ffeexpr_nil_binary_;
}
break;
case FFELEX_typePERIOD:
ffeexpr_find_.t = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_nil_number_period_;
case FFELEX_typeHOLLERITH:
return (ffelexHandler) ffeexpr_nil_binary_;
default:
break;
}
return (ffelexHandler) ffeexpr_nil_binary_ (t);
}
/* Expects ffeexpr_find_.t. */
static ffelexHandler
ffeexpr_nil_number_exponent_ (ffelexToken t)
{
ffelexHandler nexthandler;
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
nexthandler
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) (*nexthandler) (t);
}
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) ffeexpr_nil_number_exp_sign_;
}
static ffelexHandler
ffeexpr_nil_number_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
/* Expects ffeexpr_find_.t. */
static ffelexHandler
ffeexpr_nil_number_period_ (ffelexToken t)
{
ffelexHandler nexthandler;
char d;
const char *p;
1999-08-26 09:30:50 +00:00
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q'))
&& ffeexpr_isdigits_ (++p))
{
if (*p == '\0')
return (ffelexHandler) ffeexpr_nil_number_per_exp_;
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
nexthandler
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) (*nexthandler) (t);
case FFELEX_typeNUMBER:
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) ffeexpr_nil_number_real_;
default:
break;
}
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) ffeexpr_nil_binary_ (t);
}
/* Expects ffeexpr_find_.t. */
static ffelexHandler
ffeexpr_nil_number_per_exp_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
ffelexHandler nexthandler;
nexthandler
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) (*nexthandler) (t);
}
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) ffeexpr_nil_num_per_exp_sign_;
}
static ffelexHandler
ffeexpr_nil_number_real_ (ffelexToken t)
{
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q')))
&& ffeexpr_isdigits_ (++p)))
return (ffelexHandler) ffeexpr_nil_binary_ (t);
if (*p == '\0')
return (ffelexHandler) ffeexpr_nil_number_real_exp_;
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_num_per_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_number_real_exp_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_num_real_exp_sn_;
}
static ffelexHandler
ffeexpr_nil_num_real_exp_sn_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_binary_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typePLUS:
case FFELEX_typeMINUS:
case FFELEX_typeASTERISK:
case FFELEX_typeSLASH:
case FFELEX_typePOWER:
case FFELEX_typeCONCAT:
case FFELEX_typeOPEN_ANGLE:
case FFELEX_typeCLOSE_ANGLE:
case FFELEX_typeREL_EQ:
case FFELEX_typeREL_NE:
case FFELEX_typeREL_GE:
case FFELEX_typeREL_LE:
return (ffelexHandler) ffeexpr_nil_rhs_;
case FFELEX_typePERIOD:
return (ffelexHandler) ffeexpr_nil_binary_period_;
default:
return (ffelexHandler) ffeexpr_nil_finished_ (t);
}
}
static ffelexHandler
ffeexpr_nil_binary_period_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_current_dotdot_ = ffestr_other (t);
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherTRUE:
case FFESTR_otherFALSE:
case FFESTR_otherNOT:
return (ffelexHandler) ffeexpr_nil_binary_sw_per_;
default:
return (ffelexHandler) ffeexpr_nil_binary_end_per_;
}
break; /* Nothing really reaches here. */
default:
return (ffelexHandler) ffeexpr_nil_binary_ (t);
}
}
static ffelexHandler
ffeexpr_nil_binary_end_per_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
return (ffelexHandler) ffeexpr_nil_rhs_;
}
static ffelexHandler
ffeexpr_nil_binary_sw_per_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_quote_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
return (ffelexHandler) ffeexpr_nil_binary_;
}
static ffelexHandler
ffeexpr_nil_apostrophe_ (ffelexToken t)
{
assert (ffelex_token_type (t) == FFELEX_typeCHARACTER);
return (ffelexHandler) ffeexpr_nil_apos_char_;
}
static ffelexHandler
ffeexpr_nil_apos_char_ (ffelexToken t)
{
char c;
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
{
if ((ffelex_token_length (t) == 1)
&& (ffesrc_char_match_init ((c = ffelex_token_text (t)[0]),
'B', 'b')
|| ffesrc_char_match_init (c, 'O', 'o')
|| ffesrc_char_match_init (c, 'X', 'x')
|| ffesrc_char_match_init (c, 'Z', 'z')))
return (ffelexHandler) ffeexpr_nil_binary_;
}
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
return (ffelexHandler) ffeexpr_nil_substrp_ (t);
}
static ffelexHandler
ffeexpr_nil_name_rhs_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeQUOTE:
case FFELEX_typeAPOSTROPHE:
ffelex_set_hexnum (TRUE);
return (ffelexHandler) ffeexpr_nil_name_apos_;
case FFELEX_typeOPEN_PAREN:
++ffeexpr_find_.level;
return (ffelexHandler) ffeexpr_nil_rhs_;
default:
return (ffelexHandler) ffeexpr_nil_binary_ (t);
}
}
static ffelexHandler
ffeexpr_nil_name_apos_ (ffelexToken t)
{
if (ffelex_token_type (t) == FFELEX_typeNAME)
return (ffelexHandler) ffeexpr_nil_name_apos_name_;
return (ffelexHandler) ffeexpr_nil_binary_ (t);
}
static ffelexHandler
ffeexpr_nil_name_apos_name_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeAPOSTROPHE:
case FFELEX_typeQUOTE:
return (ffelexHandler) ffeexpr_nil_finished_;
default:
return (ffelexHandler) ffeexpr_nil_finished_ (t);
}
}
static ffelexHandler
ffeexpr_nil_percent_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_stack_->percent = ffeexpr_percent_ (t);
ffeexpr_find_.t = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_nil_percent_name_;
default:
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
}
}
/* Expects ffeexpr_find_.t. */
static ffelexHandler
ffeexpr_nil_percent_name_ (ffelexToken t)
{
ffelexHandler nexthandler;
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
{
nexthandler
= (ffelexHandler) ffeexpr_nil_rhs_ (ffeexpr_find_.t);
ffelex_token_kill (ffeexpr_find_.t);
return (ffelexHandler) (*nexthandler) (t);
}
ffelex_token_kill (ffeexpr_find_.t);
++ffeexpr_find_.level;
return (ffelexHandler) ffeexpr_nil_rhs_;
}
static ffelexHandler
ffeexpr_nil_substrp_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
return (ffelexHandler) ffeexpr_nil_binary_ (t);
++ffeexpr_find_.level;
return (ffelexHandler) ffeexpr_nil_rhs_;
}
/* ffeexpr_finished_ -- Reduce expression stack to one expr, finish
ffelexToken t;
return ffeexpr_finished_(t);
Reduces expression stack to one (or zero) elements by repeatedly reducing
the top operator on the stack (or, if the top element on the stack is
itself an operator, issuing an error message and discarding it). Calls
finishing routine with the expression, returning the ffelexHandler it
returns to the caller. */
static ffelexHandler
ffeexpr_finished_ (ffelexToken t)
{
ffeexprExpr_ operand; /* This is B in -B or A+B. */
ffebld expr;
ffeexprCallback callback;
ffeexprStack_ s;
ffebldConstant constnode; /* For detecting magical number. */
ffelexToken ft; /* Temporary copy of first token in
expression. */
ffelexHandler next;
ffeinfo info;
bool error = FALSE;
while (((operand = ffeexpr_stack_->exprstack) != NULL)
&& ((operand->previous != NULL) || (operand->type != FFEEXPR_exprtypeOPERAND_)))
{
if (operand->type == FFEEXPR_exprtypeOPERAND_)
ffeexpr_reduce_ ();
else
{
if (ffest_ffebad_start (FFEBAD_MISSING_OPERAND_FOR_OPERATOR))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
ffebad_finish ();
}
ffeexpr_stack_->exprstack = operand->previous; /* Pop the useless
operator. */
ffeexpr_expr_kill_ (operand);
}
}
assert ((operand == NULL) || (operand->previous == NULL));
ffebld_pool_pop ();
if (operand == NULL)
expr = NULL;
else
{
expr = operand->u.operand;
info = ffebld_info (expr);
if ((ffebld_op (expr) == FFEBLD_opCONTER)
&& (ffebld_conter_orig (expr) == NULL)
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
{
ffetarget_integer_bad_magical (operand->token);
}
ffeexpr_expr_kill_ (operand);
ffeexpr_stack_->exprstack = NULL;
}
ft = ffeexpr_stack_->first_token;
again: /* :::::::::::::::::::: */
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextLET:
case FFEEXPR_contextSFUNCDEF:
error = (expr == NULL)
|| (ffeinfo_rank (info) != 0);
break;
case FFEEXPR_contextPAREN_:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
break;
}
break;
case FFEEXPR_contextPARENFILENUM_:
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
ffeexpr_stack_->context = FFEEXPR_contextPAREN_;
else
ffeexpr_stack_->context = FFEEXPR_contextFILENUM;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextPARENFILEUNIT_:
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
ffeexpr_stack_->context = FFEEXPR_contextPAREN_;
else
ffeexpr_stack_->context = FFEEXPR_contextFILEUNIT;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
if (!ffe_is_ugly_args ()
&& ffebad_start (FFEBAD_ACTUALARG))
{
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
break;
default:
break;
}
error = (expr != NULL) && (ffeinfo_rank (info) != 0);
break;
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextSFUNCDEFACTUALARG_:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
#if 0 /* Should never get here. */
expr = ffeexpr_convert (expr, ft, ft,
FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT,
0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
#else
assert ("why hollerith/typeless in actualarg_?" == NULL);
#endif
break;
default:
break;
}
switch ((expr == NULL) ? FFEBLD_opANY : ffebld_op (expr))
{
case FFEBLD_opSYMTER:
case FFEBLD_opPERCENT_LOC:
case FFEBLD_opPERCENT_VAL:
case FFEBLD_opPERCENT_REF:
case FFEBLD_opPERCENT_DESCR:
error = FALSE;
break;
default:
error = (expr != NULL) && (ffeinfo_rank (info) != 0);
break;
}
{
ffesymbol s;
ffeinfoWhere where;
ffeinfoKind kind;
if (!error
&& (expr != NULL)
&& (ffebld_op (expr) == FFEBLD_opSYMTER)
&& ((s = ffebld_symter (expr)), (where = ffesymbol_where (s)),
(where == FFEINFO_whereINTRINSIC)
|| (where == FFEINFO_whereGLOBAL)
|| ((where == FFEINFO_whereDUMMY)
&& ((kind = ffesymbol_kind (s)),
(kind == FFEINFO_kindFUNCTION)
|| (kind == FFEINFO_kindSUBROUTINE))))
&& !ffesymbol_explicitwhere (s))
{
ffebad_start (where == FFEINFO_whereINTRINSIC
? FFEBAD_NEED_INTRINSIC : FFEBAD_NEED_EXTERNAL);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_string (ffesymbol_text (s));
ffebad_finish ();
ffesymbol_signal_change (s);
ffesymbol_set_explicitwhere (s, TRUE);
ffesymbol_signal_unreported (s);
}
}
break;
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextSFUNCDEFINDEX_:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeNONE:
error = FALSE;
break;
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeINTEGER:
/* Specifically, allow INTEGER(KIND=2), aka INTEGER*8, through
unmolested. Leave it to downstream to handle kinds. */
break;
1999-08-26 09:30:50 +00:00
default:
error = TRUE;
break;
}
break; /* expr==NULL ok for substring; element case
caught by callback. */
case FFEEXPR_contextRETURN:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeNONE:
error = FALSE;
break;
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
break;
1999-08-26 09:30:50 +00:00
case FFEEXPR_contextDO:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
error = !ffe_is_ugly_logint ();
if (!ffeexpr_stack_->is_rhs)
break; /* Don't convert lhs variable. */
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
ffeinfo_kindtype (ffebld_info (expr)), 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
if (!ffeexpr_stack_->is_rhs)
{
error = TRUE;
break; /* Don't convert lhs variable. */
}
break;
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeREAL:
break;
default:
error = TRUE;
break;
}
if (!ffeexpr_stack_->is_rhs
&& (ffebld_op (expr) != FFEBLD_opSYMTER))
error = TRUE;
break;
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextIF:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeLOGICAL:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextAGOTO:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
error = (ffeinfo_kindtype (info) != ffecom_label_kind ());
break;
case FFEINFO_basictypeLOGICAL:
error = !ffe_is_ugly_logint ()
|| (ffeinfo_kindtype (info) != ffecom_label_kind ());
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0)
|| (ffebld_op (expr) != FFEBLD_opSYMTER))
error = TRUE;
break;
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextFILENUM: /* See equiv code in _ambig_. */
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextARITHIF:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeREAL:
error = FALSE;
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextSTOP:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
break;
case FFEINFO_basictypeCHARACTER:
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT);
break;
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeNONE:
error = FALSE;
break;
default:
error = TRUE;
break;
}
if ((expr != NULL) && ((ffebld_op (expr) != FFEBLD_opCONTER)
|| (ffebld_conter_orig (expr) != NULL)))
error = TRUE;
break;
case FFEEXPR_contextINCLUDE:
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|| (ffeinfo_basictype (info) != FFEINFO_basictypeCHARACTER)
|| (ffebld_op (expr) != FFEBLD_opCONTER)
|| (ffebld_conter_orig (expr) != NULL);
break;
case FFEEXPR_contextSELECTCASE:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeCHARACTER:
case FFEINFO_basictypeLOGICAL:
error = FALSE;
break;
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextCASE:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeINTEGER
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeCHARACTER:
case FFEINFO_basictypeLOGICAL:
error = FALSE;
break;
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
error = TRUE;
break;
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextDIMLISTCOMMON:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
error = TRUE;
break;
case FFEEXPR_contextEQVINDEX_:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeNONE:
error = FALSE;
break;
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
error = TRUE;
break;
case FFEEXPR_contextPARAMETER:
if (ffeexpr_stack_->is_rhs)
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|| (ffebld_op (expr) != FFEBLD_opCONTER);
else
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|| (ffebld_op (expr) != FFEBLD_opSYMTER);
break;
case FFEEXPR_contextINDEXORACTUALARG_:
if (ffelex_token_type (t) == FFELEX_typeCOLON)
ffeexpr_stack_->context = FFEEXPR_contextINDEX_;
else
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
if (ffelex_token_type (t) == FFELEX_typeCOLON)
ffeexpr_stack_->context = FFEEXPR_contextINDEX_;
else
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
if (ffelex_token_type (t) == FFELEX_typeCOLON)
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_;
else
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
if (ffelex_token_type (t) == FFELEX_typeCOLON)
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_;
else
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
goto again; /* :::::::::::::::::::: */
case FFEEXPR_contextIMPDOCTRL_:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
if (!ffeexpr_stack_->is_rhs
&& (ffebld_op (expr) != FFEBLD_opSYMTER))
error = TRUE;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
if (! ffe_is_ugly_logint ())
error = TRUE;
if (! ffeexpr_stack_->is_rhs)
break;
1999-08-26 09:30:50 +00:00
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
ffeinfo_kindtype (info), 0,
1999-08-26 09:30:50 +00:00
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
break;
case FFEINFO_basictypeREAL:
if (!ffeexpr_stack_->is_rhs
&& ffe_is_warn_surprising ()
&& !error)
{
ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_string (ffelex_token_text (ft));
ffebad_finish ();
}
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextDATAIMPDOCTRL_:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
if (ffeexpr_stack_->is_rhs)
{
if ((ffebld_op (expr) != FFEBLD_opCONTER)
&& (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE))
error = TRUE;
}
else if ((ffebld_op (expr) != FFEBLD_opSYMTER)
|| (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE))
error = TRUE;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
if (! ffeexpr_stack_->is_rhs)
break;
1999-08-26 09:30:50 +00:00
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
ffeinfo_kindtype (info), 0,
FFETARGET_charactersizeNONE,
1999-08-26 09:30:50 +00:00
FFEEXPR_contextLET);
/* Fall through. */
1999-08-26 09:30:50 +00:00
case FFEINFO_basictypeINTEGER:
if (ffeexpr_stack_->is_rhs
&& (ffeinfo_kindtype (ffebld_info (expr))
!= FFEINFO_kindtypeINTEGERDEFAULT))
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
1999-08-26 09:30:50 +00:00
break;
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeREAL:
if (!ffeexpr_stack_->is_rhs
&& ffe_is_warn_surprising ()
&& !error)
{
ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_string (ffelex_token_text (ft));
ffebad_finish ();
}
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextIMPDOITEM_:
if (ffelex_token_type (t) == FFELEX_typeEQUALS)
{
ffeexpr_stack_->is_rhs = FALSE;
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
goto again; /* :::::::::::::::::::: */
}
/* Fall through. */
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextFILEVXTCODE:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
break;
}
error = (expr == NULL)
|| ((ffeinfo_rank (info) != 0)
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
== FFEBLD_opSTAR))); /* Bad if null expr, or if
array that is not a SYMTER
(can't happen yet, I
think) or has a NULL or
STAR (assumed) array
size. */
break;
case FFEEXPR_contextIMPDOITEMDF_:
if (ffelex_token_type (t) == FFELEX_typeEQUALS)
{
ffeexpr_stack_->is_rhs = FALSE;
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
goto again; /* :::::::::::::::::::: */
}
/* Fall through. */
case FFEEXPR_contextIOLISTDF:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
break;
}
error
= (expr == NULL)
|| ((ffeinfo_basictype (info) == FFEINFO_basictypeCHARACTER)
&& (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT))
|| ((ffeinfo_rank (info) != 0)
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
== FFEBLD_opSTAR))); /* Bad if null expr,
non-default-kindtype
character expr, or if
array that is not a SYMTER
(can't happen yet, I
think) or has a NULL or
STAR (assumed) array
size. */
break;
case FFEEXPR_contextDATAIMPDOITEM_:
error = (expr == NULL)
|| (ffebld_op (expr) != FFEBLD_opARRAYREF)
|| ((ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR)
&& (ffeinfo_where (info) != FFEINFO_whereFLEETING_IADDR));
break;
case FFEEXPR_contextDATAIMPDOINDEX_:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
if ((ffeinfo_where (info) != FFEINFO_whereCONSTANT)
&& (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE))
error = TRUE;
break;
case FFEEXPR_contextDATA:
if (expr == NULL)
error = TRUE;
else if (ffeexpr_stack_->is_rhs)
error = (ffebld_op (expr) != FFEBLD_opCONTER);
else if (ffebld_op (expr) == FFEBLD_opSYMTER)
error = FALSE;
else
error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR);
break;
case FFEEXPR_contextINITVAL:
error = (expr == NULL) || (ffebld_op (expr) != FFEBLD_opCONTER);
break;
case FFEEXPR_contextEQUIVALENCE:
if (expr == NULL)
error = TRUE;
else if (ffebld_op (expr) == FFEBLD_opSYMTER)
error = FALSE;
else
error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR);
break;
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
/* Maybe this should be supported someday, but, right now,
g77 can't generate a call to libf2c to write to an
integer other than the default size. */
error = ((! ffeexpr_stack_->is_rhs)
&& ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
1999-08-26 09:30:50 +00:00
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
error = TRUE;
break;
case FFEEXPR_contextFILEDFINT:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
error = TRUE;
break;
case FFEEXPR_contextFILELOG:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
error = FALSE;
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
error = TRUE;
break;
case FFEEXPR_contextFILECHAR:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeCHARACTER:
error = FALSE;
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
error = TRUE;
break;
case FFEEXPR_contextFILENUMCHAR:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeCHARACTER:
error = FALSE;
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextFILEDFCHAR:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeCHARACTER:
error
= (ffeinfo_kindtype (info)
!= FFEINFO_kindtypeCHARACTERDEFAULT);
break;
default:
error = TRUE;
break;
}
if (!ffeexpr_stack_->is_rhs
&& (ffebld_op (expr) == FFEBLD_opSUBSTR))
error = TRUE;
break;
case FFEEXPR_contextFILEUNIT: /* See equiv code in _ambig_. */
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
if ((error = (ffeinfo_rank (info) != 0)))
break;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if ((error = (ffeinfo_rank (info) != 0)))
break;
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
if ((error = (ffeinfo_rank (info) != 0)))
break;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeCHARACTER:
switch (ffebld_op (expr))
{ /* As if _lhs had been called instead of
_rhs. */
case FFEBLD_opSYMTER:
error
= (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT);
break;
case FFEBLD_opSUBSTR:
error = (ffeinfo_where (ffebld_info (expr))
== FFEINFO_whereCONSTANT_SUBOBJECT);
break;
case FFEBLD_opARRAYREF:
error = FALSE;
break;
default:
error = TRUE;
break;
}
if (!error
&& ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT)
|| ((ffeinfo_rank (info) != 0)
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
== FFEBLD_opSTAR))))) /* Bad if
non-default-kindtype
character expr, or if
array that is not a SYMTER
(can't happen yet, I
think), or has a NULL or
STAR (assumed) array
size. */
error = TRUE;
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextFILEFORMAT:
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
error = (expr == NULL)
|| ((ffeinfo_rank (info) != 0) ?
ffe_is_pedantic () /* F77 C5. */
: (bool) (ffeinfo_kindtype (info) != ffecom_label_kind ()))
1999-08-26 09:30:50 +00:00
|| (ffebld_op (expr) != FFEBLD_opSYMTER);
break;
case FFEINFO_basictypeLOGICAL:
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
/* F77 C5 -- must be an array of hollerith. */
error
= ffe_is_pedantic ()
|| (ffeinfo_rank (info) == 0);
break;
case FFEINFO_basictypeCHARACTER:
if ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT)
|| ((ffeinfo_rank (info) != 0)
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
== FFEBLD_opSTAR)))) /* Bad if
non-default-kindtype
character expr, or if
array that is not a SYMTER
(can't happen yet, I
think), or has a NULL or
STAR (assumed) array
size. */
error = TRUE;
else
error = FALSE;
break;
default:
error = TRUE;
break;
}
break;
case FFEEXPR_contextLOC_:
/* See also ffeintrin_check_loc_. */
if ((expr == NULL)
|| (ffeinfo_kind (info) != FFEINFO_kindENTITY)
|| ((ffebld_op (expr) != FFEBLD_opSYMTER)
&& (ffebld_op (expr) != FFEBLD_opSUBSTR)
&& (ffebld_op (expr) != FFEBLD_opARRAYREF)))
error = TRUE;
break;
default:
error = FALSE;
break;
}
if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY)))
{
ffebad_start (FFEBAD_EXPR_WRONG);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
expr = ffebld_new_any ();
ffebld_set_info (expr, ffeinfo_new_any ());
}
callback = ffeexpr_stack_->callback;
s = ffeexpr_stack_->previous;
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
sizeof (*ffeexpr_stack_));
ffeexpr_stack_ = s;
next = (ffelexHandler) (*callback) (ft, expr, t);
ffelex_token_kill (ft);
return (ffelexHandler) next;
}
/* ffeexpr_finished_ambig_ -- Check validity of ambiguous unit/form spec
ffebld expr;
expr = ffeexpr_finished_ambig_(expr);
Replicates a bit of ffeexpr_finished_'s task when in a context
of UNIT or FORMAT. */
static ffebld
ffeexpr_finished_ambig_ (ffelexToken ft, ffebld expr)
{
ffeinfo info = ffebld_info (expr);
bool error;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFILENUMAMBIG: /* Same as FILENUM in _finished_. */
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
default:
error = TRUE;
break;
}
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
error = TRUE;
break;
case FFEEXPR_contextFILEUNITAMBIG: /* Same as FILEUNIT in _finished_. */
if ((expr != NULL) && (ffebld_op (expr) == FFEBLD_opSTAR))
{
error = FALSE;
break;
}
switch ((expr == NULL) ? FFEINFO_basictypeNONE
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
/* Fall through. */
case FFEINFO_basictypeREAL:
case FFEINFO_basictypeCOMPLEX:
if (ffe_is_pedantic ())
{
error = TRUE;
break;
}
/* Fall through. */
case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = (ffeinfo_rank (info) != 0);
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
case FFEINFO_basictypeCHARACTER:
switch (ffebld_op (expr))
{ /* As if _lhs had been called instead of
_rhs. */
case FFEBLD_opSYMTER:
error
= (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT);
break;
case FFEBLD_opSUBSTR:
error = (ffeinfo_where (ffebld_info (expr))
== FFEINFO_whereCONSTANT_SUBOBJECT);
break;
case FFEBLD_opARRAYREF:
error = FALSE;
break;
default:
error = TRUE;
break;
}
break;
default:
error = TRUE;
break;
}
break;
default:
assert ("bad context" == NULL);
error = TRUE;
break;
}
if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY)))
{
ffebad_start (FFEBAD_EXPR_WRONG);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
expr = ffebld_new_any ();
ffebld_set_info (expr, ffeinfo_new_any ());
}
return expr;
}
/* ffeexpr_token_lhs_ -- Initial state for lhs expression
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Basically a smaller version of _rhs_; keep them both in sync, of course. */
static ffelexHandler
ffeexpr_token_lhs_ (ffelexToken t)
{
/* When changing the list of valid initial lhs tokens, check whether to
update a corresponding list in ffeexpr_cb_close_paren_ambig_1_ for the
READ (expr) <token> case -- it assumes it knows which tokens <token> can
be to indicate an lhs (or implied DO), which right now is the set
{NAME,OPEN_PAREN}.
This comment also appears in ffeexpr_token_first_lhs_. */
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_tokens_[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_name_lhs_;
default:
return (ffelexHandler) ffeexpr_finished_ (t);
}
}
/* ffeexpr_token_rhs_ -- Initial state for rhs expression
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
The initial state and the post-binary-operator state are the same and
both handled here, with the expression stack used to distinguish
between them. Binary operators are invalid here; unary operators,
constants, subexpressions, and name references are valid. */
static ffelexHandler
ffeexpr_token_rhs_ (ffelexToken t)
{
ffeexprExpr_ e;
switch (ffelex_token_type (t))
{
case FFELEX_typeQUOTE:
if (ffe_is_vxt ())
{
ffeexpr_tokens_[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_quote_;
}
ffeexpr_tokens_[0] = ffelex_token_use (t);
ffelex_set_expecting_hollerith (-1, '\"',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
/* Don't have to unset this one. */
return (ffelexHandler) ffeexpr_token_apostrophe_;
case FFELEX_typeAPOSTROPHE:
ffeexpr_tokens_[0] = ffelex_token_use (t);
ffelex_set_expecting_hollerith (-1, '\'',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
/* Don't have to unset this one. */
return (ffelexHandler) ffeexpr_token_apostrophe_;
case FFELEX_typePERCENT:
ffeexpr_tokens_[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_percent_;
case FFELEX_typeOPEN_PAREN:
ffeexpr_stack_->tokens[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextPAREN_,
ffeexpr_cb_close_paren_c_);
case FFELEX_typePLUS:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeUNARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorADD_;
e->u.operator.prec = FFEEXPR_operatorprecedenceADD_;
e->u.operator.as = FFEEXPR_operatorassociativityADD_;
ffeexpr_exprstack_push_unary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeMINUS:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeUNARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorSUBTRACT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_;
e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_;
ffeexpr_exprstack_push_unary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typePERIOD:
ffeexpr_tokens_[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_period_;
case FFELEX_typeNUMBER:
ffeexpr_tokens_[0] = ffelex_token_use (t);
ffeexpr_hollerith_count_ = atol (ffelex_token_text (t));
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_,
'\0',
ffelex_token_where_line (t),
ffelex_token_where_column (t));
return (ffelexHandler) ffeexpr_token_number_;
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_tokens_[0] = ffelex_token_use (t);
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextINDEXORACTUALARG_:
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
return (ffelexHandler) ffeexpr_token_name_arg_;
default:
return (ffelexHandler) ffeexpr_token_name_rhs_;
}
case FFELEX_typeASTERISK:
case FFELEX_typeSLASH:
case FFELEX_typePOWER:
case FFELEX_typeCONCAT:
case FFELEX_typeREL_EQ:
case FFELEX_typeREL_NE:
case FFELEX_typeREL_LE:
case FFELEX_typeREL_GE:
if (ffest_ffebad_start (FFEBAD_MISSING_FIRST_BINARY_OPERAND))
{
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
return (ffelexHandler) ffeexpr_token_rhs_;
#if 0
case FFELEX_typeEQUALS:
case FFELEX_typePOINTS:
case FFELEX_typeCLOSE_ANGLE:
case FFELEX_typeCLOSE_PAREN:
case FFELEX_typeCOMMA:
case FFELEX_typeCOLON:
case FFELEX_typeEOS:
case FFELEX_typeSEMICOLON:
#endif
default:
return (ffelexHandler) ffeexpr_finished_ (t);
}
}
/* ffeexpr_token_period_ -- Rhs PERIOD
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle a period detected at rhs (expecting unary op or operand) state.
Must begin a floating-point value (as in .12) or a dot-dot name, of
which only .NOT., .TRUE., and .FALSE. are truly valid. Other sort-of-
valid names represent binary operators, which are invalid here because
there isn't an operand at the top of the stack. */
static ffelexHandler
ffeexpr_token_period_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_current_dotdot_ = ffestr_other (t);
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherNone:
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_rhs_ (t);
case FFESTR_otherTRUE:
case FFESTR_otherFALSE:
case FFESTR_otherNOT:
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_end_period_;
default:
if (ffest_ffebad_start (FFEBAD_MISSING_FIRST_BINARY_OPERAND))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_swallow_period_;
}
break; /* Nothing really reaches here. */
case FFELEX_typeNUMBER:
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_real_;
default:
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
}
/* ffeexpr_token_end_period_ -- Rhs PERIOD NAME(NOT, TRUE, or FALSE)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Expecting a period to close a .NOT, .TRUE, or .FALSE at rhs (unary op
or operator) state. If period isn't found, issue a diagnostic but
pretend we saw one. ffeexpr_current_dotdot_ must already contained the
dotdot representation of the name in between the two PERIOD tokens. */
static ffelexHandler
ffeexpr_token_end_period_ (ffelexToken t)
{
ffeexprExpr_ e;
if (ffelex_token_type (t) != FFELEX_typePERIOD)
{
if (ffest_ffebad_start (FFEBAD_INSERTING_PERIOD))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
ffebad_finish ();
}
}
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill "NOT"/"TRUE"/"FALSE"
token. */
e = ffeexpr_expr_new_ ();
e->token = ffeexpr_tokens_[0];
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherNOT:
e->type = FFEEXPR_exprtypeUNARY_;
e->u.operator.op = FFEEXPR_operatorNOT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceNOT_;
e->u.operator.as = FFEEXPR_operatorassociativityNOT_;
ffeexpr_exprstack_push_unary_ (e);
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_token_rhs_ (t);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFESTR_otherTRUE:
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand
= ffebld_new_conter (ffebld_constant_new_logicaldefault (TRUE));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_token_binary_ (t);
return (ffelexHandler) ffeexpr_token_binary_;
case FFESTR_otherFALSE:
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand
= ffebld_new_conter (ffebld_constant_new_logicaldefault (FALSE));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_token_binary_ (t);
return (ffelexHandler) ffeexpr_token_binary_;
default:
assert ("Bad unary dotdot in ffeexpr_current_dotdot_" == NULL);
exit (0);
return NULL;
}
}
/* ffeexpr_token_swallow_period_ -- Rhs PERIOD NAME(not NOT, TRUE, or FALSE)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
A diagnostic has already been issued; just swallow a period if there is
one, then continue with ffeexpr_token_rhs_. */
static ffelexHandler
ffeexpr_token_swallow_period_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_token_rhs_ (t);
return (ffelexHandler) ffeexpr_token_rhs_;
}
/* ffeexpr_token_real_ -- Rhs PERIOD NUMBER
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
After a period and a string of digits, check next token for possible
exponent designation (D, E, or Q as first/only character) and continue
real-number handling accordingly. Else form basic real constant, push
onto expression stack, and enter binary state using current token (which,
if it is a name not beginning with D, E, or Q, will certainly result
in an error, but that's not for this routine to deal with). */
static ffelexHandler
ffeexpr_token_real_ (ffelexToken t)
{
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q')))
&& ffeexpr_isdigits_ (++p)))
{
#if 0
/* This code has been removed because it seems inconsistent to
produce a diagnostic in this case, but not all of the other
ones that look for an exponent and cannot recognize one. */
if (((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
&& ffest_ffebad_start (FFEBAD_INVALID_EXPONENT))
{
char bad[2];
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
bad[0] = *(p - 1);
bad[1] = '\0';
ffebad_string (bad);
ffebad_finish ();
}
#endif
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* Just exponent character by itself? In which case, PLUS or MINUS must
surely be next, followed by a NUMBER token. */
if (*p == '\0')
{
ffeexpr_tokens_[2] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_real_exponent_;
}
ffeexpr_make_float_const_ (d, NULL, ffeexpr_tokens_[0], ffeexpr_tokens_[1],
t, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_real_exponent_ -- Rhs PERIOD NUMBER NAME(D, E, or Q)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Ensures this token is PLUS or MINUS, preserves it, goes to final state
for real number (exponent digits). Else issues diagnostic, assumes a
zero exponent field for number, passes token on to binary state as if
previous token had been "E0" instead of "E", for example. */
static ffelexHandler
ffeexpr_token_real_exponent_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
ffelex_token_where_column (ffeexpr_tokens_[2]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_tokens_[3] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_real_exp_sign_;
}
/* ffeexpr_token_real_exp_sign_ -- Rhs PERIOD NUMBER NAME(D,E,Q) PLUS/MINUS
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Make sure token is a NUMBER, make a real constant out of all we have and
push it onto the expression stack. Else issue diagnostic and pretend
exponent field was a zero. */
static ffelexHandler
ffeexpr_token_real_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
ffelex_token_where_column (ffeexpr_tokens_[2]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0], NULL,
ffeexpr_tokens_[0], ffeexpr_tokens_[1], ffeexpr_tokens_[2],
ffeexpr_tokens_[3], t);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_number_ -- Rhs NUMBER
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
If the token is a period, we may have a floating-point number, or an
integer followed by a dotdot binary operator. If the token is a name
beginning with D, E, or Q, we definitely have a floating-point number.
If the token is a hollerith constant, that's what we've got, so push
it onto the expression stack and continue with the binary state.
Otherwise, we have an integer followed by something the binary state
should be able to swallow. */
static ffelexHandler
ffeexpr_token_number_ (ffelexToken t)
{
ffeexprExpr_ e;
ffeinfo ni;
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (0, '\0',
ffewhere_line_unknown (),
ffewhere_column_unknown ());
/* See if we've got a floating-point number here. */
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q'))
&& ffeexpr_isdigits_ (++p))
{
/* Just exponent character by itself? In which case, PLUS or MINUS
must surely be next, followed by a NUMBER token. */
if (*p == '\0')
{
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_exponent_;
}
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], NULL, NULL, t,
NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_binary_;
}
break;
case FFELEX_typePERIOD:
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_period_;
case FFELEX_typeHOLLERITH:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
e->u.operand = ffebld_new_conter (ffebld_constant_new_hollerith (t));
ni = ffeinfo_new (FFEINFO_basictypeHOLLERITH, FFEINFO_kindtypeNONE,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
ffelex_token_length (t));
ffebld_set_info (e->u.operand, ni);
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_token_binary_;
default:
break;
}
/* Nothing specific we were looking for, so make an integer and pass the
current token to the binary state. */
ffeexpr_make_float_const_ ('I', ffeexpr_tokens_[0], NULL, NULL,
NULL, NULL, NULL);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* ffeexpr_token_number_exponent_ -- Rhs NUMBER NAME(D, E, or Q)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Ensures this token is PLUS or MINUS, preserves it, goes to final state
for real number (exponent digits). Else treats number as integer, passes
name to binary, passes current token to subsequent handler. */
static ffelexHandler
ffeexpr_token_number_exponent_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
ffeexprExpr_ e;
ffelexHandler nexthandler;
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
(ffeexpr_tokens_[0]));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGERDEFAULT,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
nexthandler = (ffelexHandler) ffeexpr_token_binary_ (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) (*nexthandler) (t);
}
ffeexpr_tokens_[2] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_exp_sign_;
}
/* ffeexpr_token_number_exp_sign_ -- Rhs NUMBER NAME(D,E,Q) PLUS/MINUS
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Make sure token is a NUMBER, make a real constant out of all we have and
push it onto the expression stack. Else issue diagnostic and pretend
exponent field was a zero. */
static ffelexHandler
ffeexpr_token_number_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[1]),
ffelex_token_where_column (ffeexpr_tokens_[1]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[1])[0],
ffeexpr_tokens_[0], NULL, NULL,
ffeexpr_tokens_[1], ffeexpr_tokens_[2],
NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[1])[0],
ffeexpr_tokens_[0], NULL, NULL,
ffeexpr_tokens_[1], ffeexpr_tokens_[2], t);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_number_period_ -- Rhs NUMBER PERIOD
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle a period detected following a number at rhs state. Must begin a
floating-point value (as in 1., 1.2, 1.E3, or 1.E+3) or a dot-dot name. */
static ffelexHandler
ffeexpr_token_number_period_ (ffelexToken t)
{
ffeexprExpr_ e;
ffelexHandler nexthandler;
const char *p;
1999-08-26 09:30:50 +00:00
char d;
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q'))
&& ffeexpr_isdigits_ (++p))
{
/* Just exponent character by itself? In which case, PLUS or MINUS
must surely be next, followed by a NUMBER token. */
if (*p == '\0')
{
ffeexpr_tokens_[2] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_per_exp_;
}
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0],
ffeexpr_tokens_[1], NULL, t, NULL,
NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* A name not representing an exponent, so assume it will be something
like EQ, make an integer from the number, pass the period to binary
state and the current token to the resulting state. */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
(ffeexpr_tokens_[0]));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
nexthandler = (ffelexHandler) ffeexpr_token_binary_
(ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) (*nexthandler) (t);
case FFELEX_typeNUMBER:
ffeexpr_tokens_[2] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_real_;
default:
break;
}
/* Nothing specific we were looking for, so make a real number and pass the
period and then the current token to the binary state. */
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* ffeexpr_token_number_per_exp_ -- Rhs NUMBER PERIOD NAME(D, E, or Q)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Ensures this token is PLUS or MINUS, preserves it, goes to final state
for real number (exponent digits). Else treats number as real, passes
name to binary, passes current token to subsequent handler. */
static ffelexHandler
ffeexpr_token_number_per_exp_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
ffelexHandler nexthandler;
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
nexthandler = (ffelexHandler) ffeexpr_token_binary_ (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) (*nexthandler) (t);
}
ffeexpr_tokens_[3] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_num_per_exp_sign_;
}
/* ffeexpr_token_number_real_ -- Rhs NUMBER PERIOD NUMBER
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
After a number, period, and number, check next token for possible
exponent designation (D, E, or Q as first/only character) and continue
real-number handling accordingly. Else form basic real constant, push
onto expression stack, and enter binary state using current token (which,
if it is a name not beginning with D, E, or Q, will certainly result
in an error, but that's not for this routine to deal with). */
static ffelexHandler
ffeexpr_token_number_real_ (ffelexToken t)
{
char d;
const char *p;
1999-08-26 09:30:50 +00:00
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
'D', 'd')
|| ffesrc_char_match_init (d, 'E', 'e')
|| ffesrc_char_match_init (d, 'Q', 'q')))
&& ffeexpr_isdigits_ (++p)))
{
#if 0
/* This code has been removed because it seems inconsistent to
produce a diagnostic in this case, but not all of the other
ones that look for an exponent and cannot recognize one. */
if (((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
&& ffest_ffebad_start (FFEBAD_INVALID_EXPONENT))
{
char bad[2];
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
bad[0] = *(p - 1);
bad[1] = '\0';
ffebad_string (bad);
ffebad_finish ();
}
#endif
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
ffeexpr_tokens_[2], NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* Just exponent character by itself? In which case, PLUS or MINUS must
surely be next, followed by a NUMBER token. */
if (*p == '\0')
{
ffeexpr_tokens_[3] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_number_real_exp_;
}
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], ffeexpr_tokens_[1],
ffeexpr_tokens_[2], t, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_num_per_exp_sign_ -- Rhs NUMBER PERIOD NAME(D,E,Q) PLUS/MINUS
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Make sure token is a NUMBER, make a real constant out of all we have and
push it onto the expression stack. Else issue diagnostic and pretend
exponent field was a zero. */
static ffelexHandler
ffeexpr_token_num_per_exp_sign_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
ffelex_token_where_column (ffeexpr_tokens_[2]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
NULL, NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0],
ffeexpr_tokens_[0], ffeexpr_tokens_[1], NULL,
ffeexpr_tokens_[2], ffeexpr_tokens_[3], t);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_number_real_exp_ -- Rhs NUMBER PERIOD NUMBER NAME(D, E, or Q)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Ensures this token is PLUS or MINUS, preserves it, goes to final state
for real number (exponent digits). Else issues diagnostic, assumes a
zero exponent field for number, passes token on to binary state as if
previous token had been "E0" instead of "E", for example. */
static ffelexHandler
ffeexpr_token_number_real_exp_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typePLUS)
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]),
ffelex_token_where_column (ffeexpr_tokens_[3]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
ffeexpr_tokens_[2], NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_tokens_[4] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_num_real_exp_sn_;
}
/* ffeexpr_token_num_real_exp_sn_ -- Rhs NUMBER PERIOD NUMBER NAME(D,E,Q)
PLUS/MINUS
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Make sure token is a NUMBER, make a real constant out of all we have and
push it onto the expression stack. Else issue diagnostic and pretend
exponent field was a zero. */
static ffelexHandler
ffeexpr_token_num_real_exp_sn_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]),
ffelex_token_where_column (ffeexpr_tokens_[3]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
ffeexpr_tokens_[2], NULL, NULL, NULL);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
ffelex_token_kill (ffeexpr_tokens_[4]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[3])[0],
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
ffeexpr_tokens_[2], ffeexpr_tokens_[3],
ffeexpr_tokens_[4], t);
ffelex_token_kill (ffeexpr_tokens_[0]);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
ffelex_token_kill (ffeexpr_tokens_[3]);
ffelex_token_kill (ffeexpr_tokens_[4]);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_binary_ -- Handle binary operator possibility
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
The possibility of a binary operator is handled here, meaning the previous
token was an operand. */
static ffelexHandler
ffeexpr_token_binary_ (ffelexToken t)
{
ffeexprExpr_ e;
if (!ffeexpr_stack_->is_rhs)
return (ffelexHandler) ffeexpr_finished_ (t); /* For now. */
switch (ffelex_token_type (t))
{
case FFELEX_typePLUS:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorADD_;
e->u.operator.prec = FFEEXPR_operatorprecedenceADD_;
e->u.operator.as = FFEEXPR_operatorassociativityADD_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeMINUS:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorSUBTRACT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_;
e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeASTERISK:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
return (ffelexHandler) ffeexpr_finished_ (t);
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorMULTIPLY_;
e->u.operator.prec = FFEEXPR_operatorprecedenceMULTIPLY_;
e->u.operator.as = FFEEXPR_operatorassociativityMULTIPLY_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeSLASH:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATA:
return (ffelexHandler) ffeexpr_finished_ (t);
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorDIVIDE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceDIVIDE_;
e->u.operator.as = FFEEXPR_operatorassociativityDIVIDE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typePOWER:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorPOWER_;
e->u.operator.prec = FFEEXPR_operatorprecedencePOWER_;
e->u.operator.as = FFEEXPR_operatorassociativityPOWER_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeCONCAT:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorCONCATENATE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_;
e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeOPEN_ANGLE:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorLT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceLT_;
e->u.operator.as = FFEEXPR_operatorassociativityLT_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeCLOSE_ANGLE:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
return ffeexpr_finished_ (t);
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorGT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceGT_;
e->u.operator.as = FFEEXPR_operatorassociativityGT_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeREL_EQ:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorEQ_;
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeREL_NE:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorNE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceNE_;
e->u.operator.as = FFEEXPR_operatorassociativityNE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeREL_LE:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorLE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceLE_;
e->u.operator.as = FFEEXPR_operatorassociativityLE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typeREL_GE:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextFORMAT:
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorGE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceGE_;
e->u.operator.as = FFEEXPR_operatorassociativityGE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_;
case FFELEX_typePERIOD:
ffeexpr_tokens_[0] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_binary_period_;
#if 0
case FFELEX_typeOPEN_PAREN:
case FFELEX_typeCLOSE_PAREN:
case FFELEX_typeEQUALS:
case FFELEX_typePOINTS:
case FFELEX_typeCOMMA:
case FFELEX_typeCOLON:
case FFELEX_typeEOS:
case FFELEX_typeSEMICOLON:
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
#endif
default:
return (ffelexHandler) ffeexpr_finished_ (t);
}
}
/* ffeexpr_token_binary_period_ -- Binary PERIOD
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle a period detected at binary (expecting binary op or end) state.
Must begin a dot-dot name, of which .NOT., .TRUE., and .FALSE. are not
valid. */
static ffelexHandler
ffeexpr_token_binary_period_ (ffelexToken t)
{
ffeexprExpr_ operand;
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_current_dotdot_ = ffestr_other (t);
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherTRUE:
case FFESTR_otherFALSE:
case FFESTR_otherNOT:
if (ffest_ffebad_start (FFEBAD_MISSING_BINARY_OPERATOR))
{
operand = ffeexpr_stack_->exprstack;
assert (operand != NULL);
assert (operand->type == FFEEXPR_exprtypeOPERAND_);
ffebad_here (0, ffelex_token_where_line (operand->token), ffelex_token_where_column (operand->token));
ffebad_here (1, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_binary_sw_per_;
default:
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_binary_end_per_;
}
break; /* Nothing really reaches here. */
default:
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
}
/* ffeexpr_token_binary_end_per_ -- Binary PERIOD NAME(not NOT, TRUE, or FALSE)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Expecting a period to close a dot-dot at binary (binary op
or operator) state. If period isn't found, issue a diagnostic but
pretend we saw one. ffeexpr_current_dotdot_ must already contained the
dotdot representation of the name in between the two PERIOD tokens. */
static ffelexHandler
ffeexpr_token_binary_end_per_ (ffelexToken t)
{
ffeexprExpr_ e;
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffeexpr_tokens_[0];
switch (ffeexpr_current_dotdot_)
{
case FFESTR_otherAND:
e->u.operator.op = FFEEXPR_operatorAND_;
e->u.operator.prec = FFEEXPR_operatorprecedenceAND_;
e->u.operator.as = FFEEXPR_operatorassociativityAND_;
break;
case FFESTR_otherOR:
e->u.operator.op = FFEEXPR_operatorOR_;
e->u.operator.prec = FFEEXPR_operatorprecedenceOR_;
e->u.operator.as = FFEEXPR_operatorassociativityOR_;
break;
case FFESTR_otherXOR:
e->u.operator.op = FFEEXPR_operatorXOR_;
e->u.operator.prec = FFEEXPR_operatorprecedenceXOR_;
e->u.operator.as = FFEEXPR_operatorassociativityXOR_;
break;
case FFESTR_otherEQV:
e->u.operator.op = FFEEXPR_operatorEQV_;
e->u.operator.prec = FFEEXPR_operatorprecedenceEQV_;
e->u.operator.as = FFEEXPR_operatorassociativityEQV_;
break;
case FFESTR_otherNEQV:
e->u.operator.op = FFEEXPR_operatorNEQV_;
e->u.operator.prec = FFEEXPR_operatorprecedenceNEQV_;
e->u.operator.as = FFEEXPR_operatorassociativityNEQV_;
break;
case FFESTR_otherLT:
e->u.operator.op = FFEEXPR_operatorLT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceLT_;
e->u.operator.as = FFEEXPR_operatorassociativityLT_;
break;
case FFESTR_otherLE:
e->u.operator.op = FFEEXPR_operatorLE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceLE_;
e->u.operator.as = FFEEXPR_operatorassociativityLE_;
break;
case FFESTR_otherEQ:
e->u.operator.op = FFEEXPR_operatorEQ_;
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
break;
case FFESTR_otherNE:
e->u.operator.op = FFEEXPR_operatorNE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceNE_;
e->u.operator.as = FFEEXPR_operatorassociativityNE_;
break;
case FFESTR_otherGT:
e->u.operator.op = FFEEXPR_operatorGT_;
e->u.operator.prec = FFEEXPR_operatorprecedenceGT_;
e->u.operator.as = FFEEXPR_operatorassociativityGT_;
break;
case FFESTR_otherGE:
e->u.operator.op = FFEEXPR_operatorGE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceGE_;
e->u.operator.as = FFEEXPR_operatorassociativityGE_;
break;
default:
if (ffest_ffebad_start (FFEBAD_INVALID_DOTDOT))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
ffebad_finish ();
}
e->u.operator.op = FFEEXPR_operatorEQ_;
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
break;
}
ffeexpr_exprstack_push_binary_ (e);
if (ffelex_token_type (t) != FFELEX_typePERIOD)
{
if (ffest_ffebad_start (FFEBAD_INSERTING_PERIOD))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */
return (ffelexHandler) ffeexpr_token_rhs_;
}
/* ffeexpr_token_binary_sw_per_ -- Rhs PERIOD NAME(NOT, TRUE, or FALSE)
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
A diagnostic has already been issued; just swallow a period if there is
one, then continue with ffeexpr_token_binary_. */
static ffelexHandler
ffeexpr_token_binary_sw_per_ (ffelexToken t)
{
if (ffelex_token_type (t) != FFELEX_typePERIOD)
return (ffelexHandler) ffeexpr_token_binary_ (t);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_quote_ -- Rhs QUOTE
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Expecting a NUMBER that we'll treat as an octal integer. */
static ffelexHandler
ffeexpr_token_quote_ (ffelexToken t)
{
ffeexprExpr_ e;
ffebld anyexpr;
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
{
if (ffest_ffebad_start (FFEBAD_QUOTE_MISSES_DIGITS))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
/* This is kind of a kludge to prevent any whining about magical numbers
that start out as these octal integers, so "20000000000 (on a 32-bit
2's-complement machine) by itself won't produce an error. */
anyexpr = ffebld_new_any ();
ffebld_set_info (anyexpr, ffeinfo_new_any ());
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
e->u.operand = ffebld_new_conter_with_orig
(ffebld_constant_new_integeroctal (t), anyexpr);
ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_token_binary_;
}
/* ffeexpr_token_apostrophe_ -- Rhs APOSTROPHE
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle an open-apostrophe, which begins either a character ('char-const'),
typeless octal ('octal-const'O), or typeless hexadecimal ('hex-const'Z or
'hex-const'X) constant. */
static ffelexHandler
ffeexpr_token_apostrophe_ (ffelexToken t)
{
assert (ffelex_token_type (t) == FFELEX_typeCHARACTER);
if (ffe_is_pedantic_not_90 () && (ffelex_token_length (t) == 0))
{
ffebad_start (FFEBAD_NULL_CHAR_CONST);
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_apos_char_;
}
/* ffeexpr_token_apos_char_ -- Rhs APOSTROPHE CHARACTER
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Close-apostrophe is implicit; if this token is NAME, it is a possible
typeless-constant radix specifier. */
static ffelexHandler
ffeexpr_token_apos_char_ (ffelexToken t)
{
ffeexprExpr_ e;
ffeinfo ni;
char c;
ffetargetCharacterSize size;
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
{
if ((ffelex_token_length (t) == 1)
&& (ffesrc_char_match_init ((c = ffelex_token_text (t)[0]), 'B',
'b')
|| ffesrc_char_match_init (c, 'O', 'o')
|| ffesrc_char_match_init (c, 'X', 'x')
|| ffesrc_char_match_init (c, 'Z', 'z')))
{
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
switch (c)
{
case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match):
e->u.operand = ffebld_new_conter
(ffebld_constant_new_typeless_bv (ffeexpr_tokens_[1]));
size = ffetarget_size_typeless_binary (ffeexpr_tokens_[1]);
break;
case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match):
e->u.operand = ffebld_new_conter
(ffebld_constant_new_typeless_ov (ffeexpr_tokens_[1]));
size = ffetarget_size_typeless_octal (ffeexpr_tokens_[1]);
break;
case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match):
e->u.operand = ffebld_new_conter
(ffebld_constant_new_typeless_hxv (ffeexpr_tokens_[1]));
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]);
break;
case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match):
e->u.operand = ffebld_new_conter
(ffebld_constant_new_typeless_hzv (ffeexpr_tokens_[1]));
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]);
break;
default:
no_match: /* :::::::::::::::::::: */
assert ("not BOXZ!" == NULL);
size = 0;
break;
}
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size));
ffeexpr_exprstack_push_operand_ (e);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) ffeexpr_token_binary_;
}
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
e->u.operand = ffebld_new_conter (ffebld_constant_new_characterdefault
(ffeexpr_tokens_[1]));
ni = ffeinfo_new (FFEINFO_basictypeCHARACTER, FFEINFO_kindtypeCHARACTERDEFAULT,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
ffelex_token_length (ffeexpr_tokens_[1]));
ffebld_set_info (e->u.operand, ni);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffeexpr_exprstack_push_operand_ (e);
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
{
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
{
ffebad_string (ffelex_token_text (t));
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_finish ();
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeBINARY_;
e->token = ffelex_token_use (t);
e->u.operator.op = FFEEXPR_operatorCONCATENATE_;
e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_;
e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_;
ffeexpr_exprstack_push_binary_ (e);
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
ffeexpr_is_substr_ok_ = !ffe_is_pedantic_not_90 (); /* Allow "'hello'(3:5)". */
return (ffelexHandler) ffeexpr_token_substrp_ (t);
}
/* ffeexpr_token_name_lhs_ -- Lhs NAME
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle a name followed by open-paren, period (RECORD.MEMBER), percent
(RECORD%MEMBER), or nothing at all. */
static ffelexHandler
ffeexpr_token_name_lhs_ (ffelexToken t)
{
ffeexprExpr_ e;
ffeexprParenType_ paren_type;
ffesymbol s;
ffebld expr;
ffeinfo info;
switch (ffelex_token_type (t))
{
case FFELEX_typeOPEN_PAREN:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextFILEUNIT_DF:
goto just_name; /* :::::::::::::::::::: */
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffelex_token_use (ffeexpr_tokens_[0]);
s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], FALSE,
&paren_type);
switch (ffesymbol_where (s))
{
case FFEINFO_whereLOCAL:
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recursion. */
break;
case FFEINFO_whereINTRINSIC:
case FFEINFO_whereGLOBAL:
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */
break;
case FFEINFO_whereCOMMON:
case FFEINFO_whereDUMMY:
case FFEINFO_whereRESULT:
break;
case FFEINFO_whereNONE:
case FFEINFO_whereANY:
break;
default:
ffesymbol_error (s, ffeexpr_tokens_[0]);
break;
}
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
{
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
}
else
{
e->u.operand = ffebld_new_symter (s,
ffesymbol_generic (s),
ffesymbol_specific (s),
ffesymbol_implementation (s));
ffebld_set_info (e->u.operand, ffesymbol_info (s));
}
ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
switch (paren_type)
{
case FFEEXPR_parentypeSUBROUTINE_:
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextACTUALARG_,
ffeexpr_token_arguments_);
case FFEEXPR_parentypeARRAY_:
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
ffeexpr_stack_->rank = 0;
ffeexpr_stack_->constant = TRUE;
ffeexpr_stack_->immediate = TRUE;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextDATAIMPDOITEM_:
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextDATAIMPDOINDEX_,
ffeexpr_token_elements_);
case FFEEXPR_contextEQUIVALENCE:
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextEQVINDEX_,
ffeexpr_token_elements_);
default:
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextINDEX_,
ffeexpr_token_elements_);
}
case FFEEXPR_parentypeSUBSTRING_:
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
ffeexpr_tokens_[0]);
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextINDEX_,
ffeexpr_token_substring_);
case FFEEXPR_parentypeEQUIVALENCE_:
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
ffeexpr_stack_->rank = 0;
ffeexpr_stack_->constant = TRUE;
ffeexpr_stack_->immediate = TRUE;
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextEQVINDEX_,
ffeexpr_token_equivalence_);
case FFEEXPR_parentypeFUNCTION_: /* Invalid case. */
case FFEEXPR_parentypeFUNSUBSTR_: /* Invalid case. */
ffesymbol_error (s, ffeexpr_tokens_[0]);
/* Fall through. */
case FFEEXPR_parentypeANY_:
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextACTUALARG_,
ffeexpr_token_anything_);
default:
assert ("bad paren type" == NULL);
break;
}
case FFELEX_typeEQUALS: /* As in "VAR=". */
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextIMPDOITEM_: /* within
"(,VAR=start,end[,incr])". */
case FFEEXPR_contextIMPDOITEMDF_:
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
break;
case FFEEXPR_contextDATAIMPDOITEM_:
ffeexpr_stack_->context = FFEEXPR_contextDATAIMPDOCTRL_;
break;
default:
break;
}
break;
#if 0
case FFELEX_typePERIOD:
case FFELEX_typePERCENT:
assert ("FOO%, FOO. not yet supported!~~" == NULL);
break;
#endif
default:
break;
}
just_name: /* :::::::::::::::::::: */
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0],
(ffeexpr_stack_->context
== FFEEXPR_contextSUBROUTINEREF));
switch (ffesymbol_where (s))
{
case FFEINFO_whereCONSTANT:
if ((ffeexpr_stack_->context != FFEEXPR_contextPARAMETER)
|| (ffesymbol_kind (s) != FFEINFO_kindENTITY))
ffesymbol_error (s, ffeexpr_tokens_[0]);
break;
case FFEINFO_whereIMMEDIATE:
if ((ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOCTRL_)
&& (ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOINDEX_))
ffesymbol_error (s, ffeexpr_tokens_[0]);
break;
case FFEINFO_whereLOCAL:
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recurse!. */
break;
case FFEINFO_whereINTRINSIC:
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */
break;
default:
break;
}
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
{
expr = ffebld_new_any ();
info = ffeinfo_new_any ();
ffebld_set_info (expr, info);
}
else
{
expr = ffebld_new_symter (s,
ffesymbol_generic (s),
ffesymbol_specific (s),
ffesymbol_implementation (s));
info = ffesymbol_info (s);
ffebld_set_info (expr, info);
if (ffesymbol_is_doiter (s))
{
ffebad_start (FFEBAD_DOITER);
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffest_ffebad_here_doiter (1, s);
ffebad_string (ffesymbol_text (s));
ffebad_finish ();
}
expr = ffeexpr_collapse_symter (expr, ffeexpr_tokens_[0]);
}
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
{
if (ffebld_op (expr) == FFEBLD_opANY)
{
expr = ffebld_new_any ();
ffebld_set_info (expr, ffeinfo_new_any ());
}
else
{
expr = ffebld_new_subrref (expr, NULL); /* No argument list. */
if (ffesymbol_generic (s) != FFEINTRIN_genNONE)
ffeintrin_fulfill_generic (&expr, &info, e->token);
else if (ffesymbol_specific (s) != FFEINTRIN_specNONE)
ffeintrin_fulfill_specific (&expr, &info, NULL, e->token);
else
ffeexpr_fulfill_call_ (&expr, e->token);
if (ffebld_op (expr) != FFEBLD_opANY)
ffebld_set_info (expr,
ffeinfo_new (ffeinfo_basictype (info),
ffeinfo_kindtype (info),
0,
FFEINFO_kindENTITY,
FFEINFO_whereFLEETING,
ffeinfo_size (info)));
else
ffebld_set_info (expr, ffeinfo_new_any ());
}
}
e->u.operand = expr;
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_finished_ (t);
}
/* ffeexpr_token_name_arg_ -- Rhs NAME
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle first token in an actual-arg (or possible actual-arg) context
being a NAME, and use second token to refine the context. */
static ffelexHandler
ffeexpr_token_name_arg_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeCLOSE_PAREN:
case FFELEX_typeCOMMA:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
break;
default:
break;
}
break;
default:
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
break;
case FFEEXPR_contextINDEXORACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
break;
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
ffeexpr_stack_->context
= FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
break;
default:
assert ("bad context in _name_arg_" == NULL);
break;
}
break;
}
return (ffelexHandler) ffeexpr_token_name_rhs_ (t);
}
/* ffeexpr_token_name_rhs_ -- Rhs NAME
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle a name followed by open-paren, apostrophe (O'octal-const',
Z'hex-const', or X'hex-const'), period (RECORD.MEMBER).
26-Nov-91 JCB 1.2
When followed by apostrophe or quote, set lex hexnum flag on so
[0-9] as first char of next token seen as starting a potentially
hex number (NAME).
04-Oct-91 JCB 1.1
In case of intrinsic, decorate its SYMTER with the type info for
the specific intrinsic. */
static ffelexHandler
ffeexpr_token_name_rhs_ (ffelexToken t)
{
ffeexprExpr_ e;
ffeexprParenType_ paren_type;
ffesymbol s;
bool sfdef;
switch (ffelex_token_type (t))
{
case FFELEX_typeQUOTE:
case FFELEX_typeAPOSTROPHE:
ffeexpr_tokens_[1] = ffelex_token_use (t);
ffelex_set_hexnum (TRUE);
return (ffelexHandler) ffeexpr_token_name_apos_;
case FFELEX_typeOPEN_PAREN:
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffelex_token_use (ffeexpr_tokens_[0]);
s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], TRUE,
&paren_type);
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
e->u.operand = ffebld_new_any ();
else
e->u.operand = ffebld_new_symter (s, ffesymbol_generic (s),
ffesymbol_specific (s),
ffesymbol_implementation (s));
ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
sfdef = TRUE;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("weird context!" == NULL);
sfdef = FALSE;
break;
default:
sfdef = FALSE;
break;
}
switch (paren_type)
{
case FFEEXPR_parentypeFUNCTION_:
ffebld_set_info (e->u.operand, ffesymbol_info (s));
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
{ /* A statement function. */
ffeexpr_stack_->num_args
= ffebld_list_length
(ffeexpr_stack_->next_dummy
= ffesymbol_dummyargs (s));
ffeexpr_stack_->tokens[1] = NULL; /* !=NULL when > num_args. */
}
else if ((ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
&& !ffe_is_pedantic_not_90 ()
&& ((ffesymbol_implementation (s)
== FFEINTRIN_impICHAR)
|| (ffesymbol_implementation (s)
== FFEINTRIN_impIACHAR)
|| (ffesymbol_implementation (s)
== FFEINTRIN_impLEN)))
{ /* Allow arbitrary concatenations. */
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEF
: FFEEXPR_contextLET,
ffeexpr_token_arguments_);
}
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEFACTUALARG_
: FFEEXPR_contextACTUALARG_,
ffeexpr_token_arguments_);
case FFEEXPR_parentypeARRAY_:
ffebld_set_info (e->u.operand,
ffesymbol_info (ffebld_symter (e->u.operand)));
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
ffeexpr_stack_->rank = 0;
ffeexpr_stack_->constant = TRUE;
ffeexpr_stack_->immediate = TRUE;
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEFINDEX_
: FFEEXPR_contextINDEX_,
ffeexpr_token_elements_);
case FFEEXPR_parentypeSUBSTRING_:
ffebld_set_info (e->u.operand,
ffesymbol_info (ffebld_symter (e->u.operand)));
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
ffeexpr_tokens_[0]);
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEFINDEX_
: FFEEXPR_contextINDEX_,
ffeexpr_token_substring_);
case FFEEXPR_parentypeFUNSUBSTR_:
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_
: FFEEXPR_contextINDEXORACTUALARG_,
ffeexpr_token_funsubstr_);
case FFEEXPR_parentypeANY_:
ffebld_set_info (e->u.operand, ffesymbol_info (s));
return
(ffelexHandler)
ffeexpr_rhs (ffeexpr_stack_->pool,
sfdef
? FFEEXPR_contextSFUNCDEFACTUALARG_
: FFEEXPR_contextACTUALARG_,
ffeexpr_token_anything_);
default:
assert ("bad paren type" == NULL);
break;
}
case FFELEX_typeEQUALS: /* As in "VAR=". */
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextIMPDOITEM_: /* "(,VAR=start,end[,incr])". */
case FFEEXPR_contextIMPDOITEMDF_:
ffeexpr_stack_->is_rhs = FALSE; /* Really an lhs construct. */
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
break;
default:
break;
}
break;
#if 0
case FFELEX_typePERIOD:
case FFELEX_typePERCENT:
~~Support these two someday, though not required
assert ("FOO%, FOO. not yet supported!~~" == NULL);
break;
#endif
default:
break;
}
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextINDEXORACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("strange context" == NULL);
break;
default:
break;
}
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0], FALSE);
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
{
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
}
else
{
e->u.operand = ffebld_new_symter (s, FFEINTRIN_genNONE,
ffesymbol_specific (s),
ffesymbol_implementation (s));
if (ffesymbol_specific (s) == FFEINTRIN_specNONE)
ffebld_set_info (e->u.operand, ffeinfo_use (ffesymbol_info (s)));
else
{ /* Decorate the SYMTER with the actual type
of the intrinsic. */
ffebld_set_info (e->u.operand, ffeinfo_new
(ffeintrin_basictype (ffesymbol_specific (s)),
ffeintrin_kindtype (ffesymbol_specific (s)),
0,
ffesymbol_kind (s),
ffesymbol_where (s),
FFETARGET_charactersizeNONE));
}
if (ffesymbol_is_doiter (s))
ffebld_symter_set_is_doiter (e->u.operand, TRUE);
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
ffeexpr_tokens_[0]);
}
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* ffeexpr_token_name_apos_ -- Rhs NAME APOSTROPHE
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Expecting a NAME token, analyze the previous NAME token to see what kind,
if any, typeless constant we've got.
01-Sep-90 JCB 1.1
Expect a NAME instead of CHARACTER in this situation. */
static ffelexHandler
ffeexpr_token_name_apos_ (ffelexToken t)
{
ffeexprExpr_ e;
ffelex_set_hexnum (FALSE);
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
ffeexpr_tokens_[2] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_name_apos_name_;
default:
break;
}
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
{
ffebad_string (ffelex_token_text (ffeexpr_tokens_[0]));
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[1]);
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
e->token = ffeexpr_tokens_[0];
ffeexpr_exprstack_push_operand_ (e);
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
/* ffeexpr_token_name_apos_name_ -- Rhs NAME APOSTROPHE NAME
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Expecting an APOSTROPHE token, analyze the previous NAME token to see
what kind, if any, typeless constant we've got. */
static ffelexHandler
ffeexpr_token_name_apos_name_ (ffelexToken t)
{
ffeexprExpr_ e;
char c;
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
e->token = ffeexpr_tokens_[0];
if ((ffelex_token_type (t) == ffelex_token_type (ffeexpr_tokens_[1]))
&& (ffelex_token_length (ffeexpr_tokens_[0]) == 1)
&& (ffesrc_char_match_init ((c = ffelex_token_text (ffeexpr_tokens_[0])[0]),
'B', 'b')
|| ffesrc_char_match_init (c, 'O', 'o')
|| ffesrc_char_match_init (c, 'X', 'x')
|| ffesrc_char_match_init (c, 'Z', 'z')))
{
ffetargetCharacterSize size;
if (!ffe_is_typeless_boz ()) {
switch (c)
{
case FFESRC_CASE_MATCH_INIT ('B', 'b', imatch_b, no_imatch):
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerbinary
(ffeexpr_tokens_[2]));
break;
case FFESRC_CASE_MATCH_INIT ('O', 'o', imatch_o, no_imatch):
e->u.operand = ffebld_new_conter (ffebld_constant_new_integeroctal
(ffeexpr_tokens_[2]));
break;
case FFESRC_CASE_MATCH_INIT ('X', 'x', imatch_x, no_imatch):
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex
(ffeexpr_tokens_[2]));
break;
case FFESRC_CASE_MATCH_INIT ('Z', 'z', imatch_z, no_imatch):
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex
(ffeexpr_tokens_[2]));
break;
default:
no_imatch: /* :::::::::::::::::::: */
assert ("not BOXZ!" == NULL);
abort ();
}
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
ffeexpr_exprstack_push_operand_ (e);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_;
}
switch (c)
{
case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_bm
(ffeexpr_tokens_[2]));
size = ffetarget_size_typeless_binary (ffeexpr_tokens_[2]);
break;
case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_om
(ffeexpr_tokens_[2]));
size = ffetarget_size_typeless_octal (ffeexpr_tokens_[2]);
break;
case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hxm
(ffeexpr_tokens_[2]));
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
break;
case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm
(ffeexpr_tokens_[2]));
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
break;
default:
no_match: /* :::::::::::::::::::: */
assert ("not BOXZ!" == NULL);
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm
(ffeexpr_tokens_[2]));
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
break;
}
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size));
ffeexpr_exprstack_push_operand_ (e);
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
return (ffelexHandler) ffeexpr_token_binary_;
}
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
{
ffebad_string (ffelex_token_text (ffeexpr_tokens_[0]));
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[2]);
e->type = FFEEXPR_exprtypeOPERAND_;
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
e->token = ffeexpr_tokens_[0];
ffeexpr_exprstack_push_operand_ (e);
switch (ffelex_token_type (t))
{
case FFELEX_typeAPOSTROPHE:
case FFELEX_typeQUOTE:
return (ffelexHandler) ffeexpr_token_binary_;
default:
return (ffelexHandler) ffeexpr_token_binary_ (t);
}
}
/* ffeexpr_token_percent_ -- Rhs PERCENT
Handle a percent sign possibly followed by "LOC". If followed instead
by "VAL", "REF", or "DESCR", issue an error message and substitute
"LOC". If followed by something else, treat the percent sign as a
spurious incorrect token and reprocess the token via _rhs_. */
static ffelexHandler
ffeexpr_token_percent_ (ffelexToken t)
{
switch (ffelex_token_type (t))
{
case FFELEX_typeNAME:
case FFELEX_typeNAMES:
ffeexpr_stack_->percent = ffeexpr_percent_ (t);
ffeexpr_tokens_[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_token_percent_name_;
default:
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_rhs_ (t);
}
}
/* ffeexpr_token_percent_name_ -- Rhs PERCENT NAME
Make sure the token is OPEN_PAREN and prepare for the one-item list of
LHS expressions. Else display an error message. */
static ffelexHandler
ffeexpr_token_percent_name_ (ffelexToken t)
{
ffelexHandler nexthandler;
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
{
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
ffelex_token_where_column (ffeexpr_stack_->first_token));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_tokens_[0]);
nexthandler = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_tokens_[1]);
ffelex_token_kill (ffeexpr_tokens_[1]);
return (ffelexHandler) (*nexthandler) (t);
}
switch (ffeexpr_stack_->percent)
{
default:
if (ffest_ffebad_start (FFEBAD_INVALID_PERCENT))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
ffelex_token_where_column (ffeexpr_tokens_[0]));
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
ffebad_finish ();
}
ffeexpr_stack_->percent = FFEEXPR_percentLOC_;
/* Fall through. */
case FFEEXPR_percentLOC_:
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
ffelex_token_kill (ffeexpr_tokens_[1]);
ffeexpr_stack_->tokens[1] = ffelex_token_use (t);
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextLOC_,
ffeexpr_cb_end_loc_);
}
}
/* ffeexpr_make_float_const_ -- Make a floating-point constant
See prototype.
Pass 'E', 'D', or 'Q' for exponent letter. */
static void
ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer,
ffelexToken decimal, ffelexToken fraction,
ffelexToken exponent, ffelexToken exponent_sign,
ffelexToken exponent_digits)
{
ffeexprExpr_ e;
e = ffeexpr_expr_new_ ();
e->type = FFEEXPR_exprtypeOPERAND_;
if (integer != NULL)
e->token = ffelex_token_use (integer);
else
{
assert (decimal != NULL);
e->token = ffelex_token_use (decimal);
}
switch (exp_letter)
{
#if !FFETARGET_okREALQUAD
case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match):
if (ffebad_start (FFEBAD_QUAD_UNSUPPORTED))
{
ffebad_here (0, ffelex_token_where_line (e->token),
ffelex_token_where_column (e->token));
ffebad_finish ();
}
goto match_d; /* The FFESRC_CASE_* macros don't
allow fall-through! */
#endif
case FFESRC_CASE_MATCH_INIT ('D', 'd', match_d, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_realdouble
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
break;
case FFESRC_CASE_MATCH_INIT ('E', 'e', match_e, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_realdefault
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeREAL,
FFEINFO_kindtypeREALDEFAULT, 0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
break;
#if FFETARGET_okREALQUAD
case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match):
e->u.operand = ffebld_new_conter (ffebld_constant_new_realquad
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALQUAD,
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
break;
#endif
case 'I': /* Make an integer. */
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
(ffeexpr_tokens_[0]));
ffebld_set_info (e->u.operand,
ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT, 0,
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
break;
default:
no_match: /* :::::::::::::::::::: */
assert ("Lost the exponent letter!" == NULL);
}
ffeexpr_exprstack_push_operand_ (e);
}
/* Just like ffesymbol_declare_local, except performs any implicit info
assignment necessary. */
static ffesymbol
ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin)
{
ffesymbol s;
ffeinfoKind k;
bool bad;
s = ffesymbol_declare_local (t, maybe_intrin);
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
/* Special-case these since they can involve a different concept
of "state" (in the stmtfunc name space). */
{
case FFEEXPR_contextDATAIMPDOINDEX_:
case FFEEXPR_contextDATAIMPDOCTRL_:
if (ffeexpr_context_outer_ (ffeexpr_stack_)
== FFEEXPR_contextDATAIMPDOINDEX_)
s = ffeexpr_sym_impdoitem_ (s, t);
else
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_sym_impdoitem_ (s, t);
else
s = ffeexpr_sym_lhs_impdoctrl_ (s, t);
bad = (ffesymbol_kind (s) != FFEINFO_kindENTITY)
|| ((ffesymbol_where (s) != FFEINFO_whereCONSTANT)
&& (ffesymbol_where (s) != FFEINFO_whereIMMEDIATE));
if (bad && (ffesymbol_kind (s) != FFEINFO_kindANY))
ffesymbol_error (s, t);
return s;
default:
break;
}
switch ((ffesymbol_sfdummyparent (s) == NULL)
? ffesymbol_state (s)
: FFESYMBOL_stateUNDERSTOOD)
{
case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr
context. */
if (!ffest_seen_first_exec ())
goto seen; /* :::::::::::::::::::: */
/* Fall through. */
case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSUBROUTINEREF:
s = ffeexpr_sym_lhs_call_ (s, t);
break;
case FFEEXPR_contextFILEEXTFUNC:
s = ffeexpr_sym_lhs_extfunc_ (s, t);
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
/* Fall through. */
case FFEEXPR_contextACTUALARG_:
s = ffeexpr_sym_rhs_actualarg_ (s, t);
break;
case FFEEXPR_contextDATA:
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_sym_rhs_let_ (s, t);
else
s = ffeexpr_sym_lhs_data_ (s, t);
break;
case FFEEXPR_contextDATAIMPDOITEM_:
s = ffeexpr_sym_lhs_data_ (s, t);
break;
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
/* Fall through. */
case FFEEXPR_contextLET:
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextDO:
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextIF:
case FFEEXPR_contextARITHIF:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextSTOP:
case FFEEXPR_contextRETURN:
case FFEEXPR_contextSELECTCASE:
case FFEEXPR_contextCASE:
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
case FFEEXPR_contextFILEDFINT:
case FFEEXPR_contextFILELOG:
case FFEEXPR_contextFILENUM:
case FFEEXPR_contextFILENUMAMBIG:
case FFEEXPR_contextFILECHAR:
case FFEEXPR_contextFILENUMCHAR:
case FFEEXPR_contextFILEDFCHAR:
case FFEEXPR_contextFILEKEY:
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextFILEUNIT_DF:
case FFEEXPR_contextFILEUNITAMBIG:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextFILENAMELIST:
case FFEEXPR_contextFILEVXTCODE:
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
case FFEEXPR_contextIMPDOCTRL_:
case FFEEXPR_contextLOC_:
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_sym_rhs_let_ (s, t);
else
s = ffeexpr_sym_lhs_let_ (s, t);
break;
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextEQUIVALENCE:
case FFEEXPR_contextINCLUDE:
case FFEEXPR_contextPARAMETER:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
break; /* Will turn into errors below. */
default:
ffesymbol_error (s, t);
break;
}
/* Fall through. */
case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */
understood: /* :::::::::::::::::::: */
k = ffesymbol_kind (s);
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSUBROUTINEREF:
bad = ((k != FFEINFO_kindSUBROUTINE)
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|| (k != FFEINFO_kindNONE)));
break;
case FFEEXPR_contextFILEEXTFUNC:
bad = (k != FFEINFO_kindFUNCTION)
|| (ffesymbol_where (s) != FFEINFO_whereGLOBAL);
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextACTUALARG_:
switch (k)
{
case FFEINFO_kindENTITY:
bad = FALSE;
break;
case FFEINFO_kindFUNCTION:
case FFEINFO_kindSUBROUTINE:
bad
= ((ffesymbol_where (s) != FFEINFO_whereGLOBAL)
&& (ffesymbol_where (s) != FFEINFO_whereDUMMY)
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|| !ffeintrin_is_actualarg (ffesymbol_specific (s))));
break;
case FFEINFO_kindNONE:
if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
{
bad = !(ffeintrin_is_actualarg (ffesymbol_specific (s)));
break;
}
/* If state is UNDERSTOOD here, it's CHAR*(*) or attrsANY,
and in the former case, attrsTYPE is set, so we
see this as an error as we should, since CHAR*(*)
cannot be actually referenced in a main/block data
program unit. */
if ((ffesymbol_attrs (s) & (FFESYMBOL_attrsANY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE))
== FFESYMBOL_attrsEXTERNAL)
bad = FALSE;
else
bad = TRUE;
break;
default:
bad = TRUE;
break;
}
break;
case FFEEXPR_contextDATA:
if (ffeexpr_stack_->is_rhs)
bad = (k != FFEINFO_kindENTITY)
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
else
bad = (k != FFEINFO_kindENTITY)
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
break;
case FFEEXPR_contextDATAIMPDOITEM_:
bad = TRUE; /* Unadorned item never valid. */
break;
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
case FFEEXPR_contextLET:
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextDO:
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextIF:
case FFEEXPR_contextARITHIF:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextSTOP:
case FFEEXPR_contextRETURN:
case FFEEXPR_contextSELECTCASE:
case FFEEXPR_contextCASE:
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
case FFEEXPR_contextFILEDFINT:
case FFEEXPR_contextFILELOG:
case FFEEXPR_contextFILENUM:
case FFEEXPR_contextFILENUMAMBIG:
case FFEEXPR_contextFILECHAR:
case FFEEXPR_contextFILENUMCHAR:
case FFEEXPR_contextFILEDFCHAR:
case FFEEXPR_contextFILEKEY:
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextFILEUNIT_DF:
case FFEEXPR_contextFILEUNITAMBIG:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextFILENAMELIST:
case FFEEXPR_contextFILEVXTCODE:
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
case FFEEXPR_contextIMPDOCTRL_:
case FFEEXPR_contextLOC_:
bad = (k != FFEINFO_kindENTITY); /* This catches "SUBROUTINE
X(A);EXTERNAL A;CALL
Y(A);B=A", for example. */
break;
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextEQUIVALENCE:
case FFEEXPR_contextPARAMETER:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
bad = (k != FFEINFO_kindENTITY)
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
break;
case FFEEXPR_contextINCLUDE:
bad = TRUE;
break;
default:
bad = TRUE;
break;
}
if (bad && (k != FFEINFO_kindANY))
ffesymbol_error (s, t);
return s;
case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */
seen: /* :::::::::::::::::::: */
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextPARAMETER:
if (ffeexpr_stack_->is_rhs)
ffesymbol_error (s, t);
else
s = ffeexpr_sym_lhs_parameter_ (s, t);
break;
case FFEEXPR_contextDATA:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
if (ffeexpr_stack_->is_rhs)
ffesymbol_error (s, t);
else
s = ffeexpr_sym_lhs_data_ (s, t);
goto understood; /* :::::::::::::::::::: */
case FFEEXPR_contextDATAIMPDOITEM_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
s = ffeexpr_sym_lhs_data_ (s, t);
goto understood; /* :::::::::::::::::::: */
case FFEEXPR_contextEQUIVALENCE:
s = ffeexpr_sym_lhs_equivalence_ (s, t);
break;
case FFEEXPR_contextDIMLIST:
s = ffeexpr_sym_rhs_dimlist_ (s, t);
break;
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
ffesymbol_error (s, t);
break;
case FFEEXPR_contextINCLUDE:
ffesymbol_error (s, t);
break;
case FFEEXPR_contextACTUALARG_: /* E.g. I in REAL A(Y(I)). */
case FFEEXPR_contextSFUNCDEFACTUALARG_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
s = ffeexpr_sym_rhs_actualarg_ (s, t);
goto understood; /* :::::::::::::::::::: */
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
assert (ffeexpr_stack_->is_rhs);
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
s = ffeexpr_sym_rhs_let_ (s, t);
goto understood; /* :::::::::::::::::::: */
default:
ffesymbol_error (s, t);
break;
}
return s;
default:
assert ("bad symbol state" == NULL);
return NULL;
break;
}
}
/* Have FOO in DATA (XYZ(FOO),...)/.../ or DATA (...,XYZ=FOO,BAR,BLETCH).
Could be found via the "statement-function" name space (in which case
it should become an iterator) or the local name space (in which case
it should be either a named constant, or a variable that will have an
sfunc name space sibling that should become an iterator). */
static ffesymbol
ffeexpr_sym_impdoitem_ (ffesymbol sp, ffelexToken t)
{
ffesymbol s;
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffesymbolState ss;
ffesymbolState ns;
ffeinfoKind kind;
ffeinfoWhere where;
ss = ffesymbol_state (sp);
if (ffesymbol_sfdummyparent (sp) != NULL)
{ /* Have symbol in sfunc name space. */
switch (ss)
{
case FFESYMBOL_stateNONE: /* Used as iterator already. */
if (ffeexpr_level_ < ffesymbol_maxentrynum (sp))
ffesymbol_error (sp, t); /* Can't use dead iterator. */
else
{ /* Can use dead iterator because we're at at
least an innermore (higher-numbered) level
than the iterator's outermost
(lowest-numbered) level. */
ffesymbol_signal_change (sp);
ffesymbol_set_state (sp, FFESYMBOL_stateSEEN);
ffesymbol_set_maxentrynum (sp, ffeexpr_level_);
ffesymbol_signal_unreported (sp);
}
break;
case FFESYMBOL_stateSEEN: /* Seen already in this or other
implied-DO. Set symbol level
number to outermost value, as that
tells us we can see it as iterator
at that level at the innermost. */
if (ffeexpr_level_ < ffesymbol_maxentrynum (sp))
{
ffesymbol_signal_change (sp);
ffesymbol_set_maxentrynum (sp, ffeexpr_level_);
ffesymbol_signal_unreported (sp);
}
break;
case FFESYMBOL_stateUNCERTAIN: /* Iterator. */
assert (ffeexpr_level_ == ffesymbol_maxentrynum (sp));
ffesymbol_error (sp, t); /* (,,,I=I,10). */
break;
case FFESYMBOL_stateUNDERSTOOD:
break; /* ANY. */
default:
assert ("Foo Bar!!" == NULL);
break;
}
return sp;
}
/* Got symbol in local name space, so we haven't seen it in impdo yet.
First, if it is brand-new and we're in executable statements, set the
attributes and exec-transition it to set state UNCERTAIN or UNDERSTOOD.
Second, if it is now a constant (PARAMETER), then just return it, it
can't be an implied-do iterator. If it is understood, complain if it is
not a valid variable, but make the inner name space iterator anyway and
return that. If it is not understood, improve understanding of the
symbol accordingly, complain accordingly, in either case make the inner
name space iterator and return that. */
sa = ffesymbol_attrs (sp);
if (ffesymbol_state_is_specable (ss)
&& ffest_seen_first_exec ())
{
assert (sa == FFESYMBOL_attrsetNONE);
ffesymbol_signal_change (sp);
ffesymbol_set_state (sp, FFESYMBOL_stateSEEN);
ffesymbol_resolve_intrin (sp);
if (ffeimplic_establish_symbol (sp))
ffesymbol_set_attr (sp, FFESYMBOL_attrSFARG);
else
ffesymbol_error (sp, t);
/* After the exec transition, the state will either be UNCERTAIN (could
be a dummy or local var) or UNDERSTOOD (local var, because this is a
PROGRAM/BLOCKDATA program unit). */
sp = ffecom_sym_exec_transition (sp);
sa = ffesymbol_attrs (sp);
ss = ffesymbol_state (sp);
}
ns = ss;
kind = ffesymbol_kind (sp);
where = ffesymbol_where (sp);
if (ss == FFESYMBOL_stateUNDERSTOOD)
{
if (kind != FFEINFO_kindENTITY)
ffesymbol_error (sp, t);
if (where == FFEINFO_whereCONSTANT)
return sp;
}
else
{
/* Enhance understanding of local symbol. This used to imply exec
transition, but that doesn't seem necessary, since the local symbol
doesn't actually get put into an ffebld tree here -- we just learn
more about it, just like when we see a local symbol's name in the
dummy-arg list of a statement function. */
if (ss != FFESYMBOL_stateUNCERTAIN)
{
/* Figure out what kind of object we've got based on previous
declarations of or references to the object. */
ns = FFESYMBOL_stateSEEN;
if (sa & FFESYMBOL_attrsANY)
na = sa;
else if (!(sa & ~(FFESYMBOL_attrsADJUSTS
| FFESYMBOL_attrsANY
| FFESYMBOL_attrsCOMMON
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEQUIV
| FFESYMBOL_attrsINIT
| FFESYMBOL_attrsNAMELIST
| FFESYMBOL_attrsRESULT
| FFESYMBOL_attrsSAVE
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)))
na = sa | FFESYMBOL_attrsSFARG;
else
na = FFESYMBOL_attrsetNONE;
}
else
{ /* stateUNCERTAIN. */
na = sa | FFESYMBOL_attrsSFARG;
ns = FFESYMBOL_stateUNDERSTOOD;
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
na = FFESYMBOL_attrsetNONE;
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
kind = FFEINFO_kindENTITY;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
na = FFESYMBOL_attrsetNONE;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
ns = FFESYMBOL_stateUNCERTAIN;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
kind = FFEINFO_kindENTITY;
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
na = FFESYMBOL_attrsetNONE;
else if (ffest_is_entry_valid ())
ns = FFESYMBOL_stateUNCERTAIN; /* Could be DUMMY or LOCAL. */
else
where = FFEINFO_whereLOCAL;
}
else
na = FFESYMBOL_attrsetNONE; /* Error. */
}
/* Now see what we've got for a new object: NONE means a new error
cropped up; ANY means an old error to be ignored; otherwise,
everything's ok, update the object (symbol) and continue on. */
if (na == FFESYMBOL_attrsetNONE)
ffesymbol_error (sp, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (sp); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (sp))
ffesymbol_error (sp, t);
else
{
ffesymbol_set_info (sp,
ffeinfo_new (ffesymbol_basictype (sp),
ffesymbol_kindtype (sp),
ffesymbol_rank (sp),
kind,
where,
ffesymbol_size (sp)));
ffesymbol_set_attrs (sp, na);
ffesymbol_set_state (sp, ns);
ffesymbol_resolve_intrin (sp);
if (!ffesymbol_state_is_specable (ns))
sp = ffecom_sym_learned (sp);
ffesymbol_signal_unreported (sp); /* For debugging purposes. */
}
}
}
/* Here we create the sfunc-name-space symbol representing what should
become an iterator in this name space at this or an outermore (lower-
numbered) expression level, else the implied-DO construct is in error. */
s = ffesymbol_declare_sfdummy (t); /* Sets maxentrynum to 0 for new obj;
also sets sfa_dummy_parent to
parent symbol. */
assert (sp == ffesymbol_sfdummyparent (s));
ffesymbol_signal_change (s);
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
ffesymbol_set_info (s,
ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT,
0,
FFEINFO_kindENTITY,
FFEINFO_whereIMMEDIATE,
FFETARGET_charactersizeNONE));
ffesymbol_signal_unreported (s);
if (((ffesymbol_basictype (sp) != FFEINFO_basictypeINTEGER)
&& (ffesymbol_basictype (sp) != FFEINFO_basictypeANY))
|| ((ffesymbol_kindtype (sp) != FFEINFO_kindtypeINTEGERDEFAULT)
&& (ffesymbol_kindtype (sp) != FFEINFO_kindtypeANY)))
ffesymbol_error (s, t);
return s;
}
/* Have FOO in CALL FOO. Local name space, executable context only. */
static ffesymbol
ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
ffeintrinGen gen;
ffeintrinSpec spec;
ffeintrinImp imp;
bool error = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsTYPE)
error = TRUE;
else
/* Not TYPE. */
{
kind = FFEINFO_kindSUBROUTINE;
if (sa & FFESYMBOL_attrsDUMMY)
; /* Not TYPE. */
else if (sa & FFESYMBOL_attrsACTUALARG)
; /* Not DUMMY or TYPE. */
else /* Not ACTUALARG, DUMMY, or TYPE. */
where = FFEINFO_whereGLOBAL;
}
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsTYPE)
error = TRUE;
else
kind = FFEINFO_kindSUBROUTINE;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
error = TRUE;
}
else if (sa == FFESYMBOL_attrsetNONE)
{
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
&gen, &spec, &imp))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
ffesymbol_set_generic (s, gen);
ffesymbol_set_specific (s, spec);
ffesymbol_set_implementation (s, imp);
ffesymbol_set_info (s,
ffeinfo_new (FFEINFO_basictypeNONE,
FFEINFO_kindtypeNONE,
0,
FFEINFO_kindSUBROUTINE,
FFEINFO_whereINTRINSIC,
FFETARGET_charactersizeNONE));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
ffesymbol_reference (s, t, FALSE);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
return s;
}
kind = FFEINFO_kindSUBROUTINE;
where = FFEINFO_whereGLOBAL;
}
else
error = TRUE;
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (error)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* SUBROUTINE. */
where, /* GLOBAL or DUMMY. */
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
ffesymbol_reference (s, t, FALSE);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in DATA FOO/.../. Local name space and executable context
only. (This will change in the future when DATA FOO may be followed
by COMMON FOO or even INTEGER FOO(10), etc.) */
static ffesymbol
ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
bool error = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsADJUSTABLE)
error = TRUE;
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
error = TRUE;
else
{
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
}
else if (sa == FFESYMBOL_attrsetNONE)
{
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
else
error = TRUE;
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (error)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* ENTITY. */
where, /* LOCAL. */
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in EQUIVALENCE (...,FOO,...). Does not include
EQUIVALENCE (...,BAR(FOO),...). */
static ffesymbol
ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
na = sa = ffesymbol_attrs (s);
kind = FFEINFO_kindENTITY;
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (!(sa & ~(FFESYMBOL_attrsADJUSTS
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsCOMMON
| FFESYMBOL_attrsEQUIV
| FFESYMBOL_attrsINIT
| FFESYMBOL_attrsNAMELIST
| FFESYMBOL_attrsSAVE
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)))
na = sa | FFESYMBOL_attrsEQUIV;
else
na = FFESYMBOL_attrsetNONE;
/* Don't know why we're bothering to set kind and where in this code, but
added the following to make it complete, in case it's really important.
Generally this is left up to symbol exec transition. */
if (where == FFEINFO_whereNONE)
{
if (na & (FFESYMBOL_attrsADJUSTS
| FFESYMBOL_attrsCOMMON))
where = FFEINFO_whereCOMMON;
else if (na & FFESYMBOL_attrsSAVE)
where = FFEINFO_whereLOCAL;
}
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (na == FFESYMBOL_attrsetNONE)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* Always ENTITY. */
where, /* NONE, COMMON, or LOCAL. */
ffesymbol_size (s)));
ffesymbol_set_attrs (s, na);
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
ffesymbol_resolve_intrin (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in OPEN(...,USEROPEN=FOO,...). Executable context only.
Note that I think this should be considered semantically similar to
doing CALL XYZ(FOO), in that it should be considered like an
ACTUALARG context. In particular, without EXTERNAL being specified,
it should not be allowed. */
static ffesymbol
ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
bool needs_type = FALSE;
bool error = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsTYPE)
where = FFEINFO_whereGLOBAL;
else
/* Not TYPE. */
{
kind = FFEINFO_kindFUNCTION;
needs_type = TRUE;
if (sa & FFESYMBOL_attrsDUMMY)
; /* Not TYPE. */
else if (sa & FFESYMBOL_attrsACTUALARG)
; /* Not DUMMY or TYPE. */
else /* Not ACTUALARG, DUMMY, or TYPE. */
where = FFEINFO_whereGLOBAL;
}
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
kind = FFEINFO_kindFUNCTION;
if (!(sa & FFESYMBOL_attrsTYPE))
needs_type = TRUE;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
error = TRUE;
else
{
kind = FFEINFO_kindFUNCTION;
where = FFEINFO_whereGLOBAL;
}
}
else if (sa == FFESYMBOL_attrsetNONE)
{
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
kind = FFEINFO_kindFUNCTION;
where = FFEINFO_whereGLOBAL;
needs_type = TRUE;
}
else
error = TRUE;
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (error)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (needs_type && !ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
if (!ffesymbol_explicitwhere (s))
{
ffebad_start (FFEBAD_NEED_EXTERNAL);
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_string (ffesymbol_text (s));
ffebad_finish ();
ffesymbol_set_explicitwhere (s, TRUE);
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* FUNCTION. */
where, /* GLOBAL or DUMMY. */
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
ffesymbol_reference (s, t, FALSE);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in DATA (stuff,FOO=1,10)/.../. */
static ffesymbol
ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t)
{
ffesymbolState ss;
/* If the symbol isn't in the sfunc name space, pretend as though we saw a
reference to it already within the imp-DO construct at this level, so as
to get a symbol that is in the sfunc name space. But this is an
erroneous construct, and should be caught elsewhere. */
if (ffesymbol_sfdummyparent (s) == NULL)
{
s = ffeexpr_sym_impdoitem_ (s, t);
if (ffesymbol_sfdummyparent (s) == NULL)
{ /* PARAMETER FOO...DATA (A(I),FOO=...). */
ffesymbol_error (s, t);
return s;
}
}
ss = ffesymbol_state (s);
switch (ss)
{
case FFESYMBOL_stateNONE: /* Used as iterator already. */
if (ffeexpr_level_ < ffesymbol_maxentrynum (s))
ffesymbol_error (s, t); /* Can't reuse dead iterator. F90 disallows
this; F77 allows it but it is a stupid
feature. */
else
{ /* Can use dead iterator because we're at at
least a innermore (higher-numbered) level
than the iterator's outermost
(lowest-numbered) level. This should be
diagnosed later, because it means an item
in this list didn't reference this
iterator. */
#if 1
ffesymbol_error (s, t); /* For now, complain. */
#else /* Someday will detect all cases where initializer doesn't reference
all applicable iterators, in which case reenable this code. */
ffesymbol_signal_change (s);
ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN);
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
ffesymbol_signal_unreported (s);
#endif
}
break;
case FFESYMBOL_stateSEEN: /* Seen already in this or other implied-DO.
If seen in outermore level, can't be an
iterator here, so complain. If not seen
at current level, complain for now,
because that indicates something F90
rejects (though we currently don't detect
all such cases for now). */
if (ffeexpr_level_ <= ffesymbol_maxentrynum (s))
{
ffesymbol_signal_change (s);
ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN);
ffesymbol_signal_unreported (s);
}
else
ffesymbol_error (s, t);
break;
case FFESYMBOL_stateUNCERTAIN: /* Already iterator! */
assert ("DATA implied-DO control var seen twice!!" == NULL);
ffesymbol_error (s, t);
break;
case FFESYMBOL_stateUNDERSTOOD:
break; /* ANY. */
default:
assert ("Foo Bletch!!" == NULL);
break;
}
return s;
}
/* Have FOO in PARAMETER (FOO=...). */
static ffesymbol
ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
sa = ffesymbol_attrs (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & ~(FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsTYPE))
{
if (!(sa & FFESYMBOL_attrsANY))
ffesymbol_error (s, t);
}
else
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in CALL XYZ(...,FOO,...). Does not include any other
embedding of FOO, such as CALL XYZ((FOO)) or CALL XYZ(FOO+1). */
static ffesymbol
ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
ffesymbolState ns;
bool needs_type = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
ns = FFESYMBOL_stateUNDERSTOOD;
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsTYPE)
where = FFEINFO_whereGLOBAL;
else
/* Not TYPE. */
{
ns = FFESYMBOL_stateUNCERTAIN;
if (sa & FFESYMBOL_attrsDUMMY)
assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */
else if (sa & FFESYMBOL_attrsACTUALARG)
; /* Not DUMMY or TYPE. */
else
/* Not ACTUALARG, DUMMY, or TYPE. */
{
assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */
na |= FFESYMBOL_attrsACTUALARG;
where = FFEINFO_whereGLOBAL;
}
}
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
kind = FFEINFO_kindENTITY;
if (!(sa & FFESYMBOL_attrsTYPE))
needs_type = TRUE;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
if (sa & FFESYMBOL_attrsANYLEN)
ns = FFESYMBOL_stateNONE;
else
{
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
}
else if (sa == FFESYMBOL_attrsetNONE)
{
/* New state is left empty because there isn't any state flag to
set for this case, and it's UNDERSTOOD after all. */
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
needs_type = TRUE;
}
else
ns = FFESYMBOL_stateNONE; /* Error. */
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (ns == FFESYMBOL_stateNONE)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (needs_type && !ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind,
where,
ffesymbol_size (s)));
ffesymbol_set_attrs (s, na);
ffesymbol_set_state (s, ns);
s = ffecom_sym_learned (s);
ffesymbol_reference (s, t, FALSE);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in DIMENSION XYZ(FOO) or any array declarator containing
a reference to FOO. */
static ffesymbol
ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
na = sa = ffesymbol_attrs (s);
kind = FFEINFO_kindENTITY;
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (!(sa & ~(FFESYMBOL_attrsADJUSTS
| FFESYMBOL_attrsCOMMON
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEQUIV
| FFESYMBOL_attrsINIT
| FFESYMBOL_attrsNAMELIST
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsARRAY
1999-08-26 09:30:50 +00:00
| FFESYMBOL_attrsTYPE)))
na = sa | FFESYMBOL_attrsADJUSTS;
else
na = FFESYMBOL_attrsetNONE;
/* Since this symbol definitely is going into an expression (the
dimension-list for some dummy array, presumably), figure out WHERE if
possible. */
if (where == FFEINFO_whereNONE)
{
if (na & (FFESYMBOL_attrsCOMMON
| FFESYMBOL_attrsEQUIV
| FFESYMBOL_attrsINIT
| FFESYMBOL_attrsNAMELIST))
where = FFEINFO_whereCOMMON;
else if (na & FFESYMBOL_attrsDUMMY)
where = FFEINFO_whereDUMMY;
}
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (na == FFESYMBOL_attrsetNONE)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* Always ENTITY. */
where, /* NONE, COMMON, or DUMMY. */
ffesymbol_size (s)));
ffesymbol_set_attrs (s, na);
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
ffesymbol_resolve_intrin (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* Have FOO in XYZ = ...FOO.... Does not include cases like FOO in
XYZ = BAR(FOO), as such cases are handled elsewhere. */
static ffesymbol
ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
bool error = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
error = TRUE;
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
kind = FFEINFO_kindENTITY;
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
if (sa & FFESYMBOL_attrsANYLEN)
error = TRUE;
else
{
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
}
else if (sa == FFESYMBOL_attrsetNONE)
{
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
else
error = TRUE;
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (error)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind, /* ENTITY. */
where, /* LOCAL. */
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* ffeexpr_declare_parenthesized_ -- ffesymbol wrapper for NAME(...) operand
ffelexToken t;
bool maybe_intrin;
ffeexprParenType_ paren_type;
ffesymbol s;
s = ffeexpr_declare_parenthesized_ (t, maybe_intrin, &paren_type);
Just like ffesymbol_declare_local, except performs any implicit info
assignment necessary, and it returns the type of the parenthesized list
(list of function args, list of array args, or substring spec). */
static ffesymbol
ffeexpr_declare_parenthesized_ (ffelexToken t, bool maybe_intrin,
ffeexprParenType_ *paren_type)
{
ffesymbol s;
ffesymbolState st; /* Effective state. */
ffeinfoKind k;
bool bad;
if (maybe_intrin && ffesrc_check_symbol ())
{ /* Knock off some easy cases. */
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextSUBROUTINEREF:
case FFEEXPR_contextDATA:
case FFEEXPR_contextDATAIMPDOINDEX_:
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
case FFEEXPR_contextLET:
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextDO:
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextIF:
case FFEEXPR_contextARITHIF:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextSTOP:
case FFEEXPR_contextRETURN:
case FFEEXPR_contextSELECTCASE:
case FFEEXPR_contextCASE:
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
case FFEEXPR_contextFILEDFINT:
case FFEEXPR_contextFILELOG:
case FFEEXPR_contextFILENUM:
case FFEEXPR_contextFILENUMAMBIG:
case FFEEXPR_contextFILECHAR:
case FFEEXPR_contextFILENUMCHAR:
case FFEEXPR_contextFILEDFCHAR:
case FFEEXPR_contextFILEKEY:
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextFILEUNIT_DF:
case FFEEXPR_contextFILEUNITAMBIG:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextFILENAMELIST:
case FFEEXPR_contextFILEVXTCODE:
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
case FFEEXPR_contextIMPDOCTRL_:
case FFEEXPR_contextDATAIMPDOCTRL_:
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextPARAMETER:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
break; /* These could be intrinsic invocations. */
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextFILEFORMATNML:
case FFEEXPR_contextALLOCATE:
case FFEEXPR_contextDEALLOCATE:
case FFEEXPR_contextHEAPSTAT:
case FFEEXPR_contextNULLIFY:
case FFEEXPR_contextINCLUDE:
case FFEEXPR_contextDATAIMPDOITEM_:
case FFEEXPR_contextLOC_:
case FFEEXPR_contextINDEXORACTUALARG_:
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
case FFEEXPR_contextPARENFILENUM_:
case FFEEXPR_contextPARENFILEUNIT_:
maybe_intrin = FALSE;
break; /* Can't be intrinsic invocation. */
default:
assert ("blah! blah! waaauuggh!" == NULL);
break;
}
}
s = ffesymbol_declare_local (t, maybe_intrin);
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
/* Special-case these since they can involve a different concept
of "state" (in the stmtfunc name space). */
{
case FFEEXPR_contextDATAIMPDOINDEX_:
case FFEEXPR_contextDATAIMPDOCTRL_:
if (ffeexpr_context_outer_ (ffeexpr_stack_)
== FFEEXPR_contextDATAIMPDOINDEX_)
s = ffeexpr_sym_impdoitem_ (s, t);
else
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_sym_impdoitem_ (s, t);
else
s = ffeexpr_sym_lhs_impdoctrl_ (s, t);
if (ffesymbol_kind (s) != FFEINFO_kindANY)
ffesymbol_error (s, t);
return s;
default:
break;
}
switch ((ffesymbol_sfdummyparent (s) == NULL)
? ffesymbol_state (s)
: FFESYMBOL_stateUNDERSTOOD)
{
case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr
context. */
if (!ffest_seen_first_exec ())
goto seen; /* :::::::::::::::::::: */
/* Fall through. */
case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSUBROUTINEREF:
s = ffeexpr_sym_lhs_call_ (s, t); /* "CALL FOO"=="CALL
FOO(...)". */
break;
case FFEEXPR_contextDATA:
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_sym_rhs_let_ (s, t);
else
s = ffeexpr_sym_lhs_data_ (s, t);
break;
case FFEEXPR_contextDATAIMPDOITEM_:
s = ffeexpr_sym_lhs_data_ (s, t);
break;
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
/* Fall through. */
case FFEEXPR_contextLET:
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextDO:
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextIF:
case FFEEXPR_contextARITHIF:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextSTOP:
case FFEEXPR_contextRETURN:
case FFEEXPR_contextSELECTCASE:
case FFEEXPR_contextCASE:
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
case FFEEXPR_contextFILEDFINT:
case FFEEXPR_contextFILELOG:
case FFEEXPR_contextFILENUM:
case FFEEXPR_contextFILENUMAMBIG:
case FFEEXPR_contextFILECHAR:
case FFEEXPR_contextFILENUMCHAR:
case FFEEXPR_contextFILEDFCHAR:
case FFEEXPR_contextFILEKEY:
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextFILEUNIT_DF:
case FFEEXPR_contextFILEUNITAMBIG:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextFILENAMELIST:
case FFEEXPR_contextFILEVXTCODE:
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
case FFEEXPR_contextIMPDOCTRL_:
case FFEEXPR_contextLOC_:
if (ffeexpr_stack_->is_rhs)
s = ffeexpr_paren_rhs_let_ (s, t);
else
s = ffeexpr_paren_lhs_let_ (s, t);
break;
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextEQUIVALENCE:
case FFEEXPR_contextINCLUDE:
case FFEEXPR_contextPARAMETER:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
break; /* Will turn into errors below. */
default:
ffesymbol_error (s, t);
break;
}
/* Fall through. */
case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */
understood: /* :::::::::::::::::::: */
/* State might have changed, update it. */
st = ((ffesymbol_sfdummyparent (s) == NULL)
? ffesymbol_state (s)
: FFESYMBOL_stateUNDERSTOOD);
k = ffesymbol_kind (s);
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSUBROUTINEREF:
bad = ((k != FFEINFO_kindSUBROUTINE)
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|| (k != FFEINFO_kindNONE)));
break;
case FFEEXPR_contextDATA:
if (ffeexpr_stack_->is_rhs)
bad = (k != FFEINFO_kindENTITY)
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
else
bad = (k != FFEINFO_kindENTITY)
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
break;
case FFEEXPR_contextDATAIMPDOITEM_:
bad = (k != FFEINFO_kindENTITY) || (ffesymbol_rank (s) == 0)
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
break;
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
case FFEEXPR_contextLET:
case FFEEXPR_contextPAREN_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextIOLIST:
case FFEEXPR_contextIOLISTDF:
case FFEEXPR_contextDO:
case FFEEXPR_contextDOWHILE:
case FFEEXPR_contextACTUALARG_:
case FFEEXPR_contextCGOTO:
case FFEEXPR_contextIF:
case FFEEXPR_contextARITHIF:
case FFEEXPR_contextFORMAT:
case FFEEXPR_contextSTOP:
case FFEEXPR_contextRETURN:
case FFEEXPR_contextSELECTCASE:
case FFEEXPR_contextCASE:
case FFEEXPR_contextFILEASSOC:
case FFEEXPR_contextFILEINT:
case FFEEXPR_contextFILEDFINT:
case FFEEXPR_contextFILELOG:
case FFEEXPR_contextFILENUM:
case FFEEXPR_contextFILENUMAMBIG:
case FFEEXPR_contextFILECHAR:
case FFEEXPR_contextFILENUMCHAR:
case FFEEXPR_contextFILEDFCHAR:
case FFEEXPR_contextFILEKEY:
case FFEEXPR_contextFILEUNIT:
case FFEEXPR_contextFILEUNIT_DF:
case FFEEXPR_contextFILEUNITAMBIG:
case FFEEXPR_contextFILEFORMAT:
case FFEEXPR_contextFILENAMELIST:
case FFEEXPR_contextFILEVXTCODE:
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextIMPDOITEM_:
case FFEEXPR_contextIMPDOITEMDF_:
case FFEEXPR_contextIMPDOCTRL_:
case FFEEXPR_contextLOC_:
bad = FALSE; /* Let paren-switch handle the cases. */
break;
case FFEEXPR_contextASSIGN:
case FFEEXPR_contextAGOTO:
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextEQUIVALENCE:
case FFEEXPR_contextPARAMETER:
case FFEEXPR_contextDIMLIST:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
bad = (k != FFEINFO_kindENTITY)
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
break;
case FFEEXPR_contextINCLUDE:
bad = TRUE;
break;
default:
bad = TRUE;
break;
}
switch (bad ? FFEINFO_kindANY : k)
{
case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */
if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
{
if (ffeexpr_context_outer_ (ffeexpr_stack_)
== FFEEXPR_contextSUBROUTINEREF)
*paren_type = FFEEXPR_parentypeSUBROUTINE_;
else
*paren_type = FFEEXPR_parentypeFUNCTION_;
break;
}
if (st == FFESYMBOL_stateUNDERSTOOD)
{
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
}
else
*paren_type = FFEEXPR_parentypeFUNSUBSTR_;
break;
case FFEINFO_kindFUNCTION:
*paren_type = FFEEXPR_parentypeFUNCTION_;
switch (ffesymbol_where (s))
{
case FFEINFO_whereLOCAL:
bad = TRUE; /* Attempt to recurse! */
break;
case FFEINFO_whereCONSTANT:
bad = ((ffesymbol_sfexpr (s) == NULL)
|| (ffebld_op (ffesymbol_sfexpr (s))
== FFEBLD_opANY)); /* Attempt to recurse! */
break;
default:
break;
}
break;
case FFEINFO_kindSUBROUTINE:
if ((ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
|| (ffeexpr_stack_->previous != NULL))
{
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
break;
}
*paren_type = FFEEXPR_parentypeSUBROUTINE_;
switch (ffesymbol_where (s))
{
case FFEINFO_whereLOCAL:
case FFEINFO_whereCONSTANT:
bad = TRUE; /* Attempt to recurse! */
break;
default:
break;
}
break;
case FFEINFO_kindENTITY:
if (ffesymbol_rank (s) == 0)
{
if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)
*paren_type = FFEEXPR_parentypeSUBSTRING_;
else
{
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
}
}
else
*paren_type = FFEEXPR_parentypeARRAY_;
break;
default:
case FFEINFO_kindANY:
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
break;
}
if (bad)
{
if (k == FFEINFO_kindANY)
ffest_shutdown ();
else
ffesymbol_error (s, t);
}
return s;
case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */
seen: /* :::::::::::::::::::: */
bad = TRUE;
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextPARAMETER:
if (ffeexpr_stack_->is_rhs)
ffesymbol_error (s, t);
else
s = ffeexpr_sym_lhs_parameter_ (s, t);
break;
case FFEEXPR_contextDATA:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
if (ffeexpr_stack_->is_rhs)
ffesymbol_error (s, t);
else
s = ffeexpr_sym_lhs_data_ (s, t);
goto understood; /* :::::::::::::::::::: */
case FFEEXPR_contextDATAIMPDOITEM_:
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
s = ffeexpr_sym_lhs_data_ (s, t);
goto understood; /* :::::::::::::::::::: */
case FFEEXPR_contextEQUIVALENCE:
s = ffeexpr_sym_lhs_equivalence_ (s, t);
bad = FALSE;
break;
case FFEEXPR_contextDIMLIST:
s = ffeexpr_sym_rhs_dimlist_ (s, t);
bad = FALSE;
1999-08-26 09:30:50 +00:00
break;
case FFEEXPR_contextCHARACTERSIZE:
case FFEEXPR_contextKINDTYPE:
case FFEEXPR_contextDIMLISTCOMMON:
case FFEEXPR_contextINITVAL:
case FFEEXPR_contextEQVINDEX_:
break;
case FFEEXPR_contextINCLUDE:
break;
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextACTUALARGEXPR_:
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
assert (ffeexpr_stack_->is_rhs);
s = ffecom_sym_exec_transition (s);
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
goto understood; /* :::::::::::::::::::: */
s = ffeexpr_paren_rhs_let_ (s, t);
goto understood; /* :::::::::::::::::::: */
default:
break;
}
k = ffesymbol_kind (s);
switch (bad ? FFEINFO_kindANY : k)
{
case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */
*paren_type = FFEEXPR_parentypeFUNSUBSTR_;
break;
case FFEINFO_kindFUNCTION:
*paren_type = FFEEXPR_parentypeFUNCTION_;
switch (ffesymbol_where (s))
{
case FFEINFO_whereLOCAL:
bad = TRUE; /* Attempt to recurse! */
break;
case FFEINFO_whereCONSTANT:
bad = ((ffesymbol_sfexpr (s) == NULL)
|| (ffebld_op (ffesymbol_sfexpr (s))
== FFEBLD_opANY)); /* Attempt to recurse! */
break;
default:
break;
}
break;
case FFEINFO_kindSUBROUTINE:
*paren_type = FFEEXPR_parentypeANY_;
bad = TRUE; /* Cannot possibly be in
contextSUBROUTINEREF. */
break;
case FFEINFO_kindENTITY:
if (ffesymbol_rank (s) == 0)
{
if (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE)
*paren_type = FFEEXPR_parentypeEQUIVALENCE_;
else if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)
*paren_type = FFEEXPR_parentypeSUBSTRING_;
else
{
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
}
}
else
*paren_type = FFEEXPR_parentypeARRAY_;
break;
default:
case FFEINFO_kindANY:
bad = TRUE;
*paren_type = FFEEXPR_parentypeANY_;
break;
}
if (bad)
{
if (k == FFEINFO_kindANY)
ffest_shutdown ();
else
ffesymbol_error (s, t);
}
return s;
default:
assert ("bad symbol state" == NULL);
return NULL;
}
}
/* Have FOO in XYZ = ...FOO(...).... Executable context only. */
static ffesymbol
ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t)
{
ffesymbolAttrs sa;
ffesymbolAttrs na;
ffeinfoKind kind;
ffeinfoWhere where;
ffeintrinGen gen;
ffeintrinSpec spec;
ffeintrinImp imp;
bool maybe_ambig = FALSE;
bool error = FALSE;
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
na = sa = ffesymbol_attrs (s);
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
kind = ffesymbol_kind (s);
where = ffesymbol_where (s);
/* Figure out what kind of object we've got based on previous declarations
of or references to the object. */
if (sa & FFESYMBOL_attrsEXTERNAL)
{
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
if (sa & FFESYMBOL_attrsTYPE)
where = FFEINFO_whereGLOBAL;
else
/* Not TYPE. */
{
kind = FFEINFO_kindFUNCTION;
if (sa & FFESYMBOL_attrsDUMMY)
; /* Not TYPE. */
else if (sa & FFESYMBOL_attrsACTUALARG)
; /* Not DUMMY or TYPE. */
else /* Not ACTUALARG, DUMMY, or TYPE. */
where = FFEINFO_whereGLOBAL;
}
}
else if (sa & FFESYMBOL_attrsDUMMY)
{
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsTYPE)));
kind = FFEINFO_kindFUNCTION;
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure; kind
could be ENTITY w/substring ref. */
}
else if (sa & FFESYMBOL_attrsARRAY)
{
assert (!(sa & ~(FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL;
}
else if (sa & FFESYMBOL_attrsSFARG)
{
assert (!(sa & ~(FFESYMBOL_attrsSFARG
| FFESYMBOL_attrsTYPE)));
where = FFEINFO_whereLOCAL; /* Actually an error, but at least we
know it's a local var. */
}
else if (sa & FFESYMBOL_attrsTYPE)
{
assert (!(sa & (FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG))); /* Handled above. */
assert (!(sa & ~(FFESYMBOL_attrsTYPE
| FFESYMBOL_attrsADJUSTABLE
| FFESYMBOL_attrsANYLEN
| FFESYMBOL_attrsARRAY
| FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsEXTERNAL
| FFESYMBOL_attrsSFARG)));
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
&gen, &spec, &imp))
{
if (!(sa & FFESYMBOL_attrsANYLEN)
&& (ffeimplic_peek_symbol_type (s, NULL)
== FFEINFO_basictypeCHARACTER))
return s; /* Haven't learned anything yet. */
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
ffesymbol_set_generic (s, gen);
ffesymbol_set_specific (s, spec);
ffesymbol_set_implementation (s, imp);
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
0,
FFEINFO_kindFUNCTION,
FFEINFO_whereINTRINSIC,
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
ffesymbol_reference (s, t, FALSE);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
return s;
}
if (sa & FFESYMBOL_attrsANYLEN)
error = TRUE; /* Error, since the only way we can,
given CHARACTER*(*) FOO, accept
FOO(...) is for FOO to be a dummy
arg or constant, but it can't
become either now. */
else if (sa & FFESYMBOL_attrsADJUSTABLE)
{
kind = FFEINFO_kindENTITY;
where = FFEINFO_whereLOCAL;
}
else
{
kind = FFEINFO_kindFUNCTION;
where = FFEINFO_whereGLOBAL;
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure;
could be ENTITY/LOCAL w/substring ref. */
}
}
else if (sa == FFESYMBOL_attrsetNONE)
{
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
&gen, &spec, &imp))
{
if (ffeimplic_peek_symbol_type (s, NULL)
== FFEINFO_basictypeCHARACTER)
return s; /* Haven't learned anything yet. */
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
ffesymbol_set_generic (s, gen);
ffesymbol_set_specific (s, spec);
ffesymbol_set_implementation (s, imp);
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
0,
FFEINFO_kindFUNCTION,
FFEINFO_whereINTRINSIC,
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_reference (s, t, FALSE);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
return s;
}
kind = FFEINFO_kindFUNCTION;
where = FFEINFO_whereGLOBAL;
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure;
could be ENTITY/LOCAL w/substring ref. */
}
else
error = TRUE;
/* Now see what we've got for a new object: NONE means a new error cropped
up; ANY means an old error to be ignored; otherwise, everything's ok,
update the object (symbol) and continue on. */
if (error)
ffesymbol_error (s, t);
else if (!(na & FFESYMBOL_attrsANY))
{
ffesymbol_signal_change (s); /* May need to back up to previous
version. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, t);
return s;
}
if (maybe_ambig
&& (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
return s; /* Still not sure, let caller deal with it
based on (...). */
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
kind,
where,
ffesymbol_size (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_reference (s, t, FALSE);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
}
return s;
}
/* ffeexpr_token_arguments_ -- OPEN_PAREN [expr COMMA]...expr
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle expression (which might be null) and COMMA or CLOSE_PAREN. */
static ffelexHandler
ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ procedure;
ffebld reduced;
ffeinfo info;
ffeexprContext ctx;
bool check_intrin = FALSE; /* Set TRUE if intrinsic is REAL(Z) or AIMAG(Z). */
procedure = ffeexpr_stack_->exprstack;
info = ffebld_info (procedure->u.operand);
/* Is there an expression to add? If the expression is nil,
it might still be an argument. It is if:
- The current token is comma, or
- The -fugly-comma flag was specified *and* the procedure
being invoked is external.
Otherwise, if neither of the above is the case, just
ignore this (nil) expression. */
if ((expr != NULL)
|| (ffelex_token_type (t) == FFELEX_typeCOMMA)
|| (ffe_is_ugly_comma ()
&& (ffeinfo_where (info) == FFEINFO_whereGLOBAL)))
{
/* This expression, even if nil, is apparently intended as an argument. */
/* Internal procedure (CONTAINS, or statement function)? */
if (ffeinfo_where (info) == FFEINFO_whereCONSTANT)
{
if ((expr == NULL)
&& ffebad_start (FFEBAD_NULL_ARGUMENT))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_here (1, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
if (expr == NULL)
;
else
{
if (ffeexpr_stack_->next_dummy == NULL)
{ /* Report later which was the first extra argument. */
if (ffeexpr_stack_->tokens[1] == NULL)
{
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
ffeexpr_stack_->num_args = 0;
}
++ffeexpr_stack_->num_args; /* Count # of extra arguments. */
}
else
{
if ((ffeinfo_rank (ffebld_info (expr)) != 0)
&& ffebad_start (FFEBAD_ARRAY_AS_SFARG))
{
ffebad_here (0,
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_here (1, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_string (ffesymbol_text (ffesymbol_sfdummyparent
(ffebld_symter (ffebld_head
(ffeexpr_stack_->next_dummy)))));
ffebad_finish ();
}
else
{
expr = ffeexpr_convert_expr (expr, ft,
ffebld_head (ffeexpr_stack_->next_dummy),
ffeexpr_stack_->tokens[0],
FFEEXPR_contextLET);
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
}
--ffeexpr_stack_->num_args; /* Count down # of args. */
ffeexpr_stack_->next_dummy
= ffebld_trail (ffeexpr_stack_->next_dummy);
}
}
}
else
{
if ((expr == NULL)
&& ffe_is_pedantic ()
&& ffebad_start (FFEBAD_NULL_ARGUMENT_W))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_here (1, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
}
}
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
case FFEEXPR_contextSFUNCDEFINDEX_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
ctx = FFEEXPR_contextSFUNCDEFACTUALARG_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("bad context" == NULL);
ctx = FFEEXPR_context;
break;
default:
ctx = FFEEXPR_contextACTUALARG_;
break;
}
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
ffeexpr_token_arguments_);
default:
break;
}
if ((ffeinfo_where (info) == FFEINFO_whereCONSTANT)
&& (ffeexpr_stack_->next_dummy != NULL))
{ /* Too few arguments. */
if (ffebad_start (FFEBAD_TOO_FEW_ARGUMENTS))
{
char num[10];
sprintf (num, "%" ffebldListLength_f "u", ffeexpr_stack_->num_args);
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_string (num);
ffebad_string (ffesymbol_text (ffesymbol_sfdummyparent (ffebld_symter
(ffebld_head (ffeexpr_stack_->next_dummy)))));
ffebad_finish ();
}
for (;
ffeexpr_stack_->next_dummy != NULL;
ffeexpr_stack_->next_dummy
= ffebld_trail (ffeexpr_stack_->next_dummy))
{
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (0));
ffebld_set_info (expr, ffeinfo_new_any ());
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
}
}
if ((ffeinfo_where (info) == FFEINFO_whereCONSTANT)
&& (ffeexpr_stack_->tokens[1] != NULL))
{ /* Too many arguments to statement function. */
if (ffebad_start (FFEBAD_TOO_MANY_ARGUMENTS))
{
char num[10];
sprintf (num, "%" ffebldListLength_f "u", ffeexpr_stack_->num_args);
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_string (num);
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
}
ffebld_end_list (&ffeexpr_stack_->bottom);
if (ffebld_op (procedure->u.operand) == FFEBLD_opANY)
{
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
}
else
{
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
reduced = ffebld_new_funcref (procedure->u.operand,
ffeexpr_stack_->expr);
else
reduced = ffebld_new_subrref (procedure->u.operand,
ffeexpr_stack_->expr);
if (ffebld_symter_generic (procedure->u.operand) != FFEINTRIN_genNONE)
ffeintrin_fulfill_generic (&reduced, &info, ffeexpr_stack_->tokens[0]);
else if (ffebld_symter_specific (procedure->u.operand)
!= FFEINTRIN_specNONE)
ffeintrin_fulfill_specific (&reduced, &info, &check_intrin,
ffeexpr_stack_->tokens[0]);
else
ffeexpr_fulfill_call_ (&reduced, ffeexpr_stack_->tokens[0]);
if (ffebld_op (reduced) != FFEBLD_opANY)
ffebld_set_info (reduced,
ffeinfo_new (ffeinfo_basictype (info),
ffeinfo_kindtype (info),
0,
FFEINFO_kindENTITY,
FFEINFO_whereFLEETING,
ffeinfo_size (info)));
else
ffebld_set_info (reduced, ffeinfo_new_any ());
}
if (ffebld_op (reduced) == FFEBLD_opFUNCREF)
reduced = ffeexpr_collapse_funcref (reduced, ffeexpr_stack_->tokens[0]);
ffeexpr_stack_->exprstack = procedure->previous; /* Pops
not-quite-operand off
stack. */
procedure->u.operand = reduced; /* Save the line/column ffewhere
info. */
ffeexpr_exprstack_push_operand_ (procedure); /* Push it back on stack. */
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
{
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
ffeexpr_is_substr_ok_ = FALSE; /* Nobody likes "FUNC(3)(1:1)".... */
/* If the intrinsic needs checking (is REAL(Z) or AIMAG(Z), where
Z is DOUBLE COMPLEX), and a command-line option doesn't already
establish interpretation, probably complain. */
if (check_intrin
&& !ffe_is_90 ()
&& !ffe_is_ugly_complex ())
{
/* If the outer expression is REAL(me...), issue diagnostic
only if next token isn't the close-paren for REAL(me). */
if ((ffeexpr_stack_->previous != NULL)
&& (ffeexpr_stack_->previous->exprstack != NULL)
&& (ffeexpr_stack_->previous->exprstack->type == FFEEXPR_exprtypeOPERAND_)
&& ((reduced = ffeexpr_stack_->previous->exprstack->u.operand) != NULL)
&& (ffebld_op (reduced) == FFEBLD_opSYMTER)
&& (ffebld_symter_implementation (reduced) == FFEINTRIN_impREAL))
return (ffelexHandler) ffeexpr_token_intrincheck_;
/* Diagnose the ambiguity now. */
if (ffebad_start (FFEBAD_INTRINSIC_CMPAMBIG))
{
ffebad_string (ffeintrin_name_implementation
(ffebld_symter_implementation
(ffebld_left
(ffeexpr_stack_->exprstack->u.operand))));
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
ffebad_finish ();
}
}
return (ffelexHandler) ffeexpr_token_substrp_;
}
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
ffeexpr_is_substr_ok_ = FALSE;/* Nobody likes "FUNC(3)(1:1)".... */
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_substrp_);
}
/* ffeexpr_token_elements_ -- OPEN_PAREN [expr COMMA]...expr
Return a pointer to this array to the lexer (ffelex), which will
invoke it for the next token.
Handle expression and COMMA or CLOSE_PAREN. */
static ffelexHandler
ffeexpr_token_elements_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ array;
ffebld reduced;
ffeinfo info;
ffeinfoWhere where;
ffetargetIntegerDefault val;
ffetargetIntegerDefault lval = 0;
ffetargetIntegerDefault uval = 0;
ffebld lbound;
ffebld ubound;
bool lcheck;
bool ucheck;
array = ffeexpr_stack_->exprstack;
info = ffebld_info (array->u.operand);
if ((expr == NULL) /* && ((ffeexpr_stack_->rank != 0) ||
(ffelex_token_type(t) ==
FFELEX_typeCOMMA)) */ )
{
if (ffebad_start (FFEBAD_NULL_ELEMENT))
{
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_here (1, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_finish ();
}
if (ffeexpr_stack_->rank < ffeinfo_rank (info))
{ /* Don't bother if we're going to complain
later! */
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
ffebld_set_info (expr, ffeinfo_new_any ());
}
}
if (expr == NULL)
;
else if (ffeinfo_rank (info) == 0)
{ /* In EQUIVALENCE context, ffeinfo_rank(info)
may == 0. */
++ffeexpr_stack_->rank; /* Track anyway, may need for new VXT
feature. */
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
}
else
{
++ffeexpr_stack_->rank;
if (ffeexpr_stack_->rank > ffeinfo_rank (info))
{ /* Report later which was the first extra
element. */
if (ffeexpr_stack_->rank == ffeinfo_rank (info) + 1)
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
}
else
{
switch (ffeinfo_where (ffebld_info (expr)))
{
case FFEINFO_whereCONSTANT:
break;
case FFEINFO_whereIMMEDIATE:
ffeexpr_stack_->constant = FALSE;
break;
default:
ffeexpr_stack_->constant = FALSE;
ffeexpr_stack_->immediate = FALSE;
break;
}
if (ffebld_op (expr) == FFEBLD_opCONTER
&& ffebld_kindtype (expr) == FFEINFO_kindtypeINTEGERDEFAULT)
1999-08-26 09:30:50 +00:00
{
val = ffebld_constant_integerdefault (ffebld_conter (expr));
lbound = ffebld_left (ffebld_head (ffeexpr_stack_->bound_list));
if (lbound == NULL)
{
lcheck = TRUE;
lval = 1;
}
else if (ffebld_op (lbound) == FFEBLD_opCONTER)
{
lcheck = TRUE;
lval = ffebld_constant_integerdefault (ffebld_conter (lbound));
}
else
lcheck = FALSE;
ubound = ffebld_right (ffebld_head (ffeexpr_stack_->bound_list));
assert (ubound != NULL);
if (ffebld_op (ubound) == FFEBLD_opCONTER)
{
ucheck = TRUE;
uval = ffebld_constant_integerdefault (ffebld_conter (ubound));
}
else
ucheck = FALSE;
if ((lcheck && (val < lval)) || (ucheck && (val > uval)))
{
ffebad_start (FFEBAD_RANGE_ARRAY);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
}
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
ffeexpr_stack_->bound_list = ffebld_trail (ffeexpr_stack_->bound_list);
}
}
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
{
case FFEEXPR_contextDATAIMPDOITEM_:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextDATAIMPDOINDEX_,
ffeexpr_token_elements_);
case FFEEXPR_contextEQUIVALENCE:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextEQVINDEX_,
ffeexpr_token_elements_);
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextSFUNCDEFINDEX_,
ffeexpr_token_elements_);
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("bad context" == NULL);
break;
default:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextINDEX_,
ffeexpr_token_elements_);
}
default:
break;
}
if ((ffeexpr_stack_->rank != ffeinfo_rank (info))
&& (ffeinfo_rank (info) != 0))
{
char num[10];
if (ffeexpr_stack_->rank < ffeinfo_rank (info))
{
if (ffebad_start (FFEBAD_TOO_FEW_ELEMENTS))
{
sprintf (num, "%d",
(int) (ffeinfo_rank (info) - ffeexpr_stack_->rank));
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1,
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_string (num);
ffebad_finish ();
}
}
else
{
if (ffebad_start (FFEBAD_TOO_MANY_ELEMENTS))
{
sprintf (num, "%d",
(int) (ffeexpr_stack_->rank - ffeinfo_rank (info)));
ffebad_here (0,
ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
ffebad_here (1,
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_string (num);
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
}
while (ffeexpr_stack_->rank++ < ffeinfo_rank (info))
{
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeINTEGER,
FFEINFO_kindtypeINTEGERDEFAULT,
0, FFEINFO_kindENTITY,
FFEINFO_whereCONSTANT,
FFETARGET_charactersizeNONE));
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
}
}
ffebld_end_list (&ffeexpr_stack_->bottom);
if (ffebld_op (array->u.operand) == FFEBLD_opANY)
{
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
}
else
{
reduced = ffebld_new_arrayref (array->u.operand, ffeexpr_stack_->expr);
if (ffeexpr_stack_->constant)
where = FFEINFO_whereFLEETING_CADDR;
else if (ffeexpr_stack_->immediate)
where = FFEINFO_whereFLEETING_IADDR;
else
where = FFEINFO_whereFLEETING;
ffebld_set_info (reduced,
ffeinfo_new (ffeinfo_basictype (info),
ffeinfo_kindtype (info),
0,
FFEINFO_kindENTITY,
where,
ffeinfo_size (info)));
reduced = ffeexpr_collapse_arrayref (reduced, ffeexpr_stack_->tokens[0]);
}
ffeexpr_stack_->exprstack = array->previous; /* Pops not-quite-operand off
stack. */
array->u.operand = reduced; /* Save the line/column ffewhere info. */
ffeexpr_exprstack_push_operand_ (array); /* Push it back on stack. */
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeCHARACTER:
ffeexpr_is_substr_ok_ = TRUE; /* Everyone likes "FOO(3)(1:1)".... */
break;
case FFEINFO_basictypeNONE:
ffeexpr_is_substr_ok_ = TRUE;
assert (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE);
break;
default:
ffeexpr_is_substr_ok_ = FALSE;
break;
}
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
{
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
return (ffelexHandler) ffeexpr_token_substrp_;
}
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_substrp_);
}
/* ffeexpr_token_equivalence_ -- OPEN_PAREN expr
Return a pointer to this array to the lexer (ffelex), which will
invoke it for the next token.
If token is COLON, pass off to _substr_, else init list and pass off
to _elements_. This handles the case "EQUIVALENCE (FOO(expr?", where
? marks the token, and where FOO's rank/type has not yet been established,
meaning we could be in a list of indices or in a substring
specification. */
static ffelexHandler
ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
if (ffelex_token_type (t) == FFELEX_typeCOLON)
return ffeexpr_token_substring_ (ft, expr, t);
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return ffeexpr_token_elements_ (ft, expr, t);
}
/* ffeexpr_token_substring_ -- NAME(of kindENTITY) OPEN_PAREN expr
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle expression (which may be null) and COLON. */
static ffelexHandler
ffeexpr_token_substring_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeexprExpr_ string;
ffeinfo info;
ffetargetIntegerDefault i;
ffeexprContext ctx;
ffetargetCharacterSize size;
string = ffeexpr_stack_->exprstack;
info = ffebld_info (string->u.operand);
size = ffebld_size_max (string->u.operand);
if (ffelex_token_type (t) == FFELEX_typeCOLON)
{
if ((expr != NULL)
&& (ffebld_op (expr) == FFEBLD_opCONTER)
&& (((i = ffebld_constant_integerdefault (ffebld_conter (expr)))
< 1)
|| ((size != FFETARGET_charactersizeNONE) && (i > size))))
{
ffebad_start (FFEBAD_RANGE_SUBSTR);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
ffeexpr_stack_->expr = expr;
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
ctx = FFEEXPR_contextSFUNCDEFINDEX_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("bad context" == NULL);
ctx = FFEEXPR_context;
break;
default:
ctx = FFEEXPR_contextINDEX_;
break;
}
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
ffeexpr_token_substring_1_);
}
if (ffest_ffebad_start (FFEBAD_MISSING_COLON_IN_SUBSTR))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
ffeexpr_stack_->expr = NULL;
return (ffelexHandler) ffeexpr_token_substring_1_ (ft, expr, t);
}
/* ffeexpr_token_substring_1_ -- NAME OPEN_PAREN [expr COMMA]...expr
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
Handle expression (which might be null) and CLOSE_PAREN. */
static ffelexHandler
ffeexpr_token_substring_1_ (ffelexToken ft, ffebld last, ffelexToken t)
{
ffeexprExpr_ string;
ffebld reduced;
ffebld substrlist;
ffebld first = ffeexpr_stack_->expr;
ffebld strop;
ffeinfo info;
ffeinfoWhere lwh;
ffeinfoWhere rwh;
ffeinfoWhere where;
ffeinfoKindtype first_kt;
ffeinfoKindtype last_kt;
ffetargetIntegerDefault first_val;
ffetargetIntegerDefault last_val;
ffetargetCharacterSize size;
ffetargetCharacterSize strop_size_max;
bool first_known;
1999-08-26 09:30:50 +00:00
string = ffeexpr_stack_->exprstack;
strop = string->u.operand;
info = ffebld_info (strop);
if (first == NULL
|| (ffebld_op (first) == FFEBLD_opCONTER
&& ffebld_kindtype (first) == FFEINFO_kindtypeINTEGERDEFAULT))
1999-08-26 09:30:50 +00:00
{ /* The starting point is known. */
first_val = (first == NULL) ? 1
: ffebld_constant_integerdefault (ffebld_conter (first));
first_known = TRUE;
1999-08-26 09:30:50 +00:00
}
else
{ /* Assume start of the entity. */
first_val = 1;
first_known = FALSE;
1999-08-26 09:30:50 +00:00
}
if (last != NULL
&& (ffebld_op (last) == FFEBLD_opCONTER
&& ffebld_kindtype (last) == FFEINFO_kindtypeINTEGERDEFAULT))
1999-08-26 09:30:50 +00:00
{ /* The ending point is known. */
last_val = ffebld_constant_integerdefault (ffebld_conter (last));
if (first_known)
1999-08-26 09:30:50 +00:00
{ /* The beginning point is a constant. */
if (first_val <= last_val)
size = last_val - first_val + 1;
else
{
if (0 && ffe_is_90 ())
size = 0;
else
{
size = 1;
ffebad_start (FFEBAD_ZERO_SIZE);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
}
}
else
size = FFETARGET_charactersizeNONE;
strop_size_max = ffebld_size_max (strop);
if ((strop_size_max != FFETARGET_charactersizeNONE)
&& (last_val > strop_size_max))
{ /* Beyond maximum possible end of string. */
ffebad_start (FFEBAD_RANGE_SUBSTR);
ffebad_here (0, ffelex_token_where_line (ft),
ffelex_token_where_column (ft));
ffebad_finish ();
}
}
else
size = FFETARGET_charactersizeNONE; /* The size is not known. */
#if 0 /* Don't do this, or "is size of target
known?" would no longer be easily
answerable. To see if there is a max
size, use ffebld_size_max; to get only the
known size, else NONE, use
ffebld_size_known; use ffebld_size if
values are sure to be the same (not
opSUBSTR or opCONCATENATE or known to have
known length). By getting rid of this
"useful info" stuff, we don't end up
blank-padding the constant in the
assignment "A(I:J)='XYZ'" to the known
length of A. */
if (size == FFETARGET_charactersizeNONE)
size = strop_size_max; /* Assume we use the entire string. */
#endif
substrlist
= ffebld_new_item
(first,
ffebld_new_item
(last,
NULL
)
)
;
if (first == NULL)
lwh = FFEINFO_whereCONSTANT;
else
lwh = ffeinfo_where (ffebld_info (first));
if (last == NULL)
rwh = FFEINFO_whereCONSTANT;
else
rwh = ffeinfo_where (ffebld_info (last));
switch (lwh)
{
case FFEINFO_whereCONSTANT:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
where = FFEINFO_whereCONSTANT;
break;
case FFEINFO_whereIMMEDIATE:
where = FFEINFO_whereIMMEDIATE;
break;
default:
where = FFEINFO_whereFLEETING;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (rwh)
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE:
where = FFEINFO_whereIMMEDIATE;
break;
default:
where = FFEINFO_whereFLEETING;
break;
}
break;
default:
where = FFEINFO_whereFLEETING;
break;
}
if (first == NULL)
first_kt = FFEINFO_kindtypeINTEGERDEFAULT;
else
first_kt = ffeinfo_kindtype (ffebld_info (first));
if (last == NULL)
last_kt = FFEINFO_kindtypeINTEGERDEFAULT;
else
last_kt = ffeinfo_kindtype (ffebld_info (last));
switch (where)
{
case FFEINFO_whereCONSTANT:
switch (ffeinfo_where (info))
{
case FFEINFO_whereCONSTANT:
break;
case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */
where = FFEINFO_whereIMMEDIATE;
break;
default:
where = FFEINFO_whereFLEETING_CADDR;
break;
}
break;
case FFEINFO_whereIMMEDIATE:
switch (ffeinfo_where (info))
{
case FFEINFO_whereCONSTANT:
case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */
break;
default:
where = FFEINFO_whereFLEETING_IADDR;
break;
}
break;
default:
switch (ffeinfo_where (info))
{
case FFEINFO_whereCONSTANT:
where = FFEINFO_whereCONSTANT_SUBOBJECT; /* An F90 concept. */
break;
case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */
default:
where = FFEINFO_whereFLEETING;
break;
}
break;
}
if (ffebld_op (strop) == FFEBLD_opANY)
{
reduced = ffebld_new_any ();
ffebld_set_info (reduced, ffeinfo_new_any ());
}
else
{
reduced = ffebld_new_substr (strop, substrlist);
ffebld_set_info (reduced, ffeinfo_new
(FFEINFO_basictypeCHARACTER,
ffeinfo_kindtype (info),
0,
FFEINFO_kindENTITY,
where,
size));
reduced = ffeexpr_collapse_substr (reduced, ffeexpr_stack_->tokens[0]);
}
ffeexpr_stack_->exprstack = string->previous; /* Pops not-quite-operand off
stack. */
string->u.operand = reduced; /* Save the line/column ffewhere info. */
ffeexpr_exprstack_push_operand_ (string); /* Push it back on stack. */
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
{
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
ffeexpr_is_substr_ok_ = FALSE; /* Nobody likes "FOO(3:5)(1:1)".... */
return (ffelexHandler) ffeexpr_token_substrp_;
}
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
ffebad_finish ();
}
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
ffeexpr_is_substr_ok_ = FALSE;/* Nobody likes "FOO(3:5)(1:1)".... */
return
(ffelexHandler) ffeexpr_find_close_paren_ (t,
(ffelexHandler)
ffeexpr_token_substrp_);
}
/* ffeexpr_token_substrp_ -- Rhs <character entity>
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
If OPEN_PAREN, treat as start of a substring ("(3:4)") construct, and
issue error message if flag (serves as argument) is set. Else, just
forward token to binary_. */
static ffelexHandler
ffeexpr_token_substrp_ (ffelexToken t)
{
ffeexprContext ctx;
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
return (ffelexHandler) ffeexpr_token_binary_ (t);
ffeexpr_stack_->tokens[0] = ffelex_token_use (t);
switch (ffeexpr_stack_->context)
{
case FFEEXPR_contextSFUNCDEF:
case FFEEXPR_contextSFUNCDEFINDEX_:
ctx = FFEEXPR_contextSFUNCDEFINDEX_;
break;
case FFEEXPR_contextSFUNCDEFACTUALARG_:
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
assert ("bad context" == NULL);
ctx = FFEEXPR_context;
break;
default:
ctx = FFEEXPR_contextINDEX_;
break;
}
if (!ffeexpr_is_substr_ok_)
{
if (ffebad_start (FFEBAD_BAD_SUBSTR))
{
ffebad_here (0, ffelex_token_where_line (t),
ffelex_token_where_column (t));
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
ffebad_finish ();
}
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
ffeexpr_token_anything_);
}
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
ffeexpr_token_substring_);
}
static ffelexHandler
ffeexpr_token_intrincheck_ (ffelexToken t)
{
if ((ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
&& ffebad_start (FFEBAD_INTRINSIC_CMPAMBIG))
{
ffebad_string (ffeintrin_name_implementation
(ffebld_symter_implementation
(ffebld_left
(ffeexpr_stack_->exprstack->u.operand))));
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
ffebad_finish ();
}
return (ffelexHandler) ffeexpr_token_substrp_ (t);
}
/* ffeexpr_token_funsubstr_ -- NAME OPEN_PAREN expr
Return a pointer to this function to the lexer (ffelex), which will
invoke it for the next token.
If COLON, do everything we would have done since _parenthesized_ if
we had known NAME represented a kindENTITY instead of a kindFUNCTION.
If not COLON, do likewise for kindFUNCTION instead. */
static ffelexHandler
ffeexpr_token_funsubstr_ (ffelexToken ft, ffebld expr, ffelexToken t)
{
ffeinfoWhere where;
ffesymbol s;
ffesymbolAttrs sa;
ffebld symter = ffeexpr_stack_->exprstack->u.operand;
bool needs_type;
ffeintrinGen gen;
ffeintrinSpec spec;
ffeintrinImp imp;
s = ffebld_symter (symter);
sa = ffesymbol_attrs (s);
where = ffesymbol_where (s);
/* We get here only if we don't already know enough about FOO when seeing a
FOO(stuff) reference, and FOO might turn out to be a CHARACTER type. If
"stuff" is a substring reference, then FOO is a CHARACTER scalar type.
Else FOO is a function, either intrinsic or external. If intrinsic, it
wouldn't necessarily be CHARACTER type, so unless it has already been
declared DUMMY, it hasn't had its type established yet. It can't be
CHAR*(*) in any case, though it can have an explicit CHAR*n type. */
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
| FFESYMBOL_attrsTYPE)));
needs_type = !(ffesymbol_attrs (s) & FFESYMBOL_attrsDUMMY);
ffesymbol_signal_change (s); /* Probably already done, but in case.... */
if (ffelex_token_type (t) == FFELEX_typeCOLON)
{ /* Definitely an ENTITY (char substring). */
if (needs_type && !ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, ffeexpr_stack_->tokens[0]);
return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t);
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
FFEINFO_kindENTITY,
(where == FFEINFO_whereNONE)
? FFEINFO_whereLOCAL
: where,
ffesymbol_size (s)));
ffebld_set_info (symter, ffeinfo_use (ffesymbol_info (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
ffeexpr_stack_->exprstack->u.operand
= ffeexpr_collapse_symter (symter, ffeexpr_tokens_[0]);
return (ffelexHandler) ffeexpr_token_substring_ (ft, expr, t);
}
/* The "stuff" isn't a substring notation, so we now know the overall
reference is to a function. */
if (ffeintrin_is_intrinsic (ffesymbol_text (s), ffeexpr_stack_->tokens[0],
FALSE, &gen, &spec, &imp))
{
ffebld_symter_set_generic (symter, gen);
ffebld_symter_set_specific (symter, spec);
ffebld_symter_set_implementation (symter, imp);
ffesymbol_set_generic (s, gen);
ffesymbol_set_specific (s, spec);
ffesymbol_set_implementation (s, imp);
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
0,
FFEINFO_kindFUNCTION,
FFEINFO_whereINTRINSIC,
ffesymbol_size (s)));
}
else
{ /* Not intrinsic, now needs CHAR type. */
if (!ffeimplic_establish_symbol (s))
{
ffesymbol_error (s, ffeexpr_stack_->tokens[0]);
return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t);
}
ffesymbol_set_info (s,
ffeinfo_new (ffesymbol_basictype (s),
ffesymbol_kindtype (s),
ffesymbol_rank (s),
FFEINFO_kindFUNCTION,
(where == FFEINFO_whereNONE)
? FFEINFO_whereGLOBAL
: where,
ffesymbol_size (s)));
}
ffebld_set_info (symter, ffeinfo_use (ffesymbol_info (s)));
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
ffesymbol_resolve_intrin (s);
s = ffecom_sym_learned (s);
ffesymbol_reference (s, ffeexpr_stack_->tokens[0], FALSE);
ffesymbol_signal_unreported (s); /* For debugging purposes. */
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t);
}
/* ffeexpr_token_anything_ -- NAME OPEN_PAREN any-expr
Handle basically any expression, looking for CLOSE_PAREN. */
static ffelexHandler
ffeexpr_token_anything_ (ffelexToken ft UNUSED, ffebld expr UNUSED,
ffelexToken t)
{
ffeexprExpr_ e = ffeexpr_stack_->exprstack;
switch (ffelex_token_type (t))
{
case FFELEX_typeCOMMA:
case FFELEX_typeCOLON:
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
FFEEXPR_contextACTUALARG_,
ffeexpr_token_anything_);
default:
e->u.operand = ffebld_new_any ();
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
ffeexpr_is_substr_ok_ = FALSE;
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
return (ffelexHandler) ffeexpr_token_substrp_;
return (ffelexHandler) ffeexpr_token_substrp_ (t);
}
}
/* Terminate module. */
void
ffeexpr_terminate_2 ()
{
assert (ffeexpr_stack_ == NULL);
assert (ffeexpr_level_ == 0);
}