aboutsummaryrefslogtreecommitdiff
path: root/gcc/f/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/f/expr.c')
-rw-r--r--gcc/f/expr.c19405
1 files changed, 19405 insertions, 0 deletions
diff --git a/gcc/f/expr.c b/gcc/f/expr.c
new file mode 100644
index 00000000000..057293b0eef
--- /dev/null
+++ b/gcc/f/expr.c
@@ -0,0 +1,19405 @@
+/* expr.c -- Implementation File (module.c template V1.0)
+ Copyright (C) 1995-1997 Free Software Foundation, Inc.
+ Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
+
+This file is part of GNU Fortran.
+
+GNU Fortran is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Fortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Fortran; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+ Related Modules:
+ None.
+
+ Description:
+ Handles syntactic and semantic analysis of Fortran expressions.
+
+ Modifications:
+*/
+
+/* Include files. */
+
+#include "proj.h"
+#include <ctype.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 "target.h"
+#include "where.h"
+
+/* Externals defined here. */
+
+
+/* Simple definitions and enumerations. */
+
+typedef enum
+ {
+ FFEEXPR_dotdotNONE_,
+ FFEEXPR_dotdotTRUE_,
+ FFEEXPR_dotdotFALSE_,
+ FFEEXPR_dotdotNOT_,
+ FFEEXPR_dotdotAND_,
+ FFEEXPR_dotdotOR_,
+ FFEEXPR_dotdotXOR_,
+ FFEEXPR_dotdotEQV_,
+ FFEEXPR_dotdotNEQV_,
+ FFEEXPR_dotdotLT_,
+ FFEEXPR_dotdotLE_,
+ FFEEXPR_dotdotEQ_,
+ FFEEXPR_dotdotNE_,
+ FFEEXPR_dotdotGT_,
+ FFEEXPR_dotdotGE_,
+ FFEEXPR_dotdot
+ } ffeexprDotdot_;
+
+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 ffeexprDotdot_ 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 ffeexprDotdot_ ffeexpr_dotdot_ (ffelexToken t);
+static ffeexprExpr_ ffeexpr_expr_new_ (void);
+static void ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t);
+static bool ffeexpr_isdigits_ (char *p);
+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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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 = ffeinfo_basictype (ffebld_info (ffeexpr_stack_->expr));
+ ffeinfoBasictype rty = ffeinfo_basictype (ffebld_info (expr));
+ ffeinfoKindtype lkt;
+ ffeinfoKindtype rkt;
+ ffeinfoKindtype nkt;
+ bool ok = TRUE;
+ ffebld orig;
+
+ if ((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_dotdot_ -- Look up name in list of .FOO. possibilities
+
+ ffeexprDotdot_ d;
+ ffelexToken t;
+ d = ffeexpr_dotdot_(t);
+
+ Returns the identifier for the name, or the NONE identifier. */
+
+static ffeexprDotdot_
+ffeexpr_dotdot_ (ffelexToken t)
+{
+ char *p;
+
+ switch (ffelex_token_length (t))
+ {
+ case 2:
+ switch (*(p = ffelex_token_text (t)))
+ {
+ case FFESRC_CASE_MATCH_INIT ('E', 'e', match_2e, no_match_2):
+ if (ffesrc_char_match_noninit (*++p, 'Q', 'q'))
+ return FFEEXPR_dotdotEQ_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('G', 'g', match_2g, no_match_2):
+ if (ffesrc_char_match_noninit (*++p, 'E', 'e'))
+ return FFEEXPR_dotdotGE_;
+ if (ffesrc_char_match_noninit (*p, 'T', 't'))
+ return FFEEXPR_dotdotGT_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('L', 'l', match_2l, no_match_2):
+ if (ffesrc_char_match_noninit (*++p, 'E', 'e'))
+ return FFEEXPR_dotdotLE_;
+ if (ffesrc_char_match_noninit (*p, 'T', 't'))
+ return FFEEXPR_dotdotLT_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('N', 'n', match_2n, no_match_2):
+ if (ffesrc_char_match_noninit (*++p, 'E', 'e'))
+ return FFEEXPR_dotdotNE_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('O', 'o', match_2o, no_match_2):
+ if (ffesrc_char_match_noninit (*++p, 'R', 'r'))
+ return FFEEXPR_dotdotOR_;
+ return FFEEXPR_dotdotNONE_;
+
+ default:
+ no_match_2: /* :::::::::::::::::::: */
+ return FFEEXPR_dotdotNONE_;
+ }
+
+ case 3:
+ switch (*(p = ffelex_token_text (t)))
+ {
+ case FFESRC_CASE_MATCH_INIT ('A', 'a', match_3a, no_match_3):
+ if ((ffesrc_char_match_noninit (*++p, 'N', 'n'))
+ && (ffesrc_char_match_noninit (*++p, 'D', 'd')))
+ return FFEEXPR_dotdotAND_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('E', 'e', match_3e, no_match_3):
+ if ((ffesrc_char_match_noninit (*++p, 'Q', 'q'))
+ && (ffesrc_char_match_noninit (*++p, 'V', 'v')))
+ return FFEEXPR_dotdotEQV_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('N', 'n', match_3n, no_match_3):
+ if ((ffesrc_char_match_noninit (*++p, 'O', 'o'))
+ && (ffesrc_char_match_noninit (*++p, 'T', 't')))
+ return FFEEXPR_dotdotNOT_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('X', 'x', match_3x, no_match_3):
+ if ((ffesrc_char_match_noninit (*++p, 'O', 'o'))
+ && (ffesrc_char_match_noninit (*++p, 'R', 'r')))
+ return FFEEXPR_dotdotXOR_;
+ return FFEEXPR_dotdotNONE_;
+
+ default:
+ no_match_3: /* :::::::::::::::::::: */
+ return FFEEXPR_dotdotNONE_;
+ }
+
+ case 4:
+ switch (*(p = ffelex_token_text (t)))
+ {
+ case FFESRC_CASE_MATCH_INIT ('N', 'n', match_4n, no_match_4):
+ if ((ffesrc_char_match_noninit (*++p, 'E', 'e'))
+ && (ffesrc_char_match_noninit (*++p, 'Q', 'q'))
+ && (ffesrc_char_match_noninit (*++p, 'V', 'v')))
+ return FFEEXPR_dotdotNEQV_;
+ return FFEEXPR_dotdotNONE_;
+
+ case FFESRC_CASE_MATCH_INIT ('T', 't', match_4t, no_match_4):
+ if ((ffesrc_char_match_noninit (*++p, 'R', 'r'))
+ && (ffesrc_char_match_noninit (*++p, 'U', 'u'))
+ && (ffesrc_char_match_noninit (*++p, 'E', 'e')))
+ return FFEEXPR_dotdotTRUE_;
+ return FFEEXPR_dotdotNONE_;
+
+ default:
+ no_match_4: /* :::::::::::::::::::: */
+ return FFEEXPR_dotdotNONE_;
+ }
+
+ case 5:
+ if (ffesrc_strcmp_2c (ffe_case_match (), ffelex_token_text (t), "FALSE",
+ "false", "False")
+ == 0)
+ return FFEEXPR_dotdotFALSE_;
+ return FFEEXPR_dotdotNONE_;
+
+ default:
+ return FFEEXPR_dotdotNONE_;
+ }
+}
+
+/* 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)
+{
+ char *p;
+
+ 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;
+
+ case FFEBLD_opPERCENT_LOC:
+ as = FFEGLOBAL_argsummaryPTR;
+ break;
+
+ 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 ((ffebld_op (ffebld_left (item)) == FFEBLD_opSYMTER)
+ && (ffesymbol_specific (ffebld_symter (ffebld_left (item)))
+ == FFEINTRIN_specLOC))
+ {
+ as = FFEGLOBAL_argsummaryPTR;
+ break;
+ }
+ /* 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_ (char *p)
+{
+ 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))
+ {
+ char *what;
+
+ 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))
+ {
+ char *what;
+
+ 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) && (lbt != 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)
+ && (lbt != 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_ = ffeexpr_dotdot_ (t);
+ switch (ffeexpr_current_dotdot_)
+ {
+ case FFEEXPR_dotdotNONE_:
+ return (ffelexHandler) ffeexpr_nil_rhs_ (t);
+
+ case FFEEXPR_dotdotTRUE_:
+ case FFEEXPR_dotdotFALSE_:
+ case FFEEXPR_dotdotNOT_:
+ 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 FFEEXPR_dotdotNOT_:
+ if (ffelex_token_type (t) != FFELEX_typePERIOD)
+ return (ffelexHandler) ffeexpr_nil_rhs_ (t);
+ return (ffelexHandler) ffeexpr_nil_rhs_;
+
+ case FFEEXPR_dotdotTRUE_:
+ case FFEEXPR_dotdotFALSE_:
+ 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;
+ char *p;
+
+ 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;
+ char *p;
+
+ 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;
+ char *p;
+
+ 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;
+ char *p;
+
+ 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_ = ffeexpr_dotdot_ (t);
+ switch (ffeexpr_current_dotdot_)
+ {
+ case FFEEXPR_dotdotTRUE_:
+ case FFEEXPR_dotdotFALSE_:
+ case FFEEXPR_dotdotNOT_:
+ 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) && ffe_is_pedantic ())
+ || ((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_:
+ 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; /* expr==NULL ok for substring; element case
+ caught by callback. */
+
+ 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:
+ error = 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_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:
+ error = error
+ && (ffeinfo_kindtype (info) != FFEINFO_kindtypeLOGICALDEFAULT);
+ if (!ffeexpr_stack_->is_rhs)
+ break; /* Don't convert lhs variable. */
+ expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET);
+ break;
+
+ case FFEINFO_basictypeINTEGER:
+ error = error &&
+ (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
+ 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:
+ error = FALSE;
+ 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. */
+ : (ffeinfo_kindtype (info) != ffecom_label_kind ()))
+ || (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_ = ffeexpr_dotdot_ (t);
+ switch (ffeexpr_current_dotdot_)
+ {
+ case FFEEXPR_dotdotNONE_:
+ 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 FFEEXPR_dotdotTRUE_:
+ case FFEEXPR_dotdotFALSE_:
+ case FFEEXPR_dotdotNOT_:
+ 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 FFEEXPR_dotdotNOT_:
+ 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 FFEEXPR_dotdotTRUE_:
+ 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 FFEEXPR_dotdotFALSE_:
+ 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;
+ char *p;
+
+ 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;
+ char *p;
+
+ 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. */
+
+ 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);
+ 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;
+ char *p;
+ 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;
+ char *p;
+
+ 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_ = ffeexpr_dotdot_ (t);
+ switch (ffeexpr_current_dotdot_)
+ {
+ case FFEEXPR_dotdotTRUE_:
+ case FFEEXPR_dotdotFALSE_:
+ case FFEEXPR_dotdotNOT_:
+ 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_;
+
+ case FFEEXPR_dotdotNONE_:
+ if (ffest_ffebad_start (FFEBAD_INVALID_DOTDOT))
+ {
+ ffebad_string (ffelex_token_text (t));
+ ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
+ ffelex_token_where_column (ffeexpr_tokens_[0]));
+ ffebad_finish ();
+ }
+ ffeexpr_current_dotdot_ = FFEEXPR_dotdotEQ_;
+ /* Fall through here, pretending we got a .EQ. operator. */
+ 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;
+
+ 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. */
+
+ e = ffeexpr_expr_new_ ();
+ e->type = FFEEXPR_exprtypeBINARY_;
+ e->token = ffeexpr_tokens_[0];
+
+ switch (ffeexpr_current_dotdot_)
+ {
+ case FFEEXPR_dotdotAND_:
+ e->u.operator.op = FFEEXPR_operatorAND_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceAND_;
+ e->u.operator.as = FFEEXPR_operatorassociativityAND_;
+ break;
+
+ case FFEEXPR_dotdotOR_:
+ e->u.operator.op = FFEEXPR_operatorOR_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceOR_;
+ e->u.operator.as = FFEEXPR_operatorassociativityOR_;
+ break;
+
+ case FFEEXPR_dotdotXOR_:
+ e->u.operator.op = FFEEXPR_operatorXOR_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceXOR_;
+ e->u.operator.as = FFEEXPR_operatorassociativityXOR_;
+ break;
+
+ case FFEEXPR_dotdotEQV_:
+ e->u.operator.op = FFEEXPR_operatorEQV_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceEQV_;
+ e->u.operator.as = FFEEXPR_operatorassociativityEQV_;
+ break;
+
+ case FFEEXPR_dotdotNEQV_:
+ e->u.operator.op = FFEEXPR_operatorNEQV_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceNEQV_;
+ e->u.operator.as = FFEEXPR_operatorassociativityNEQV_;
+ break;
+
+ case FFEEXPR_dotdotLT_:
+ e->u.operator.op = FFEEXPR_operatorLT_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceLT_;
+ e->u.operator.as = FFEEXPR_operatorassociativityLT_;
+ break;
+
+ case FFEEXPR_dotdotLE_:
+ e->u.operator.op = FFEEXPR_operatorLE_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceLE_;
+ e->u.operator.as = FFEEXPR_operatorassociativityLE_;
+ break;
+
+ case FFEEXPR_dotdotEQ_:
+ e->u.operator.op = FFEEXPR_operatorEQ_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
+ e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
+ break;
+
+ case FFEEXPR_dotdotNE_:
+ e->u.operator.op = FFEEXPR_operatorNE_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceNE_;
+ e->u.operator.as = FFEEXPR_operatorassociativityNE_;
+ break;
+
+ case FFEEXPR_dotdotGT_:
+ e->u.operator.op = FFEEXPR_operatorGT_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceGT_;
+ e->u.operator.as = FFEEXPR_operatorassociativityGT_;
+ break;
+
+ case FFEEXPR_dotdotGE_:
+ e->u.operator.op = FFEEXPR_operatorGE_;
+ e->u.operator.prec = FFEEXPR_operatorprecedenceGE_;
+ e->u.operator.as = FFEEXPR_operatorassociativityGE_;
+ break;
+
+ default:
+ assert ("Bad unary dotdot in ffeexpr_current_dotdot_" == NULL);
+ }
+
+ ffeexpr_exprstack_push_binary_ (e);
+
+ if (ffelex_token_type (t) != FFELEX_typePERIOD)
+ return (ffelexHandler) ffeexpr_token_rhs_ (t);
+ 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
+
+ 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);
+ 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_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);
+ 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);
+
+ if (ffeinfo_where (info) == FFEINFO_whereCONSTANT)
+ { /* Statement function (or subroutine, if
+ there was such a thing). */
+ if ((expr == NULL)
+ && ((ffe_is_pedantic ()
+ && (ffeexpr_stack_->expr != NULL))
+ || (ffelex_token_type (t) == FFELEX_typeCOMMA)))
+ {
+ if (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 (ffeexpr_stack_->next_dummy != NULL)
+ { /* Don't bother if we're going to complain
+ later! */
+ expr = ffebld_new_conter
+ (ffebld_constant_new_integerdefault_val (0));
+ ffebld_set_info (expr, ffeinfo_new_any ());
+ }
+ }
+
+ 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)
+ {
+ if (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_ugly_comma ()
+ || (ffelex_token_type (t) == FFELEX_typeCOMMA))
+ 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->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)
+ {
+ 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;
+
+ string = ffeexpr_stack_->exprstack;
+ strop = string->u.operand;
+ info = ffebld_info (strop);
+
+ if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER))
+ { /* The starting point is known. */
+ first_val = (first == NULL) ? 1
+ : ffebld_constant_integerdefault (ffebld_conter (first));
+ }
+ else
+ { /* Assume start of the entity. */
+ first_val = 1;
+ }
+
+ if ((last != NULL) && (ffebld_op (last) == FFEBLD_opCONTER))
+ { /* The ending point is known. */
+ last_val = ffebld_constant_integerdefault (ffebld_conter (last));
+
+ if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER))
+ { /* 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);
+}