19450 lines
554 KiB
C
19450 lines
554 KiB
C
/* expr.c -- Implementation File (module.c template V1.0)
|
||
Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002
|
||
Free Software Foundation, Inc.
|
||
Contributed by James Craig Burley.
|
||
|
||
This file is part of GNU Fortran.
|
||
|
||
GNU Fortran is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 2, or (at your option)
|
||
any later version.
|
||
|
||
GNU Fortran is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GNU Fortran; see the file COPYING. If not, write to
|
||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||
02111-1307, USA.
|
||
|
||
Related Modules:
|
||
None.
|
||
|
||
Description:
|
||
Handles syntactic and semantic analysis of Fortran expressions.
|
||
|
||
Modifications:
|
||
*/
|
||
|
||
/* Include files. */
|
||
|
||
#include "proj.h"
|
||
#include "expr.h"
|
||
#include "bad.h"
|
||
#include "bld.h"
|
||
#include "com.h"
|
||
#include "global.h"
|
||
#include "implic.h"
|
||
#include "intrin.h"
|
||
#include "info.h"
|
||
#include "lex.h"
|
||
#include "malloc.h"
|
||
#include "src.h"
|
||
#include "st.h"
|
||
#include "symbol.h"
|
||
#include "str.h"
|
||
#include "target.h"
|
||
#include "where.h"
|
||
#include "real.h"
|
||
|
||
/* Externals defined here. */
|
||
|
||
|
||
/* Simple definitions and enumerations. */
|
||
|
||
typedef enum
|
||
{
|
||
FFEEXPR_exprtypeUNKNOWN_,
|
||
FFEEXPR_exprtypeOPERAND_,
|
||
FFEEXPR_exprtypeUNARY_,
|
||
FFEEXPR_exprtypeBINARY_,
|
||
FFEEXPR_exprtype_
|
||
} ffeexprExprtype_;
|
||
|
||
typedef enum
|
||
{
|
||
FFEEXPR_operatorPOWER_,
|
||
FFEEXPR_operatorMULTIPLY_,
|
||
FFEEXPR_operatorDIVIDE_,
|
||
FFEEXPR_operatorADD_,
|
||
FFEEXPR_operatorSUBTRACT_,
|
||
FFEEXPR_operatorCONCATENATE_,
|
||
FFEEXPR_operatorLT_,
|
||
FFEEXPR_operatorLE_,
|
||
FFEEXPR_operatorEQ_,
|
||
FFEEXPR_operatorNE_,
|
||
FFEEXPR_operatorGT_,
|
||
FFEEXPR_operatorGE_,
|
||
FFEEXPR_operatorNOT_,
|
||
FFEEXPR_operatorAND_,
|
||
FFEEXPR_operatorOR_,
|
||
FFEEXPR_operatorXOR_,
|
||
FFEEXPR_operatorEQV_,
|
||
FFEEXPR_operatorNEQV_,
|
||
FFEEXPR_operator_
|
||
} ffeexprOperator_;
|
||
|
||
typedef enum
|
||
{
|
||
FFEEXPR_operatorprecedenceHIGHEST_ = 1,
|
||
FFEEXPR_operatorprecedencePOWER_ = 1,
|
||
FFEEXPR_operatorprecedenceMULTIPLY_ = 2,
|
||
FFEEXPR_operatorprecedenceDIVIDE_ = 2,
|
||
FFEEXPR_operatorprecedenceADD_ = 3,
|
||
FFEEXPR_operatorprecedenceSUBTRACT_ = 3,
|
||
FFEEXPR_operatorprecedenceLOWARITH_ = 3,
|
||
FFEEXPR_operatorprecedenceCONCATENATE_ = 3,
|
||
FFEEXPR_operatorprecedenceLT_ = 4,
|
||
FFEEXPR_operatorprecedenceLE_ = 4,
|
||
FFEEXPR_operatorprecedenceEQ_ = 4,
|
||
FFEEXPR_operatorprecedenceNE_ = 4,
|
||
FFEEXPR_operatorprecedenceGT_ = 4,
|
||
FFEEXPR_operatorprecedenceGE_ = 4,
|
||
FFEEXPR_operatorprecedenceNOT_ = 5,
|
||
FFEEXPR_operatorprecedenceAND_ = 6,
|
||
FFEEXPR_operatorprecedenceOR_ = 7,
|
||
FFEEXPR_operatorprecedenceXOR_ = 8,
|
||
FFEEXPR_operatorprecedenceEQV_ = 8,
|
||
FFEEXPR_operatorprecedenceNEQV_ = 8,
|
||
FFEEXPR_operatorprecedenceLOWEST_ = 8,
|
||
FFEEXPR_operatorprecedence_
|
||
} ffeexprOperatorPrecedence_;
|
||
|
||
#define FFEEXPR_operatorassociativityL2R_ TRUE
|
||
#define FFEEXPR_operatorassociativityR2L_ FALSE
|
||
#define FFEEXPR_operatorassociativityPOWER_ FFEEXPR_operatorassociativityR2L_
|
||
#define FFEEXPR_operatorassociativityMULTIPLY_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityDIVIDE_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityADD_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativitySUBTRACT_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityCONCATENATE_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityLT_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityLE_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityEQ_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityNE_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityGT_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityGE_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityNOT_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityAND_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityOR_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityXOR_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityEQV_ FFEEXPR_operatorassociativityL2R_
|
||
#define FFEEXPR_operatorassociativityNEQV_ FFEEXPR_operatorassociativityL2R_
|
||
|
||
typedef enum
|
||
{
|
||
FFEEXPR_parentypeFUNCTION_,
|
||
FFEEXPR_parentypeSUBROUTINE_,
|
||
FFEEXPR_parentypeARRAY_,
|
||
FFEEXPR_parentypeSUBSTRING_,
|
||
FFEEXPR_parentypeFUNSUBSTR_,/* Ambig: check for colon after first expr. */
|
||
FFEEXPR_parentypeEQUIVALENCE_, /* Ambig: ARRAY_ or SUBSTRING_. */
|
||
FFEEXPR_parentypeANY_, /* Allow basically anything. */
|
||
FFEEXPR_parentype_
|
||
} ffeexprParenType_;
|
||
|
||
typedef enum
|
||
{
|
||
FFEEXPR_percentNONE_,
|
||
FFEEXPR_percentLOC_,
|
||
FFEEXPR_percentVAL_,
|
||
FFEEXPR_percentREF_,
|
||
FFEEXPR_percentDESCR_,
|
||
FFEEXPR_percent_
|
||
} ffeexprPercent_;
|
||
|
||
/* Internal typedefs. */
|
||
|
||
typedef struct _ffeexpr_expr_ *ffeexprExpr_;
|
||
typedef bool ffeexprOperatorAssociativity_;
|
||
typedef struct _ffeexpr_stack_ *ffeexprStack_;
|
||
|
||
/* Private include files. */
|
||
|
||
|
||
/* Internal structure definitions. */
|
||
|
||
struct _ffeexpr_expr_
|
||
{
|
||
ffeexprExpr_ previous;
|
||
ffelexToken token;
|
||
ffeexprExprtype_ type;
|
||
union
|
||
{
|
||
struct
|
||
{
|
||
ffeexprOperator_ op;
|
||
ffeexprOperatorPrecedence_ prec;
|
||
ffeexprOperatorAssociativity_ as;
|
||
}
|
||
operator;
|
||
ffebld operand;
|
||
}
|
||
u;
|
||
};
|
||
|
||
struct _ffeexpr_stack_
|
||
{
|
||
ffeexprStack_ previous;
|
||
mallocPool pool;
|
||
ffeexprContext context;
|
||
ffeexprCallback callback;
|
||
ffelexToken first_token;
|
||
ffeexprExpr_ exprstack;
|
||
ffelexToken tokens[10]; /* Used in certain cases, like (unary)
|
||
open-paren. */
|
||
ffebld expr; /* For first of
|
||
complex/implied-do/substring/array-elements
|
||
/ actual-args expression. */
|
||
ffebld bound_list; /* For tracking dimension bounds list of
|
||
array. */
|
||
ffebldListBottom bottom; /* For building lists. */
|
||
ffeinfoRank rank; /* For elements in an array reference. */
|
||
bool constant; /* TRUE while elements seen so far are
|
||
constants. */
|
||
bool immediate; /* TRUE while elements seen so far are
|
||
immediate/constants. */
|
||
ffebld next_dummy; /* Next SFUNC dummy arg in arg list. */
|
||
ffebldListLength num_args; /* Number of dummy args expected in arg list. */
|
||
bool is_rhs; /* TRUE if rhs context, FALSE otherwise. */
|
||
ffeexprPercent_ percent; /* Current %FOO keyword. */
|
||
};
|
||
|
||
struct _ffeexpr_find_
|
||
{
|
||
ffelexToken t;
|
||
ffelexHandler after;
|
||
int level;
|
||
};
|
||
|
||
/* Static objects accessed by functions in this module. */
|
||
|
||
static ffeexprStack_ ffeexpr_stack_; /* Expression stack for semantic. */
|
||
static ffelexToken ffeexpr_tokens_[10]; /* Scratchpad tokens for syntactic. */
|
||
static ffestrOther ffeexpr_current_dotdot_; /* Current .FOO. keyword. */
|
||
static long ffeexpr_hollerith_count_; /* ffeexpr_token_number_ and caller. */
|
||
static int ffeexpr_level_; /* Level of DATA implied-DO construct. */
|
||
static bool ffeexpr_is_substr_ok_; /* If OPEN_PAREN as binary "op" ok. */
|
||
static struct _ffeexpr_find_ ffeexpr_find_;
|
||
|
||
/* Static functions (internal). */
|
||
|
||
static ffelexHandler ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_close_paren_ambig_ (ffelexToken ft,
|
||
ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_close_paren_c_ (ffelexToken ft,
|
||
ffebld expr, ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_close_paren_ci_ (ffelexToken ft,
|
||
ffebld expr, ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_ci_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_1_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_2_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_3_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_4_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_comma_i_5_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_end_loc_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_end_notloc_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_cb_end_notloc_1_ (ffelexToken t);
|
||
static ffesymbol ffeexpr_check_impctrl_ (ffesymbol s);
|
||
static void ffeexpr_check_impdo_ (ffebld list, ffelexToken list_t,
|
||
ffebld dovar, ffelexToken dovar_t);
|
||
static void ffeexpr_update_impdo_ (ffebld expr, ffebld dovar);
|
||
static void ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar);
|
||
static ffeexprContext ffeexpr_context_outer_ (ffeexprStack_ s);
|
||
static ffeexprExpr_ ffeexpr_expr_new_ (void);
|
||
static void ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t);
|
||
static bool ffeexpr_isdigits_ (const char *p);
|
||
static ffelexHandler ffeexpr_token_first_lhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_lhs_1_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_1_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_2_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_3_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_4_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_5_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_first_rhs_6_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_namelist_ (ffelexToken t);
|
||
static void ffeexpr_expr_kill_ (ffeexprExpr_ e);
|
||
static void ffeexpr_exprstack_push_ (ffeexprExpr_ e);
|
||
static void ffeexpr_exprstack_push_binary_ (ffeexprExpr_ e);
|
||
static void ffeexpr_exprstack_push_operand_ (ffeexprExpr_ e);
|
||
static void ffeexpr_exprstack_push_unary_ (ffeexprExpr_ e);
|
||
static void ffeexpr_reduce_ (void);
|
||
static ffebld ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op,
|
||
ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_eqop2_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op,
|
||
ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op,
|
||
ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffebld ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l,
|
||
ffeexprExpr_ op, ffeexprExpr_ r);
|
||
static ffelexHandler ffeexpr_find_close_paren_ (ffelexToken t,
|
||
ffelexHandler after);
|
||
static ffelexHandler ffeexpr_nil_finished_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_rhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_end_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_swallow_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_real_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_real_exponent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_real_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_exponent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_per_exp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_real_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_num_per_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_number_real_exp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_num_real_exp_sn_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_binary_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_binary_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_binary_end_per_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_binary_sw_per_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_quote_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_apostrophe_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_apos_char_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_name_rhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_name_apos_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_name_apos_name_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_percent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_percent_name_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_nil_substrp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_finished_ (ffelexToken t);
|
||
static ffebld ffeexpr_finished_ambig_ (ffelexToken t, ffebld expr);
|
||
static ffelexHandler ffeexpr_token_lhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_rhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_binary_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_end_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_swallow_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_real_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_real_exponent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_real_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_exponent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_per_exp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_real_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_num_per_exp_sign_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_number_real_exp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_num_real_exp_sn_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_binary_period_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_binary_end_per_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_binary_sw_per_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_quote_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_apostrophe_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_apos_char_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_name_lhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_name_arg_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_name_rhs_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_name_apos_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_name_apos_name_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_percent_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_percent_name_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_elements_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_substring_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_substring_1_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_substrp_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_intrincheck_ (ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_funsubstr_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static ffelexHandler ffeexpr_token_anything_ (ffelexToken ft, ffebld expr,
|
||
ffelexToken t);
|
||
static void ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer,
|
||
ffelexToken decimal, ffelexToken fraction, ffelexToken exponent,
|
||
ffelexToken exponent_sign, ffelexToken exponent_digits);
|
||
static ffesymbol ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin);
|
||
static ffesymbol ffeexpr_sym_impdoitem_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t);
|
||
static ffesymbol ffeexpr_declare_parenthesized_ (ffelexToken t,
|
||
bool maybe_intrin,
|
||
ffeexprParenType_ *paren_type);
|
||
static ffesymbol ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t);
|
||
|
||
/* Internal macros. */
|
||
|
||
#define ffeexpr_paren_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t)
|
||
#define ffeexpr_sym_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t)
|
||
|
||
/* ffeexpr_collapse_convert -- Collapse convert expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_convert(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize sz;
|
||
ffetargetCharacterSize sz2;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
sz = FFETARGET_charactersizeNONE;
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_integer1_integer2
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_integer1_integer3
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_integer1_integer4
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER1/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer1_real1
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer1_real2
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer1_real3
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer1_real4
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER1/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer1_complex1
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer1_complex2
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer1_complex3
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer1_complex4
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER1/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_integer1_logical1
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_integer1_logical2
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_integer1_logical3
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_integer1_logical4
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER1/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_integer1_character1
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_integer1_hollerith
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_integer1_typeless
|
||
(ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("INTEGER1 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_integer2_integer1
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_integer2_integer3
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_integer2_integer4
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER2/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer2_real1
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer2_real2
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer2_real3
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer2_real4
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER2/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer2_complex1
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer2_complex2
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer2_complex3
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer2_complex4
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER2/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_integer2_logical1
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_integer2_logical2
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_integer2_logical3
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_integer2_logical4
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER2/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_integer2_character1
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_integer2_hollerith
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_integer2_typeless
|
||
(ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("INTEGER2 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_integer3_integer1
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_integer3_integer2
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_integer3_integer4
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER3/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer3_real1
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer3_real2
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer3_real3
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer3_real4
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER3/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer3_complex1
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer3_complex2
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer3_complex3
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer3_complex4
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER3/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_integer3_logical1
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_integer3_logical2
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_integer3_logical3
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_integer3_logical4
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER3/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_integer3_character1
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_integer3_hollerith
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_integer3_typeless
|
||
(ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("INTEGER3 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_integer4_integer1
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_integer4_integer2
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_integer4_integer3
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER4/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer4_real1
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer4_real2
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer4_real3
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer4_real4
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER4/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_integer4_complex1
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_integer4_complex2
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_integer4_complex3
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_integer4_complex4
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER3/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_integer4_logical1
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_integer4_logical2
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_integer4_logical3
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_integer4_logical4
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("INTEGER4/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_integer4_character1
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_integer4_hollerith
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_integer4_typeless
|
||
(ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("INTEGER4 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
sz = FFETARGET_charactersizeNONE;
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_logical1_logical2
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_logical1_logical3
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_logical1_logical4
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL1/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_logical1_integer1
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_logical1_integer2
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_logical1_integer3
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_logical1_integer4
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL1/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_logical1_character1
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_logical1_hollerith
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_logical1_typeless
|
||
(ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("LOGICAL1 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_logical2_logical1
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_logical2_logical3
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_logical2_logical4
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL2/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_logical2_integer1
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_logical2_integer2
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_logical2_integer3
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_logical2_integer4
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL2/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_logical2_character1
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_logical2_hollerith
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_logical2_typeless
|
||
(ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("LOGICAL2 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_logical3_logical1
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_logical3_logical2
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_convert_logical3_logical4
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL3/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_logical3_integer1
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_logical3_integer2
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_logical3_integer3
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_logical3_integer4
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL3/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_logical3_character1
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_logical3_hollerith
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_logical3_typeless
|
||
(ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("LOGICAL3 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_convert_logical4_logical1
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_convert_logical4_logical2
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_convert_logical4_logical3
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL4/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_logical4_integer1
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_logical4_integer2
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_logical4_integer3
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_logical4_integer4
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("LOGICAL4/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_logical4_character1
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_logical4_hollerith
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_logical4_typeless
|
||
(ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("LOGICAL4 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
sz = FFETARGET_charactersizeNONE;
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_real1_integer1
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_real1_integer2
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_real1_integer3
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_real1_integer4
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL1/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real1_real2
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real1_real3
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real1_real4
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL1/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real1_complex1
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real1_complex2
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real1_complex3
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real1_complex4
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL1/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_real1_character1
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_real1_hollerith
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_real1_typeless
|
||
(ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("REAL1 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_real2_integer1
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_real2_integer2
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_real2_integer3
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_real2_integer4
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL2/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real2_real1
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real2_real3
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real2_real4
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL2/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real2_complex1
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real2_complex2
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real2_complex3
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real2_complex4
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL2/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_real2_character1
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_real2_hollerith
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_real2_typeless
|
||
(ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("REAL2 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_real3_integer1
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_real3_integer2
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_real3_integer3
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_real3_integer4
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL3/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real3_real1
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real3_real2
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real3_real4
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL3/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real3_complex1
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real3_complex2
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real3_complex3
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real3_complex4
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL3/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_real3_character1
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_real3_hollerith
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_real3_typeless
|
||
(ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("REAL3 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_real4_integer1
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_real4_integer2
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_real4_integer3
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_real4_integer4
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL4/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real4_real1
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real4_real2
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real4_real3
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL4/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_real4_complex1
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_real4_complex2
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_real4_complex3
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_real4_complex4
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("REAL4/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_real4_character1
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_real4_hollerith
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_real4_typeless
|
||
(ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("REAL4 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
sz = FFETARGET_charactersizeNONE;
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_complex1_integer1
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_complex1_integer2
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_complex1_integer3
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_complex1_integer4
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX1/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex1_real1
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex1_real2
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex1_real3
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex1_real4
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX1/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex1_complex2
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex1_complex3
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex1_complex4
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX1/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_complex1_character1
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_complex1_hollerith
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_complex1_typeless
|
||
(ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("COMPLEX1 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_complex2_integer1
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_complex2_integer2
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_complex2_integer3
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_complex2_integer4
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX2/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex2_real1
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex2_real2
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex2_real3
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex2_real4
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX2/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex2_complex1
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex2_complex3
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex2_complex4
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX2/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_complex2_character1
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_complex2_hollerith
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_complex2_typeless
|
||
(ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("COMPLEX2 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_complex3_integer1
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_complex3_integer2
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_complex3_integer3
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_complex3_integer4
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX3/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex3_real1
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex3_real2
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex3_real3
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex3_real4
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX3/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex3_complex1
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex3_complex2
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex3_complex4
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX3/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_complex3_character1
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_complex3_hollerith
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_complex3_typeless
|
||
(ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("COMPLEX3 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_convert_complex4_integer1
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_convert_complex4_integer2
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_convert_complex4_integer3
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_convert_complex4_integer4
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX4/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex4_real1
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex4_real2
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex4_real3
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_convert_complex4_real4
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX4/REAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_convert_complex4_complex1
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_convert_complex4_complex2
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_convert_complex4_complex3
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("COMPLEX4/COMPLEX bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = ffetarget_convert_complex4_character1
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error = ffetarget_convert_complex4_hollerith
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_hollerith (ffebld_conter (l)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = ffetarget_convert_complex4_typeless
|
||
(ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_typeless (ffebld_conter (l)));
|
||
break;
|
||
|
||
default:
|
||
assert ("COMPLEX4 bad type" == NULL);
|
||
break;
|
||
}
|
||
|
||
/* If conversion operation is not implemented, return original expr. */
|
||
if (error == FFEBAD_NOCANDO)
|
||
return expr;
|
||
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
if ((sz = ffebld_size (expr)) == FFETARGET_charactersizeNONE)
|
||
return expr;
|
||
kt = ffeinfo_kindtype (ffebld_info (expr));
|
||
switch (kt)
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
switch (ffeinfo_basictype (ffebld_info (l)))
|
||
{
|
||
case FFEINFO_basictypeCHARACTER:
|
||
if ((sz2 = ffebld_size (l)) == FFETARGET_charactersizeNONE)
|
||
return expr;
|
||
assert (kt == ffeinfo_kindtype (ffebld_info (l)));
|
||
assert (sz2 == ffetarget_length_character1
|
||
(ffebld_constant_character1
|
||
(ffebld_conter (l))));
|
||
error
|
||
= ffetarget_convert_character1_character1
|
||
(ffebld_cu_ptr_character1 (u), sz,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error
|
||
= ffetarget_convert_character1_integer1
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error
|
||
= ffetarget_convert_character1_integer2
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error
|
||
= ffetarget_convert_character1_integer3
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error
|
||
= ffetarget_convert_character1_integer4
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("CHARACTER1/INTEGER bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (l)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error
|
||
= ffetarget_convert_character1_logical1
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error
|
||
= ffetarget_convert_character1_logical2
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error
|
||
= ffetarget_convert_character1_logical3
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error
|
||
= ffetarget_convert_character1_logical4
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("CHARACTER1/LOGICAL bad source kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
error
|
||
= ffetarget_convert_character1_hollerith
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_hollerith (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error
|
||
= ffetarget_convert_character1_typeless
|
||
(ffebld_cu_ptr_character1 (u),
|
||
sz,
|
||
ffebld_constant_typeless (ffebld_conter (l)),
|
||
ffebld_constant_pool ());
|
||
break;
|
||
|
||
default:
|
||
assert ("CHARACTER1 bad type" == NULL);
|
||
}
|
||
|
||
expr
|
||
= ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_character1_val
|
||
(ffebld_cu_val_character1 (u)),
|
||
expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
sz));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
assert (t != NULL);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_paren -- Collapse paren expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_paren(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_paren (ffebld expr, ffelexToken t UNUSED)
|
||
{
|
||
ffebld r;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize len;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
r = ffebld_left (expr);
|
||
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
bt = ffeinfo_basictype (ffebld_info (r));
|
||
kt = ffeinfo_kindtype (ffebld_info (r));
|
||
len = ffebld_size (r);
|
||
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
|
||
expr);
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_uplus -- Collapse uplus expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_uplus(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_uplus (ffebld expr, ffelexToken t UNUSED)
|
||
{
|
||
ffebld r;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize len;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
r = ffebld_left (expr);
|
||
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
bt = ffeinfo_basictype (ffebld_info (r));
|
||
kt = ffeinfo_kindtype (ffebld_info (r));
|
||
len = ffebld_size (r);
|
||
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
|
||
expr);
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_uminus -- Collapse uminus expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_uminus(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_uminus (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
r = ffebld_left (expr);
|
||
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_uminus_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_uminus_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_uminus_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_uminus_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_uminus_real1 (ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_uminus_real2 (ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_uminus_real3 (ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_uminus_real4 (ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_uminus_complex1 (ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_uminus_complex2 (ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_uminus_complex3 (ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_uminus_complex4 (ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_not -- Collapse not expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_not(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_not (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
r = ffebld_left (expr);
|
||
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_not_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_not_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_not_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_not_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_not_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_not_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_not_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_not_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_add -- Collapse add expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_add(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_add (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_add_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_add_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_add_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_add_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_add_real1 (ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_add_real2 (ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_add_real3 (ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_add_real4 (ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_add_complex1 (ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_add_complex2 (ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_add_complex3 (ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_add_complex4 (ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_subtract -- Collapse subtract expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_subtract(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_subtract (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_subtract_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_subtract_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_subtract_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_subtract_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_subtract_real1 (ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_subtract_real2 (ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_subtract_real3 (ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_subtract_real4 (ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_subtract_complex1 (ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_subtract_complex2 (ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_subtract_complex3 (ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_subtract_complex4 (ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_multiply -- Collapse multiply expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_multiply(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_multiply (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_multiply_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_multiply_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_multiply_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_multiply_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_multiply_real1 (ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_multiply_real2 (ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_multiply_real3 (ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_multiply_real4 (ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_multiply_complex1 (ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_multiply_complex2 (ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_multiply_complex3 (ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_multiply_complex4 (ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_divide -- Collapse divide expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_divide(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_divide (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_divide_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_divide_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_divide_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_divide_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_divide_real1 (ffebld_cu_ptr_real1 (u),
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val
|
||
(ffebld_cu_val_real1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_divide_real2 (ffebld_cu_ptr_real2 (u),
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val
|
||
(ffebld_cu_val_real2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_divide_real3 (ffebld_cu_ptr_real3 (u),
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val
|
||
(ffebld_cu_val_real3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_divide_real4 (ffebld_cu_ptr_real4 (u),
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val
|
||
(ffebld_cu_val_real4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_divide_complex1 (ffebld_cu_ptr_complex1 (u),
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val
|
||
(ffebld_cu_val_complex1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_divide_complex2 (ffebld_cu_ptr_complex2 (u),
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val
|
||
(ffebld_cu_val_complex2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_divide_complex3 (ffebld_cu_ptr_complex3 (u),
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val
|
||
(ffebld_cu_val_complex3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_divide_complex4 (ffebld_cu_ptr_complex4 (u),
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val
|
||
(ffebld_cu_val_complex4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_power -- Collapse power expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_power(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_power (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
if ((ffeinfo_basictype (ffebld_info (r)) != FFEINFO_basictypeINTEGER)
|
||
|| (ffeinfo_kindtype (ffebld_info (r)) != FFEINFO_kindtypeINTEGERDEFAULT))
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_kindtypeINTEGERDEFAULT:
|
||
error = ffetarget_power_integerdefault_integerdefault
|
||
(ffebld_cu_ptr_integerdefault (u),
|
||
ffebld_constant_integerdefault (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integerdefault_val
|
||
(ffebld_cu_val_integerdefault (u)), expr);
|
||
break;
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_kindtypeREALDEFAULT:
|
||
error = ffetarget_power_realdefault_integerdefault
|
||
(ffebld_cu_ptr_realdefault (u),
|
||
ffebld_constant_realdefault (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_realdefault_val
|
||
(ffebld_cu_val_realdefault (u)), expr);
|
||
break;
|
||
|
||
case FFEINFO_kindtypeREALDOUBLE:
|
||
error = ffetarget_power_realdouble_integerdefault
|
||
(ffebld_cu_ptr_realdouble (u),
|
||
ffebld_constant_realdouble (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_realdouble_val
|
||
(ffebld_cu_val_realdouble (u)), expr);
|
||
break;
|
||
|
||
#if FFETARGET_okREALQUAD
|
||
case FFEINFO_kindtypeREALQUAD:
|
||
error = ffetarget_power_realquad_integerdefault
|
||
(ffebld_cu_ptr_realquad (u),
|
||
ffebld_constant_realquad (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_realquad_val
|
||
(ffebld_cu_val_realquad (u)), expr);
|
||
break;
|
||
#endif
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_kindtypeREALDEFAULT:
|
||
error = ffetarget_power_complexdefault_integerdefault
|
||
(ffebld_cu_ptr_complexdefault (u),
|
||
ffebld_constant_complexdefault (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complexdefault_val
|
||
(ffebld_cu_val_complexdefault (u)), expr);
|
||
break;
|
||
|
||
#if FFETARGET_okCOMPLEXDOUBLE
|
||
case FFEINFO_kindtypeREALDOUBLE:
|
||
error = ffetarget_power_complexdouble_integerdefault
|
||
(ffebld_cu_ptr_complexdouble (u),
|
||
ffebld_constant_complexdouble (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complexdouble_val
|
||
(ffebld_cu_val_complexdouble (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEXQUAD
|
||
case FFEINFO_kindtypeREALQUAD:
|
||
error = ffetarget_power_complexquad_integerdefault
|
||
(ffebld_cu_ptr_complexquad (u),
|
||
ffebld_constant_complexquad (ffebld_conter (l)),
|
||
ffebld_constant_integerdefault (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_complexquad_val
|
||
(ffebld_cu_val_complexquad (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_concatenate -- Collapse concatenate expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_concatenate(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_concatenate (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize len;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_concatenate_character1 (ffebld_cu_ptr_character1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)),
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val
|
||
(ffebld_cu_val_character1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_concatenate_character2 (ffebld_cu_ptr_character2 (u),
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)),
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val
|
||
(ffebld_cu_val_character2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_concatenate_character3 (ffebld_cu_ptr_character3 (u),
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)),
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val
|
||
(ffebld_cu_val_character3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_concatenate_character4 (ffebld_cu_ptr_character4 (u),
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)),
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val
|
||
(ffebld_cu_val_character4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeCHARACTER,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_eq -- Collapse eq expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_eq(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_eq (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_eq_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_eq_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_eq_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_eq_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_eq_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_eq_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_eq_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_eq_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_eq_complex1 (&val,
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_eq_complex2 (&val,
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_eq_complex3 (&val,
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_eq_complex4 (&val,
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_eq_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_eq_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_eq_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_eq_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_ne -- Collapse ne expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_ne(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_ne (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_ne_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_ne_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_ne_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_ne_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_ne_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_ne_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_ne_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_ne_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_ne_complex1 (&val,
|
||
ffebld_constant_complex1 (ffebld_conter (l)),
|
||
ffebld_constant_complex1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_ne_complex2 (&val,
|
||
ffebld_constant_complex2 (ffebld_conter (l)),
|
||
ffebld_constant_complex2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_ne_complex3 (&val,
|
||
ffebld_constant_complex3 (ffebld_conter (l)),
|
||
ffebld_constant_complex3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_ne_complex4 (&val,
|
||
ffebld_constant_complex4 (ffebld_conter (l)),
|
||
ffebld_constant_complex4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad complex kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_ne_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_ne_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_ne_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_ne_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_ge -- Collapse ge expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_ge(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_ge (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_ge_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_ge_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_ge_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_ge_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_ge_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_ge_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_ge_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_ge_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_ge_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_ge_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_ge_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_ge_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_gt -- Collapse gt expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_gt(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_gt (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_gt_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_gt_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_gt_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_gt_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_gt_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_gt_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_gt_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_gt_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_gt_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_gt_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_gt_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_gt_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_le -- Collapse le expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_le(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_le (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_le_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_le_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_le_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_le_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_le_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_le_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_le_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_le_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_le_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_le_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_le_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_le_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_lt -- Collapse lt expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_lt(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_lt (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
bool val;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_lt_integer1 (&val,
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_lt_integer2 (&val,
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_lt_integer3 (&val,
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_lt_integer4 (&val,
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okREAL1
|
||
case FFEINFO_kindtypeREAL1:
|
||
error = ffetarget_lt_real1 (&val,
|
||
ffebld_constant_real1 (ffebld_conter (l)),
|
||
ffebld_constant_real1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL2
|
||
case FFEINFO_kindtypeREAL2:
|
||
error = ffetarget_lt_real2 (&val,
|
||
ffebld_constant_real2 (ffebld_conter (l)),
|
||
ffebld_constant_real2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL3
|
||
case FFEINFO_kindtypeREAL3:
|
||
error = ffetarget_lt_real3 (&val,
|
||
ffebld_constant_real3 (ffebld_conter (l)),
|
||
ffebld_constant_real3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okREAL4
|
||
case FFEINFO_kindtypeREAL4:
|
||
error = ffetarget_lt_real4 (&val,
|
||
ffebld_constant_real4 (ffebld_conter (l)),
|
||
ffebld_constant_real4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad real kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr))))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_lt_character1 (&val,
|
||
ffebld_constant_character1 (ffebld_conter (l)),
|
||
ffebld_constant_character1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_lt_character2 (&val,
|
||
ffebld_constant_character2 (ffebld_conter (l)),
|
||
ffebld_constant_character2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_lt_character3 (&val,
|
||
ffebld_constant_character3 (ffebld_conter (l)),
|
||
ffebld_constant_character3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_lt_character4 (&val,
|
||
ffebld_constant_character4 (ffebld_conter (l)),
|
||
ffebld_constant_character4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_logicaldefault (val), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_and -- Collapse and expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_and(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_and (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_and_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_and_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_and_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_and_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_and_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_and_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_and_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_and_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_or -- Collapse or expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_or(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_or (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_or_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_or_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_or_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_or_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_or_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_or_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_or_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_or_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_xor -- Collapse xor expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_xor(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_xor (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_xor_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_xor_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_xor_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_xor_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_xor_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_xor_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_xor_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_xor_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_eqv -- Collapse eqv expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_eqv(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_eqv (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_eqv_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_eqv_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_eqv_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_eqv_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_eqv_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_eqv_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_eqv_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_eqv_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_neqv -- Collapse neqv expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_neqv(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_neqv (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebldConstantUnion u;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr);
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
if (ffebld_op (r) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
switch (bt = ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okINTEGER1
|
||
case FFEINFO_kindtypeINTEGER1:
|
||
error = ffetarget_neqv_integer1 (ffebld_cu_ptr_integer1 (u),
|
||
ffebld_constant_integer1 (ffebld_conter (l)),
|
||
ffebld_constant_integer1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val
|
||
(ffebld_cu_val_integer1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER2
|
||
case FFEINFO_kindtypeINTEGER2:
|
||
error = ffetarget_neqv_integer2 (ffebld_cu_ptr_integer2 (u),
|
||
ffebld_constant_integer2 (ffebld_conter (l)),
|
||
ffebld_constant_integer2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val
|
||
(ffebld_cu_val_integer2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER3
|
||
case FFEINFO_kindtypeINTEGER3:
|
||
error = ffetarget_neqv_integer3 (ffebld_cu_ptr_integer3 (u),
|
||
ffebld_constant_integer3 (ffebld_conter (l)),
|
||
ffebld_constant_integer3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val
|
||
(ffebld_cu_val_integer3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okINTEGER4
|
||
case FFEINFO_kindtypeINTEGER4:
|
||
error = ffetarget_neqv_integer4 (ffebld_cu_ptr_integer4 (u),
|
||
ffebld_constant_integer4 (ffebld_conter (l)),
|
||
ffebld_constant_integer4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val
|
||
(ffebld_cu_val_integer4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad integer kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okLOGICAL1
|
||
case FFEINFO_kindtypeLOGICAL1:
|
||
error = ffetarget_neqv_logical1 (ffebld_cu_ptr_logical1 (u),
|
||
ffebld_constant_logical1 (ffebld_conter (l)),
|
||
ffebld_constant_logical1 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val
|
||
(ffebld_cu_val_logical1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL2
|
||
case FFEINFO_kindtypeLOGICAL2:
|
||
error = ffetarget_neqv_logical2 (ffebld_cu_ptr_logical2 (u),
|
||
ffebld_constant_logical2 (ffebld_conter (l)),
|
||
ffebld_constant_logical2 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val
|
||
(ffebld_cu_val_logical2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL3
|
||
case FFEINFO_kindtypeLOGICAL3:
|
||
error = ffetarget_neqv_logical3 (ffebld_cu_ptr_logical3 (u),
|
||
ffebld_constant_logical3 (ffebld_conter (l)),
|
||
ffebld_constant_logical3 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val
|
||
(ffebld_cu_val_logical3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okLOGICAL4
|
||
case FFEINFO_kindtypeLOGICAL4:
|
||
error = ffetarget_neqv_logical4 (ffebld_cu_ptr_logical4 (u),
|
||
ffebld_constant_logical4 (ffebld_conter (l)),
|
||
ffebld_constant_logical4 (ffebld_conter (r)));
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val
|
||
(ffebld_cu_val_logical4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad logical kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_symter -- Collapse symter expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_symter(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_symter (ffebld expr, ffelexToken t UNUSED)
|
||
{
|
||
ffebld r;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize len;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
if ((r = ffesymbol_init (ffebld_symter (expr))) == NULL)
|
||
return expr; /* A PARAMETER lhs in progress. */
|
||
|
||
switch (ffebld_op (r))
|
||
{
|
||
case FFEBLD_opCONTER:
|
||
break;
|
||
|
||
case FFEBLD_opANY:
|
||
return r;
|
||
|
||
default:
|
||
return expr;
|
||
}
|
||
|
||
bt = ffeinfo_basictype (ffebld_info (r));
|
||
kt = ffeinfo_kindtype (ffebld_info (r));
|
||
len = ffebld_size (r);
|
||
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)),
|
||
expr);
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_funcref -- Collapse funcref expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_funcref(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_funcref (ffebld expr, ffelexToken t UNUSED)
|
||
{
|
||
return expr; /* ~~someday go ahead and collapse these,
|
||
though not required */
|
||
}
|
||
|
||
/* ffeexpr_collapse_arrayref -- Collapse arrayref expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_arrayref(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_arrayref (ffebld expr, ffelexToken t UNUSED)
|
||
{
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_collapse_substr -- Collapse substr expr
|
||
|
||
ffebld expr;
|
||
ffelexToken token;
|
||
expr = ffeexpr_collapse_substr(expr,token);
|
||
|
||
If the result of the expr is a constant, replaces the expr with the
|
||
computed constant. */
|
||
|
||
ffebld
|
||
ffeexpr_collapse_substr (ffebld expr, ffelexToken t)
|
||
{
|
||
ffebad error = FFEBAD;
|
||
ffebld l;
|
||
ffebld r;
|
||
ffebld start;
|
||
ffebld stop;
|
||
ffebldConstantUnion u;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharacterSize len;
|
||
ffetargetIntegerDefault first;
|
||
ffetargetIntegerDefault last;
|
||
|
||
if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT)
|
||
return expr;
|
||
|
||
l = ffebld_left (expr);
|
||
r = ffebld_right (expr); /* opITEM. */
|
||
|
||
if (ffebld_op (l) != FFEBLD_opCONTER)
|
||
return expr;
|
||
|
||
kt = ffeinfo_kindtype (ffebld_info (l));
|
||
len = ffebld_size (l);
|
||
|
||
start = ffebld_head (r);
|
||
stop = ffebld_head (ffebld_trail (r));
|
||
if (start == NULL)
|
||
first = 1;
|
||
else
|
||
{
|
||
if ((ffebld_op (start) != FFEBLD_opCONTER)
|
||
|| (ffeinfo_basictype (ffebld_info (start)) != FFEINFO_basictypeINTEGER)
|
||
|| (ffeinfo_kindtype (ffebld_info (start))
|
||
!= FFEINFO_kindtypeINTEGERDEFAULT))
|
||
return expr;
|
||
first = ffebld_constant_integerdefault (ffebld_conter (start));
|
||
}
|
||
if (stop == NULL)
|
||
last = len;
|
||
else
|
||
{
|
||
if ((ffebld_op (stop) != FFEBLD_opCONTER)
|
||
|| (ffeinfo_basictype (ffebld_info (stop)) != FFEINFO_basictypeINTEGER)
|
||
|| (ffeinfo_kindtype (ffebld_info (stop))
|
||
!= FFEINFO_kindtypeINTEGERDEFAULT))
|
||
return expr;
|
||
last = ffebld_constant_integerdefault (ffebld_conter (stop));
|
||
}
|
||
|
||
/* Handle problems that should have already been diagnosed, but
|
||
left in the expression tree. */
|
||
|
||
if (first <= 0)
|
||
first = 1;
|
||
if (last < first)
|
||
last = first + len - 1;
|
||
|
||
if ((first == 1) && (last == len))
|
||
{ /* Same as original. */
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_copy
|
||
(ffebld_conter (l)), expr);
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeCHARACTER,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
return expr;
|
||
}
|
||
|
||
switch (ffeinfo_basictype (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_basictypeANY:
|
||
return expr;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (kt = ffeinfo_kindtype (ffebld_info (expr)))
|
||
{
|
||
#if FFETARGET_okCHARACTER1
|
||
case FFEINFO_kindtypeCHARACTER1:
|
||
error = ffetarget_substr_character1 (ffebld_cu_ptr_character1 (u),
|
||
ffebld_constant_character1 (ffebld_conter (l)), first, last,
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val
|
||
(ffebld_cu_val_character1 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER2
|
||
case FFEINFO_kindtypeCHARACTER2:
|
||
error = ffetarget_substr_character2 (ffebld_cu_ptr_character2 (u),
|
||
ffebld_constant_character2 (ffebld_conter (l)), first, last,
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val
|
||
(ffebld_cu_val_character2 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER3
|
||
case FFEINFO_kindtypeCHARACTER3:
|
||
error = ffetarget_substr_character3 (ffebld_cu_ptr_character3 (u),
|
||
ffebld_constant_character3 (ffebld_conter (l)), first, last,
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val
|
||
(ffebld_cu_val_character3 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCHARACTER4
|
||
case FFEINFO_kindtypeCHARACTER4:
|
||
error = ffetarget_substr_character4 (ffebld_cu_ptr_character4 (u),
|
||
ffebld_constant_character4 (ffebld_conter (l)), first, last,
|
||
ffebld_constant_pool (), &len);
|
||
expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val
|
||
(ffebld_cu_val_character4 (u)), expr);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
assert ("bad character kind type" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad type" == NULL);
|
||
return expr;
|
||
}
|
||
|
||
ffebld_set_info (expr, ffeinfo_new
|
||
(FFEINFO_basictypeCHARACTER,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
len));
|
||
|
||
if ((error != FFEBAD)
|
||
&& ffebad_start (error))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_convert -- Convert source expression to given type
|
||
|
||
ffebld source;
|
||
ffelexToken source_token;
|
||
ffelexToken dest_token; // Any appropriate token for "destination".
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
ffetargetCharactersize sz;
|
||
ffeexprContext context; // Mainly LET or DATA.
|
||
source = ffeexpr_convert(source,source_token,dest_token,bt,kt,sz,context);
|
||
|
||
If the expression conforms, returns the source expression. Otherwise
|
||
returns source wrapped in a convert node doing the conversion, or
|
||
ANY wrapped in convert if there is a conversion error (and issues an
|
||
error message). Be sensitive to the context for certain aspects of
|
||
the conversion. */
|
||
|
||
ffebld
|
||
ffeexpr_convert (ffebld source, ffelexToken source_token, ffelexToken dest_token,
|
||
ffeinfoBasictype bt, ffeinfoKindtype kt, ffeinfoRank rk,
|
||
ffetargetCharacterSize sz, ffeexprContext context)
|
||
{
|
||
bool bad;
|
||
ffeinfo info;
|
||
ffeinfoWhere wh;
|
||
|
||
info = ffebld_info (source);
|
||
if ((bt != ffeinfo_basictype (info))
|
||
|| (kt != ffeinfo_kindtype (info))
|
||
|| (rk != 0) /* Can't convert from or to arrays yet. */
|
||
|| (ffeinfo_rank (info) != 0)
|
||
|| (sz != ffebld_size_known (source)))
|
||
#if 0 /* Nobody seems to need this spurious CONVERT node. */
|
||
|| ((context != FFEEXPR_contextLET)
|
||
&& (bt == FFEINFO_basictypeCHARACTER)
|
||
&& (sz == FFETARGET_charactersizeNONE)))
|
||
#endif
|
||
{
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
switch (bt)
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
bad = !ffe_is_ugly_logint ();
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
bad = ffe_is_pedantic ()
|
||
|| !(ffe_is_ugly_init ()
|
||
&& (context == FFEEXPR_contextDATA));
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
switch (bt)
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
bad = !ffe_is_ugly_logint ();
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
bad = ffe_is_pedantic ()
|
||
|| !(ffe_is_ugly_init ()
|
||
&& (context == FFEEXPR_contextDATA));
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
switch (bt)
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
bad = TRUE;
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
bad = (bt != FFEINFO_basictypeCHARACTER)
|
||
&& (ffe_is_pedantic ()
|
||
|| (bt != FFEINFO_basictypeINTEGER)
|
||
|| !(ffe_is_ugly_init ()
|
||
&& (context == FFEEXPR_contextDATA)));
|
||
break;
|
||
|
||
case FFEINFO_basictypeTYPELESS:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
bad = ffe_is_pedantic ()
|
||
|| !(ffe_is_ugly_init ()
|
||
&& ((context == FFEEXPR_contextDATA)
|
||
|| (context == FFEEXPR_contextLET)));
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
|
||
if (!bad && ((rk != 0) || (ffeinfo_rank (info) != 0)))
|
||
bad = TRUE;
|
||
|
||
if (bad && (bt != FFEINFO_basictypeANY) && (kt != FFEINFO_kindtypeANY)
|
||
&& (ffeinfo_basictype (info) != FFEINFO_basictypeANY)
|
||
&& (ffeinfo_kindtype (info) != FFEINFO_kindtypeANY)
|
||
&& (ffeinfo_where (info) != FFEINFO_whereANY))
|
||
{
|
||
if (ffebad_start (FFEBAD_BAD_TYPES))
|
||
{
|
||
if (dest_token == NULL)
|
||
ffebad_here (0, ffewhere_line_unknown (),
|
||
ffewhere_column_unknown ());
|
||
else
|
||
ffebad_here (0, ffelex_token_where_line (dest_token),
|
||
ffelex_token_where_column (dest_token));
|
||
assert (source_token != NULL);
|
||
ffebad_here (1, ffelex_token_where_line (source_token),
|
||
ffelex_token_where_column (source_token));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
source = ffebld_new_any ();
|
||
ffebld_set_info (source, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
switch (ffeinfo_where (info))
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
wh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
wh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
wh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
source = ffebld_new_convert (source);
|
||
ffebld_set_info (source, ffeinfo_new
|
||
(bt,
|
||
kt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
wh,
|
||
sz));
|
||
source = ffeexpr_collapse_convert (source, source_token);
|
||
}
|
||
}
|
||
|
||
return source;
|
||
}
|
||
|
||
/* ffeexpr_convert_expr -- Convert source expr to conform to dest expr
|
||
|
||
ffebld source;
|
||
ffebld dest;
|
||
ffelexToken source_token;
|
||
ffelexToken dest_token;
|
||
ffeexprContext context;
|
||
source = ffeexpr_convert_expr(source,source_token,dest,dest_token,context);
|
||
|
||
If the expressions conform, returns the source expression. Otherwise
|
||
returns source wrapped in a convert node doing the conversion, or
|
||
ANY wrapped in convert if there is a conversion error (and issues an
|
||
error message). Be sensitive to the context, such as LET or DATA. */
|
||
|
||
ffebld
|
||
ffeexpr_convert_expr (ffebld source, ffelexToken source_token, ffebld dest,
|
||
ffelexToken dest_token, ffeexprContext context)
|
||
{
|
||
ffeinfo info;
|
||
|
||
info = ffebld_info (dest);
|
||
return ffeexpr_convert (source, source_token, dest_token,
|
||
ffeinfo_basictype (info),
|
||
ffeinfo_kindtype (info),
|
||
ffeinfo_rank (info),
|
||
ffebld_size_known (dest),
|
||
context);
|
||
}
|
||
|
||
/* ffeexpr_convert_to_sym -- Convert source expression to conform to symbol
|
||
|
||
ffebld source;
|
||
ffesymbol dest;
|
||
ffelexToken source_token;
|
||
ffelexToken dest_token;
|
||
source = ffeexpr_convert_to_sym(source,source_token,dest,dest_token);
|
||
|
||
If the expressions conform, returns the source expression. Otherwise
|
||
returns source wrapped in a convert node doing the conversion, or
|
||
ANY wrapped in convert if there is a conversion error (and issues an
|
||
error message). */
|
||
|
||
ffebld
|
||
ffeexpr_convert_to_sym (ffebld source, ffelexToken source_token,
|
||
ffesymbol dest, ffelexToken dest_token)
|
||
{
|
||
return ffeexpr_convert (source, source_token, dest_token, ffesymbol_basictype (dest),
|
||
ffesymbol_kindtype (dest), ffesymbol_rank (dest), ffesymbol_size (dest),
|
||
FFEEXPR_contextLET);
|
||
}
|
||
|
||
/* Initializes the module. */
|
||
|
||
void
|
||
ffeexpr_init_2 ()
|
||
{
|
||
ffeexpr_stack_ = NULL;
|
||
ffeexpr_level_ = 0;
|
||
}
|
||
|
||
/* ffeexpr_lhs -- Begin processing left-hand-side-context expression
|
||
|
||
Prepares cluster for delivery of lexer tokens representing an expression
|
||
in a left-hand-side context (A in A=B, for example). ffebld is used
|
||
to build expressions in the given pool. The appropriate lexer-token
|
||
handling routine within ffeexpr is returned. When the end of the
|
||
expression is detected, mycallbackroutine is called with the resulting
|
||
single ffebld object specifying the entire expression and the first
|
||
lexer token that is not considered part of the expression. This caller-
|
||
supplied routine itself returns a lexer-token handling routine. Thus,
|
||
if necessary, ffeexpr can return several tokens as end-of-expression
|
||
tokens if it needs to scan forward more than one in any instance. */
|
||
|
||
ffelexHandler
|
||
ffeexpr_lhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback)
|
||
{
|
||
ffeexprStack_ s;
|
||
|
||
ffebld_pool_push (pool);
|
||
s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s));
|
||
s->previous = ffeexpr_stack_;
|
||
s->pool = pool;
|
||
s->context = context;
|
||
s->callback = callback;
|
||
s->first_token = NULL;
|
||
s->exprstack = NULL;
|
||
s->is_rhs = FALSE;
|
||
ffeexpr_stack_ = s;
|
||
return (ffelexHandler) ffeexpr_token_first_lhs_;
|
||
}
|
||
|
||
/* ffeexpr_rhs -- Begin processing right-hand-side-context expression
|
||
|
||
return ffeexpr_rhs(malloc_pool_image(),mycallbackroutine); // to lexer.
|
||
|
||
Prepares cluster for delivery of lexer tokens representing an expression
|
||
in a right-hand-side context (B in A=B, for example). ffebld is used
|
||
to build expressions in the given pool. The appropriate lexer-token
|
||
handling routine within ffeexpr is returned. When the end of the
|
||
expression is detected, mycallbackroutine is called with the resulting
|
||
single ffebld object specifying the entire expression and the first
|
||
lexer token that is not considered part of the expression. This caller-
|
||
supplied routine itself returns a lexer-token handling routine. Thus,
|
||
if necessary, ffeexpr can return several tokens as end-of-expression
|
||
tokens if it needs to scan forward more than one in any instance. */
|
||
|
||
ffelexHandler
|
||
ffeexpr_rhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback)
|
||
{
|
||
ffeexprStack_ s;
|
||
|
||
ffebld_pool_push (pool);
|
||
s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s));
|
||
s->previous = ffeexpr_stack_;
|
||
s->pool = pool;
|
||
s->context = context;
|
||
s->callback = callback;
|
||
s->first_token = NULL;
|
||
s->exprstack = NULL;
|
||
s->is_rhs = TRUE;
|
||
ffeexpr_stack_ = s;
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_;
|
||
}
|
||
|
||
/* ffeexpr_cb_close_paren_ -- OPEN_PAREN expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Makes sure the end token is close-paren and swallows it, else issues
|
||
an error message and doesn't swallow the token (passing it along instead).
|
||
In either case wraps up subexpression construction by enclosing the
|
||
ffebld expression in a paren. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
|
||
{
|
||
/* Oops, naughty user didn't specify the close paren! */
|
||
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_token_binary_);
|
||
}
|
||
|
||
if (expr->op == FFEBLD_opIMPDO)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_IMPDO_PAREN))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
expr = ffebld_new_paren (expr);
|
||
ffebld_set_info (expr, ffeinfo_use (ffebld_info (ffebld_left (expr))));
|
||
}
|
||
|
||
/* Now push the (parenthesized) expression as an operand onto the
|
||
expression stack. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand = expr;
|
||
e->u.operand = ffeexpr_collapse_paren (e->u.operand, ft);
|
||
e->token = ffeexpr_stack_->tokens[0];
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_cb_close_paren_ambig_ -- OPEN_PAREN expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)"
|
||
with the next token in t. If the next token is possibly a binary
|
||
operator, continue processing the outer expression. If the next
|
||
token is COMMA, then the expression is a unit specifier, and
|
||
parentheses should not be added to it because it surrounds the
|
||
I/O control list that starts with the unit specifier (and continues
|
||
on from here -- we haven't seen the CLOSE_PAREN that matches the
|
||
OPEN_PAREN, it is up to the callback function to expect to see it
|
||
at some point). In this case, we notify the callback function that
|
||
the COMMA is inside, not outside, the parens by wrapping the expression
|
||
in an opITEM (with a NULL trail) -- the callback function presumably
|
||
unwraps it after seeing this kludgey indicator.
|
||
|
||
If the next token is CLOSE_PAREN, then we go to the _1_ state to
|
||
decide what to do with the token after that.
|
||
|
||
15-Feb-91 JCB 1.1
|
||
Use an extra state for the CLOSE_PAREN case to make READ &co really
|
||
work right. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_close_paren_ambig_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
{ /* Need to see the next token before we
|
||
decide anything. */
|
||
ffeexpr_stack_->expr = expr;
|
||
ffeexpr_tokens_[0] = ffelex_token_use (ft);
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_cb_close_paren_ambig_1_;
|
||
}
|
||
|
||
expr = ffeexpr_finished_ambig_ (ft, expr);
|
||
|
||
/* Let the callback function handle the case where t isn't COMMA. */
|
||
|
||
/* Here is a kludge whereby we tell the callback function the OPEN_PAREN
|
||
that preceded the expression starts a list of expressions, and the expr
|
||
hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN
|
||
node. The callback function should extract the real expr from the head
|
||
of this opITEM node after testing it. */
|
||
|
||
expr = ffebld_new_item (expr, NULL);
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ffelex_token_kill (ffeexpr_stack_->first_token);
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
return (ffelexHandler) (*callback) (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_cb_close_paren_ambig_1_ -- OPEN_PAREN expr CLOSE_PAREN
|
||
|
||
See ffeexpr_cb_close_paren_ambig_.
|
||
|
||
We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)"
|
||
with the next token in t. If the next token is possibly a binary
|
||
operator, continue processing the outer expression. If the next
|
||
token is COMMA, the expression is a parenthesized format specifier.
|
||
If the next token is not EOS or SEMICOLON, then because it is not a
|
||
binary operator (it is NAME, OPEN_PAREN, &c), the expression is
|
||
a unit specifier, and parentheses should not be added to it because
|
||
they surround the I/O control list that consists of only the unit
|
||
specifier. If the next token is EOS or SEMICOLON, the statement
|
||
must be disambiguated by looking at the type of the expression -- a
|
||
character expression is a parenthesized format specifier, while a
|
||
non-character expression is a unit specifier.
|
||
|
||
Another issue is how to do the callback so the recipient of the
|
||
next token knows how to handle it if it is a COMMA. In all other
|
||
cases, disambiguation is straightforward: the same approach as the
|
||
above is used.
|
||
|
||
EXTENSION: in COMMA case, if not pedantic, use same disambiguation
|
||
as for EOS/SEMICOLON case; f2c allows "READ (cilist) [[,]iolist]"
|
||
and apparently other compilers do, as well, and some code out there
|
||
uses this "feature".
|
||
|
||
19-Feb-91 JCB 1.1
|
||
Extend to allow COMMA as nondisambiguating by itself. Remember
|
||
to not try and check info field for opSTAR, since that expr doesn't
|
||
have a valid info field. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken orig_ft = ffeexpr_tokens_[0]; /* In case callback clobbers
|
||
these. */
|
||
ffelexToken orig_t = ffeexpr_tokens_[1];
|
||
ffebld expr = ffeexpr_stack_->expr;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA: /* Subexpr is parenthesized format specifier. */
|
||
if (ffe_is_pedantic ())
|
||
goto pedantic_comma; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFELEX_typeEOS: /* Ambiguous; use type of expr to
|
||
disambiguate. */
|
||
case FFELEX_typeSEMICOLON:
|
||
if ((expr == NULL) || (ffebld_op (expr) == FFEBLD_opANY)
|
||
|| (ffebld_op (expr) == FFEBLD_opSTAR)
|
||
|| (ffeinfo_basictype (ffebld_info (expr))
|
||
!= FFEINFO_basictypeCHARACTER))
|
||
break; /* Not a valid CHARACTER entity, can't be a
|
||
format spec. */
|
||
/* Fall through. */
|
||
default: /* Binary op (we assume; error otherwise);
|
||
format specifier. */
|
||
|
||
pedantic_comma: /* :::::::::::::::::::: */
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILENUM;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
break;
|
||
}
|
||
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
|
||
next = (ffelexHandler) ffeexpr_cb_close_paren_ (orig_ft, expr, orig_t);
|
||
ffelex_token_kill (orig_ft);
|
||
ffelex_token_kill (orig_t);
|
||
return (ffelexHandler) (*next) (t);
|
||
|
||
case FFELEX_typeOPEN_PAREN:/* Non-binary op; beginning of I/O list. */
|
||
case FFELEX_typeNAME:
|
||
break;
|
||
}
|
||
|
||
expr = ffeexpr_finished_ambig_ (orig_ft, expr);
|
||
|
||
/* Here is a kludge whereby we tell the callback function the OPEN_PAREN
|
||
that preceded the expression starts a list of expressions, and the expr
|
||
hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN
|
||
node. The callback function should extract the real expr from the head
|
||
of this opITEM node after testing it. */
|
||
|
||
expr = ffebld_new_item (expr, NULL);
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ffelex_token_kill (ffeexpr_stack_->first_token);
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (orig_ft, expr, orig_t);
|
||
ffelex_token_kill (orig_ft);
|
||
ffelex_token_kill (orig_t);
|
||
return (ffelexHandler) (*next) (t);
|
||
}
|
||
|
||
/* ffeexpr_cb_close_paren_c_ -- OPEN_PAREN expr (possible complex)
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Makes sure the end token is close-paren and swallows it, or a comma
|
||
and handles complex/implied-do possibilities, else issues
|
||
an error message and doesn't swallow the token (passing it along instead). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_close_paren_c_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
/* First check to see if this is a possible complex entity. It is if the
|
||
token is a comma. */
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCOMMA)
|
||
{
|
||
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
|
||
ffeexpr_stack_->expr = expr;
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextPAREN_, ffeexpr_cb_comma_c_);
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_cb_close_paren_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_c_ -- OPEN_PAREN expr COMMA expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
If this token is not a comma, we have a complex constant (or an attempt
|
||
at one), so handle it accordingly, displaying error messages if the token
|
||
is not a close-paren. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffeinfoBasictype lty = (ffeexpr_stack_->expr == NULL)
|
||
? FFEINFO_basictypeNONE : ffeinfo_basictype (ffebld_info (ffeexpr_stack_->expr));
|
||
ffeinfoBasictype rty = (expr == NULL)
|
||
? FFEINFO_basictypeNONE : ffeinfo_basictype (ffebld_info (expr));
|
||
ffeinfoKindtype lkt;
|
||
ffeinfoKindtype rkt;
|
||
ffeinfoKindtype nkt;
|
||
bool ok = TRUE;
|
||
ffebld orig;
|
||
|
||
if ((ffeexpr_stack_->expr == NULL)
|
||
|| (ffebld_op (ffeexpr_stack_->expr) != FFEBLD_opCONTER)
|
||
|| (((orig = ffebld_conter_orig (ffeexpr_stack_->expr)) != NULL)
|
||
&& (((ffebld_op (orig) != FFEBLD_opUMINUS)
|
||
&& (ffebld_op (orig) != FFEBLD_opUPLUS))
|
||
|| (ffebld_conter_orig (ffebld_left (orig)) != NULL)))
|
||
|| ((lty != FFEINFO_basictypeINTEGER)
|
||
&& (lty != FFEINFO_basictypeREAL)))
|
||
{
|
||
if ((lty != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_INVALID_COMPLEX_PART))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
|
||
ffebad_string ("Real");
|
||
ffebad_finish ();
|
||
}
|
||
ok = FALSE;
|
||
}
|
||
if ((expr == NULL)
|
||
|| (ffebld_op (expr) != FFEBLD_opCONTER)
|
||
|| (((orig = ffebld_conter_orig (expr)) != NULL)
|
||
&& (((ffebld_op (orig) != FFEBLD_opUMINUS)
|
||
&& (ffebld_op (orig) != FFEBLD_opUPLUS))
|
||
|| (ffebld_conter_orig (ffebld_left (orig)) != NULL)))
|
||
|| ((rty != FFEINFO_basictypeINTEGER)
|
||
&& (rty != FFEINFO_basictypeREAL)))
|
||
{
|
||
if ((rty != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_INVALID_COMPLEX_PART))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_string ("Imaginary");
|
||
ffebad_finish ();
|
||
}
|
||
ok = FALSE;
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
|
||
/* Push the (parenthesized) expression as an operand onto the expression
|
||
stack. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_stack_->tokens[0];
|
||
|
||
if (ok)
|
||
{
|
||
if (lty == FFEINFO_basictypeINTEGER)
|
||
lkt = FFEINFO_kindtypeREALDEFAULT;
|
||
else
|
||
lkt = ffeinfo_kindtype (ffebld_info (ffeexpr_stack_->expr));
|
||
if (rty == FFEINFO_basictypeINTEGER)
|
||
rkt = FFEINFO_kindtypeREALDEFAULT;
|
||
else
|
||
rkt = ffeinfo_kindtype (ffebld_info (expr));
|
||
|
||
nkt = ffeinfo_kindtype_max (FFEINFO_basictypeCOMPLEX, lkt, rkt);
|
||
ffeexpr_stack_->expr = ffeexpr_convert (ffeexpr_stack_->expr,
|
||
ffeexpr_stack_->tokens[1], ffeexpr_stack_->tokens[0],
|
||
FFEINFO_basictypeREAL, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
expr = ffeexpr_convert (expr,
|
||
ffeexpr_stack_->tokens[1], ffeexpr_stack_->tokens[0],
|
||
FFEINFO_basictypeREAL, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
}
|
||
else
|
||
nkt = FFEINFO_kindtypeANY;
|
||
|
||
switch (nkt)
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex1
|
||
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex2
|
||
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex3
|
||
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
break;
|
||
#endif
|
||
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_complex4
|
||
(ffebld_conter (ffeexpr_stack_->expr), ffebld_conter (expr)));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeCOMPLEX, nkt, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
if (ffebad_start ((nkt == FFEINFO_kindtypeREALDOUBLE)
|
||
? FFEBAD_BAD_DBLCMPLX : FFEBAD_BAD_COMPLEX))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_kindtypeANY:
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
break;
|
||
}
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
/* Now, if the token is a close parenthese, we're in great shape so return
|
||
the next handler. */
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
|
||
/* Oops, naughty user didn't specify the close paren! */
|
||
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_token_binary_);
|
||
}
|
||
|
||
/* ffeexpr_cb_close_paren_ci_ -- OPEN_PAREN expr (possible complex or
|
||
implied-DO construct)
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Makes sure the end token is close-paren and swallows it, or a comma
|
||
and handles complex/implied-do possibilities, else issues
|
||
an error message and doesn't swallow the token (passing it along instead). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_close_paren_ci_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprContext ctx;
|
||
|
||
/* First check to see if this is a possible complex or implied-DO entity.
|
||
It is if the token is a comma. */
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCOMMA)
|
||
{
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
ctx = FFEEXPR_contextIMPDOITEM_;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ctx = FFEEXPR_contextIMPDOITEMDF_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
ctx = FFEEXPR_contextIMPDOITEM_;
|
||
break;
|
||
}
|
||
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (ft);
|
||
ffeexpr_stack_->expr = expr;
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ctx, ffeexpr_cb_comma_ci_);
|
||
}
|
||
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
|
||
return (ffelexHandler) ffeexpr_cb_close_paren_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_ci_ -- OPEN_PAREN expr COMMA expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
If this token is not a comma, we have a complex constant (or an attempt
|
||
at one), so handle it accordingly, displaying error messages if the token
|
||
is not a close-paren. If we have a comma here, it is an attempt at an
|
||
implied-DO, so start making a list accordingly. Oh, it might be an
|
||
equal sign also, meaning an implied-DO with only one item in its list. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_ci_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffebld fexpr;
|
||
|
||
/* First check to see if this is a possible complex constant. It is if the
|
||
token is not a comma or an equals sign, in which case it should be a
|
||
close-paren. */
|
||
|
||
if ((ffelex_token_type (t) != FFELEX_typeCOMMA)
|
||
&& (ffelex_token_type (t) != FFELEX_typeEQUALS))
|
||
{
|
||
ffeexpr_stack_->tokens[1] = ffeexpr_stack_->tokens[0];
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token);
|
||
return (ffelexHandler) ffeexpr_cb_comma_c_ (ft, expr, t);
|
||
}
|
||
|
||
/* Here we have either EQUALS or COMMA, meaning we are in an implied-DO
|
||
construct. Make a list and handle accordingly. */
|
||
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
|
||
fexpr = ffeexpr_stack_->expr;
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, fexpr);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_1_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_ -- OPEN_PAREN expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Handle first item in an implied-DO construct. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->expr = ffebld_new_any ();
|
||
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
|
||
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_1_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_1_ -- OPEN_PAREN expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Handle first item in an implied-DO construct. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_1_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprContext ctxi;
|
||
ffeexprContext ctxc;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
ctxi = FFEEXPR_contextDATAIMPDOITEM_;
|
||
ctxc = FFEEXPR_contextDATAIMPDOCTRL_;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
ctxi = FFEEXPR_contextIMPDOITEM_;
|
||
ctxc = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ctxi = FFEEXPR_contextIMPDOITEMDF_;
|
||
ctxc = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
ctxi = FFEEXPR_context;
|
||
ctxc = FFEEXPR_context;
|
||
break;
|
||
}
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
if (ffeexpr_stack_->is_rhs)
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ctxi, ffeexpr_cb_comma_i_1_);
|
||
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
|
||
ctxi, ffeexpr_cb_comma_i_1_);
|
||
|
||
case FFELEX_typeEQUALS:
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
|
||
/* Complain if implied-DO variable in list of items to be read. */
|
||
|
||
if ((ctxc == FFEEXPR_contextIMPDOCTRL_) && !ffeexpr_stack_->is_rhs)
|
||
ffeexpr_check_impdo_ (ffeexpr_stack_->expr,
|
||
ffeexpr_stack_->first_token, expr, ft);
|
||
|
||
/* Set doiter flag for all appropriate SYMTERs. */
|
||
|
||
ffeexpr_update_impdo_ (ffeexpr_stack_->expr, expr);
|
||
|
||
ffeexpr_stack_->expr = ffebld_new_impdo (ffeexpr_stack_->expr, NULL);
|
||
ffebld_set_info (ffeexpr_stack_->expr,
|
||
ffeinfo_new (FFEINFO_basictypeNONE,
|
||
FFEINFO_kindtypeNONE,
|
||
0,
|
||
FFEINFO_kindNONE,
|
||
FFEINFO_whereNONE,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_init_list (&(ffebld_right (ffeexpr_stack_->expr)),
|
||
&ffeexpr_stack_->bottom);
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ctxc, ffeexpr_cb_comma_i_2_);
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->expr = ffebld_new_any ();
|
||
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
|
||
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_2_ -- OPEN_PAREN expr-list EQUALS expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Handle start-value in an implied-DO construct. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_2_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprContext ctx;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
ctx = FFEEXPR_contextDATAIMPDOCTRL_;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ctx = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
ctx = FFEEXPR_context;
|
||
break;
|
||
}
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ctx, ffeexpr_cb_comma_i_3_);
|
||
break;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->expr = ffebld_new_any ();
|
||
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
|
||
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_3_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Handle end-value in an implied-DO construct. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_3_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprContext ctx;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
ctx = FFEEXPR_contextDATAIMPDOCTRL_;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ctx = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
ctx = FFEEXPR_context;
|
||
break;
|
||
}
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ctx, ffeexpr_cb_comma_i_4_);
|
||
break;
|
||
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_4_ (NULL, NULL, t);
|
||
break;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->expr = ffebld_new_any ();
|
||
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
|
||
if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_4_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
|
||
[COMMA expr]
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Handle incr-value in an implied-DO construct. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_4_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
{
|
||
ffebld item;
|
||
|
||
for (item = ffebld_left (ffeexpr_stack_->expr);
|
||
item != NULL;
|
||
item = ffebld_trail (item))
|
||
if (ffebld_op (ffebld_head (item)) == FFEBLD_opANY)
|
||
goto replace_with_any; /* :::::::::::::::::::: */
|
||
|
||
for (item = ffebld_right (ffeexpr_stack_->expr);
|
||
item != NULL;
|
||
item = ffebld_trail (item))
|
||
if ((ffebld_head (item) != NULL) /* Increment may be NULL. */
|
||
&& (ffebld_op (ffebld_head (item)) == FFEBLD_opANY))
|
||
goto replace_with_any; /* :::::::::::::::::::: */
|
||
}
|
||
break;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_BAD_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
|
||
replace_with_any: /* :::::::::::::::::::: */
|
||
|
||
ffeexpr_stack_->expr = ffebld_new_any ();
|
||
ffebld_set_info (ffeexpr_stack_->expr, ffeinfo_new_any ());
|
||
break;
|
||
}
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_;
|
||
return (ffelexHandler) ffeexpr_cb_comma_i_5_ (t);
|
||
}
|
||
|
||
/* ffeexpr_cb_comma_i_5_ -- OPEN_PAREN expr-list EQUALS expr COMMA expr
|
||
[COMMA expr] CLOSE_PAREN
|
||
|
||
Pass it to ffeexpr_rhs as the callback routine.
|
||
|
||
Collects token following implied-DO construct for callback function. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_comma_i_5_ (ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
ffebld expr;
|
||
bool terminate;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
terminate = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
terminate = FALSE;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
terminate = FALSE;
|
||
break;
|
||
}
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
expr = ffeexpr_stack_->expr;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
|
||
sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
if (terminate)
|
||
{
|
||
ffesymbol_drive_sfnames (ffeexpr_check_impctrl_);
|
||
--ffeexpr_level_;
|
||
if (ffeexpr_level_ == 0)
|
||
ffe_terminate_4 ();
|
||
}
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_cb_end_loc_ -- Handle end of %LOC subexpression
|
||
|
||
Makes sure the end token is close-paren and swallows it, else issues
|
||
an error message and doesn't swallow the token (passing it along instead).
|
||
In either case wraps up subexpression construction by enclosing the
|
||
ffebld expression in a %LOC. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_end_loc_ (ffelexToken ft UNUSED, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
/* First push the (%LOC) expression as an operand onto the expression
|
||
stack. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_stack_->tokens[0];
|
||
e->u.operand = ffebld_new_percent_loc (expr);
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
ffecom_pointer_kind (),
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereFLEETING,
|
||
FFETARGET_charactersizeNONE));
|
||
#if 0 /* ~~ */
|
||
e->u.operand = ffeexpr_collapse_percent_loc (e->u.operand, ft);
|
||
#endif
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
/* Now, if the token is a close parenthese, we're in great shape so return
|
||
the next handler. */
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
{
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* Oops, naughty user didn't specify the close paren! */
|
||
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_token_binary_);
|
||
}
|
||
|
||
/* ffeexpr_cb_end_notloc_ -- PERCENT NAME(VAL,REF,DESCR) OPEN_PAREN expr
|
||
|
||
Should be CLOSE_PAREN, and make sure expr isn't a %(VAL,REF,DESCR). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_end_notloc_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffebldOp op;
|
||
|
||
/* If expression is itself a %(VAL,REF,DESCR), complain and strip off all
|
||
such things until the lowest-level expression is reached. */
|
||
|
||
op = ffebld_op (expr);
|
||
if ((op == FFEBLD_opPERCENT_VAL) || (op == FFEBLD_opPERCENT_REF)
|
||
|| (op == FFEBLD_opPERCENT_DESCR))
|
||
{
|
||
if (ffebad_start (FFEBAD_NESTED_PERCENT))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
do
|
||
{
|
||
expr = ffebld_left (expr);
|
||
op = ffebld_op (expr);
|
||
}
|
||
while ((op == FFEBLD_opPERCENT_VAL) || (op == FFEBLD_opPERCENT_REF)
|
||
|| (op == FFEBLD_opPERCENT_DESCR));
|
||
}
|
||
|
||
/* Push the expression as an operand onto the expression stack. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_stack_->tokens[0];
|
||
switch (ffeexpr_stack_->percent)
|
||
{
|
||
case FFEEXPR_percentVAL_:
|
||
e->u.operand = ffebld_new_percent_val (expr);
|
||
break;
|
||
|
||
case FFEEXPR_percentREF_:
|
||
e->u.operand = ffebld_new_percent_ref (expr);
|
||
break;
|
||
|
||
case FFEEXPR_percentDESCR_:
|
||
e->u.operand = ffebld_new_percent_descr (expr);
|
||
break;
|
||
|
||
default:
|
||
assert ("%lossage" == NULL);
|
||
e->u.operand = expr;
|
||
break;
|
||
}
|
||
ffebld_set_info (e->u.operand, ffebld_info (expr));
|
||
#if 0 /* ~~ */
|
||
e->u.operand = ffeexpr_collapse_percent_ ? ? ? (e->u.operand, ft);
|
||
#endif
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
/* Now, if the token is a close parenthese, we're in great shape so return
|
||
the next handler. */
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
return (ffelexHandler) ffeexpr_cb_end_notloc_1_;
|
||
|
||
/* Oops, naughty user didn't specify the close paren! */
|
||
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffebld_set_op (e->u.operand, FFEBLD_opPERCENT_LOC);
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context?!?!" == NULL);
|
||
break;
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_cb_end_notloc_1_);
|
||
}
|
||
|
||
/* ffeexpr_cb_end_notloc_1_ -- PERCENT NAME(VAL,REF,DESCR) OPEN_PAREN expr
|
||
CLOSE_PAREN
|
||
|
||
Should be COMMA or CLOSE_PAREN, else change back to %LOC. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_cb_end_notloc_1_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context?!?!" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
if (ffebad_start (FFEBAD_INVALID_PERCENT))
|
||
{
|
||
ffebad_here (0,
|
||
ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_string (ffelex_token_text (ffeexpr_stack_->tokens[1]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffebld_set_op (ffeexpr_stack_->exprstack->u.operand,
|
||
FFEBLD_opPERCENT_LOC);
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context?!?!" == NULL);
|
||
break;
|
||
}
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
return
|
||
(ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* Process DATA implied-DO iterator variables as this implied-DO level
|
||
terminates. At this point, ffeexpr_level_ == 1 when we see the
|
||
last right-paren in "DATA (A(I),I=1,10)/.../". */
|
||
|
||
static ffesymbol
|
||
ffeexpr_check_impctrl_ (ffesymbol s)
|
||
{
|
||
assert (s != NULL);
|
||
assert (ffesymbol_sfdummyparent (s) != NULL);
|
||
|
||
switch (ffesymbol_state (s))
|
||
{
|
||
case FFESYMBOL_stateNONE: /* Used as iterator already. Now let symbol
|
||
be used as iterator at any level at or
|
||
innermore than the outermost of the
|
||
current level and the symbol's current
|
||
level. */
|
||
if (ffeexpr_level_ < ffesymbol_maxentrynum (s))
|
||
{
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
|
||
ffesymbol_signal_unreported (s);
|
||
}
|
||
break;
|
||
|
||
case FFESYMBOL_stateSEEN: /* Seen already in this or other implied-DO.
|
||
Error if at outermost level, else it can
|
||
still become an iterator. */
|
||
if ((ffeexpr_level_ == 1)
|
||
&& ffebad_start (FFEBAD_BAD_IMPDCL))
|
||
{
|
||
ffebad_string (ffesymbol_text (s));
|
||
ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
|
||
ffebad_finish ();
|
||
}
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNCERTAIN: /* Iterator. */
|
||
assert (ffeexpr_level_ <= ffesymbol_maxentrynum (s));
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateNONE);
|
||
ffesymbol_signal_unreported (s);
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNDERSTOOD:
|
||
break; /* ANY. */
|
||
|
||
default:
|
||
assert ("Sasha Foo!!" == NULL);
|
||
break;
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Issue diagnostic if implied-DO variable appears in list of lhs
|
||
expressions (as in "READ *, (I,I=1,10)"). */
|
||
|
||
static void
|
||
ffeexpr_check_impdo_ (ffebld list, ffelexToken list_t,
|
||
ffebld dovar, ffelexToken dovar_t)
|
||
{
|
||
ffebld item;
|
||
ffesymbol dovar_sym;
|
||
int itemnum;
|
||
|
||
if (ffebld_op (dovar) != FFEBLD_opSYMTER)
|
||
return; /* Presumably opANY. */
|
||
|
||
dovar_sym = ffebld_symter (dovar);
|
||
|
||
for (itemnum = 1; list != NULL; list = ffebld_trail (list), ++itemnum)
|
||
{
|
||
if (((item = ffebld_head (list)) != NULL)
|
||
&& (ffebld_op (item) == FFEBLD_opSYMTER)
|
||
&& (ffebld_symter (item) == dovar_sym))
|
||
{
|
||
char itemno[20];
|
||
|
||
sprintf (&itemno[0], "%d", itemnum);
|
||
if (ffebad_start (FFEBAD_DOITER_IMPDO))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (list_t),
|
||
ffelex_token_where_column (list_t));
|
||
ffebad_here (1, ffelex_token_where_line (dovar_t),
|
||
ffelex_token_where_column (dovar_t));
|
||
ffebad_string (ffesymbol_text (dovar_sym));
|
||
ffebad_string (itemno);
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Decorate any SYMTERs referencing the DO variable with the "doiter"
|
||
flag. */
|
||
|
||
static void
|
||
ffeexpr_update_impdo_ (ffebld list, ffebld dovar)
|
||
{
|
||
ffesymbol dovar_sym;
|
||
|
||
if (ffebld_op (dovar) != FFEBLD_opSYMTER)
|
||
return; /* Presumably opANY. */
|
||
|
||
dovar_sym = ffebld_symter (dovar);
|
||
|
||
ffeexpr_update_impdo_sym_ (list, dovar_sym); /* Recurse! */
|
||
}
|
||
|
||
/* Recursive function to update any expr so SYMTERs have "doiter" flag
|
||
if they refer to the given variable. */
|
||
|
||
static void
|
||
ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar)
|
||
{
|
||
tail_recurse: /* :::::::::::::::::::: */
|
||
|
||
if (expr == NULL)
|
||
return;
|
||
|
||
switch (ffebld_op (expr))
|
||
{
|
||
case FFEBLD_opSYMTER:
|
||
if (ffebld_symter (expr) == dovar)
|
||
ffebld_symter_set_is_doiter (expr, TRUE);
|
||
break;
|
||
|
||
case FFEBLD_opITEM:
|
||
ffeexpr_update_impdo_sym_ (ffebld_head (expr), dovar);
|
||
expr = ffebld_trail (expr);
|
||
goto tail_recurse; /* :::::::::::::::::::: */
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
switch (ffebld_arity (expr))
|
||
{
|
||
case 2:
|
||
ffeexpr_update_impdo_sym_ (ffebld_left (expr), dovar);
|
||
expr = ffebld_right (expr);
|
||
goto tail_recurse; /* :::::::::::::::::::: */
|
||
|
||
case 1:
|
||
expr = ffebld_left (expr);
|
||
goto tail_recurse; /* :::::::::::::::::::: */
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/* ffeexpr_context_outer_ -- Determine context of stack entry, skipping PARENs
|
||
|
||
if (ffeexpr_context_outer_(ffeexpr_stack_) == FFEEXPR_contextIF)
|
||
// After zero or more PAREN_ contexts, an IF context exists */
|
||
|
||
static ffeexprContext
|
||
ffeexpr_context_outer_ (ffeexprStack_ s)
|
||
{
|
||
assert (s != NULL);
|
||
|
||
for (;;)
|
||
{
|
||
switch (s->context)
|
||
{
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextPARENFILENUM_:
|
||
case FFEEXPR_contextPARENFILEUNIT_:
|
||
break;
|
||
|
||
default:
|
||
return s->context;
|
||
}
|
||
s = s->previous;
|
||
assert (s != NULL);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_percent_ -- Look up name in list of %FOO possibilities
|
||
|
||
ffeexprPercent_ p;
|
||
ffelexToken t;
|
||
p = ffeexpr_percent_(t);
|
||
|
||
Returns the identifier for the name, or the NONE identifier. */
|
||
|
||
static ffeexprPercent_
|
||
ffeexpr_percent_ (ffelexToken t)
|
||
{
|
||
const char *p;
|
||
|
||
switch (ffelex_token_length (t))
|
||
{
|
||
case 3:
|
||
switch (*(p = ffelex_token_text (t)))
|
||
{
|
||
case FFESRC_CASE_MATCH_INIT ('L', 'l', match_3l, no_match_3):
|
||
if ((ffesrc_char_match_noninit (*++p, 'O', 'o'))
|
||
&& (ffesrc_char_match_noninit (*++p, 'C', 'c')))
|
||
return FFEEXPR_percentLOC_;
|
||
return FFEEXPR_percentNONE_;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('R', 'r', match_3r, no_match_3):
|
||
if ((ffesrc_char_match_noninit (*++p, 'E', 'e'))
|
||
&& (ffesrc_char_match_noninit (*++p, 'F', 'f')))
|
||
return FFEEXPR_percentREF_;
|
||
return FFEEXPR_percentNONE_;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('V', 'v', match_3v, no_match_3):
|
||
if ((ffesrc_char_match_noninit (*++p, 'A', 'a'))
|
||
&& (ffesrc_char_match_noninit (*++p, 'L', 'l')))
|
||
return FFEEXPR_percentVAL_;
|
||
return FFEEXPR_percentNONE_;
|
||
|
||
default:
|
||
no_match_3: /* :::::::::::::::::::: */
|
||
return FFEEXPR_percentNONE_;
|
||
}
|
||
|
||
case 5:
|
||
if (ffesrc_strcmp_2c (ffe_case_match (), ffelex_token_text (t), "DESCR",
|
||
"descr", "Descr") == 0)
|
||
return FFEEXPR_percentDESCR_;
|
||
return FFEEXPR_percentNONE_;
|
||
|
||
default:
|
||
return FFEEXPR_percentNONE_;
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_type_combine -- Binop combine types, check for mythical new COMPLEX
|
||
|
||
See prototype.
|
||
|
||
If combining the two basictype/kindtype pairs produces a COMPLEX with an
|
||
unsupported kind type, complain and use the default kind type for
|
||
COMPLEX. */
|
||
|
||
void
|
||
ffeexpr_type_combine (ffeinfoBasictype *xnbt, ffeinfoKindtype *xnkt,
|
||
ffeinfoBasictype lbt, ffeinfoKindtype lkt,
|
||
ffeinfoBasictype rbt, ffeinfoKindtype rkt,
|
||
ffelexToken t)
|
||
{
|
||
ffeinfoBasictype nbt;
|
||
ffeinfoKindtype nkt;
|
||
|
||
nbt = ffeinfo_basictype_combine (lbt, rbt);
|
||
if ((nbt == FFEINFO_basictypeCOMPLEX)
|
||
&& ((lbt == nbt) || (lbt == FFEINFO_basictypeREAL))
|
||
&& ((rbt == nbt) || (rbt == FFEINFO_basictypeREAL)))
|
||
{
|
||
nkt = ffeinfo_kindtype_max (nbt, lkt, rkt);
|
||
if (ffe_is_pedantic_not_90 () && (nkt == FFEINFO_kindtypeREALDOUBLE))
|
||
nkt = FFEINFO_kindtypeNONE; /* Force error. */
|
||
switch (nkt)
|
||
{
|
||
#if FFETARGET_okCOMPLEX1
|
||
case FFEINFO_kindtypeREAL1:
|
||
#endif
|
||
#if FFETARGET_okCOMPLEX2
|
||
case FFEINFO_kindtypeREAL2:
|
||
#endif
|
||
#if FFETARGET_okCOMPLEX3
|
||
case FFEINFO_kindtypeREAL3:
|
||
#endif
|
||
#if FFETARGET_okCOMPLEX4
|
||
case FFEINFO_kindtypeREAL4:
|
||
#endif
|
||
break; /* Fine and dandy. */
|
||
|
||
default:
|
||
if (t != NULL)
|
||
{
|
||
ffebad_start ((nkt == FFEINFO_kindtypeREALDOUBLE)
|
||
? FFEBAD_BAD_DBLCMPLX : FFEBAD_BAD_COMPLEX);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
nbt = FFEINFO_basictypeNONE;
|
||
nkt = FFEINFO_kindtypeNONE;
|
||
break;
|
||
|
||
case FFEINFO_kindtypeANY:
|
||
nkt = FFEINFO_kindtypeREALDEFAULT;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{ /* The normal stuff. */
|
||
if (nbt == lbt)
|
||
{
|
||
if (nbt == rbt)
|
||
nkt = ffeinfo_kindtype_max (nbt, lkt, rkt);
|
||
else
|
||
nkt = lkt;
|
||
}
|
||
else if (nbt == rbt)
|
||
nkt = rkt;
|
||
else
|
||
{ /* Let the caller do the complaining. */
|
||
nbt = FFEINFO_basictypeNONE;
|
||
nkt = FFEINFO_kindtypeNONE;
|
||
}
|
||
}
|
||
|
||
/* Always a good idea to avoid aliasing problems. */
|
||
|
||
*xnbt = nbt;
|
||
*xnkt = nkt;
|
||
}
|
||
|
||
/* ffeexpr_token_first_lhs_ -- First state for lhs expression
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Record line and column of first token in expression, then invoke the
|
||
initial-state lhs handler. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_lhs_ (ffelexToken t)
|
||
{
|
||
ffeexpr_stack_->first_token = ffelex_token_use (t);
|
||
|
||
/* When changing the list of valid initial lhs tokens, check whether to
|
||
update a corresponding list in ffeexpr_cb_close_paren_ambig_1_ for the
|
||
READ (expr) <token> case -- it assumes it knows which tokens <token> can
|
||
be to indicate an lhs (or implied DO), which right now is the set
|
||
{NAME,OPEN_PAREN}.
|
||
|
||
This comment also appears in ffeexpr_token_lhs_. */
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeOPEN_PAREN:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
ffe_init_4 ();
|
||
ffeexpr_level_ = 1; /* Level of DATA implied-DO construct. */
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextDATAIMPDOITEM_, ffeexpr_cb_comma_i_);
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
++ffeexpr_level_; /* Level of DATA implied-DO construct. */
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextDATAIMPDOITEM_, ffeexpr_cb_comma_i_);
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextIMPDOITEM_, ffeexpr_cb_comma_i_);
|
||
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return (ffelexHandler) ffeexpr_lhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextIMPDOITEMDF_, ffeexpr_cb_comma_i_);
|
||
|
||
case FFEEXPR_contextFILEEXTFUNC:
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typeNAME:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_namelist_;
|
||
|
||
case FFEEXPR_contextFILEEXTFUNC:
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILEEXTFUNC:
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_lhs_1_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_token_lhs_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_first_lhs_1_ -- NAME
|
||
|
||
return ffeexpr_token_first_lhs_1_; // to lexer
|
||
|
||
Handle NAME as an external function (USEROPEN= VXT extension to OPEN
|
||
statement). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_lhs_1_ (ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
ffesymbol sy = NULL;
|
||
ffebld expr;
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
s = ffeexpr_stack_->previous;
|
||
|
||
if ((ffelex_token_type (ft) != FFELEX_typeNAME)
|
||
|| (ffesymbol_attrs (sy = ffeexpr_declare_unadorned_ (ft, FALSE))
|
||
& FFESYMBOL_attrANY))
|
||
{
|
||
if ((ffelex_token_type (ft) != FFELEX_typeNAME)
|
||
|| !(ffesymbol_attrs (sy) & FFESYMBOL_attrsANY))
|
||
{
|
||
ffebad_start (FFEBAD_EXPR_WRONG);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
}
|
||
expr = ffebld_new_any ();
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
expr = ffebld_new_symter (sy, FFEINTRIN_genNONE, FFEINTRIN_specNONE,
|
||
FFEINTRIN_impNONE);
|
||
ffebld_set_info (expr, ffesymbol_info (sy));
|
||
}
|
||
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
|
||
sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_ -- First state for rhs expression
|
||
|
||
Record line and column of first token in expression, then invoke the
|
||
initial-state rhs handler.
|
||
|
||
19-Feb-91 JCB 1.1
|
||
Allow ASTERISK in PARENFILEUNIT_ case, but only on second level only
|
||
(i.e. only as in READ(*), not READ((*))). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_ (ffelexToken t)
|
||
{
|
||
ffesymbol s;
|
||
|
||
ffeexpr_stack_->first_token = ffelex_token_use (t);
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeASTERISK:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
/* Fall through. */
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
if (ffeexpr_stack_->previous != NULL)
|
||
break; /* Valid only on first level. */
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_1_;
|
||
|
||
case FFEEXPR_contextPARENFILEUNIT_:
|
||
if (ffeexpr_stack_->previous->previous != NULL)
|
||
break; /* Valid only on second level. */
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_1_;
|
||
|
||
case FFEEXPR_contextACTUALARG_:
|
||
if (ffeexpr_stack_->previous->context
|
||
!= FFEEXPR_contextSUBROUTINEREF)
|
||
{
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
}
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_3_;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typeOPEN_PAREN:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextPARENFILENUM_,
|
||
ffeexpr_cb_close_paren_ambig_);
|
||
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextPARENFILEUNIT_,
|
||
ffeexpr_cb_close_paren_ambig_);
|
||
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextIMPDOITEM_,
|
||
ffeexpr_cb_close_paren_ci_);
|
||
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextIMPDOITEMDF_,
|
||
ffeexpr_cb_close_paren_ci_);
|
||
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
break;
|
||
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typeNUMBER:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
/* Fall through. */
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
if (ffeexpr_stack_->previous != NULL)
|
||
break; /* Valid only on first level. */
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_2_;
|
||
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typeNAME:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
assert (ffeexpr_stack_->exprstack == NULL);
|
||
s = ffesymbol_lookup_local (t);
|
||
if ((s != NULL) && (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
|
||
return (ffelexHandler) ffeexpr_token_namelist_;
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typePERCENT:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_5_;
|
||
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
default:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_1_ -- ASTERISK
|
||
|
||
return ffeexpr_token_first_rhs_1_; // to lexer
|
||
|
||
Return STAR as expression. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_1_ (ffelexToken t)
|
||
{
|
||
ffebld expr;
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
|
||
expr = ffebld_new_star ();
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_2_ -- NUMBER
|
||
|
||
return ffeexpr_token_first_rhs_2_; // to lexer
|
||
|
||
Return NULL as expression; NUMBER as first (and only) token, unless the
|
||
current token is not a terminating token, in which case run normal
|
||
expression handling. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_2_ (ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
case FFELEX_typeCOMMA:
|
||
case FFELEX_typeEOS:
|
||
case FFELEX_typeSEMICOLON:
|
||
break;
|
||
|
||
default:
|
||
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
|
||
return (ffelexHandler) (*next) (t);
|
||
}
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
|
||
sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (ft, NULL, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_3_ -- ASTERISK
|
||
|
||
return ffeexpr_token_first_rhs_3_; // to lexer
|
||
|
||
Expect NUMBER, make LABTOK (with copy of token if not inhibited after
|
||
confirming, else NULL). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_3_ (ffelexToken t)
|
||
{
|
||
ffelexHandler next;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{ /* An error, but let normal processing handle
|
||
it. */
|
||
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
|
||
return (ffelexHandler) (*next) (t);
|
||
}
|
||
|
||
/* Special case: when we see "*10" as an argument to a subroutine
|
||
reference, we confirm the current statement and, if not inhibited at
|
||
this point, put a copy of the token into a LABTOK node. We do this
|
||
instead of just resolving the label directly via ffelab and putting it
|
||
into a LABTER simply to improve error reporting and consistency in
|
||
ffestc. We put NULL in the LABTOK if we're still inhibited, so ffestb
|
||
doesn't have to worry about killing off any tokens when retracting. */
|
||
|
||
ffest_confirmed ();
|
||
if (ffest_is_inhibited ())
|
||
ffeexpr_stack_->expr = ffebld_new_labtok (NULL);
|
||
else
|
||
ffeexpr_stack_->expr = ffebld_new_labtok (ffelex_token_use (t));
|
||
ffebld_set_info (ffeexpr_stack_->expr,
|
||
ffeinfo_new (FFEINFO_basictypeNONE,
|
||
FFEINFO_kindtypeNONE,
|
||
0,
|
||
FFEINFO_kindNONE,
|
||
FFEINFO_whereNONE,
|
||
FFETARGET_charactersizeNONE));
|
||
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_4_;
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_4_ -- ASTERISK NUMBER
|
||
|
||
return ffeexpr_token_first_rhs_4_; // to lexer
|
||
|
||
Collect/flush appropriate stuff, send token to callback function. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_4_ (ffelexToken t)
|
||
{
|
||
ffebld expr;
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
|
||
expr = ffeexpr_stack_->expr;
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_5_ -- PERCENT
|
||
|
||
Should be NAME, or pass through original mechanism. If NAME is LOC,
|
||
pass through original mechanism, otherwise must be VAL, REF, or DESCR,
|
||
in which case handle the argument (in parentheses), etc. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_5_ (ffelexToken t)
|
||
{
|
||
ffelexHandler next;
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeNAME)
|
||
{
|
||
ffeexprPercent_ p = ffeexpr_percent_ (t);
|
||
|
||
switch (p)
|
||
{
|
||
case FFEEXPR_percentNONE_:
|
||
case FFEEXPR_percentLOC_:
|
||
break; /* Treat %LOC as any other expression. */
|
||
|
||
case FFEEXPR_percentVAL_:
|
||
case FFEEXPR_percentREF_:
|
||
case FFEEXPR_percentDESCR_:
|
||
ffeexpr_stack_->percent = p;
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_first_rhs_6_;
|
||
|
||
default:
|
||
assert ("bad percent?!?" == NULL);
|
||
break;
|
||
}
|
||
}
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context?!?!" == NULL);
|
||
break;
|
||
}
|
||
|
||
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
|
||
return (ffelexHandler) (*next) (t);
|
||
}
|
||
|
||
/* ffeexpr_token_first_rhs_6_ -- PERCENT NAME(VAL,REF,DESCR)
|
||
|
||
Should be OPEN_PAREN, or pass through original mechanism. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_first_rhs_6_ (ffelexToken t)
|
||
{
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeOPEN_PAREN)
|
||
{
|
||
ffeexpr_stack_->tokens[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
ffeexpr_stack_->context,
|
||
ffeexpr_cb_end_notloc_);
|
||
}
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context?!?!" == NULL);
|
||
break;
|
||
}
|
||
|
||
ft = ffeexpr_stack_->tokens[0];
|
||
next = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_stack_->first_token);
|
||
next = (ffelexHandler) (*next) (ft);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) (*next) (t);
|
||
}
|
||
|
||
/* ffeexpr_token_namelist_ -- NAME
|
||
|
||
return ffeexpr_token_namelist_; // to lexer
|
||
|
||
Make sure NAME was a valid namelist object, wrap it in a SYMTER and
|
||
return. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_namelist_ (ffelexToken t)
|
||
{
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffelexHandler next;
|
||
ffelexToken ft;
|
||
ffesymbol sy;
|
||
ffebld expr;
|
||
|
||
ffebld_pool_pop ();
|
||
callback = ffeexpr_stack_->callback;
|
||
ft = ffeexpr_stack_->first_token;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
|
||
sy = ffesymbol_lookup_local (ft);
|
||
if ((sy == NULL) || (ffesymbol_kind (sy) != FFEINFO_kindNAMELIST))
|
||
{
|
||
ffebad_start (FFEBAD_EXPR_WRONG);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
expr = ffebld_new_any ();
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
expr = ffebld_new_symter (sy, FFEINTRIN_genNONE, FFEINTRIN_specNONE,
|
||
FFEINTRIN_impNONE);
|
||
ffebld_set_info (expr, ffesymbol_info (sy));
|
||
}
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_expr_kill_ -- Kill an existing internal expression object
|
||
|
||
ffeexprExpr_ e;
|
||
ffeexpr_expr_kill_(e);
|
||
|
||
Kills the ffewhere info, if necessary, then kills the object. */
|
||
|
||
static void
|
||
ffeexpr_expr_kill_ (ffeexprExpr_ e)
|
||
{
|
||
if (e->token != NULL)
|
||
ffelex_token_kill (e->token);
|
||
malloc_kill_ks (ffe_pool_program_unit (), e, sizeof (*e));
|
||
}
|
||
|
||
/* ffeexpr_expr_new_ -- Make a new internal expression object
|
||
|
||
ffeexprExpr_ e;
|
||
e = ffeexpr_expr_new_();
|
||
|
||
Allocates and initializes a new expression object, returns it. */
|
||
|
||
static ffeexprExpr_
|
||
ffeexpr_expr_new_ ()
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
e = (ffeexprExpr_) malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR expr",
|
||
sizeof (*e));
|
||
e->previous = NULL;
|
||
e->type = FFEEXPR_exprtypeUNKNOWN_;
|
||
e->token = NULL;
|
||
return e;
|
||
}
|
||
|
||
/* Verify that call to global is valid, and register whatever
|
||
new information about a global might be discoverable by looking
|
||
at the call. */
|
||
|
||
static void
|
||
ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t)
|
||
{
|
||
int n_args;
|
||
ffebld list;
|
||
ffebld item;
|
||
ffesymbol s;
|
||
|
||
assert ((ffebld_op (*expr) == FFEBLD_opSUBRREF)
|
||
|| (ffebld_op (*expr) == FFEBLD_opFUNCREF));
|
||
|
||
if (ffebld_op (ffebld_left (*expr)) != FFEBLD_opSYMTER)
|
||
return;
|
||
|
||
if (ffesymbol_retractable ())
|
||
return;
|
||
|
||
s = ffebld_symter (ffebld_left (*expr));
|
||
if (ffesymbol_global (s) == NULL)
|
||
return;
|
||
|
||
for (n_args = 0, list = ffebld_right (*expr);
|
||
list != NULL;
|
||
list = ffebld_trail (list), ++n_args)
|
||
;
|
||
|
||
if (ffeglobal_proc_ref_nargs (s, n_args, t))
|
||
{
|
||
ffeglobalArgSummary as;
|
||
ffeinfoBasictype bt;
|
||
ffeinfoKindtype kt;
|
||
bool array;
|
||
bool fail = FALSE;
|
||
|
||
for (n_args = 0, list = ffebld_right (*expr);
|
||
list != NULL;
|
||
list = ffebld_trail (list), ++n_args)
|
||
{
|
||
item = ffebld_head (list);
|
||
if (item != NULL)
|
||
{
|
||
bt = ffeinfo_basictype (ffebld_info (item));
|
||
kt = ffeinfo_kindtype (ffebld_info (item));
|
||
array = (ffeinfo_rank (ffebld_info (item)) > 0);
|
||
switch (ffebld_op (item))
|
||
{
|
||
case FFEBLD_opLABTOK:
|
||
case FFEBLD_opLABTER:
|
||
as = FFEGLOBAL_argsummaryALTRTN;
|
||
break;
|
||
|
||
#if 0
|
||
/* No, %LOC(foo) is just like any INTEGER(KIND=7)
|
||
expression, so don't treat it specially. */
|
||
case FFEBLD_opPERCENT_LOC:
|
||
as = FFEGLOBAL_argsummaryPTR;
|
||
break;
|
||
#endif
|
||
|
||
case FFEBLD_opPERCENT_VAL:
|
||
as = FFEGLOBAL_argsummaryVAL;
|
||
break;
|
||
|
||
case FFEBLD_opPERCENT_REF:
|
||
as = FFEGLOBAL_argsummaryREF;
|
||
break;
|
||
|
||
case FFEBLD_opPERCENT_DESCR:
|
||
as = FFEGLOBAL_argsummaryDESCR;
|
||
break;
|
||
|
||
case FFEBLD_opFUNCREF:
|
||
#if 0
|
||
/* No, LOC(foo) is just like any INTEGER(KIND=7)
|
||
expression, so don't treat it specially. */
|
||
if ((ffebld_op (ffebld_left (item)) == FFEBLD_opSYMTER)
|
||
&& (ffesymbol_specific (ffebld_symter (ffebld_left (item)))
|
||
== FFEINTRIN_specLOC))
|
||
{
|
||
as = FFEGLOBAL_argsummaryPTR;
|
||
break;
|
||
}
|
||
#endif
|
||
/* Fall through. */
|
||
default:
|
||
if (ffebld_op (item) == FFEBLD_opSYMTER)
|
||
{
|
||
as = FFEGLOBAL_argsummaryNONE;
|
||
|
||
switch (ffeinfo_kind (ffebld_info (item)))
|
||
{
|
||
case FFEINFO_kindFUNCTION:
|
||
as = FFEGLOBAL_argsummaryFUNC;
|
||
break;
|
||
|
||
case FFEINFO_kindSUBROUTINE:
|
||
as = FFEGLOBAL_argsummarySUBR;
|
||
break;
|
||
|
||
case FFEINFO_kindNONE:
|
||
as = FFEGLOBAL_argsummaryPROC;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (as != FFEGLOBAL_argsummaryNONE)
|
||
break;
|
||
}
|
||
|
||
if (bt == FFEINFO_basictypeCHARACTER)
|
||
as = FFEGLOBAL_argsummaryDESCR;
|
||
else
|
||
as = FFEGLOBAL_argsummaryREF;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
array = FALSE;
|
||
as = FFEGLOBAL_argsummaryNONE;
|
||
bt = FFEINFO_basictypeNONE;
|
||
kt = FFEINFO_kindtypeNONE;
|
||
}
|
||
|
||
if (! ffeglobal_proc_ref_arg (s, n_args, as, bt, kt, array, t))
|
||
fail = TRUE;
|
||
}
|
||
if (! fail)
|
||
return;
|
||
}
|
||
|
||
*expr = ffebld_new_any ();
|
||
ffebld_set_info (*expr, ffeinfo_new_any ());
|
||
}
|
||
|
||
/* Check whether rest of string is all decimal digits. */
|
||
|
||
static bool
|
||
ffeexpr_isdigits_ (const char *p)
|
||
{
|
||
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_))
|
||
{
|
||
/* xgettext:no-c-format */
|
||
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))
|
||
{
|
||
/* xgettext:no-c-format */
|
||
ffebad_start_msg ("Operator at %0 has lower precedence than that at %1 -- use parentheses", FFEBAD_severityWARNING);
|
||
ffebad_here (0,
|
||
ffelex_token_where_line (ffeexpr_stack_->exprstack->previous->token),
|
||
ffelex_token_where_column (ffeexpr_stack_->exprstack->previous->token));
|
||
ffebad_here (1,
|
||
ffelex_token_where_line (e->token),
|
||
ffelex_token_where_column (e->token));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
again:
|
||
assert (ffeexpr_stack_->exprstack != NULL);
|
||
assert (ffeexpr_stack_->exprstack->type == FFEEXPR_exprtypeOPERAND_);
|
||
if ((ce = ffeexpr_stack_->exprstack->previous) != NULL)
|
||
{
|
||
assert (ce->type != FFEEXPR_exprtypeOPERAND_);
|
||
if ((ce->u.operator.prec < e->u.operator.prec)
|
||
|| ((ce->u.operator.prec == e->u.operator.prec)
|
||
&& (e->u.operator.as == FFEEXPR_operatorassociativityL2R_)))
|
||
{
|
||
ffeexpr_reduce_ ();
|
||
goto again; /* :::::::::::::::::::: */
|
||
}
|
||
}
|
||
|
||
ffeexpr_exprstack_push_ (e);
|
||
}
|
||
|
||
/* ffeexpr_reduce_ -- Reduce highest operator w/operands on stack
|
||
|
||
ffeexpr_reduce_();
|
||
|
||
Converts operand binop operand or unop operand at top of stack to a
|
||
single operand having the appropriate ffebld expression, and makes
|
||
sure that the expression is proper (like not trying to add two character
|
||
variables, not trying to concatenate two numbers). Also does the
|
||
requisite type-assignment. */
|
||
|
||
static void
|
||
ffeexpr_reduce_ ()
|
||
{
|
||
ffeexprExpr_ operand; /* This is B in -B or A+B. */
|
||
ffeexprExpr_ left_operand; /* When operator is binary, this is A in A+B. */
|
||
ffeexprExpr_ operator; /* This is + in A+B. */
|
||
ffebld reduced; /* This is +(A,B) in A+B or u-(B) in -B. */
|
||
ffebldConstant constnode; /* For checking magical numbers (where mag ==
|
||
-mag). */
|
||
ffebld expr;
|
||
ffebld left_expr;
|
||
bool submag = FALSE;
|
||
|
||
operand = ffeexpr_stack_->exprstack;
|
||
assert (operand != NULL);
|
||
assert (operand->type == FFEEXPR_exprtypeOPERAND_);
|
||
operator = operand->previous;
|
||
assert (operator != NULL);
|
||
assert (operator->type != FFEEXPR_exprtypeOPERAND_);
|
||
if (operator->type == FFEEXPR_exprtypeUNARY_)
|
||
{
|
||
expr = operand->u.operand;
|
||
switch (operator->u.operator.op)
|
||
{
|
||
case FFEEXPR_operatorADD_:
|
||
reduced = ffebld_new_uplus (expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand);
|
||
reduced = ffeexpr_reduced_math1_ (reduced, operator, operand);
|
||
reduced = ffeexpr_collapse_uplus (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorSUBTRACT_:
|
||
submag = TRUE; /* Ok to negate a magic number. */
|
||
reduced = ffebld_new_uminus (expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand);
|
||
reduced = ffeexpr_reduced_math1_ (reduced, operator, operand);
|
||
reduced = ffeexpr_collapse_uminus (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorNOT_:
|
||
reduced = ffebld_new_not (expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly1log_ (reduced, operator, operand);
|
||
reduced = ffeexpr_reduced_bool1_ (reduced, operator, operand);
|
||
reduced = ffeexpr_collapse_not (reduced, operator->token);
|
||
break;
|
||
|
||
default:
|
||
assert ("unexpected unary op" != NULL);
|
||
reduced = NULL;
|
||
break;
|
||
}
|
||
if (!submag
|
||
&& (ffebld_op (expr) == FFEBLD_opCONTER)
|
||
&& (ffebld_conter_orig (expr) == NULL)
|
||
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
|
||
{
|
||
ffetarget_integer_bad_magical (operand->token);
|
||
}
|
||
ffeexpr_stack_->exprstack = operator->previous; /* Pops unary-op operand
|
||
off stack. */
|
||
ffeexpr_expr_kill_ (operand);
|
||
operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but
|
||
save */
|
||
operator->u.operand = reduced; /* the line/column ffewhere info. */
|
||
ffeexpr_exprstack_push_operand_ (operator); /* Push it back on
|
||
stack. */
|
||
}
|
||
else
|
||
{
|
||
assert (operator->type == FFEEXPR_exprtypeBINARY_);
|
||
left_operand = operator->previous;
|
||
assert (left_operand != NULL);
|
||
assert (left_operand->type == FFEEXPR_exprtypeOPERAND_);
|
||
expr = operand->u.operand;
|
||
left_expr = left_operand->u.operand;
|
||
switch (operator->u.operator.op)
|
||
{
|
||
case FFEEXPR_operatorADD_:
|
||
reduced = ffebld_new_add (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_add (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorSUBTRACT_:
|
||
submag = TRUE; /* Just to pick the right error if magic
|
||
number. */
|
||
reduced = ffebld_new_subtract (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_subtract (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorMULTIPLY_:
|
||
reduced = ffebld_new_multiply (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_multiply (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorDIVIDE_:
|
||
reduced = ffebld_new_divide (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_divide (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorPOWER_:
|
||
reduced = ffebld_new_power (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_power_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_power (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorCONCATENATE_:
|
||
reduced = ffebld_new_concatenate (left_expr, expr);
|
||
reduced = ffeexpr_reduced_concatenate_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_concatenate (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorLT_:
|
||
reduced = ffebld_new_lt (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_lt (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorLE_:
|
||
reduced = ffebld_new_le (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_le (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorEQ_:
|
||
reduced = ffebld_new_eq (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_eq (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorNE_:
|
||
reduced = ffebld_new_ne (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_ne (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorGT_:
|
||
reduced = ffebld_new_gt (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_gt (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorGE_:
|
||
reduced = ffebld_new_ge (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_ge (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorAND_:
|
||
reduced = ffebld_new_and (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_and (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorOR_:
|
||
reduced = ffebld_new_or (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_or (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorXOR_:
|
||
reduced = ffebld_new_xor (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_xor (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorEQV_:
|
||
reduced = ffebld_new_eqv (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_eqv (reduced, operator->token);
|
||
break;
|
||
|
||
case FFEEXPR_operatorNEQV_:
|
||
reduced = ffebld_new_neqv (left_expr, expr);
|
||
if (ffe_is_ugly_logint ())
|
||
reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator,
|
||
operand);
|
||
reduced = ffeexpr_collapse_neqv (reduced, operator->token);
|
||
break;
|
||
|
||
default:
|
||
assert ("bad bin op" == NULL);
|
||
reduced = expr;
|
||
break;
|
||
}
|
||
if ((ffebld_op (left_expr) == FFEBLD_opCONTER)
|
||
&& (ffebld_conter_orig (expr) == NULL)
|
||
&& ffebld_constant_is_magical (constnode = ffebld_conter (left_expr)))
|
||
{
|
||
if ((left_operand->previous != NULL)
|
||
&& (left_operand->previous->type != FFEEXPR_exprtypeOPERAND_)
|
||
&& (left_operand->previous->u.operator.op
|
||
== FFEEXPR_operatorSUBTRACT_))
|
||
{
|
||
if (left_operand->previous->type == FFEEXPR_exprtypeUNARY_)
|
||
ffetarget_integer_bad_magical_precedence (left_operand->token,
|
||
left_operand->previous->token,
|
||
operator->token);
|
||
else
|
||
ffetarget_integer_bad_magical_precedence_binary
|
||
(left_operand->token,
|
||
left_operand->previous->token,
|
||
operator->token);
|
||
}
|
||
else
|
||
ffetarget_integer_bad_magical (left_operand->token);
|
||
}
|
||
if ((ffebld_op (expr) == FFEBLD_opCONTER)
|
||
&& (ffebld_conter_orig (expr) == NULL)
|
||
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
|
||
{
|
||
if (submag)
|
||
ffetarget_integer_bad_magical_binary (operand->token,
|
||
operator->token);
|
||
else
|
||
ffetarget_integer_bad_magical (operand->token);
|
||
}
|
||
ffeexpr_stack_->exprstack = left_operand->previous; /* Pops binary-op
|
||
operands off stack. */
|
||
ffeexpr_expr_kill_ (left_operand);
|
||
ffeexpr_expr_kill_ (operand);
|
||
operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but
|
||
save */
|
||
operator->u.operand = reduced; /* the line/column ffewhere info. */
|
||
ffeexpr_exprstack_push_operand_ (operator); /* Push it back on
|
||
stack. */
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_reduced_bool1_ -- Wrap up reduction of NOT operator
|
||
|
||
reduced = ffeexpr_reduced_bool1_(reduced,op,r);
|
||
|
||
Makes sure the argument for reduced has basictype of
|
||
LOGICAL or (ugly) INTEGER. If
|
||
argument has where of CONSTANT, assign where CONSTANT to
|
||
reduced, else assign where FLEETING.
|
||
|
||
If these requirements cannot be met, generate error message. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
|
||
{
|
||
ffeinfo rinfo, ninfo;
|
||
ffeinfoBasictype rbt;
|
||
ffeinfoKindtype rkt;
|
||
ffeinfoRank rrk;
|
||
ffeinfoKind rkd;
|
||
ffeinfoWhere rwh, nwh;
|
||
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if (((rbt == FFEINFO_basictypeLOGICAL)
|
||
|| (ffe_is_ugly_logint () && (rbt == FFEINFO_basictypeINTEGER)))
|
||
&& (rrk == 0))
|
||
{
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh,
|
||
FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
return reduced;
|
||
}
|
||
|
||
if ((rbt != FFEINFO_basictypeLOGICAL)
|
||
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_NOT_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_NOT_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_bool2_ -- Wrap up reduction of boolean operators
|
||
|
||
reduced = ffeexpr_reduced_bool2_(reduced,l,op,r);
|
||
|
||
Makes sure the left and right arguments for reduced have basictype of
|
||
LOGICAL or (ugly) INTEGER. Determine common basictype and
|
||
size for reduction (flag expression for combined hollerith/typeless
|
||
situations for later determination of effective basictype). If both left
|
||
and right arguments have where of CONSTANT, assign where CONSTANT to
|
||
reduced, else assign where FLEETING. Create CONVERT ops for args where
|
||
needed. Convert typeless
|
||
constants to the desired type/size explicitly.
|
||
|
||
If these requirements cannot be met, generate error message. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo, ninfo;
|
||
ffeinfoBasictype lbt, rbt, nbt;
|
||
ffeinfoKindtype lkt, rkt, nkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh, nwh;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
|
||
|
||
if (((nbt == FFEINFO_basictypeLOGICAL)
|
||
|| (ffe_is_ugly_logint () && (nbt == FFEINFO_basictypeINTEGER)))
|
||
&& (lrk == 0) && (rrk == 0))
|
||
{
|
||
switch (lwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
|
||
FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
return reduced;
|
||
}
|
||
|
||
if ((lbt != FFEINFO_basictypeLOGICAL)
|
||
&& (!ffe_is_ugly_logint () || (lbt != FFEINFO_basictypeINTEGER)))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeLOGICAL)
|
||
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_BOOL_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_BOOL_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
else if ((rbt != FFEINFO_basictypeLOGICAL)
|
||
&& (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER)))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_BOOL_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lrk != 0)
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_BOOL_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_BOOL_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_concatenate_ -- Wrap up reduction of concatenate operator
|
||
|
||
reduced = ffeexpr_reduced_concatenate_(reduced,l,op,r);
|
||
|
||
Makes sure the left and right arguments for reduced have basictype of
|
||
CHARACTER and kind of SCALAR, FUNCTION, or STATEMENT FUNCTION. Assign
|
||
basictype of CHARACTER and kind of SCALAR to reduced. Calculate effective
|
||
size of concatenation and assign that size to reduced. If both left and
|
||
right arguments have where of CONSTANT, assign where CONSTANT to reduced,
|
||
else assign where FLEETING.
|
||
|
||
If these requirements cannot be met, generate error message using the
|
||
info in l, op, and r arguments and assign basictype, size, kind, and where
|
||
of ANY. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo, ninfo;
|
||
ffeinfoBasictype lbt, rbt, nbt;
|
||
ffeinfoKindtype lkt, rkt, nkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd, nkd;
|
||
ffeinfoWhere lwh, rwh, nwh;
|
||
ffetargetCharacterSize lszm, lszk, rszm, rszk, nszk;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
lszk = ffeinfo_size (linfo); /* Known size. */
|
||
lszm = ffebld_size_max (ffebld_left (reduced));
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
rszk = ffeinfo_size (rinfo); /* Known size. */
|
||
rszm = ffebld_size_max (ffebld_right (reduced));
|
||
|
||
if ((lbt == FFEINFO_basictypeCHARACTER) && (rbt == FFEINFO_basictypeCHARACTER)
|
||
&& (lkt == rkt) && (lrk == 0) && (rrk == 0)
|
||
&& (((lszm != FFETARGET_charactersizeNONE)
|
||
&& (rszm != FFETARGET_charactersizeNONE))
|
||
|| (ffeexpr_context_outer_ (ffeexpr_stack_)
|
||
== FFEEXPR_contextLET)
|
||
|| (ffeexpr_context_outer_ (ffeexpr_stack_)
|
||
== FFEEXPR_contextSFUNCDEF)))
|
||
{
|
||
nbt = FFEINFO_basictypeCHARACTER;
|
||
nkd = FFEINFO_kindENTITY;
|
||
if ((lszk == FFETARGET_charactersizeNONE)
|
||
|| (rszk == FFETARGET_charactersizeNONE))
|
||
nszk = FFETARGET_charactersizeNONE; /* Ok only in rhs of LET
|
||
stmt. */
|
||
else
|
||
nszk = lszk + rszk;
|
||
|
||
switch (lwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
nkt = lkt;
|
||
ninfo = ffeinfo_new (nbt, nkt, 0, nkd, nwh, nszk);
|
||
ffebld_set_info (reduced, ninfo);
|
||
return reduced;
|
||
}
|
||
|
||
if ((lbt != FFEINFO_basictypeCHARACTER) && (rbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_CONCAT_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lbt != FFEINFO_basictypeCHARACTER)
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_CONCAT_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (rbt != FFEINFO_basictypeCHARACTER)
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_CONCAT_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if ((lrk != 0) || (lszm == FFETARGET_charactersizeNONE))
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_CONCAT_ARG_KIND))
|
||
{
|
||
const char *what;
|
||
|
||
if (lrk != 0)
|
||
what = "an array";
|
||
else
|
||
what = "of indeterminate length";
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string (what);
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (ffebad_start (FFEBAD_CONCAT_ARG_KIND))
|
||
{
|
||
const char *what;
|
||
|
||
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))
|
||
{
|
||
/* xgettext:no-c-format */
|
||
if (ffebad_start_msg ("Use .EQV./.NEQV. instead of .EQ./.NE. at %0 for LOGICAL operands at %1 and %2",
|
||
FFEBAD_severityFATAL))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
|
||
&& (lbt != FFEINFO_basictypeCOMPLEX) && (lbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_EQOP_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_EQOP_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_EQOP_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lrk != 0)
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_EQOP_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_EQOP_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_math1_ -- Wrap up reduction of + - unary operators
|
||
|
||
reduced = ffeexpr_reduced_math1_(reduced,op,r);
|
||
|
||
Makes sure the argument for reduced has basictype of
|
||
INTEGER, REAL, or COMPLEX. If the argument has where of CONSTANT,
|
||
assign where CONSTANT to
|
||
reduced, else assign where FLEETING.
|
||
|
||
If these requirements cannot be met, generate error message. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
|
||
{
|
||
ffeinfo rinfo, ninfo;
|
||
ffeinfoBasictype rbt;
|
||
ffeinfoKindtype rkt;
|
||
ffeinfoRank rrk;
|
||
ffeinfoKind rkd;
|
||
ffeinfoWhere rwh, nwh;
|
||
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if (((rbt == FFEINFO_basictypeINTEGER) || (rbt == FFEINFO_basictypeREAL)
|
||
|| (rbt == FFEINFO_basictypeCOMPLEX)) && (rrk == 0))
|
||
{
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh,
|
||
FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
return reduced;
|
||
}
|
||
|
||
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_math2_ -- Wrap up reduction of + - * / operators
|
||
|
||
reduced = ffeexpr_reduced_math2_(reduced,l,op,r);
|
||
|
||
Makes sure the left and right arguments for reduced have basictype of
|
||
INTEGER, REAL, or COMPLEX. Determine common basictype and
|
||
size for reduction (flag expression for combined hollerith/typeless
|
||
situations for later determination of effective basictype). If both left
|
||
and right arguments have where of CONSTANT, assign where CONSTANT to
|
||
reduced, else assign where FLEETING. Create CONVERT ops for args where
|
||
needed. Convert typeless
|
||
constants to the desired type/size explicitly.
|
||
|
||
If these requirements cannot be met, generate error message. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo, ninfo;
|
||
ffeinfoBasictype lbt, rbt, nbt;
|
||
ffeinfoKindtype lkt, rkt, nkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh, nwh;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
|
||
|
||
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|
||
|| (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0))
|
||
{
|
||
switch (lwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
|
||
FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
return reduced;
|
||
}
|
||
|
||
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
|
||
&& (lbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeINTEGER)
|
||
&& (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lrk != 0)
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_power_ -- Wrap up reduction of ** operator
|
||
|
||
reduced = ffeexpr_reduced_power_(reduced,l,op,r);
|
||
|
||
Makes sure the left and right arguments for reduced have basictype of
|
||
INTEGER, REAL, or COMPLEX. Determine common basictype and
|
||
size for reduction (flag expression for combined hollerith/typeless
|
||
situations for later determination of effective basictype). If both left
|
||
and right arguments have where of CONSTANT, assign where CONSTANT to
|
||
reduced, else assign where FLEETING. Create CONVERT ops for args where
|
||
needed. Note that real**int or complex**int
|
||
comes out as int = real**int etc with no conversions.
|
||
|
||
If these requirements cannot be met, generate error message using the
|
||
info in l, op, and r arguments and assign basictype, size, kind, and where
|
||
of ANY. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo, ninfo;
|
||
ffeinfoBasictype lbt, rbt, nbt;
|
||
ffeinfoKindtype lkt, rkt, nkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh, nwh;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if ((rbt == FFEINFO_basictypeINTEGER)
|
||
&& ((lbt == FFEINFO_basictypeREAL)
|
||
|| (lbt == FFEINFO_basictypeCOMPLEX)))
|
||
{
|
||
nbt = lbt;
|
||
nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDEFAULT);
|
||
if (nkt != FFEINFO_kindtypeREALDEFAULT)
|
||
{
|
||
nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDOUBLE);
|
||
if (nkt != FFEINFO_kindtypeREALDOUBLE)
|
||
nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */
|
||
}
|
||
if (rkt == FFEINFO_kindtypeINTEGER4)
|
||
{
|
||
/* xgettext:no-c-format */
|
||
ffebad_start_msg ("Unsupported operand for ** at %1 -- converting to default INTEGER",
|
||
FFEBAD_severityWARNING);
|
||
ffebad_here (0, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
if (rkt != FFEINFO_kindtypeINTEGERDEFAULT)
|
||
{
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token,
|
||
FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
rkt = FFEINFO_kindtypeINTEGERDEFAULT;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
|
||
|
||
#if 0 /* INTEGER4**INTEGER4 works now. */
|
||
if ((nbt == FFEINFO_basictypeINTEGER)
|
||
&& (nkt != FFEINFO_kindtypeINTEGERDEFAULT))
|
||
nkt = FFEINFO_kindtypeINTEGERDEFAULT; /* Highest kt we can power! */
|
||
#endif
|
||
if (((nbt == FFEINFO_basictypeREAL)
|
||
|| (nbt == FFEINFO_basictypeCOMPLEX))
|
||
&& (nkt != FFEINFO_kindtypeREALDEFAULT))
|
||
{
|
||
nkt = ffeinfo_kindtype_max (nbt, nkt, FFEINFO_kindtypeREALDOUBLE);
|
||
if (nkt != FFEINFO_kindtypeREALDOUBLE)
|
||
nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */
|
||
}
|
||
/* else Gonna turn into an error below. */
|
||
}
|
||
|
||
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|
||
|| (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0))
|
||
{
|
||
switch (lwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh,
|
||
FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
if (rbt != FFEINFO_basictypeINTEGER)
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
return reduced;
|
||
}
|
||
|
||
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
|
||
&& (lbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeINTEGER)
|
||
&& (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCOMPLEX))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lrk != 0)
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_MATH_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_relop2_ -- Wrap up reduction of LT, LE, GE, and GT operators
|
||
|
||
reduced = ffeexpr_reduced_relop2_(reduced,l,op,r);
|
||
|
||
Makes sure the left and right arguments for reduced have basictype of
|
||
INTEGER, REAL, or CHARACTER. Determine common basictype and
|
||
size for reduction. If both left
|
||
and right arguments have where of CONSTANT, assign where CONSTANT to
|
||
reduced, else assign where FLEETING. Create CONVERT ops for args where
|
||
needed. Convert typeless
|
||
constants to the desired type/size explicitly.
|
||
|
||
If these requirements cannot be met, generate error message. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo, ninfo;
|
||
ffeinfoBasictype lbt, rbt, nbt;
|
||
ffeinfoKindtype lkt, rkt, nkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh, nwh;
|
||
ffetargetCharacterSize lsz, rsz;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
lsz = ffebld_size_known (ffebld_left (reduced));
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
rsz = ffebld_size_known (ffebld_right (reduced));
|
||
|
||
ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token);
|
||
|
||
if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL)
|
||
|| (nbt == FFEINFO_basictypeCHARACTER))
|
||
&& (lrk == 0) && (rrk == 0))
|
||
{
|
||
switch (lwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
nwh = FFEINFO_whereCONSTANT;
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
switch (rwh)
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
case FFEINFO_whereIMMEDIATE:
|
||
nwh = FFEINFO_whereIMMEDIATE;
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
nwh = FFEINFO_whereFLEETING;
|
||
break;
|
||
}
|
||
|
||
if ((lsz != FFETARGET_charactersizeNONE)
|
||
&& (rsz != FFETARGET_charactersizeNONE))
|
||
lsz = rsz = (lsz > rsz) ? lsz : rsz;
|
||
|
||
ninfo = ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0, FFEINFO_kindENTITY, nwh, FFETARGET_charactersizeNONE);
|
||
ffebld_set_info (reduced, ninfo);
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, nbt, nkt, 0, lsz,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, nbt, nkt, 0, rsz,
|
||
FFEEXPR_contextLET));
|
||
return reduced;
|
||
}
|
||
|
||
if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL)
|
||
&& (lbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_RELOP_ARGS_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((lbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_RELOP_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
}
|
||
else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL)
|
||
&& (rbt != FFEINFO_basictypeCHARACTER))
|
||
{
|
||
if ((rbt != FFEINFO_basictypeANY)
|
||
&& ffebad_start (FFEBAD_RELOP_ARG_TYPE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else if (lrk != 0)
|
||
{
|
||
if ((lkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_RELOP_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rkd != FFEINFO_kindANY)
|
||
&& ffebad_start (FFEBAD_RELOP_ARG_KIND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token));
|
||
ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token));
|
||
ffebad_string ("an array");
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_ugly1_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL
|
||
|
||
reduced = ffeexpr_reduced_ugly1_(reduced,op,r);
|
||
|
||
Sigh. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
|
||
{
|
||
ffeinfo rinfo;
|
||
ffeinfoBasictype rbt;
|
||
ffeinfoKindtype rkt;
|
||
ffeinfoRank rrk;
|
||
ffeinfoKind rkd;
|
||
ffeinfoWhere rwh;
|
||
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
r->token, op->token, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = FFEINFO_basictypeINTEGER;
|
||
rkt = FFEINFO_kindtypeINTEGERDEFAULT;
|
||
rrk = 0;
|
||
rkd = FFEINFO_kindENTITY;
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
|
||
if (rbt == FFEINFO_basictypeLOGICAL)
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
r->token, op->token, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
}
|
||
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_ugly1log_ -- Deal with TYPELESS and HOLLERITH
|
||
|
||
reduced = ffeexpr_reduced_ugly1log_(reduced,op,r);
|
||
|
||
Sigh. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r)
|
||
{
|
||
ffeinfo rinfo;
|
||
ffeinfoBasictype rbt;
|
||
ffeinfoKindtype rkt;
|
||
ffeinfoRank rrk;
|
||
ffeinfoKind rkd;
|
||
ffeinfoWhere rwh;
|
||
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
r->token, op->token, FFEINFO_basictypeLOGICAL, 0,
|
||
FFEINFO_kindtypeLOGICALDEFAULT,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
rinfo = ffebld_info (ffebld_left (reduced));
|
||
rbt = FFEINFO_basictypeLOGICAL;
|
||
rkt = FFEINFO_kindtypeLOGICALDEFAULT;
|
||
rrk = 0;
|
||
rkd = FFEINFO_kindENTITY;
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_ugly2_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL
|
||
|
||
reduced = ffeexpr_reduced_ugly2_(reduced,l,op,r);
|
||
|
||
Sigh. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo;
|
||
ffeinfoBasictype lbt, rbt;
|
||
ffeinfoKindtype lkt, rkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if ((lbt == FFEINFO_basictypeTYPELESS)
|
||
|| (lbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, FFEINFO_basictypeINTEGER, 0,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
lbt = rbt = FFEINFO_basictypeINTEGER;
|
||
lkt = rkt = FFEINFO_kindtypeINTEGERDEFAULT;
|
||
lrk = rrk = 0;
|
||
lkd = rkd = FFEINFO_kindENTITY;
|
||
lwh = ffeinfo_where (linfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
else
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced),
|
||
l->token, ffebld_right (reduced), r->token,
|
||
FFEEXPR_contextLET));
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced),
|
||
r->token, ffebld_left (reduced), l->token,
|
||
FFEEXPR_contextLET));
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
/* else Leave it alone. */
|
||
}
|
||
|
||
if (lbt == FFEINFO_basictypeLOGICAL)
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
}
|
||
|
||
if (rbt == FFEINFO_basictypeLOGICAL)
|
||
{
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
}
|
||
|
||
return reduced;
|
||
}
|
||
|
||
/* ffeexpr_reduced_ugly2log_ -- Deal with TYPELESS and HOLLERITH
|
||
|
||
reduced = ffeexpr_reduced_ugly2log_(reduced,l,op,r);
|
||
|
||
Sigh. */
|
||
|
||
static ffebld
|
||
ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
|
||
ffeexprExpr_ r)
|
||
{
|
||
ffeinfo linfo, rinfo;
|
||
ffeinfoBasictype lbt, rbt;
|
||
ffeinfoKindtype lkt, rkt;
|
||
ffeinfoRank lrk, rrk;
|
||
ffeinfoKind lkd, rkd;
|
||
ffeinfoWhere lwh, rwh;
|
||
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
|
||
if ((lbt == FFEINFO_basictypeTYPELESS)
|
||
|| (lbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
|
||
l->token, op->token, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
|
||
r->token, op->token, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET));
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
lbt = rbt = FFEINFO_basictypeLOGICAL;
|
||
lkt = rkt = FFEINFO_kindtypeLOGICALDEFAULT;
|
||
lrk = rrk = 0;
|
||
lkd = rkd = FFEINFO_kindENTITY;
|
||
lwh = ffeinfo_where (linfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
else
|
||
{
|
||
ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced),
|
||
l->token, ffebld_right (reduced), r->token,
|
||
FFEEXPR_contextLET));
|
||
linfo = ffebld_info (ffebld_left (reduced));
|
||
lbt = ffeinfo_basictype (linfo);
|
||
lkt = ffeinfo_kindtype (linfo);
|
||
lrk = ffeinfo_rank (linfo);
|
||
lkd = ffeinfo_kind (linfo);
|
||
lwh = ffeinfo_where (linfo);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((rbt == FFEINFO_basictypeTYPELESS)
|
||
|| (rbt == FFEINFO_basictypeHOLLERITH))
|
||
{
|
||
ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced),
|
||
r->token, ffebld_left (reduced), l->token,
|
||
FFEEXPR_contextLET));
|
||
rinfo = ffebld_info (ffebld_right (reduced));
|
||
rbt = ffeinfo_basictype (rinfo);
|
||
rkt = ffeinfo_kindtype (rinfo);
|
||
rrk = ffeinfo_rank (rinfo);
|
||
rkd = ffeinfo_kind (rinfo);
|
||
rwh = ffeinfo_where (rinfo);
|
||
}
|
||
/* else Leave it alone. */
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
/* Fumble through tokens until a nonmatching CLOSE_PAREN, EOS, or SEMICOLON
|
||
is found.
|
||
|
||
The idea is to process the tokens as they would be done by normal
|
||
expression processing, with the key things being telling the lexer
|
||
when hollerith/character constants are about to happen, until the
|
||
true closing token is found. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_find_close_paren_ (ffelexToken t,
|
||
ffelexHandler after)
|
||
{
|
||
ffeexpr_find_.after = after;
|
||
ffeexpr_find_.level = 1;
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_finished_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
if (--ffeexpr_find_.level == 0)
|
||
return (ffelexHandler) ffeexpr_find_.after;
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
|
||
case FFELEX_typeCOMMA:
|
||
case FFELEX_typeCOLON:
|
||
case FFELEX_typeEQUALS:
|
||
case FFELEX_typePOINTS:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
default:
|
||
if (--ffeexpr_find_.level == 0)
|
||
return (ffelexHandler) ffeexpr_find_.after (t);
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_rhs_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeQUOTE:
|
||
if (ffe_is_vxt ())
|
||
return (ffelexHandler) ffeexpr_nil_quote_;
|
||
ffelex_set_expecting_hollerith (-1, '\"',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
return (ffelexHandler) ffeexpr_nil_apostrophe_;
|
||
|
||
case FFELEX_typeAPOSTROPHE:
|
||
ffelex_set_expecting_hollerith (-1, '\'',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
return (ffelexHandler) ffeexpr_nil_apostrophe_;
|
||
|
||
case FFELEX_typePERCENT:
|
||
return (ffelexHandler) ffeexpr_nil_percent_;
|
||
|
||
case FFELEX_typeOPEN_PAREN:
|
||
++ffeexpr_find_.level;
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
case FFELEX_typePLUS:
|
||
case FFELEX_typeMINUS:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
case FFELEX_typePERIOD:
|
||
return (ffelexHandler) ffeexpr_nil_period_;
|
||
|
||
case FFELEX_typeNUMBER:
|
||
ffeexpr_hollerith_count_ = atol (ffelex_token_text (t));
|
||
if (ffeexpr_hollerith_count_ > 0)
|
||
ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_,
|
||
'\0',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
return (ffelexHandler) ffeexpr_nil_number_;
|
||
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
return (ffelexHandler) ffeexpr_nil_name_rhs_;
|
||
|
||
case FFELEX_typeASTERISK:
|
||
case FFELEX_typeSLASH:
|
||
case FFELEX_typePOWER:
|
||
case FFELEX_typeCONCAT:
|
||
case FFELEX_typeREL_EQ:
|
||
case FFELEX_typeREL_NE:
|
||
case FFELEX_typeREL_LE:
|
||
case FFELEX_typeREL_GE:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_finished_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_period_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_current_dotdot_ = ffestr_other (t);
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherNone:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
|
||
case FFESTR_otherTRUE:
|
||
case FFESTR_otherFALSE:
|
||
case FFESTR_otherNOT:
|
||
return (ffelexHandler) ffeexpr_nil_end_period_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_swallow_period_;
|
||
}
|
||
break; /* Nothing really reaches here. */
|
||
|
||
case FFELEX_typeNUMBER:
|
||
return (ffelexHandler) ffeexpr_nil_real_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_end_period_ (ffelexToken t)
|
||
{
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherNOT:
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
case FFESTR_otherTRUE:
|
||
case FFESTR_otherFALSE:
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
|
||
default:
|
||
assert ("Bad [nil] unary dotdot in ffeexpr_current_dotdot_" == NULL);
|
||
exit (0);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_swallow_period_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_real_ (ffelexToken t)
|
||
{
|
||
char d;
|
||
const char *p;
|
||
|
||
if (((ffelex_token_type (t) != FFELEX_typeNAME)
|
||
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|
||
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q')))
|
||
&& ffeexpr_isdigits_ (++p)))
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
|
||
if (*p == '\0')
|
||
return (ffelexHandler) ffeexpr_nil_real_exponent_;
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_real_exponent_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
|
||
return (ffelexHandler) ffeexpr_nil_real_exp_sign_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_real_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_ (ffelexToken t)
|
||
{
|
||
char d;
|
||
const char *p;
|
||
|
||
if (ffeexpr_hollerith_count_ > 0)
|
||
ffelex_set_expecting_hollerith (0, '\0',
|
||
ffewhere_line_unknown (),
|
||
ffewhere_column_unknown ());
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q'))
|
||
&& ffeexpr_isdigits_ (++p))
|
||
{
|
||
if (*p == '\0')
|
||
{
|
||
ffeexpr_find_.t = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_nil_number_exponent_;
|
||
}
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typePERIOD:
|
||
ffeexpr_find_.t = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_nil_number_period_;
|
||
|
||
case FFELEX_typeHOLLERITH:
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
}
|
||
|
||
/* Expects ffeexpr_find_.t. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_exponent_ (ffelexToken t)
|
||
{
|
||
ffelexHandler nexthandler;
|
||
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
nexthandler
|
||
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) ffeexpr_nil_number_exp_sign_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
/* Expects ffeexpr_find_.t. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_period_ (ffelexToken t)
|
||
{
|
||
ffelexHandler nexthandler;
|
||
char d;
|
||
const char *p;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q'))
|
||
&& ffeexpr_isdigits_ (++p))
|
||
{
|
||
if (*p == '\0')
|
||
return (ffelexHandler) ffeexpr_nil_number_per_exp_;
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
nexthandler
|
||
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
|
||
case FFELEX_typeNUMBER:
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) ffeexpr_nil_number_real_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
}
|
||
|
||
/* Expects ffeexpr_find_.t. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_per_exp_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
ffelexHandler nexthandler;
|
||
|
||
nexthandler
|
||
= (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t);
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) ffeexpr_nil_num_per_exp_sign_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_real_ (ffelexToken t)
|
||
{
|
||
char d;
|
||
const char *p;
|
||
|
||
if (((ffelex_token_type (t) != FFELEX_typeNAME)
|
||
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|
||
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q')))
|
||
&& ffeexpr_isdigits_ (++p)))
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
|
||
if (*p == '\0')
|
||
return (ffelexHandler) ffeexpr_nil_number_real_exp_;
|
||
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_num_per_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_number_real_exp_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_num_real_exp_sn_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_num_real_exp_sn_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_binary_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typePLUS:
|
||
case FFELEX_typeMINUS:
|
||
case FFELEX_typeASTERISK:
|
||
case FFELEX_typeSLASH:
|
||
case FFELEX_typePOWER:
|
||
case FFELEX_typeCONCAT:
|
||
case FFELEX_typeOPEN_ANGLE:
|
||
case FFELEX_typeCLOSE_ANGLE:
|
||
case FFELEX_typeREL_EQ:
|
||
case FFELEX_typeREL_NE:
|
||
case FFELEX_typeREL_GE:
|
||
case FFELEX_typeREL_LE:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
case FFELEX_typePERIOD:
|
||
return (ffelexHandler) ffeexpr_nil_binary_period_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_finished_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_binary_period_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_current_dotdot_ = ffestr_other (t);
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherTRUE:
|
||
case FFESTR_otherFALSE:
|
||
case FFESTR_otherNOT:
|
||
return (ffelexHandler) ffeexpr_nil_binary_sw_per_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_binary_end_per_;
|
||
}
|
||
break; /* Nothing really reaches here. */
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_binary_end_per_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_binary_sw_per_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_quote_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_apostrophe_ (ffelexToken t)
|
||
{
|
||
assert (ffelex_token_type (t) == FFELEX_typeCHARACTER);
|
||
return (ffelexHandler) ffeexpr_nil_apos_char_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_apos_char_ (ffelexToken t)
|
||
{
|
||
char c;
|
||
|
||
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
{
|
||
if ((ffelex_token_length (t) == 1)
|
||
&& (ffesrc_char_match_init ((c = ffelex_token_text (t)[0]),
|
||
'B', 'b')
|
||
|| ffesrc_char_match_init (c, 'O', 'o')
|
||
|| ffesrc_char_match_init (c, 'X', 'x')
|
||
|| ffesrc_char_match_init (c, 'Z', 'z')))
|
||
return (ffelexHandler) ffeexpr_nil_binary_;
|
||
}
|
||
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_nil_substrp_ (t);
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_name_rhs_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeQUOTE:
|
||
case FFELEX_typeAPOSTROPHE:
|
||
ffelex_set_hexnum (TRUE);
|
||
return (ffelexHandler) ffeexpr_nil_name_apos_;
|
||
|
||
case FFELEX_typeOPEN_PAREN:
|
||
++ffeexpr_find_.level;
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_name_apos_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) == FFELEX_typeNAME)
|
||
return (ffelexHandler) ffeexpr_nil_name_apos_name_;
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_name_apos_name_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeAPOSTROPHE:
|
||
case FFELEX_typeQUOTE:
|
||
return (ffelexHandler) ffeexpr_nil_finished_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_finished_ (t);
|
||
}
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_percent_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_stack_->percent = ffeexpr_percent_ (t);
|
||
ffeexpr_find_.t = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_nil_percent_name_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_nil_rhs_ (t);
|
||
}
|
||
}
|
||
|
||
/* Expects ffeexpr_find_.t. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_percent_name_ (ffelexToken t)
|
||
{
|
||
ffelexHandler nexthandler;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
|
||
{
|
||
nexthandler
|
||
= (ffelexHandler) ffeexpr_nil_rhs_ (ffeexpr_find_.t);
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_find_.t);
|
||
++ffeexpr_find_.level;
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
}
|
||
|
||
static ffelexHandler
|
||
ffeexpr_nil_substrp_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
|
||
return (ffelexHandler) ffeexpr_nil_binary_ (t);
|
||
|
||
++ffeexpr_find_.level;
|
||
return (ffelexHandler) ffeexpr_nil_rhs_;
|
||
}
|
||
|
||
/* ffeexpr_finished_ -- Reduce expression stack to one expr, finish
|
||
|
||
ffelexToken t;
|
||
return ffeexpr_finished_(t);
|
||
|
||
Reduces expression stack to one (or zero) elements by repeatedly reducing
|
||
the top operator on the stack (or, if the top element on the stack is
|
||
itself an operator, issuing an error message and discarding it). Calls
|
||
finishing routine with the expression, returning the ffelexHandler it
|
||
returns to the caller. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_finished_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ operand; /* This is B in -B or A+B. */
|
||
ffebld expr;
|
||
ffeexprCallback callback;
|
||
ffeexprStack_ s;
|
||
ffebldConstant constnode; /* For detecting magical number. */
|
||
ffelexToken ft; /* Temporary copy of first token in
|
||
expression. */
|
||
ffelexHandler next;
|
||
ffeinfo info;
|
||
bool error = FALSE;
|
||
|
||
while (((operand = ffeexpr_stack_->exprstack) != NULL)
|
||
&& ((operand->previous != NULL) || (operand->type != FFEEXPR_exprtypeOPERAND_)))
|
||
{
|
||
if (operand->type == FFEEXPR_exprtypeOPERAND_)
|
||
ffeexpr_reduce_ ();
|
||
else
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_OPERAND_FOR_OPERATOR))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
|
||
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
|
||
ffebad_finish ();
|
||
}
|
||
ffeexpr_stack_->exprstack = operand->previous; /* Pop the useless
|
||
operator. */
|
||
ffeexpr_expr_kill_ (operand);
|
||
}
|
||
}
|
||
|
||
assert ((operand == NULL) || (operand->previous == NULL));
|
||
|
||
ffebld_pool_pop ();
|
||
if (operand == NULL)
|
||
expr = NULL;
|
||
else
|
||
{
|
||
expr = operand->u.operand;
|
||
info = ffebld_info (expr);
|
||
if ((ffebld_op (expr) == FFEBLD_opCONTER)
|
||
&& (ffebld_conter_orig (expr) == NULL)
|
||
&& ffebld_constant_is_magical (constnode = ffebld_conter (expr)))
|
||
{
|
||
ffetarget_integer_bad_magical (operand->token);
|
||
}
|
||
ffeexpr_expr_kill_ (operand);
|
||
ffeexpr_stack_->exprstack = NULL;
|
||
}
|
||
|
||
ft = ffeexpr_stack_->first_token;
|
||
|
||
again: /* :::::::::::::::::::: */
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
error = (expr == NULL)
|
||
|| (ffeinfo_rank (info) != 0);
|
||
break;
|
||
|
||
case FFEEXPR_contextPAREN_:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextPARENFILENUM_:
|
||
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
|
||
ffeexpr_stack_->context = FFEEXPR_contextPAREN_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILENUM;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextPARENFILEUNIT_:
|
||
if (ffelex_token_type (t) != FFELEX_typeCOMMA)
|
||
ffeexpr_stack_->context = FFEEXPR_contextPAREN_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextFILEUNIT;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
if (!ffe_is_ugly_args ()
|
||
&& ffebad_start (FFEBAD_ACTUALARG))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
error = (expr != NULL) && (ffeinfo_rank (info) != 0);
|
||
break;
|
||
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
#if 0 /* Should never get here. */
|
||
expr = ffeexpr_convert (expr, ft, ft,
|
||
FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
#else
|
||
assert ("why hollerith/typeless in actualarg_?" == NULL);
|
||
#endif
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
switch ((expr == NULL) ? FFEBLD_opANY : ffebld_op (expr))
|
||
{
|
||
case FFEBLD_opSYMTER:
|
||
case FFEBLD_opPERCENT_LOC:
|
||
case FFEBLD_opPERCENT_VAL:
|
||
case FFEBLD_opPERCENT_REF:
|
||
case FFEBLD_opPERCENT_DESCR:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = (expr != NULL) && (ffeinfo_rank (info) != 0);
|
||
break;
|
||
}
|
||
{
|
||
ffesymbol s;
|
||
ffeinfoWhere where;
|
||
ffeinfoKind kind;
|
||
|
||
if (!error
|
||
&& (expr != NULL)
|
||
&& (ffebld_op (expr) == FFEBLD_opSYMTER)
|
||
&& ((s = ffebld_symter (expr)), (where = ffesymbol_where (s)),
|
||
(where == FFEINFO_whereINTRINSIC)
|
||
|| (where == FFEINFO_whereGLOBAL)
|
||
|| ((where == FFEINFO_whereDUMMY)
|
||
&& ((kind = ffesymbol_kind (s)),
|
||
(kind == FFEINFO_kindFUNCTION)
|
||
|| (kind == FFEINFO_kindSUBROUTINE))))
|
||
&& !ffesymbol_explicitwhere (s))
|
||
{
|
||
ffebad_start (where == FFEINFO_whereINTRINSIC
|
||
? FFEBAD_NEED_INTRINSIC : FFEBAD_NEED_EXTERNAL);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_string (ffesymbol_text (s));
|
||
ffebad_finish ();
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_explicitwhere (s, TRUE);
|
||
ffesymbol_signal_unreported (s);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeNONE:
|
||
error = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
/* Specifically, allow INTEGER(KIND=2), aka INTEGER*8, through
|
||
unmolested. Leave it to downstream to handle kinds. */
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break; /* expr==NULL ok for substring; element case
|
||
caught by callback. */
|
||
|
||
case FFEEXPR_contextRETURN:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeNONE:
|
||
error = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextDO:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
error = !ffe_is_ugly_logint ();
|
||
if (!ffeexpr_stack_->is_rhs)
|
||
break; /* Don't convert lhs variable. */
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (ffebld_info (expr)), 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
if (!ffeexpr_stack_->is_rhs)
|
||
{
|
||
error = TRUE;
|
||
break; /* Don't convert lhs variable. */
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeREAL:
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if (!ffeexpr_stack_->is_rhs
|
||
&& (ffebld_op (expr) != FFEBLD_opSYMTER))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextIF:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeLOGICAL:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextAGOTO:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
error = (ffeinfo_kindtype (info) != ffecom_label_kind ());
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
error = !ffe_is_ugly_logint ()
|
||
|| (ffeinfo_kindtype (info) != ffecom_label_kind ());
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0)
|
||
|| (ffebld_op (expr) != FFEBLD_opSYMTER))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextFILENUM: /* See equiv code in _ambig_. */
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextARITHIF:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeREAL:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextSTOP:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT);
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeNONE:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr != NULL) && ((ffebld_op (expr) != FFEBLD_opCONTER)
|
||
|| (ffebld_conter_orig (expr) != NULL)))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextINCLUDE:
|
||
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|
||
|| (ffeinfo_basictype (info) != FFEINFO_basictypeCHARACTER)
|
||
|| (ffebld_op (expr) != FFEBLD_opCONTER)
|
||
|| (ffebld_conter_orig (expr) != NULL);
|
||
break;
|
||
|
||
case FFEEXPR_contextSELECTCASE:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeCHARACTER:
|
||
case FFEINFO_basictypeLOGICAL:
|
||
error = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextCASE:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeINTEGER
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeCHARACTER:
|
||
case FFEINFO_basictypeLOGICAL:
|
||
error = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeNONE:
|
||
error = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextPARAMETER:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|
||
|| (ffebld_op (expr) != FFEBLD_opCONTER);
|
||
else
|
||
error = (expr == NULL) || (ffeinfo_rank (info) != 0)
|
||
|| (ffebld_op (expr) != FFEBLD_opSYMTER);
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEX_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEX_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_;
|
||
else
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
if (!ffeexpr_stack_->is_rhs
|
||
&& (ffebld_op (expr) != FFEBLD_opSYMTER))
|
||
error = TRUE;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
if (! ffe_is_ugly_logint ())
|
||
error = TRUE;
|
||
if (! ffeexpr_stack_->is_rhs)
|
||
break;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (info), 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:
|
||
if (! ffeexpr_stack_->is_rhs)
|
||
break;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (info), 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
if (ffeexpr_stack_->is_rhs
|
||
&& (ffeinfo_kindtype (ffebld_info (expr))
|
||
!= FFEINFO_kindtypeINTEGERDEFAULT))
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeREAL:
|
||
if (!ffeexpr_stack_->is_rhs
|
||
&& ffe_is_warn_surprising ()
|
||
&& !error)
|
||
{
|
||
ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_string (ffelex_token_text (ft));
|
||
ffebad_finish ();
|
||
}
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
if (ffelex_token_type (t) == FFELEX_typeEQUALS)
|
||
{
|
||
ffeexpr_stack_->is_rhs = FALSE;
|
||
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
}
|
||
/* Fall through. */
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
error = (expr == NULL)
|
||
|| ((ffeinfo_rank (info) != 0)
|
||
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|
||
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|
||
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
|
||
== FFEBLD_opSTAR))); /* Bad if null expr, or if
|
||
array that is not a SYMTER
|
||
(can't happen yet, I
|
||
think) or has a NULL or
|
||
STAR (assumed) array
|
||
size. */
|
||
break;
|
||
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
if (ffelex_token_type (t) == FFELEX_typeEQUALS)
|
||
{
|
||
ffeexpr_stack_->is_rhs = FALSE;
|
||
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
|
||
goto again; /* :::::::::::::::::::: */
|
||
}
|
||
/* Fall through. */
|
||
case FFEEXPR_contextIOLISTDF:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
error
|
||
= (expr == NULL)
|
||
|| ((ffeinfo_basictype (info) == FFEINFO_basictypeCHARACTER)
|
||
&& (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT))
|
||
|| ((ffeinfo_rank (info) != 0)
|
||
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|
||
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|
||
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
|
||
== FFEBLD_opSTAR))); /* Bad if null expr,
|
||
non-default-kindtype
|
||
character expr, or if
|
||
array that is not a SYMTER
|
||
(can't happen yet, I
|
||
think) or has a NULL or
|
||
STAR (assumed) array
|
||
size. */
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
error = (expr == NULL)
|
||
|| (ffebld_op (expr) != FFEBLD_opARRAYREF)
|
||
|| ((ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR)
|
||
&& (ffeinfo_where (info) != FFEINFO_whereFLEETING_IADDR));
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOINDEX_:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((ffeinfo_where (info) != FFEINFO_whereCONSTANT)
|
||
&& (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
if (expr == NULL)
|
||
error = TRUE;
|
||
else if (ffeexpr_stack_->is_rhs)
|
||
error = (ffebld_op (expr) != FFEBLD_opCONTER);
|
||
else if (ffebld_op (expr) == FFEBLD_opSYMTER)
|
||
error = FALSE;
|
||
else
|
||
error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR);
|
||
break;
|
||
|
||
case FFEEXPR_contextINITVAL:
|
||
error = (expr == NULL) || (ffebld_op (expr) != FFEBLD_opCONTER);
|
||
break;
|
||
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
if (expr == NULL)
|
||
error = TRUE;
|
||
else if (ffebld_op (expr) == FFEBLD_opSYMTER)
|
||
error = FALSE;
|
||
else
|
||
error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR);
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
/* Maybe this should be supported someday, but, right now,
|
||
g77 can't generate a call to libf2c to write to an
|
||
integer other than the default size. */
|
||
error = ((! ffeexpr_stack_->is_rhs)
|
||
&& ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEDFINT:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILELOG:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILECHAR:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeCHARACTER:
|
||
error
|
||
= (ffeinfo_kindtype (info)
|
||
!= FFEINFO_kindtypeCHARACTERDEFAULT);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if (!ffeexpr_stack_->is_rhs
|
||
&& (ffebld_op (expr) == FFEBLD_opSUBSTR))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEUNIT: /* See equiv code in _ambig_. */
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
if ((error = (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if ((error = (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
if ((error = (ffeinfo_rank (info) != 0)))
|
||
break;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffebld_op (expr))
|
||
{ /* As if _lhs had been called instead of
|
||
_rhs. */
|
||
case FFEBLD_opSYMTER:
|
||
error
|
||
= (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT);
|
||
break;
|
||
|
||
case FFEBLD_opSUBSTR:
|
||
error = (ffeinfo_where (ffebld_info (expr))
|
||
== FFEINFO_whereCONSTANT_SUBOBJECT);
|
||
break;
|
||
|
||
case FFEBLD_opARRAYREF:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if (!error
|
||
&& ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT)
|
||
|| ((ffeinfo_rank (info) != 0)
|
||
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|
||
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|
||
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
|
||
== FFEBLD_opSTAR))))) /* Bad if
|
||
non-default-kindtype
|
||
character expr, or if
|
||
array that is not a SYMTER
|
||
(can't happen yet, I
|
||
think), or has a NULL or
|
||
STAR (assumed) array
|
||
size. */
|
||
error = TRUE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeINTEGER:
|
||
error = (expr == NULL)
|
||
|| ((ffeinfo_rank (info) != 0) ?
|
||
ffe_is_pedantic () /* F77 C5. */
|
||
: (bool) (ffeinfo_kindtype (info) != ffecom_label_kind ()))
|
||
|| (ffebld_op (expr) != FFEBLD_opSYMTER);
|
||
break;
|
||
|
||
case FFEINFO_basictypeLOGICAL:
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
/* F77 C5 -- must be an array of hollerith. */
|
||
error
|
||
= ffe_is_pedantic ()
|
||
|| (ffeinfo_rank (info) == 0);
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
if ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT)
|
||
|| ((ffeinfo_rank (info) != 0)
|
||
&& ((ffebld_op (expr) != FFEBLD_opSYMTER)
|
||
|| (ffesymbol_arraysize (ffebld_symter (expr)) == NULL)
|
||
|| (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr)))
|
||
== FFEBLD_opSTAR)))) /* Bad if
|
||
non-default-kindtype
|
||
character expr, or if
|
||
array that is not a SYMTER
|
||
(can't happen yet, I
|
||
think), or has a NULL or
|
||
STAR (assumed) array
|
||
size. */
|
||
error = TRUE;
|
||
else
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextLOC_:
|
||
/* See also ffeintrin_check_loc_. */
|
||
if ((expr == NULL)
|
||
|| (ffeinfo_kind (info) != FFEINFO_kindENTITY)
|
||
|| ((ffebld_op (expr) != FFEBLD_opSYMTER)
|
||
&& (ffebld_op (expr) != FFEBLD_opSUBSTR)
|
||
&& (ffebld_op (expr) != FFEBLD_opARRAYREF)))
|
||
error = TRUE;
|
||
break;
|
||
|
||
default:
|
||
error = FALSE;
|
||
break;
|
||
}
|
||
|
||
if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY)))
|
||
{
|
||
ffebad_start (FFEBAD_EXPR_WRONG);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
expr = ffebld_new_any ();
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
|
||
callback = ffeexpr_stack_->callback;
|
||
s = ffeexpr_stack_->previous;
|
||
malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_,
|
||
sizeof (*ffeexpr_stack_));
|
||
ffeexpr_stack_ = s;
|
||
next = (ffelexHandler) (*callback) (ft, expr, t);
|
||
ffelex_token_kill (ft);
|
||
return (ffelexHandler) next;
|
||
}
|
||
|
||
/* ffeexpr_finished_ambig_ -- Check validity of ambiguous unit/form spec
|
||
|
||
ffebld expr;
|
||
expr = ffeexpr_finished_ambig_(expr);
|
||
|
||
Replicates a bit of ffeexpr_finished_'s task when in a context
|
||
of UNIT or FORMAT. */
|
||
|
||
static ffebld
|
||
ffeexpr_finished_ambig_ (ffelexToken ft, ffebld expr)
|
||
{
|
||
ffeinfo info = ffebld_info (expr);
|
||
bool error;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFILENUMAMBIG: /* Same as FILENUM in _finished_. */
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = FALSE;
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
if ((expr == NULL) || (ffeinfo_rank (info) != 0))
|
||
error = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEUNITAMBIG: /* Same as FILEUNIT in _finished_. */
|
||
if ((expr != NULL) && (ffebld_op (expr) == FFEBLD_opSTAR))
|
||
{
|
||
error = FALSE;
|
||
break;
|
||
}
|
||
switch ((expr == NULL) ? FFEINFO_basictypeNONE
|
||
: ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeLOGICAL:
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
|
||
FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeREAL:
|
||
case FFEINFO_basictypeCOMPLEX:
|
||
if (ffe_is_pedantic ())
|
||
{
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFEINFO_basictypeINTEGER:
|
||
case FFEINFO_basictypeHOLLERITH:
|
||
case FFEINFO_basictypeTYPELESS:
|
||
error = (ffeinfo_rank (info) != 0);
|
||
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
break;
|
||
|
||
case FFEINFO_basictypeCHARACTER:
|
||
switch (ffebld_op (expr))
|
||
{ /* As if _lhs had been called instead of
|
||
_rhs. */
|
||
case FFEBLD_opSYMTER:
|
||
error
|
||
= (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT);
|
||
break;
|
||
|
||
case FFEBLD_opSUBSTR:
|
||
error = (ffeinfo_where (ffebld_info (expr))
|
||
== FFEINFO_whereCONSTANT_SUBOBJECT);
|
||
break;
|
||
|
||
case FFEBLD_opARRAYREF:
|
||
error = FALSE;
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context" == NULL);
|
||
error = TRUE;
|
||
break;
|
||
}
|
||
|
||
if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY)))
|
||
{
|
||
ffebad_start (FFEBAD_EXPR_WRONG);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
expr = ffebld_new_any ();
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
|
||
return expr;
|
||
}
|
||
|
||
/* ffeexpr_token_lhs_ -- Initial state for lhs expression
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Basically a smaller version of _rhs_; keep them both in sync, of course. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_lhs_ (ffelexToken t)
|
||
{
|
||
|
||
/* When changing the list of valid initial lhs tokens, check whether to
|
||
update a corresponding list in ffeexpr_cb_close_paren_ambig_1_ for the
|
||
READ (expr) <token> case -- it assumes it knows which tokens <token> can
|
||
be to indicate an lhs (or implied DO), which right now is the set
|
||
{NAME,OPEN_PAREN}.
|
||
|
||
This comment also appears in ffeexpr_token_first_lhs_. */
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_name_lhs_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_rhs_ -- Initial state for rhs expression
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
The initial state and the post-binary-operator state are the same and
|
||
both handled here, with the expression stack used to distinguish
|
||
between them. Binary operators are invalid here; unary operators,
|
||
constants, subexpressions, and name references are valid. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_rhs_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeQUOTE:
|
||
if (ffe_is_vxt ())
|
||
{
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_quote_;
|
||
}
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
ffelex_set_expecting_hollerith (-1, '\"',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
/* Don't have to unset this one. */
|
||
return (ffelexHandler) ffeexpr_token_apostrophe_;
|
||
|
||
case FFELEX_typeAPOSTROPHE:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
ffelex_set_expecting_hollerith (-1, '\'',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
/* Don't have to unset this one. */
|
||
return (ffelexHandler) ffeexpr_token_apostrophe_;
|
||
|
||
case FFELEX_typePERCENT:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_percent_;
|
||
|
||
case FFELEX_typeOPEN_PAREN:
|
||
ffeexpr_stack_->tokens[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextPAREN_,
|
||
ffeexpr_cb_close_paren_c_);
|
||
|
||
case FFELEX_typePLUS:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeUNARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorADD_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceADD_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityADD_;
|
||
ffeexpr_exprstack_push_unary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeMINUS:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeUNARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorSUBTRACT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_;
|
||
ffeexpr_exprstack_push_unary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typePERIOD:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_period_;
|
||
|
||
case FFELEX_typeNUMBER:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
ffeexpr_hollerith_count_ = atol (ffelex_token_text (t));
|
||
if (ffeexpr_hollerith_count_ > 0)
|
||
ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_,
|
||
'\0',
|
||
ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
return (ffelexHandler) ffeexpr_token_number_;
|
||
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
return (ffelexHandler) ffeexpr_token_name_arg_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_token_name_rhs_;
|
||
}
|
||
|
||
case FFELEX_typeASTERISK:
|
||
case FFELEX_typeSLASH:
|
||
case FFELEX_typePOWER:
|
||
case FFELEX_typeCONCAT:
|
||
case FFELEX_typeREL_EQ:
|
||
case FFELEX_typeREL_NE:
|
||
case FFELEX_typeREL_LE:
|
||
case FFELEX_typeREL_GE:
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_FIRST_BINARY_OPERAND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
#if 0
|
||
case FFELEX_typeEQUALS:
|
||
case FFELEX_typePOINTS:
|
||
case FFELEX_typeCLOSE_ANGLE:
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
case FFELEX_typeCOMMA:
|
||
case FFELEX_typeCOLON:
|
||
case FFELEX_typeEOS:
|
||
case FFELEX_typeSEMICOLON:
|
||
#endif
|
||
default:
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_period_ -- Rhs PERIOD
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle a period detected at rhs (expecting unary op or operand) state.
|
||
Must begin a floating-point value (as in .12) or a dot-dot name, of
|
||
which only .NOT., .TRUE., and .FALSE. are truly valid. Other sort-of-
|
||
valid names represent binary operators, which are invalid here because
|
||
there isn't an operand at the top of the stack. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_period_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_current_dotdot_ = ffestr_other (t);
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherNone:
|
||
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
|
||
case FFESTR_otherTRUE:
|
||
case FFESTR_otherFALSE:
|
||
case FFESTR_otherNOT:
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_end_period_;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_FIRST_BINARY_OPERAND))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_swallow_period_;
|
||
}
|
||
break; /* Nothing really reaches here. */
|
||
|
||
case FFELEX_typeNUMBER:
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_real_;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_end_period_ -- Rhs PERIOD NAME(NOT, TRUE, or FALSE)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Expecting a period to close a .NOT, .TRUE, or .FALSE at rhs (unary op
|
||
or operator) state. If period isn't found, issue a diagnostic but
|
||
pretend we saw one. ffeexpr_current_dotdot_ must already contained the
|
||
dotdot representation of the name in between the two PERIOD tokens. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_end_period_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_INSERTING_PERIOD))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill "NOT"/"TRUE"/"FALSE"
|
||
token. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->token = ffeexpr_tokens_[0];
|
||
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherNOT:
|
||
e->type = FFEEXPR_exprtypeUNARY_;
|
||
e->u.operator.op = FFEEXPR_operatorNOT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceNOT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityNOT_;
|
||
ffeexpr_exprstack_push_unary_ (e);
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFESTR_otherTRUE:
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand
|
||
= ffebld_new_conter (ffebld_constant_new_logicaldefault (TRUE));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
|
||
case FFESTR_otherFALSE:
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand
|
||
= ffebld_new_conter (ffebld_constant_new_logicaldefault (FALSE));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
|
||
default:
|
||
assert ("Bad unary dotdot in ffeexpr_current_dotdot_" == NULL);
|
||
exit (0);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_swallow_period_ -- Rhs PERIOD NAME(not NOT, TRUE, or FALSE)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
A diagnostic has already been issued; just swallow a period if there is
|
||
one, then continue with ffeexpr_token_rhs_. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_swallow_period_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
}
|
||
|
||
/* ffeexpr_token_real_ -- Rhs PERIOD NUMBER
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
After a period and a string of digits, check next token for possible
|
||
exponent designation (D, E, or Q as first/only character) and continue
|
||
real-number handling accordingly. Else form basic real constant, push
|
||
onto expression stack, and enter binary state using current token (which,
|
||
if it is a name not beginning with D, E, or Q, will certainly result
|
||
in an error, but that's not for this routine to deal with). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_real_ (ffelexToken t)
|
||
{
|
||
char d;
|
||
const char *p;
|
||
|
||
if (((ffelex_token_type (t) != FFELEX_typeNAME)
|
||
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|
||
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q')))
|
||
&& ffeexpr_isdigits_ (++p)))
|
||
{
|
||
#if 0
|
||
/* This code has been removed because it seems inconsistent to
|
||
produce a diagnostic in this case, but not all of the other
|
||
ones that look for an exponent and cannot recognize one. */
|
||
if (((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
&& ffest_ffebad_start (FFEBAD_INVALID_EXPONENT))
|
||
{
|
||
char bad[2];
|
||
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
bad[0] = *(p - 1);
|
||
bad[1] = '\0';
|
||
ffebad_string (bad);
|
||
ffebad_finish ();
|
||
}
|
||
#endif
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* Just exponent character by itself? In which case, PLUS or MINUS must
|
||
surely be next, followed by a NUMBER token. */
|
||
|
||
if (*p == '\0')
|
||
{
|
||
ffeexpr_tokens_[2] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_real_exponent_;
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (d, NULL, ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
t, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_real_exponent_ -- Rhs PERIOD NUMBER NAME(D, E, or Q)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Ensures this token is PLUS or MINUS, preserves it, goes to final state
|
||
for real number (exponent digits). Else issues diagnostic, assumes a
|
||
zero exponent field for number, passes token on to binary state as if
|
||
previous token had been "E0" instead of "E", for example. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_real_exponent_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[2]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_tokens_[3] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_real_exp_sign_;
|
||
}
|
||
|
||
/* ffeexpr_token_real_exp_sign_ -- Rhs PERIOD NUMBER NAME(D,E,Q) PLUS/MINUS
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Make sure token is a NUMBER, make a real constant out of all we have and
|
||
push it onto the expression stack. Else issue diagnostic and pretend
|
||
exponent field was a zero. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_real_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[2]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL,
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0], NULL,
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1], ffeexpr_tokens_[2],
|
||
ffeexpr_tokens_[3], t);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_number_ -- Rhs NUMBER
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
If the token is a period, we may have a floating-point number, or an
|
||
integer followed by a dotdot binary operator. If the token is a name
|
||
beginning with D, E, or Q, we definitely have a floating-point number.
|
||
If the token is a hollerith constant, that's what we've got, so push
|
||
it onto the expression stack and continue with the binary state.
|
||
|
||
Otherwise, we have an integer followed by something the binary state
|
||
should be able to swallow. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffeinfo ni;
|
||
char d;
|
||
const char *p;
|
||
|
||
if (ffeexpr_hollerith_count_ > 0)
|
||
ffelex_set_expecting_hollerith (0, '\0',
|
||
ffewhere_line_unknown (),
|
||
ffewhere_column_unknown ());
|
||
|
||
/* See if we've got a floating-point number here. */
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q'))
|
||
&& ffeexpr_isdigits_ (++p))
|
||
{
|
||
|
||
/* Just exponent character by itself? In which case, PLUS or MINUS
|
||
must surely be next, followed by a NUMBER token. */
|
||
|
||
if (*p == '\0')
|
||
{
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_exponent_;
|
||
}
|
||
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], NULL, NULL, t,
|
||
NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
break;
|
||
|
||
case FFELEX_typePERIOD:
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_period_;
|
||
|
||
case FFELEX_typeHOLLERITH:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_hollerith (t));
|
||
ni = ffeinfo_new (FFEINFO_basictypeHOLLERITH, FFEINFO_kindtypeNONE,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
ffelex_token_length (t));
|
||
ffebld_set_info (e->u.operand, ni);
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
/* Nothing specific we were looking for, so make an integer and pass the
|
||
current token to the binary state. */
|
||
|
||
ffeexpr_make_float_const_ ('I', ffeexpr_tokens_[0], NULL, NULL,
|
||
NULL, NULL, NULL);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_number_exponent_ -- Rhs NUMBER NAME(D, E, or Q)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Ensures this token is PLUS or MINUS, preserves it, goes to final state
|
||
for real number (exponent digits). Else treats number as integer, passes
|
||
name to binary, passes current token to subsequent handler. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_exponent_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffelexHandler nexthandler;
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
|
||
(ffeexpr_tokens_[0]));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
nexthandler = (ffelexHandler) ffeexpr_token_binary_ (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
ffeexpr_tokens_[2] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_exp_sign_;
|
||
}
|
||
|
||
/* ffeexpr_token_number_exp_sign_ -- Rhs NUMBER NAME(D,E,Q) PLUS/MINUS
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Make sure token is a NUMBER, make a real constant out of all we have and
|
||
push it onto the expression stack. Else issue diagnostic and pretend
|
||
exponent field was a zero. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[1]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[1]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[1])[0],
|
||
ffeexpr_tokens_[0], NULL, NULL,
|
||
ffeexpr_tokens_[1], ffeexpr_tokens_[2],
|
||
NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[1])[0],
|
||
ffeexpr_tokens_[0], NULL, NULL,
|
||
ffeexpr_tokens_[1], ffeexpr_tokens_[2], t);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_number_period_ -- Rhs NUMBER PERIOD
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle a period detected following a number at rhs state. Must begin a
|
||
floating-point value (as in 1., 1.2, 1.E3, or 1.E+3) or a dot-dot name. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_period_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffelexHandler nexthandler;
|
||
const char *p;
|
||
char d;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q'))
|
||
&& ffeexpr_isdigits_ (++p))
|
||
{
|
||
|
||
/* Just exponent character by itself? In which case, PLUS or MINUS
|
||
must surely be next, followed by a NUMBER token. */
|
||
|
||
if (*p == '\0')
|
||
{
|
||
ffeexpr_tokens_[2] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_per_exp_;
|
||
}
|
||
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0],
|
||
ffeexpr_tokens_[1], NULL, t, NULL,
|
||
NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
/* A name not representing an exponent, so assume it will be something
|
||
like EQ, make an integer from the number, pass the period to binary
|
||
state and the current token to the resulting state. */
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
|
||
(ffeexpr_tokens_[0]));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
nexthandler = (ffelexHandler) ffeexpr_token_binary_
|
||
(ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
|
||
case FFELEX_typeNUMBER:
|
||
ffeexpr_tokens_[2] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_real_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
/* Nothing specific we were looking for, so make a real number and pass the
|
||
period and then the current token to the binary state. */
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_number_per_exp_ -- Rhs NUMBER PERIOD NAME(D, E, or Q)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Ensures this token is PLUS or MINUS, preserves it, goes to final state
|
||
for real number (exponent digits). Else treats number as real, passes
|
||
name to binary, passes current token to subsequent handler. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_per_exp_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
ffelexHandler nexthandler;
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
nexthandler = (ffelexHandler) ffeexpr_token_binary_ (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
ffeexpr_tokens_[3] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_num_per_exp_sign_;
|
||
}
|
||
|
||
/* ffeexpr_token_number_real_ -- Rhs NUMBER PERIOD NUMBER
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
After a number, period, and number, check next token for possible
|
||
exponent designation (D, E, or Q as first/only character) and continue
|
||
real-number handling accordingly. Else form basic real constant, push
|
||
onto expression stack, and enter binary state using current token (which,
|
||
if it is a name not beginning with D, E, or Q, will certainly result
|
||
in an error, but that's not for this routine to deal with). */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_real_ (ffelexToken t)
|
||
{
|
||
char d;
|
||
const char *p;
|
||
|
||
if (((ffelex_token_type (t) != FFELEX_typeNAME)
|
||
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
|
||
|| !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))),
|
||
'D', 'd')
|
||
|| ffesrc_char_match_init (d, 'E', 'e')
|
||
|| ffesrc_char_match_init (d, 'Q', 'q')))
|
||
&& ffeexpr_isdigits_ (++p)))
|
||
{
|
||
#if 0
|
||
/* This code has been removed because it seems inconsistent to
|
||
produce a diagnostic in this case, but not all of the other
|
||
ones that look for an exponent and cannot recognize one. */
|
||
if (((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
&& ffest_ffebad_start (FFEBAD_INVALID_EXPONENT))
|
||
{
|
||
char bad[2];
|
||
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
bad[0] = *(p - 1);
|
||
bad[1] = '\0';
|
||
ffebad_string (bad);
|
||
ffebad_finish ();
|
||
}
|
||
#endif
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
ffeexpr_tokens_[2], NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* Just exponent character by itself? In which case, PLUS or MINUS must
|
||
surely be next, followed by a NUMBER token. */
|
||
|
||
if (*p == '\0')
|
||
{
|
||
ffeexpr_tokens_[3] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_number_real_exp_;
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
ffeexpr_tokens_[2], t, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_num_per_exp_sign_ -- Rhs NUMBER PERIOD NAME(D,E,Q) PLUS/MINUS
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Make sure token is a NUMBER, make a real constant out of all we have and
|
||
push it onto the expression stack. Else issue diagnostic and pretend
|
||
exponent field was a zero. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_num_per_exp_sign_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[2]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
NULL, NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0],
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1], NULL,
|
||
ffeexpr_tokens_[2], ffeexpr_tokens_[3], t);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_number_real_exp_ -- Rhs NUMBER PERIOD NUMBER NAME(D, E, or Q)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Ensures this token is PLUS or MINUS, preserves it, goes to final state
|
||
for real number (exponent digits). Else issues diagnostic, assumes a
|
||
zero exponent field for number, passes token on to binary state as if
|
||
previous token had been "E0" instead of "E", for example. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_number_real_exp_ (ffelexToken t)
|
||
{
|
||
if ((ffelex_token_type (t) != FFELEX_typePLUS)
|
||
&& (ffelex_token_type (t) != FFELEX_typeMINUS))
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[3]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
ffeexpr_tokens_[2], NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_tokens_[4] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_num_real_exp_sn_;
|
||
}
|
||
|
||
/* ffeexpr_token_num_real_exp_sn_ -- Rhs NUMBER PERIOD NUMBER NAME(D,E,Q)
|
||
PLUS/MINUS
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Make sure token is a NUMBER, make a real constant out of all we have and
|
||
push it onto the expression stack. Else issue diagnostic and pretend
|
||
exponent field was a zero. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_num_real_exp_sn_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[3]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'),
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
ffeexpr_tokens_[2], NULL, NULL, NULL);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
ffelex_token_kill (ffeexpr_tokens_[4]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[3])[0],
|
||
ffeexpr_tokens_[0], ffeexpr_tokens_[1],
|
||
ffeexpr_tokens_[2], ffeexpr_tokens_[3],
|
||
ffeexpr_tokens_[4], t);
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
ffelex_token_kill (ffeexpr_tokens_[3]);
|
||
ffelex_token_kill (ffeexpr_tokens_[4]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_binary_ -- Handle binary operator possibility
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
The possibility of a binary operator is handled here, meaning the previous
|
||
token was an operand. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_binary_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
if (!ffeexpr_stack_->is_rhs)
|
||
return (ffelexHandler) ffeexpr_finished_ (t); /* For now. */
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typePLUS:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorADD_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceADD_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityADD_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeMINUS:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorSUBTRACT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeASTERISK:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorMULTIPLY_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceMULTIPLY_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityMULTIPLY_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeSLASH:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATA:
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorDIVIDE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceDIVIDE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityDIVIDE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typePOWER:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorPOWER_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedencePOWER_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityPOWER_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeCONCAT:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorCONCATENATE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeOPEN_ANGLE:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorLT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceLT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityLT_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeCLOSE_ANGLE:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
return ffeexpr_finished_ (t);
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorGT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceGT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityGT_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeREL_EQ:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorEQ_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeREL_NE:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorNE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceNE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityNE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeREL_LE:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorLE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceLE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityLE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typeREL_GE:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextFORMAT:
|
||
ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN);
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorGE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceGE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityGE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
|
||
case FFELEX_typePERIOD:
|
||
ffeexpr_tokens_[0] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_binary_period_;
|
||
|
||
#if 0
|
||
case FFELEX_typeOPEN_PAREN:
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
case FFELEX_typeEQUALS:
|
||
case FFELEX_typePOINTS:
|
||
case FFELEX_typeCOMMA:
|
||
case FFELEX_typeCOLON:
|
||
case FFELEX_typeEOS:
|
||
case FFELEX_typeSEMICOLON:
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
#endif
|
||
default:
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_binary_period_ -- Binary PERIOD
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle a period detected at binary (expecting binary op or end) state.
|
||
Must begin a dot-dot name, of which .NOT., .TRUE., and .FALSE. are not
|
||
valid. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_binary_period_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ operand;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_current_dotdot_ = ffestr_other (t);
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherTRUE:
|
||
case FFESTR_otherFALSE:
|
||
case FFESTR_otherNOT:
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_BINARY_OPERATOR))
|
||
{
|
||
operand = ffeexpr_stack_->exprstack;
|
||
assert (operand != NULL);
|
||
assert (operand->type == FFEEXPR_exprtypeOPERAND_);
|
||
ffebad_here (0, ffelex_token_where_line (operand->token), ffelex_token_where_column (operand->token));
|
||
ffebad_here (1, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_binary_sw_per_;
|
||
|
||
default:
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_binary_end_per_;
|
||
}
|
||
break; /* Nothing really reaches here. */
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_binary_end_per_ -- Binary PERIOD NAME(not NOT, TRUE, or FALSE)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Expecting a period to close a dot-dot at binary (binary op
|
||
or operator) state. If period isn't found, issue a diagnostic but
|
||
pretend we saw one. ffeexpr_current_dotdot_ must already contained the
|
||
dotdot representation of the name in between the two PERIOD tokens. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_binary_end_per_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
|
||
switch (ffeexpr_current_dotdot_)
|
||
{
|
||
case FFESTR_otherAND:
|
||
e->u.operator.op = FFEEXPR_operatorAND_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceAND_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityAND_;
|
||
break;
|
||
|
||
case FFESTR_otherOR:
|
||
e->u.operator.op = FFEEXPR_operatorOR_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceOR_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityOR_;
|
||
break;
|
||
|
||
case FFESTR_otherXOR:
|
||
e->u.operator.op = FFEEXPR_operatorXOR_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceXOR_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityXOR_;
|
||
break;
|
||
|
||
case FFESTR_otherEQV:
|
||
e->u.operator.op = FFEEXPR_operatorEQV_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceEQV_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityEQV_;
|
||
break;
|
||
|
||
case FFESTR_otherNEQV:
|
||
e->u.operator.op = FFEEXPR_operatorNEQV_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceNEQV_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityNEQV_;
|
||
break;
|
||
|
||
case FFESTR_otherLT:
|
||
e->u.operator.op = FFEEXPR_operatorLT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceLT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityLT_;
|
||
break;
|
||
|
||
case FFESTR_otherLE:
|
||
e->u.operator.op = FFEEXPR_operatorLE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceLE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityLE_;
|
||
break;
|
||
|
||
case FFESTR_otherEQ:
|
||
e->u.operator.op = FFEEXPR_operatorEQ_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
|
||
break;
|
||
|
||
case FFESTR_otherNE:
|
||
e->u.operator.op = FFEEXPR_operatorNE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceNE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityNE_;
|
||
break;
|
||
|
||
case FFESTR_otherGT:
|
||
e->u.operator.op = FFEEXPR_operatorGT_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceGT_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityGT_;
|
||
break;
|
||
|
||
case FFESTR_otherGE:
|
||
e->u.operator.op = FFEEXPR_operatorGE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceGE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityGE_;
|
||
break;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_DOTDOT))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
|
||
ffebad_finish ();
|
||
}
|
||
e->u.operator.op = FFEEXPR_operatorEQ_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityEQ_;
|
||
break;
|
||
}
|
||
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_INSERTING_PERIOD))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */
|
||
return (ffelexHandler) ffeexpr_token_rhs_;
|
||
}
|
||
|
||
/* ffeexpr_token_binary_sw_per_ -- Rhs PERIOD NAME(NOT, TRUE, or FALSE)
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
A diagnostic has already been issued; just swallow a period if there is
|
||
one, then continue with ffeexpr_token_binary_. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_binary_sw_per_ (ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) != FFELEX_typePERIOD)
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_quote_ -- Rhs QUOTE
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Expecting a NUMBER that we'll treat as an octal integer. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_quote_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffebld anyexpr;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typeNUMBER)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_QUOTE_MISSES_DIGITS))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
|
||
/* This is kind of a kludge to prevent any whining about magical numbers
|
||
that start out as these octal integers, so "20000000000 (on a 32-bit
|
||
2's-complement machine) by itself won't produce an error. */
|
||
|
||
anyexpr = ffebld_new_any ();
|
||
ffebld_set_info (anyexpr, ffeinfo_new_any ());
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
e->u.operand = ffebld_new_conter_with_orig
|
||
(ffebld_constant_new_integeroctal (t), anyexpr);
|
||
ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0, FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
/* ffeexpr_token_apostrophe_ -- Rhs APOSTROPHE
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle an open-apostrophe, which begins either a character ('char-const'),
|
||
typeless octal ('octal-const'O), or typeless hexadecimal ('hex-const'Z or
|
||
'hex-const'X) constant. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_apostrophe_ (ffelexToken t)
|
||
{
|
||
assert (ffelex_token_type (t) == FFELEX_typeCHARACTER);
|
||
if (ffe_is_pedantic_not_90 () && (ffelex_token_length (t) == 0))
|
||
{
|
||
ffebad_start (FFEBAD_NULL_CHAR_CONST);
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_apos_char_;
|
||
}
|
||
|
||
/* ffeexpr_token_apos_char_ -- Rhs APOSTROPHE CHARACTER
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Close-apostrophe is implicit; if this token is NAME, it is a possible
|
||
typeless-constant radix specifier. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_apos_char_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffeinfo ni;
|
||
char c;
|
||
ffetargetCharacterSize size;
|
||
|
||
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
{
|
||
if ((ffelex_token_length (t) == 1)
|
||
&& (ffesrc_char_match_init ((c = ffelex_token_text (t)[0]), 'B',
|
||
'b')
|
||
|| ffesrc_char_match_init (c, 'O', 'o')
|
||
|| ffesrc_char_match_init (c, 'X', 'x')
|
||
|| ffesrc_char_match_init (c, 'Z', 'z')))
|
||
{
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
switch (c)
|
||
{
|
||
case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match):
|
||
e->u.operand = ffebld_new_conter
|
||
(ffebld_constant_new_typeless_bv (ffeexpr_tokens_[1]));
|
||
size = ffetarget_size_typeless_binary (ffeexpr_tokens_[1]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match):
|
||
e->u.operand = ffebld_new_conter
|
||
(ffebld_constant_new_typeless_ov (ffeexpr_tokens_[1]));
|
||
size = ffetarget_size_typeless_octal (ffeexpr_tokens_[1]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match):
|
||
e->u.operand = ffebld_new_conter
|
||
(ffebld_constant_new_typeless_hxv (ffeexpr_tokens_[1]));
|
||
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match):
|
||
e->u.operand = ffebld_new_conter
|
||
(ffebld_constant_new_typeless_hzv (ffeexpr_tokens_[1]));
|
||
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]);
|
||
break;
|
||
|
||
default:
|
||
no_match: /* :::::::::::::::::::: */
|
||
assert ("not BOXZ!" == NULL);
|
||
size = 0;
|
||
break;
|
||
}
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_characterdefault
|
||
(ffeexpr_tokens_[1]));
|
||
ni = ffeinfo_new (FFEINFO_basictypeCHARACTER, FFEINFO_kindtypeCHARACTERDEFAULT,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
ffelex_token_length (ffeexpr_tokens_[1]));
|
||
ffebld_set_info (e->u.operand, ni);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
if ((ffelex_token_type (t) == FFELEX_typeNAME)
|
||
|| (ffelex_token_type (t) == FFELEX_typeNAMES))
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
|
||
{
|
||
ffebad_string (ffelex_token_text (t));
|
||
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_finish ();
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeBINARY_;
|
||
e->token = ffelex_token_use (t);
|
||
e->u.operator.op = FFEEXPR_operatorCONCATENATE_;
|
||
e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_;
|
||
e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_;
|
||
ffeexpr_exprstack_push_binary_ (e);
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
ffeexpr_is_substr_ok_ = !ffe_is_pedantic_not_90 (); /* Allow "'hello'(3:5)". */
|
||
return (ffelexHandler) ffeexpr_token_substrp_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_name_lhs_ -- Lhs NAME
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle a name followed by open-paren, period (RECORD.MEMBER), percent
|
||
(RECORD%MEMBER), or nothing at all. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_name_lhs_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffeexprParenType_ paren_type;
|
||
ffesymbol s;
|
||
ffebld expr;
|
||
ffeinfo info;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeOPEN_PAREN:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
goto just_name; /* :::::::::::::::::::: */
|
||
|
||
default:
|
||
break;
|
||
}
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffelex_token_use (ffeexpr_tokens_[0]);
|
||
s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], FALSE,
|
||
&paren_type);
|
||
|
||
switch (ffesymbol_where (s))
|
||
{
|
||
case FFEINFO_whereLOCAL:
|
||
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recursion. */
|
||
break;
|
||
|
||
case FFEINFO_whereINTRINSIC:
|
||
case FFEINFO_whereGLOBAL:
|
||
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */
|
||
break;
|
||
|
||
case FFEINFO_whereCOMMON:
|
||
case FFEINFO_whereDUMMY:
|
||
case FFEINFO_whereRESULT:
|
||
break;
|
||
|
||
case FFEINFO_whereNONE:
|
||
case FFEINFO_whereANY:
|
||
break;
|
||
|
||
default:
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]);
|
||
break;
|
||
}
|
||
|
||
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
|
||
{
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
e->u.operand = ffebld_new_symter (s,
|
||
ffesymbol_generic (s),
|
||
ffesymbol_specific (s),
|
||
ffesymbol_implementation (s));
|
||
ffebld_set_info (e->u.operand, ffesymbol_info (s));
|
||
}
|
||
ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */
|
||
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
|
||
switch (paren_type)
|
||
{
|
||
case FFEEXPR_parentypeSUBROUTINE_:
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextACTUALARG_,
|
||
ffeexpr_token_arguments_);
|
||
|
||
case FFEEXPR_parentypeARRAY_:
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
|
||
ffeexpr_stack_->rank = 0;
|
||
ffeexpr_stack_->constant = TRUE;
|
||
ffeexpr_stack_->immediate = TRUE;
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextDATAIMPDOINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextEQVINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
default:
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextINDEX_,
|
||
ffeexpr_token_elements_);
|
||
}
|
||
|
||
case FFEEXPR_parentypeSUBSTRING_:
|
||
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
|
||
ffeexpr_tokens_[0]);
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextINDEX_,
|
||
ffeexpr_token_substring_);
|
||
|
||
case FFEEXPR_parentypeEQUIVALENCE_:
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
|
||
ffeexpr_stack_->rank = 0;
|
||
ffeexpr_stack_->constant = TRUE;
|
||
ffeexpr_stack_->immediate = TRUE;
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextEQVINDEX_,
|
||
ffeexpr_token_equivalence_);
|
||
|
||
case FFEEXPR_parentypeFUNCTION_: /* Invalid case. */
|
||
case FFEEXPR_parentypeFUNSUBSTR_: /* Invalid case. */
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]);
|
||
/* Fall through. */
|
||
case FFEEXPR_parentypeANY_:
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextACTUALARG_,
|
||
ffeexpr_token_anything_);
|
||
|
||
default:
|
||
assert ("bad paren type" == NULL);
|
||
break;
|
||
}
|
||
|
||
case FFELEX_typeEQUALS: /* As in "VAR=". */
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextIMPDOITEM_: /* within
|
||
"(,VAR=start,end[,incr])". */
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextDATAIMPDOCTRL_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
#if 0
|
||
case FFELEX_typePERIOD:
|
||
case FFELEX_typePERCENT:
|
||
assert ("FOO%, FOO. not yet supported!~~" == NULL);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
just_name: /* :::::::::::::::::::: */
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0],
|
||
(ffeexpr_stack_->context
|
||
== FFEEXPR_contextSUBROUTINEREF));
|
||
|
||
switch (ffesymbol_where (s))
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
if ((ffeexpr_stack_->context != FFEEXPR_contextPARAMETER)
|
||
|| (ffesymbol_kind (s) != FFEINFO_kindENTITY))
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]);
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
if ((ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOCTRL_)
|
||
&& (ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOINDEX_))
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]);
|
||
break;
|
||
|
||
case FFEINFO_whereLOCAL:
|
||
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recurse!. */
|
||
break;
|
||
|
||
case FFEINFO_whereINTRINSIC:
|
||
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
|
||
ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
|
||
{
|
||
expr = ffebld_new_any ();
|
||
info = ffeinfo_new_any ();
|
||
ffebld_set_info (expr, info);
|
||
}
|
||
else
|
||
{
|
||
expr = ffebld_new_symter (s,
|
||
ffesymbol_generic (s),
|
||
ffesymbol_specific (s),
|
||
ffesymbol_implementation (s));
|
||
info = ffesymbol_info (s);
|
||
ffebld_set_info (expr, info);
|
||
if (ffesymbol_is_doiter (s))
|
||
{
|
||
ffebad_start (FFEBAD_DOITER);
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffest_ffebad_here_doiter (1, s);
|
||
ffebad_string (ffesymbol_text (s));
|
||
ffebad_finish ();
|
||
}
|
||
expr = ffeexpr_collapse_symter (expr, ffeexpr_tokens_[0]);
|
||
}
|
||
|
||
if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF)
|
||
{
|
||
if (ffebld_op (expr) == FFEBLD_opANY)
|
||
{
|
||
expr = ffebld_new_any ();
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
expr = ffebld_new_subrref (expr, NULL); /* No argument list. */
|
||
if (ffesymbol_generic (s) != FFEINTRIN_genNONE)
|
||
ffeintrin_fulfill_generic (&expr, &info, e->token);
|
||
else if (ffesymbol_specific (s) != FFEINTRIN_specNONE)
|
||
ffeintrin_fulfill_specific (&expr, &info, NULL, e->token);
|
||
else
|
||
ffeexpr_fulfill_call_ (&expr, e->token);
|
||
|
||
if (ffebld_op (expr) != FFEBLD_opANY)
|
||
ffebld_set_info (expr,
|
||
ffeinfo_new (ffeinfo_basictype (info),
|
||
ffeinfo_kindtype (info),
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereFLEETING,
|
||
ffeinfo_size (info)));
|
||
else
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
}
|
||
|
||
e->u.operand = expr;
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
return (ffelexHandler) ffeexpr_finished_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_name_arg_ -- Rhs NAME
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle first token in an actual-arg (or possible actual-arg) context
|
||
being a NAME, and use second token to refine the context. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_name_arg_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCLOSE_PAREN:
|
||
case FFELEX_typeCOMMA:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
ffeexpr_stack_->context
|
||
= FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_;
|
||
break;
|
||
|
||
default:
|
||
assert ("bad context in _name_arg_" == NULL);
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_token_name_rhs_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_name_rhs_ -- Rhs NAME
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle a name followed by open-paren, apostrophe (O'octal-const',
|
||
Z'hex-const', or X'hex-const'), period (RECORD.MEMBER).
|
||
|
||
26-Nov-91 JCB 1.2
|
||
When followed by apostrophe or quote, set lex hexnum flag on so
|
||
[0-9] as first char of next token seen as starting a potentially
|
||
hex number (NAME).
|
||
04-Oct-91 JCB 1.1
|
||
In case of intrinsic, decorate its SYMTER with the type info for
|
||
the specific intrinsic. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_name_rhs_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
ffeexprParenType_ paren_type;
|
||
ffesymbol s;
|
||
bool sfdef;
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeQUOTE:
|
||
case FFELEX_typeAPOSTROPHE:
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
ffelex_set_hexnum (TRUE);
|
||
return (ffelexHandler) ffeexpr_token_name_apos_;
|
||
|
||
case FFELEX_typeOPEN_PAREN:
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffelex_token_use (ffeexpr_tokens_[0]);
|
||
s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], TRUE,
|
||
&paren_type);
|
||
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
|
||
e->u.operand = ffebld_new_any ();
|
||
else
|
||
e->u.operand = ffebld_new_symter (s, ffesymbol_generic (s),
|
||
ffesymbol_specific (s),
|
||
ffesymbol_implementation (s));
|
||
ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */
|
||
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
sfdef = TRUE;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
assert ("weird context!" == NULL);
|
||
sfdef = FALSE;
|
||
break;
|
||
|
||
default:
|
||
sfdef = FALSE;
|
||
break;
|
||
}
|
||
switch (paren_type)
|
||
{
|
||
case FFEEXPR_parentypeFUNCTION_:
|
||
ffebld_set_info (e->u.operand, ffesymbol_info (s));
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
|
||
{ /* A statement function. */
|
||
ffeexpr_stack_->num_args
|
||
= ffebld_list_length
|
||
(ffeexpr_stack_->next_dummy
|
||
= ffesymbol_dummyargs (s));
|
||
ffeexpr_stack_->tokens[1] = NULL; /* !=NULL when > num_args. */
|
||
}
|
||
else if ((ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
|
||
&& !ffe_is_pedantic_not_90 ()
|
||
&& ((ffesymbol_implementation (s)
|
||
== FFEINTRIN_impICHAR)
|
||
|| (ffesymbol_implementation (s)
|
||
== FFEINTRIN_impIACHAR)
|
||
|| (ffesymbol_implementation (s)
|
||
== FFEINTRIN_impLEN)))
|
||
{ /* Allow arbitrary concatenations. */
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEF
|
||
: FFEEXPR_contextLET,
|
||
ffeexpr_token_arguments_);
|
||
}
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEFACTUALARG_
|
||
: FFEEXPR_contextACTUALARG_,
|
||
ffeexpr_token_arguments_);
|
||
|
||
case FFEEXPR_parentypeARRAY_:
|
||
ffebld_set_info (e->u.operand,
|
||
ffesymbol_info (ffebld_symter (e->u.operand)));
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
ffeexpr_stack_->bound_list = ffesymbol_dims (s);
|
||
ffeexpr_stack_->rank = 0;
|
||
ffeexpr_stack_->constant = TRUE;
|
||
ffeexpr_stack_->immediate = TRUE;
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEFINDEX_
|
||
: FFEEXPR_contextINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
case FFEEXPR_parentypeSUBSTRING_:
|
||
ffebld_set_info (e->u.operand,
|
||
ffesymbol_info (ffebld_symter (e->u.operand)));
|
||
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
|
||
ffeexpr_tokens_[0]);
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEFINDEX_
|
||
: FFEEXPR_contextINDEX_,
|
||
ffeexpr_token_substring_);
|
||
|
||
case FFEEXPR_parentypeFUNSUBSTR_:
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_
|
||
: FFEEXPR_contextINDEXORACTUALARG_,
|
||
ffeexpr_token_funsubstr_);
|
||
|
||
case FFEEXPR_parentypeANY_:
|
||
ffebld_set_info (e->u.operand, ffesymbol_info (s));
|
||
return
|
||
(ffelexHandler)
|
||
ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
sfdef
|
||
? FFEEXPR_contextSFUNCDEFACTUALARG_
|
||
: FFEEXPR_contextACTUALARG_,
|
||
ffeexpr_token_anything_);
|
||
|
||
default:
|
||
assert ("bad paren type" == NULL);
|
||
break;
|
||
}
|
||
|
||
case FFELEX_typeEQUALS: /* As in "VAR=". */
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextIMPDOITEM_: /* "(,VAR=start,end[,incr])". */
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
ffeexpr_stack_->is_rhs = FALSE; /* Really an lhs construct. */
|
||
ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
#if 0
|
||
case FFELEX_typePERIOD:
|
||
case FFELEX_typePERCENT:
|
||
~~Support these two someday, though not required
|
||
assert ("FOO%, FOO. not yet supported!~~" == NULL);
|
||
break;
|
||
#endif
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
assert ("strange context" == NULL);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0], FALSE);
|
||
if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY)
|
||
{
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
e->u.operand = ffebld_new_symter (s, FFEINTRIN_genNONE,
|
||
ffesymbol_specific (s),
|
||
ffesymbol_implementation (s));
|
||
if (ffesymbol_specific (s) == FFEINTRIN_specNONE)
|
||
ffebld_set_info (e->u.operand, ffeinfo_use (ffesymbol_info (s)));
|
||
else
|
||
{ /* Decorate the SYMTER with the actual type
|
||
of the intrinsic. */
|
||
ffebld_set_info (e->u.operand, ffeinfo_new
|
||
(ffeintrin_basictype (ffesymbol_specific (s)),
|
||
ffeintrin_kindtype (ffesymbol_specific (s)),
|
||
0,
|
||
ffesymbol_kind (s),
|
||
ffesymbol_where (s),
|
||
FFETARGET_charactersizeNONE));
|
||
}
|
||
if (ffesymbol_is_doiter (s))
|
||
ffebld_symter_set_is_doiter (e->u.operand, TRUE);
|
||
e->u.operand = ffeexpr_collapse_symter (e->u.operand,
|
||
ffeexpr_tokens_[0]);
|
||
}
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_name_apos_ -- Rhs NAME APOSTROPHE
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Expecting a NAME token, analyze the previous NAME token to see what kind,
|
||
if any, typeless constant we've got.
|
||
|
||
01-Sep-90 JCB 1.1
|
||
Expect a NAME instead of CHARACTER in this situation. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_name_apos_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
ffelex_set_hexnum (FALSE);
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
ffeexpr_tokens_[2] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_name_apos_name_;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
|
||
{
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[0]));
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
e->token = ffeexpr_tokens_[0];
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
|
||
/* ffeexpr_token_name_apos_name_ -- Rhs NAME APOSTROPHE NAME
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Expecting an APOSTROPHE token, analyze the previous NAME token to see
|
||
what kind, if any, typeless constant we've got. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_name_apos_name_ (ffelexToken t)
|
||
{
|
||
ffeexprExpr_ e;
|
||
char c;
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->token = ffeexpr_tokens_[0];
|
||
|
||
if ((ffelex_token_type (t) == ffelex_token_type (ffeexpr_tokens_[1]))
|
||
&& (ffelex_token_length (ffeexpr_tokens_[0]) == 1)
|
||
&& (ffesrc_char_match_init ((c = ffelex_token_text (ffeexpr_tokens_[0])[0]),
|
||
'B', 'b')
|
||
|| ffesrc_char_match_init (c, 'O', 'o')
|
||
|| ffesrc_char_match_init (c, 'X', 'x')
|
||
|| ffesrc_char_match_init (c, 'Z', 'z')))
|
||
{
|
||
ffetargetCharacterSize size;
|
||
|
||
if (!ffe_is_typeless_boz ()) {
|
||
|
||
switch (c)
|
||
{
|
||
case FFESRC_CASE_MATCH_INIT ('B', 'b', imatch_b, no_imatch):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerbinary
|
||
(ffeexpr_tokens_[2]));
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('O', 'o', imatch_o, no_imatch):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integeroctal
|
||
(ffeexpr_tokens_[2]));
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('X', 'x', imatch_x, no_imatch):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex
|
||
(ffeexpr_tokens_[2]));
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('Z', 'z', imatch_z, no_imatch):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex
|
||
(ffeexpr_tokens_[2]));
|
||
break;
|
||
|
||
default:
|
||
no_imatch: /* :::::::::::::::::::: */
|
||
assert ("not BOXZ!" == NULL);
|
||
abort ();
|
||
}
|
||
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
switch (c)
|
||
{
|
||
case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_bm
|
||
(ffeexpr_tokens_[2]));
|
||
size = ffetarget_size_typeless_binary (ffeexpr_tokens_[2]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_om
|
||
(ffeexpr_tokens_[2]));
|
||
size = ffetarget_size_typeless_octal (ffeexpr_tokens_[2]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hxm
|
||
(ffeexpr_tokens_[2]));
|
||
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm
|
||
(ffeexpr_tokens_[2]));
|
||
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
|
||
break;
|
||
|
||
default:
|
||
no_match: /* :::::::::::::::::::: */
|
||
assert ("not BOXZ!" == NULL);
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm
|
||
(ffeexpr_tokens_[2]));
|
||
size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]);
|
||
break;
|
||
}
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size));
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
}
|
||
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER))
|
||
{
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[0]));
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[2]);
|
||
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
e->u.operand = ffebld_new_any ();
|
||
ffebld_set_info (e->u.operand, ffeinfo_new_any ());
|
||
e->token = ffeexpr_tokens_[0];
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeAPOSTROPHE:
|
||
case FFELEX_typeQUOTE:
|
||
return (ffelexHandler) ffeexpr_token_binary_;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_token_binary_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_percent_ -- Rhs PERCENT
|
||
|
||
Handle a percent sign possibly followed by "LOC". If followed instead
|
||
by "VAL", "REF", or "DESCR", issue an error message and substitute
|
||
"LOC". If followed by something else, treat the percent sign as a
|
||
spurious incorrect token and reprocess the token via _rhs_. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_percent_ (ffelexToken t)
|
||
{
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
ffeexpr_stack_->percent = ffeexpr_percent_ (t);
|
||
ffeexpr_tokens_[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_token_percent_name_;
|
||
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
return (ffelexHandler) ffeexpr_token_rhs_ (t);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_token_percent_name_ -- Rhs PERCENT NAME
|
||
|
||
Make sure the token is OPEN_PAREN and prepare for the one-item list of
|
||
LHS expressions. Else display an error message. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_percent_name_ (ffelexToken t)
|
||
{
|
||
ffelexHandler nexthandler;
|
||
|
||
if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN)
|
||
{
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token),
|
||
ffelex_token_where_column (ffeexpr_stack_->first_token));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_tokens_[0]);
|
||
nexthandler = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_tokens_[1]);
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
return (ffelexHandler) (*nexthandler) (t);
|
||
}
|
||
|
||
switch (ffeexpr_stack_->percent)
|
||
{
|
||
default:
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_PERCENT))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]),
|
||
ffelex_token_where_column (ffeexpr_tokens_[0]));
|
||
ffebad_string (ffelex_token_text (ffeexpr_tokens_[1]));
|
||
ffebad_finish ();
|
||
}
|
||
ffeexpr_stack_->percent = FFEEXPR_percentLOC_;
|
||
/* Fall through. */
|
||
case FFEEXPR_percentLOC_:
|
||
ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0];
|
||
ffelex_token_kill (ffeexpr_tokens_[1]);
|
||
ffeexpr_stack_->tokens[1] = ffelex_token_use (t);
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextLOC_,
|
||
ffeexpr_cb_end_loc_);
|
||
}
|
||
}
|
||
|
||
/* ffeexpr_make_float_const_ -- Make a floating-point constant
|
||
|
||
See prototype.
|
||
|
||
Pass 'E', 'D', or 'Q' for exponent letter. */
|
||
|
||
static void
|
||
ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer,
|
||
ffelexToken decimal, ffelexToken fraction,
|
||
ffelexToken exponent, ffelexToken exponent_sign,
|
||
ffelexToken exponent_digits)
|
||
{
|
||
ffeexprExpr_ e;
|
||
|
||
e = ffeexpr_expr_new_ ();
|
||
e->type = FFEEXPR_exprtypeOPERAND_;
|
||
if (integer != NULL)
|
||
e->token = ffelex_token_use (integer);
|
||
else
|
||
{
|
||
assert (decimal != NULL);
|
||
e->token = ffelex_token_use (decimal);
|
||
}
|
||
|
||
switch (exp_letter)
|
||
{
|
||
#if !FFETARGET_okREALQUAD
|
||
case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match):
|
||
if (ffebad_start (FFEBAD_QUAD_UNSUPPORTED))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (e->token),
|
||
ffelex_token_where_column (e->token));
|
||
ffebad_finish ();
|
||
}
|
||
goto match_d; /* The FFESRC_CASE_* macros don't
|
||
allow fall-through! */
|
||
#endif
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('D', 'd', match_d, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_realdouble
|
||
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
break;
|
||
|
||
case FFESRC_CASE_MATCH_INIT ('E', 'e', match_e, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_realdefault
|
||
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
|
||
ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeREAL,
|
||
FFEINFO_kindtypeREALDEFAULT, 0, FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
break;
|
||
|
||
#if FFETARGET_okREALQUAD
|
||
case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match):
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_realquad
|
||
(integer, decimal, fraction, exponent, exponent_sign, exponent_digits));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALQUAD,
|
||
0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE));
|
||
break;
|
||
#endif
|
||
|
||
case 'I': /* Make an integer. */
|
||
e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault
|
||
(ffeexpr_tokens_[0]));
|
||
ffebld_set_info (e->u.operand,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFEINFO_kindENTITY, FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
break;
|
||
|
||
default:
|
||
no_match: /* :::::::::::::::::::: */
|
||
assert ("Lost the exponent letter!" == NULL);
|
||
}
|
||
|
||
ffeexpr_exprstack_push_operand_ (e);
|
||
}
|
||
|
||
/* Just like ffesymbol_declare_local, except performs any implicit info
|
||
assignment necessary. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin)
|
||
{
|
||
ffesymbol s;
|
||
ffeinfoKind k;
|
||
bool bad;
|
||
|
||
s = ffesymbol_declare_local (t, maybe_intrin);
|
||
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
/* Special-case these since they can involve a different concept
|
||
of "state" (in the stmtfunc name space). */
|
||
{
|
||
case FFEEXPR_contextDATAIMPDOINDEX_:
|
||
case FFEEXPR_contextDATAIMPDOCTRL_:
|
||
if (ffeexpr_context_outer_ (ffeexpr_stack_)
|
||
== FFEEXPR_contextDATAIMPDOINDEX_)
|
||
s = ffeexpr_sym_impdoitem_ (s, t);
|
||
else
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_sym_impdoitem_ (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_impdoctrl_ (s, t);
|
||
bad = (ffesymbol_kind (s) != FFEINFO_kindENTITY)
|
||
|| ((ffesymbol_where (s) != FFEINFO_whereCONSTANT)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereIMMEDIATE));
|
||
if (bad && (ffesymbol_kind (s) != FFEINFO_kindANY))
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
switch ((ffesymbol_sfdummyparent (s) == NULL)
|
||
? ffesymbol_state (s)
|
||
: FFESYMBOL_stateUNDERSTOOD)
|
||
{
|
||
case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr
|
||
context. */
|
||
if (!ffest_seen_first_exec ())
|
||
goto seen; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSUBROUTINEREF:
|
||
s = ffeexpr_sym_lhs_call_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEEXTFUNC:
|
||
s = ffeexpr_sym_lhs_extfunc_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFEEXPR_contextACTUALARG_:
|
||
s = ffeexpr_sym_rhs_actualarg_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_sym_rhs_let_ (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextDO:
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextIF:
|
||
case FFEEXPR_contextARITHIF:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextSTOP:
|
||
case FFEEXPR_contextRETURN:
|
||
case FFEEXPR_contextSELECTCASE:
|
||
case FFEEXPR_contextCASE:
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
case FFEEXPR_contextFILEDFINT:
|
||
case FFEEXPR_contextFILELOG:
|
||
case FFEEXPR_contextFILENUM:
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
case FFEEXPR_contextFILECHAR:
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
case FFEEXPR_contextFILEKEY:
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
case FFEEXPR_contextLOC_:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_sym_rhs_let_ (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_let_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
case FFEEXPR_contextINCLUDE:
|
||
case FFEEXPR_contextPARAMETER:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
break; /* Will turn into errors below. */
|
||
|
||
default:
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */
|
||
understood: /* :::::::::::::::::::: */
|
||
k = ffesymbol_kind (s);
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSUBROUTINEREF:
|
||
bad = ((k != FFEINFO_kindSUBROUTINE)
|
||
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|
||
|| (k != FFEINFO_kindNONE)));
|
||
break;
|
||
|
||
case FFEEXPR_contextFILEEXTFUNC:
|
||
bad = (k != FFEINFO_kindFUNCTION)
|
||
|| (ffesymbol_where (s) != FFEINFO_whereGLOBAL);
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextACTUALARG_:
|
||
switch (k)
|
||
{
|
||
case FFEINFO_kindENTITY:
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEINFO_kindFUNCTION:
|
||
case FFEINFO_kindSUBROUTINE:
|
||
bad
|
||
= ((ffesymbol_where (s) != FFEINFO_whereGLOBAL)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereDUMMY)
|
||
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|
||
|| !ffeintrin_is_actualarg (ffesymbol_specific (s))));
|
||
break;
|
||
|
||
case FFEINFO_kindNONE:
|
||
if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
|
||
{
|
||
bad = !(ffeintrin_is_actualarg (ffesymbol_specific (s)));
|
||
break;
|
||
}
|
||
|
||
/* If state is UNDERSTOOD here, it's CHAR*(*) or attrsANY,
|
||
and in the former case, attrsTYPE is set, so we
|
||
see this as an error as we should, since CHAR*(*)
|
||
cannot be actually referenced in a main/block data
|
||
program unit. */
|
||
|
||
if ((ffesymbol_attrs (s) & (FFESYMBOL_attrsANY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE))
|
||
== FFESYMBOL_attrsEXTERNAL)
|
||
bad = FALSE;
|
||
else
|
||
bad = TRUE;
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
|
||
else
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
bad = TRUE; /* Unadorned item never valid. */
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextDO:
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextIF:
|
||
case FFEEXPR_contextARITHIF:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextSTOP:
|
||
case FFEEXPR_contextRETURN:
|
||
case FFEEXPR_contextSELECTCASE:
|
||
case FFEEXPR_contextCASE:
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
case FFEEXPR_contextFILEDFINT:
|
||
case FFEEXPR_contextFILELOG:
|
||
case FFEEXPR_contextFILENUM:
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
case FFEEXPR_contextFILECHAR:
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
case FFEEXPR_contextFILEKEY:
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
case FFEEXPR_contextLOC_:
|
||
bad = (k != FFEINFO_kindENTITY); /* This catches "SUBROUTINE
|
||
X(A);EXTERNAL A;CALL
|
||
Y(A);B=A", for example. */
|
||
break;
|
||
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
case FFEEXPR_contextPARAMETER:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
|
||
break;
|
||
|
||
case FFEEXPR_contextINCLUDE:
|
||
bad = TRUE;
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
if (bad && (k != FFEINFO_kindANY))
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
|
||
case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */
|
||
seen: /* :::::::::::::::::::: */
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextPARAMETER:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
ffesymbol_error (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_parameter_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
if (ffeexpr_stack_->is_rhs)
|
||
ffesymbol_error (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
s = ffeexpr_sym_lhs_equivalence_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDIMLIST:
|
||
s = ffeexpr_sym_rhs_dimlist_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextINCLUDE:
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextACTUALARG_: /* E.g. I in REAL A(Y(I)). */
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
s = ffeexpr_sym_rhs_actualarg_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
assert (ffeexpr_stack_->is_rhs);
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
s = ffeexpr_sym_rhs_let_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
default:
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
}
|
||
return s;
|
||
|
||
default:
|
||
assert ("bad symbol state" == NULL);
|
||
return NULL;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Have FOO in DATA (XYZ(FOO),...)/.../ or DATA (...,XYZ=FOO,BAR,BLETCH).
|
||
Could be found via the "statement-function" name space (in which case
|
||
it should become an iterator) or the local name space (in which case
|
||
it should be either a named constant, or a variable that will have an
|
||
sfunc name space sibling that should become an iterator). */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_impdoitem_ (ffesymbol sp, ffelexToken t)
|
||
{
|
||
ffesymbol s;
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffesymbolState ss;
|
||
ffesymbolState ns;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
|
||
ss = ffesymbol_state (sp);
|
||
|
||
if (ffesymbol_sfdummyparent (sp) != NULL)
|
||
{ /* Have symbol in sfunc name space. */
|
||
switch (ss)
|
||
{
|
||
case FFESYMBOL_stateNONE: /* Used as iterator already. */
|
||
if (ffeexpr_level_ < ffesymbol_maxentrynum (sp))
|
||
ffesymbol_error (sp, t); /* Can't use dead iterator. */
|
||
else
|
||
{ /* Can use dead iterator because we're at at
|
||
least an innermore (higher-numbered) level
|
||
than the iterator's outermost
|
||
(lowest-numbered) level. */
|
||
ffesymbol_signal_change (sp);
|
||
ffesymbol_set_state (sp, FFESYMBOL_stateSEEN);
|
||
ffesymbol_set_maxentrynum (sp, ffeexpr_level_);
|
||
ffesymbol_signal_unreported (sp);
|
||
}
|
||
break;
|
||
|
||
case FFESYMBOL_stateSEEN: /* Seen already in this or other
|
||
implied-DO. Set symbol level
|
||
number to outermost value, as that
|
||
tells us we can see it as iterator
|
||
at that level at the innermost. */
|
||
if (ffeexpr_level_ < ffesymbol_maxentrynum (sp))
|
||
{
|
||
ffesymbol_signal_change (sp);
|
||
ffesymbol_set_maxentrynum (sp, ffeexpr_level_);
|
||
ffesymbol_signal_unreported (sp);
|
||
}
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNCERTAIN: /* Iterator. */
|
||
assert (ffeexpr_level_ == ffesymbol_maxentrynum (sp));
|
||
ffesymbol_error (sp, t); /* (,,,I=I,10). */
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNDERSTOOD:
|
||
break; /* ANY. */
|
||
|
||
default:
|
||
assert ("Foo Bar!!" == NULL);
|
||
break;
|
||
}
|
||
|
||
return sp;
|
||
}
|
||
|
||
/* Got symbol in local name space, so we haven't seen it in impdo yet.
|
||
First, if it is brand-new and we're in executable statements, set the
|
||
attributes and exec-transition it to set state UNCERTAIN or UNDERSTOOD.
|
||
Second, if it is now a constant (PARAMETER), then just return it, it
|
||
can't be an implied-do iterator. If it is understood, complain if it is
|
||
not a valid variable, but make the inner name space iterator anyway and
|
||
return that. If it is not understood, improve understanding of the
|
||
symbol accordingly, complain accordingly, in either case make the inner
|
||
name space iterator and return that. */
|
||
|
||
sa = ffesymbol_attrs (sp);
|
||
|
||
if (ffesymbol_state_is_specable (ss)
|
||
&& ffest_seen_first_exec ())
|
||
{
|
||
assert (sa == FFESYMBOL_attrsetNONE);
|
||
ffesymbol_signal_change (sp);
|
||
ffesymbol_set_state (sp, FFESYMBOL_stateSEEN);
|
||
ffesymbol_resolve_intrin (sp);
|
||
if (ffeimplic_establish_symbol (sp))
|
||
ffesymbol_set_attr (sp, FFESYMBOL_attrSFARG);
|
||
else
|
||
ffesymbol_error (sp, t);
|
||
|
||
/* After the exec transition, the state will either be UNCERTAIN (could
|
||
be a dummy or local var) or UNDERSTOOD (local var, because this is a
|
||
PROGRAM/BLOCKDATA program unit). */
|
||
|
||
sp = ffecom_sym_exec_transition (sp);
|
||
sa = ffesymbol_attrs (sp);
|
||
ss = ffesymbol_state (sp);
|
||
}
|
||
|
||
ns = ss;
|
||
kind = ffesymbol_kind (sp);
|
||
where = ffesymbol_where (sp);
|
||
|
||
if (ss == FFESYMBOL_stateUNDERSTOOD)
|
||
{
|
||
if (kind != FFEINFO_kindENTITY)
|
||
ffesymbol_error (sp, t);
|
||
if (where == FFEINFO_whereCONSTANT)
|
||
return sp;
|
||
}
|
||
else
|
||
{
|
||
/* Enhance understanding of local symbol. This used to imply exec
|
||
transition, but that doesn't seem necessary, since the local symbol
|
||
doesn't actually get put into an ffebld tree here -- we just learn
|
||
more about it, just like when we see a local symbol's name in the
|
||
dummy-arg list of a statement function. */
|
||
|
||
if (ss != FFESYMBOL_stateUNCERTAIN)
|
||
{
|
||
/* Figure out what kind of object we've got based on previous
|
||
declarations of or references to the object. */
|
||
|
||
ns = FFESYMBOL_stateSEEN;
|
||
|
||
if (sa & FFESYMBOL_attrsANY)
|
||
na = sa;
|
||
else if (!(sa & ~(FFESYMBOL_attrsADJUSTS
|
||
| FFESYMBOL_attrsANY
|
||
| FFESYMBOL_attrsCOMMON
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEQUIV
|
||
| FFESYMBOL_attrsINIT
|
||
| FFESYMBOL_attrsNAMELIST
|
||
| FFESYMBOL_attrsRESULT
|
||
| FFESYMBOL_attrsSAVE
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)))
|
||
na = sa | FFESYMBOL_attrsSFARG;
|
||
else
|
||
na = FFESYMBOL_attrsetNONE;
|
||
}
|
||
else
|
||
{ /* stateUNCERTAIN. */
|
||
na = sa | FFESYMBOL_attrsSFARG;
|
||
ns = FFESYMBOL_stateUNDERSTOOD;
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
na = FFESYMBOL_attrsetNONE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = FFEINFO_kindENTITY;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
na = FFESYMBOL_attrsetNONE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
ns = FFESYMBOL_stateUNCERTAIN;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
kind = FFEINFO_kindENTITY;
|
||
|
||
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
|
||
na = FFESYMBOL_attrsetNONE;
|
||
else if (ffest_is_entry_valid ())
|
||
ns = FFESYMBOL_stateUNCERTAIN; /* Could be DUMMY or LOCAL. */
|
||
else
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else
|
||
na = FFESYMBOL_attrsetNONE; /* Error. */
|
||
}
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error
|
||
cropped up; ANY means an old error to be ignored; otherwise,
|
||
everything's ok, update the object (symbol) and continue on. */
|
||
|
||
if (na == FFESYMBOL_attrsetNONE)
|
||
ffesymbol_error (sp, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (sp); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (sp))
|
||
ffesymbol_error (sp, t);
|
||
else
|
||
{
|
||
ffesymbol_set_info (sp,
|
||
ffeinfo_new (ffesymbol_basictype (sp),
|
||
ffesymbol_kindtype (sp),
|
||
ffesymbol_rank (sp),
|
||
kind,
|
||
where,
|
||
ffesymbol_size (sp)));
|
||
ffesymbol_set_attrs (sp, na);
|
||
ffesymbol_set_state (sp, ns);
|
||
ffesymbol_resolve_intrin (sp);
|
||
if (!ffesymbol_state_is_specable (ns))
|
||
sp = ffecom_sym_learned (sp);
|
||
ffesymbol_signal_unreported (sp); /* For debugging purposes. */
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Here we create the sfunc-name-space symbol representing what should
|
||
become an iterator in this name space at this or an outermore (lower-
|
||
numbered) expression level, else the implied-DO construct is in error. */
|
||
|
||
s = ffesymbol_declare_sfdummy (t); /* Sets maxentrynum to 0 for new obj;
|
||
also sets sfa_dummy_parent to
|
||
parent symbol. */
|
||
assert (sp == ffesymbol_sfdummyparent (s));
|
||
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
|
||
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereIMMEDIATE,
|
||
FFETARGET_charactersizeNONE));
|
||
ffesymbol_signal_unreported (s);
|
||
|
||
if ((ffesymbol_basictype (sp) != FFEINFO_basictypeINTEGER)
|
||
&& (ffesymbol_basictype (sp) != FFEINFO_basictypeANY))
|
||
ffesymbol_error (s, t);
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in CALL FOO. Local name space, executable context only. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
ffeintrinGen gen;
|
||
ffeintrinSpec spec;
|
||
ffeintrinImp imp;
|
||
bool error = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsTYPE)
|
||
error = TRUE;
|
||
else
|
||
/* Not TYPE. */
|
||
{
|
||
kind = FFEINFO_kindSUBROUTINE;
|
||
|
||
if (sa & FFESYMBOL_attrsDUMMY)
|
||
; /* Not TYPE. */
|
||
else if (sa & FFESYMBOL_attrsACTUALARG)
|
||
; /* Not DUMMY or TYPE. */
|
||
else /* Not ACTUALARG, DUMMY, or TYPE. */
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsTYPE)
|
||
error = TRUE;
|
||
else
|
||
kind = FFEINFO_kindSUBROUTINE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
|
||
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
|
||
&gen, &spec, &imp))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
ffesymbol_set_generic (s, gen);
|
||
ffesymbol_set_specific (s, spec);
|
||
ffesymbol_set_implementation (s, imp);
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (FFEINFO_basictypeNONE,
|
||
FFEINFO_kindtypeNONE,
|
||
0,
|
||
FFEINFO_kindSUBROUTINE,
|
||
FFEINFO_whereINTRINSIC,
|
||
FFETARGET_charactersizeNONE));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
|
||
return s;
|
||
}
|
||
|
||
kind = FFEINFO_kindSUBROUTINE;
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
else
|
||
error = TRUE;
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (error)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* SUBROUTINE. */
|
||
where, /* GLOBAL or DUMMY. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in DATA FOO/.../. Local name space and executable context
|
||
only. (This will change in the future when DATA FOO may be followed
|
||
by COMMON FOO or even INTEGER FOO(10), etc.) */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
bool error = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsADJUSTABLE)
|
||
error = TRUE;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
|
||
error = TRUE;
|
||
else
|
||
{
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else
|
||
error = TRUE;
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (error)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* ENTITY. */
|
||
where, /* LOCAL. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in EQUIVALENCE (...,FOO,...). Does not include
|
||
EQUIVALENCE (...,BAR(FOO),...). */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
kind = FFEINFO_kindENTITY;
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (!(sa & ~(FFESYMBOL_attrsADJUSTS
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsCOMMON
|
||
| FFESYMBOL_attrsEQUIV
|
||
| FFESYMBOL_attrsINIT
|
||
| FFESYMBOL_attrsNAMELIST
|
||
| FFESYMBOL_attrsSAVE
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)))
|
||
na = sa | FFESYMBOL_attrsEQUIV;
|
||
else
|
||
na = FFESYMBOL_attrsetNONE;
|
||
|
||
/* Don't know why we're bothering to set kind and where in this code, but
|
||
added the following to make it complete, in case it's really important.
|
||
Generally this is left up to symbol exec transition. */
|
||
|
||
if (where == FFEINFO_whereNONE)
|
||
{
|
||
if (na & (FFESYMBOL_attrsADJUSTS
|
||
| FFESYMBOL_attrsCOMMON))
|
||
where = FFEINFO_whereCOMMON;
|
||
else if (na & FFESYMBOL_attrsSAVE)
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (na == FFESYMBOL_attrsetNONE)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* Always ENTITY. */
|
||
where, /* NONE, COMMON, or LOCAL. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_attrs (s, na);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in OPEN(...,USEROPEN=FOO,...). Executable context only.
|
||
|
||
Note that I think this should be considered semantically similar to
|
||
doing CALL XYZ(FOO), in that it should be considered like an
|
||
ACTUALARG context. In particular, without EXTERNAL being specified,
|
||
it should not be allowed. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
bool needs_type = FALSE;
|
||
bool error = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsTYPE)
|
||
where = FFEINFO_whereGLOBAL;
|
||
else
|
||
/* Not TYPE. */
|
||
{
|
||
kind = FFEINFO_kindFUNCTION;
|
||
needs_type = TRUE;
|
||
|
||
if (sa & FFESYMBOL_attrsDUMMY)
|
||
; /* Not TYPE. */
|
||
else if (sa & FFESYMBOL_attrsACTUALARG)
|
||
; /* Not DUMMY or TYPE. */
|
||
else /* Not ACTUALARG, DUMMY, or TYPE. */
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = FFEINFO_kindFUNCTION;
|
||
if (!(sa & FFESYMBOL_attrsTYPE))
|
||
needs_type = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN))
|
||
error = TRUE;
|
||
else
|
||
{
|
||
kind = FFEINFO_kindFUNCTION;
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
kind = FFEINFO_kindFUNCTION;
|
||
where = FFEINFO_whereGLOBAL;
|
||
needs_type = TRUE;
|
||
}
|
||
else
|
||
error = TRUE;
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (error)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (needs_type && !ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
if (!ffesymbol_explicitwhere (s))
|
||
{
|
||
ffebad_start (FFEBAD_NEED_EXTERNAL);
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_string (ffesymbol_text (s));
|
||
ffebad_finish ();
|
||
ffesymbol_set_explicitwhere (s, TRUE);
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* FUNCTION. */
|
||
where, /* GLOBAL or DUMMY. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in DATA (stuff,FOO=1,10)/.../. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolState ss;
|
||
|
||
/* If the symbol isn't in the sfunc name space, pretend as though we saw a
|
||
reference to it already within the imp-DO construct at this level, so as
|
||
to get a symbol that is in the sfunc name space. But this is an
|
||
erroneous construct, and should be caught elsewhere. */
|
||
|
||
if (ffesymbol_sfdummyparent (s) == NULL)
|
||
{
|
||
s = ffeexpr_sym_impdoitem_ (s, t);
|
||
if (ffesymbol_sfdummyparent (s) == NULL)
|
||
{ /* PARAMETER FOO...DATA (A(I),FOO=...). */
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
}
|
||
|
||
ss = ffesymbol_state (s);
|
||
|
||
switch (ss)
|
||
{
|
||
case FFESYMBOL_stateNONE: /* Used as iterator already. */
|
||
if (ffeexpr_level_ < ffesymbol_maxentrynum (s))
|
||
ffesymbol_error (s, t); /* Can't reuse dead iterator. F90 disallows
|
||
this; F77 allows it but it is a stupid
|
||
feature. */
|
||
else
|
||
{ /* Can use dead iterator because we're at at
|
||
least a innermore (higher-numbered) level
|
||
than the iterator's outermost
|
||
(lowest-numbered) level. This should be
|
||
diagnosed later, because it means an item
|
||
in this list didn't reference this
|
||
iterator. */
|
||
#if 1
|
||
ffesymbol_error (s, t); /* For now, complain. */
|
||
#else /* Someday will detect all cases where initializer doesn't reference
|
||
all applicable iterators, in which case reenable this code. */
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN);
|
||
ffesymbol_set_maxentrynum (s, ffeexpr_level_);
|
||
ffesymbol_signal_unreported (s);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case FFESYMBOL_stateSEEN: /* Seen already in this or other implied-DO.
|
||
If seen in outermore level, can't be an
|
||
iterator here, so complain. If not seen
|
||
at current level, complain for now,
|
||
because that indicates something F90
|
||
rejects (though we currently don't detect
|
||
all such cases for now). */
|
||
if (ffeexpr_level_ <= ffesymbol_maxentrynum (s))
|
||
{
|
||
ffesymbol_signal_change (s);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN);
|
||
ffesymbol_signal_unreported (s);
|
||
}
|
||
else
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNCERTAIN: /* Already iterator! */
|
||
assert ("DATA implied-DO control var seen twice!!" == NULL);
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
|
||
case FFESYMBOL_stateUNDERSTOOD:
|
||
break; /* ANY. */
|
||
|
||
default:
|
||
assert ("Foo Bletch!!" == NULL);
|
||
break;
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in PARAMETER (FOO=...). */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
|
||
sa = ffesymbol_attrs (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & ~(FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsTYPE))
|
||
{
|
||
if (!(sa & FFESYMBOL_attrsANY))
|
||
ffesymbol_error (s, t);
|
||
}
|
||
else
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in CALL XYZ(...,FOO,...). Does not include any other
|
||
embedding of FOO, such as CALL XYZ((FOO)) or CALL XYZ(FOO+1). */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
ffesymbolState ns;
|
||
bool needs_type = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
ns = FFESYMBOL_stateUNDERSTOOD;
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsTYPE)
|
||
where = FFEINFO_whereGLOBAL;
|
||
else
|
||
/* Not TYPE. */
|
||
{
|
||
ns = FFESYMBOL_stateUNCERTAIN;
|
||
|
||
if (sa & FFESYMBOL_attrsDUMMY)
|
||
assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */
|
||
else if (sa & FFESYMBOL_attrsACTUALARG)
|
||
; /* Not DUMMY or TYPE. */
|
||
else
|
||
/* Not ACTUALARG, DUMMY, or TYPE. */
|
||
{
|
||
assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */
|
||
na |= FFESYMBOL_attrsACTUALARG;
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
}
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = FFEINFO_kindENTITY;
|
||
if (!(sa & FFESYMBOL_attrsTYPE))
|
||
needs_type = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
if (sa & FFESYMBOL_attrsANYLEN)
|
||
ns = FFESYMBOL_stateNONE;
|
||
else
|
||
{
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
/* New state is left empty because there isn't any state flag to
|
||
set for this case, and it's UNDERSTOOD after all. */
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
needs_type = TRUE;
|
||
}
|
||
else
|
||
ns = FFESYMBOL_stateNONE; /* Error. */
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (ns == FFESYMBOL_stateNONE)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (needs_type && !ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind,
|
||
where,
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_attrs (s, na);
|
||
ffesymbol_set_state (s, ns);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in DIMENSION XYZ(FOO) or any array declarator containing
|
||
a reference to FOO. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
kind = FFEINFO_kindENTITY;
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (!(sa & ~(FFESYMBOL_attrsADJUSTS
|
||
| FFESYMBOL_attrsCOMMON
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEQUIV
|
||
| FFESYMBOL_attrsINIT
|
||
| FFESYMBOL_attrsNAMELIST
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsTYPE)))
|
||
na = sa | FFESYMBOL_attrsADJUSTS;
|
||
else
|
||
na = FFESYMBOL_attrsetNONE;
|
||
|
||
/* Since this symbol definitely is going into an expression (the
|
||
dimension-list for some dummy array, presumably), figure out WHERE if
|
||
possible. */
|
||
|
||
if (where == FFEINFO_whereNONE)
|
||
{
|
||
if (na & (FFESYMBOL_attrsCOMMON
|
||
| FFESYMBOL_attrsEQUIV
|
||
| FFESYMBOL_attrsINIT
|
||
| FFESYMBOL_attrsNAMELIST))
|
||
where = FFEINFO_whereCOMMON;
|
||
else if (na & FFESYMBOL_attrsDUMMY)
|
||
where = FFEINFO_whereDUMMY;
|
||
}
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (na == FFESYMBOL_attrsetNONE)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* Always ENTITY. */
|
||
where, /* NONE, COMMON, or DUMMY. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_attrs (s, na);
|
||
ffesymbol_set_state (s, FFESYMBOL_stateSEEN);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* Have FOO in XYZ = ...FOO.... Does not include cases like FOO in
|
||
XYZ = BAR(FOO), as such cases are handled elsewhere. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
bool error = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
error = TRUE;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = FFEINFO_kindENTITY;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
if (sa & FFESYMBOL_attrsANYLEN)
|
||
error = TRUE;
|
||
else
|
||
{
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else
|
||
error = TRUE;
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (error)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind, /* ENTITY. */
|
||
where, /* LOCAL. */
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* ffeexpr_declare_parenthesized_ -- ffesymbol wrapper for NAME(...) operand
|
||
|
||
ffelexToken t;
|
||
bool maybe_intrin;
|
||
ffeexprParenType_ paren_type;
|
||
ffesymbol s;
|
||
s = ffeexpr_declare_parenthesized_ (t, maybe_intrin, &paren_type);
|
||
|
||
Just like ffesymbol_declare_local, except performs any implicit info
|
||
assignment necessary, and it returns the type of the parenthesized list
|
||
(list of function args, list of array args, or substring spec). */
|
||
|
||
static ffesymbol
|
||
ffeexpr_declare_parenthesized_ (ffelexToken t, bool maybe_intrin,
|
||
ffeexprParenType_ *paren_type)
|
||
{
|
||
ffesymbol s;
|
||
ffesymbolState st; /* Effective state. */
|
||
ffeinfoKind k;
|
||
bool bad;
|
||
|
||
if (maybe_intrin && ffesrc_check_symbol ())
|
||
{ /* Knock off some easy cases. */
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextSUBROUTINEREF:
|
||
case FFEEXPR_contextDATA:
|
||
case FFEEXPR_contextDATAIMPDOINDEX_:
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextDO:
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextIF:
|
||
case FFEEXPR_contextARITHIF:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextSTOP:
|
||
case FFEEXPR_contextRETURN:
|
||
case FFEEXPR_contextSELECTCASE:
|
||
case FFEEXPR_contextCASE:
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
case FFEEXPR_contextFILEDFINT:
|
||
case FFEEXPR_contextFILELOG:
|
||
case FFEEXPR_contextFILENUM:
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
case FFEEXPR_contextFILECHAR:
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
case FFEEXPR_contextFILEKEY:
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
case FFEEXPR_contextDATAIMPDOCTRL_:
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextPARAMETER:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
break; /* These could be intrinsic invocations. */
|
||
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextFILEFORMATNML:
|
||
case FFEEXPR_contextALLOCATE:
|
||
case FFEEXPR_contextDEALLOCATE:
|
||
case FFEEXPR_contextHEAPSTAT:
|
||
case FFEEXPR_contextNULLIFY:
|
||
case FFEEXPR_contextINCLUDE:
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
case FFEEXPR_contextLOC_:
|
||
case FFEEXPR_contextINDEXORACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
case FFEEXPR_contextPARENFILENUM_:
|
||
case FFEEXPR_contextPARENFILEUNIT_:
|
||
maybe_intrin = FALSE;
|
||
break; /* Can't be intrinsic invocation. */
|
||
|
||
default:
|
||
assert ("blah! blah! waaauuggh!" == NULL);
|
||
break;
|
||
}
|
||
}
|
||
|
||
s = ffesymbol_declare_local (t, maybe_intrin);
|
||
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
/* Special-case these since they can involve a different concept
|
||
of "state" (in the stmtfunc name space). */
|
||
{
|
||
case FFEEXPR_contextDATAIMPDOINDEX_:
|
||
case FFEEXPR_contextDATAIMPDOCTRL_:
|
||
if (ffeexpr_context_outer_ (ffeexpr_stack_)
|
||
== FFEEXPR_contextDATAIMPDOINDEX_)
|
||
s = ffeexpr_sym_impdoitem_ (s, t);
|
||
else
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_sym_impdoitem_ (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_impdoctrl_ (s, t);
|
||
if (ffesymbol_kind (s) != FFEINFO_kindANY)
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
switch ((ffesymbol_sfdummyparent (s) == NULL)
|
||
? ffesymbol_state (s)
|
||
: FFESYMBOL_stateUNDERSTOOD)
|
||
{
|
||
case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr
|
||
context. */
|
||
if (!ffest_seen_first_exec ())
|
||
goto seen; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSUBROUTINEREF:
|
||
s = ffeexpr_sym_lhs_call_ (s, t); /* "CALL FOO"=="CALL
|
||
FOO(...)". */
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_sym_rhs_let_ (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
/* Fall through. */
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextDO:
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextIF:
|
||
case FFEEXPR_contextARITHIF:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextSTOP:
|
||
case FFEEXPR_contextRETURN:
|
||
case FFEEXPR_contextSELECTCASE:
|
||
case FFEEXPR_contextCASE:
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
case FFEEXPR_contextFILEDFINT:
|
||
case FFEEXPR_contextFILELOG:
|
||
case FFEEXPR_contextFILENUM:
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
case FFEEXPR_contextFILECHAR:
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
case FFEEXPR_contextFILEKEY:
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
case FFEEXPR_contextLOC_:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
s = ffeexpr_paren_rhs_let_ (s, t);
|
||
else
|
||
s = ffeexpr_paren_lhs_let_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
case FFEEXPR_contextINCLUDE:
|
||
case FFEEXPR_contextPARAMETER:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
break; /* Will turn into errors below. */
|
||
|
||
default:
|
||
ffesymbol_error (s, t);
|
||
break;
|
||
}
|
||
/* Fall through. */
|
||
case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */
|
||
understood: /* :::::::::::::::::::: */
|
||
|
||
/* State might have changed, update it. */
|
||
st = ((ffesymbol_sfdummyparent (s) == NULL)
|
||
? ffesymbol_state (s)
|
||
: FFESYMBOL_stateUNDERSTOOD);
|
||
|
||
k = ffesymbol_kind (s);
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSUBROUTINEREF:
|
||
bad = ((k != FFEINFO_kindSUBROUTINE)
|
||
&& ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
|
||
|| (k != FFEINFO_kindNONE)));
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
|
||
else
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
|
||
break;
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
bad = (k != FFEINFO_kindENTITY) || (ffesymbol_rank (s) == 0)
|
||
|| ((ffesymbol_where (s) != FFEINFO_whereNONE)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereLOCAL)
|
||
&& (ffesymbol_where (s) != FFEINFO_whereCOMMON));
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextLET:
|
||
case FFEEXPR_contextPAREN_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextIOLIST:
|
||
case FFEEXPR_contextIOLISTDF:
|
||
case FFEEXPR_contextDO:
|
||
case FFEEXPR_contextDOWHILE:
|
||
case FFEEXPR_contextACTUALARG_:
|
||
case FFEEXPR_contextCGOTO:
|
||
case FFEEXPR_contextIF:
|
||
case FFEEXPR_contextARITHIF:
|
||
case FFEEXPR_contextFORMAT:
|
||
case FFEEXPR_contextSTOP:
|
||
case FFEEXPR_contextRETURN:
|
||
case FFEEXPR_contextSELECTCASE:
|
||
case FFEEXPR_contextCASE:
|
||
case FFEEXPR_contextFILEASSOC:
|
||
case FFEEXPR_contextFILEINT:
|
||
case FFEEXPR_contextFILEDFINT:
|
||
case FFEEXPR_contextFILELOG:
|
||
case FFEEXPR_contextFILENUM:
|
||
case FFEEXPR_contextFILENUMAMBIG:
|
||
case FFEEXPR_contextFILECHAR:
|
||
case FFEEXPR_contextFILENUMCHAR:
|
||
case FFEEXPR_contextFILEDFCHAR:
|
||
case FFEEXPR_contextFILEKEY:
|
||
case FFEEXPR_contextFILEUNIT:
|
||
case FFEEXPR_contextFILEUNIT_DF:
|
||
case FFEEXPR_contextFILEUNITAMBIG:
|
||
case FFEEXPR_contextFILEFORMAT:
|
||
case FFEEXPR_contextFILENAMELIST:
|
||
case FFEEXPR_contextFILEVXTCODE:
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextIMPDOITEM_:
|
||
case FFEEXPR_contextIMPDOITEMDF_:
|
||
case FFEEXPR_contextIMPDOCTRL_:
|
||
case FFEEXPR_contextLOC_:
|
||
bad = FALSE; /* Let paren-switch handle the cases. */
|
||
break;
|
||
|
||
case FFEEXPR_contextASSIGN:
|
||
case FFEEXPR_contextAGOTO:
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
case FFEEXPR_contextPARAMETER:
|
||
case FFEEXPR_contextDIMLIST:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
bad = (k != FFEINFO_kindENTITY)
|
||
|| (ffesymbol_where (s) != FFEINFO_whereCONSTANT);
|
||
break;
|
||
|
||
case FFEEXPR_contextINCLUDE:
|
||
bad = TRUE;
|
||
break;
|
||
|
||
default:
|
||
bad = TRUE;
|
||
break;
|
||
}
|
||
|
||
switch (bad ? FFEINFO_kindANY : k)
|
||
{
|
||
case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */
|
||
if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
|
||
{
|
||
if (ffeexpr_context_outer_ (ffeexpr_stack_)
|
||
== FFEEXPR_contextSUBROUTINEREF)
|
||
*paren_type = FFEEXPR_parentypeSUBROUTINE_;
|
||
else
|
||
*paren_type = FFEEXPR_parentypeFUNCTION_;
|
||
break;
|
||
}
|
||
if (st == FFESYMBOL_stateUNDERSTOOD)
|
||
{
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
}
|
||
else
|
||
*paren_type = FFEEXPR_parentypeFUNSUBSTR_;
|
||
break;
|
||
|
||
case FFEINFO_kindFUNCTION:
|
||
*paren_type = FFEEXPR_parentypeFUNCTION_;
|
||
switch (ffesymbol_where (s))
|
||
{
|
||
case FFEINFO_whereLOCAL:
|
||
bad = TRUE; /* Attempt to recurse! */
|
||
break;
|
||
|
||
case FFEINFO_whereCONSTANT:
|
||
bad = ((ffesymbol_sfexpr (s) == NULL)
|
||
|| (ffebld_op (ffesymbol_sfexpr (s))
|
||
== FFEBLD_opANY)); /* Attempt to recurse! */
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_kindSUBROUTINE:
|
||
if ((ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
|
||
|| (ffeexpr_stack_->previous != NULL))
|
||
{
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
break;
|
||
}
|
||
|
||
*paren_type = FFEEXPR_parentypeSUBROUTINE_;
|
||
switch (ffesymbol_where (s))
|
||
{
|
||
case FFEINFO_whereLOCAL:
|
||
case FFEINFO_whereCONSTANT:
|
||
bad = TRUE; /* Attempt to recurse! */
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_kindENTITY:
|
||
if (ffesymbol_rank (s) == 0)
|
||
{
|
||
if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)
|
||
*paren_type = FFEEXPR_parentypeSUBSTRING_;
|
||
else
|
||
{
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
}
|
||
}
|
||
else
|
||
*paren_type = FFEEXPR_parentypeARRAY_;
|
||
break;
|
||
|
||
default:
|
||
case FFEINFO_kindANY:
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
break;
|
||
}
|
||
|
||
if (bad)
|
||
{
|
||
if (k == FFEINFO_kindANY)
|
||
ffest_shutdown ();
|
||
else
|
||
ffesymbol_error (s, t);
|
||
}
|
||
|
||
return s;
|
||
|
||
case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */
|
||
seen: /* :::::::::::::::::::: */
|
||
bad = TRUE;
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextPARAMETER:
|
||
if (ffeexpr_stack_->is_rhs)
|
||
ffesymbol_error (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_parameter_ (s, t);
|
||
break;
|
||
|
||
case FFEEXPR_contextDATA:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
if (ffeexpr_stack_->is_rhs)
|
||
ffesymbol_error (s, t);
|
||
else
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
s = ffeexpr_sym_lhs_data_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
s = ffeexpr_sym_lhs_equivalence_ (s, t);
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEEXPR_contextDIMLIST:
|
||
s = ffeexpr_sym_rhs_dimlist_ (s, t);
|
||
bad = FALSE;
|
||
break;
|
||
|
||
case FFEEXPR_contextCHARACTERSIZE:
|
||
case FFEEXPR_contextKINDTYPE:
|
||
case FFEEXPR_contextDIMLISTCOMMON:
|
||
case FFEEXPR_contextINITVAL:
|
||
case FFEEXPR_contextEQVINDEX_:
|
||
break;
|
||
|
||
case FFEEXPR_contextINCLUDE:
|
||
break;
|
||
|
||
case FFEEXPR_contextINDEX_:
|
||
case FFEEXPR_contextACTUALARGEXPR_:
|
||
case FFEEXPR_contextINDEXORACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
assert (ffeexpr_stack_->is_rhs);
|
||
s = ffecom_sym_exec_transition (s);
|
||
if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD)
|
||
goto understood; /* :::::::::::::::::::: */
|
||
s = ffeexpr_paren_rhs_let_ (s, t);
|
||
goto understood; /* :::::::::::::::::::: */
|
||
|
||
default:
|
||
break;
|
||
}
|
||
k = ffesymbol_kind (s);
|
||
switch (bad ? FFEINFO_kindANY : k)
|
||
{
|
||
case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */
|
||
*paren_type = FFEEXPR_parentypeFUNSUBSTR_;
|
||
break;
|
||
|
||
case FFEINFO_kindFUNCTION:
|
||
*paren_type = FFEEXPR_parentypeFUNCTION_;
|
||
switch (ffesymbol_where (s))
|
||
{
|
||
case FFEINFO_whereLOCAL:
|
||
bad = TRUE; /* Attempt to recurse! */
|
||
break;
|
||
|
||
case FFEINFO_whereCONSTANT:
|
||
bad = ((ffesymbol_sfexpr (s) == NULL)
|
||
|| (ffebld_op (ffesymbol_sfexpr (s))
|
||
== FFEBLD_opANY)); /* Attempt to recurse! */
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case FFEINFO_kindSUBROUTINE:
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
bad = TRUE; /* Cannot possibly be in
|
||
contextSUBROUTINEREF. */
|
||
break;
|
||
|
||
case FFEINFO_kindENTITY:
|
||
if (ffesymbol_rank (s) == 0)
|
||
{
|
||
if (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE)
|
||
*paren_type = FFEEXPR_parentypeEQUIVALENCE_;
|
||
else if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)
|
||
*paren_type = FFEEXPR_parentypeSUBSTRING_;
|
||
else
|
||
{
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
}
|
||
}
|
||
else
|
||
*paren_type = FFEEXPR_parentypeARRAY_;
|
||
break;
|
||
|
||
default:
|
||
case FFEINFO_kindANY:
|
||
bad = TRUE;
|
||
*paren_type = FFEEXPR_parentypeANY_;
|
||
break;
|
||
}
|
||
|
||
if (bad)
|
||
{
|
||
if (k == FFEINFO_kindANY)
|
||
ffest_shutdown ();
|
||
else
|
||
ffesymbol_error (s, t);
|
||
}
|
||
|
||
return s;
|
||
|
||
default:
|
||
assert ("bad symbol state" == NULL);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/* Have FOO in XYZ = ...FOO(...).... Executable context only. */
|
||
|
||
static ffesymbol
|
||
ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t)
|
||
{
|
||
ffesymbolAttrs sa;
|
||
ffesymbolAttrs na;
|
||
ffeinfoKind kind;
|
||
ffeinfoWhere where;
|
||
ffeintrinGen gen;
|
||
ffeintrinSpec spec;
|
||
ffeintrinImp imp;
|
||
bool maybe_ambig = FALSE;
|
||
bool error = FALSE;
|
||
|
||
assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE)
|
||
|| (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN));
|
||
|
||
na = sa = ffesymbol_attrs (s);
|
||
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = ffesymbol_kind (s);
|
||
where = ffesymbol_where (s);
|
||
|
||
/* Figure out what kind of object we've got based on previous declarations
|
||
of or references to the object. */
|
||
|
||
if (sa & FFESYMBOL_attrsEXTERNAL)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsACTUALARG
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
if (sa & FFESYMBOL_attrsTYPE)
|
||
where = FFEINFO_whereGLOBAL;
|
||
else
|
||
/* Not TYPE. */
|
||
{
|
||
kind = FFEINFO_kindFUNCTION;
|
||
|
||
if (sa & FFESYMBOL_attrsDUMMY)
|
||
; /* Not TYPE. */
|
||
else if (sa & FFESYMBOL_attrsACTUALARG)
|
||
; /* Not DUMMY or TYPE. */
|
||
else /* Not ACTUALARG, DUMMY, or TYPE. */
|
||
where = FFEINFO_whereGLOBAL;
|
||
}
|
||
}
|
||
else if (sa & FFESYMBOL_attrsDUMMY)
|
||
{
|
||
assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
kind = FFEINFO_kindFUNCTION;
|
||
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure; kind
|
||
could be ENTITY w/substring ref. */
|
||
}
|
||
else if (sa & FFESYMBOL_attrsARRAY)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else if (sa & FFESYMBOL_attrsSFARG)
|
||
{
|
||
assert (!(sa & ~(FFESYMBOL_attrsSFARG
|
||
| FFESYMBOL_attrsTYPE)));
|
||
|
||
where = FFEINFO_whereLOCAL; /* Actually an error, but at least we
|
||
know it's a local var. */
|
||
}
|
||
else if (sa & FFESYMBOL_attrsTYPE)
|
||
{
|
||
assert (!(sa & (FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG))); /* Handled above. */
|
||
assert (!(sa & ~(FFESYMBOL_attrsTYPE
|
||
| FFESYMBOL_attrsADJUSTABLE
|
||
| FFESYMBOL_attrsANYLEN
|
||
| FFESYMBOL_attrsARRAY
|
||
| FFESYMBOL_attrsDUMMY
|
||
| FFESYMBOL_attrsEXTERNAL
|
||
| FFESYMBOL_attrsSFARG)));
|
||
|
||
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
|
||
&gen, &spec, &imp))
|
||
{
|
||
if (!(sa & FFESYMBOL_attrsANYLEN)
|
||
&& (ffeimplic_peek_symbol_type (s, NULL)
|
||
== FFEINFO_basictypeCHARACTER))
|
||
return s; /* Haven't learned anything yet. */
|
||
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
ffesymbol_set_generic (s, gen);
|
||
ffesymbol_set_specific (s, spec);
|
||
ffesymbol_set_implementation (s, imp);
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
0,
|
||
FFEINFO_kindFUNCTION,
|
||
FFEINFO_whereINTRINSIC,
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
|
||
return s;
|
||
}
|
||
if (sa & FFESYMBOL_attrsANYLEN)
|
||
error = TRUE; /* Error, since the only way we can,
|
||
given CHARACTER*(*) FOO, accept
|
||
FOO(...) is for FOO to be a dummy
|
||
arg or constant, but it can't
|
||
become either now. */
|
||
else if (sa & FFESYMBOL_attrsADJUSTABLE)
|
||
{
|
||
kind = FFEINFO_kindENTITY;
|
||
where = FFEINFO_whereLOCAL;
|
||
}
|
||
else
|
||
{
|
||
kind = FFEINFO_kindFUNCTION;
|
||
where = FFEINFO_whereGLOBAL;
|
||
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure;
|
||
could be ENTITY/LOCAL w/substring ref. */
|
||
}
|
||
}
|
||
else if (sa == FFESYMBOL_attrsetNONE)
|
||
{
|
||
assert (ffesymbol_state (s) == FFESYMBOL_stateNONE);
|
||
|
||
if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE,
|
||
&gen, &spec, &imp))
|
||
{
|
||
if (ffeimplic_peek_symbol_type (s, NULL)
|
||
== FFEINFO_basictypeCHARACTER)
|
||
return s; /* Haven't learned anything yet. */
|
||
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
ffesymbol_set_generic (s, gen);
|
||
ffesymbol_set_specific (s, spec);
|
||
ffesymbol_set_implementation (s, imp);
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
0,
|
||
FFEINFO_kindFUNCTION,
|
||
FFEINFO_whereINTRINSIC,
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
return s;
|
||
}
|
||
|
||
kind = FFEINFO_kindFUNCTION;
|
||
where = FFEINFO_whereGLOBAL;
|
||
maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure;
|
||
could be ENTITY/LOCAL w/substring ref. */
|
||
}
|
||
else
|
||
error = TRUE;
|
||
|
||
/* Now see what we've got for a new object: NONE means a new error cropped
|
||
up; ANY means an old error to be ignored; otherwise, everything's ok,
|
||
update the object (symbol) and continue on. */
|
||
|
||
if (error)
|
||
ffesymbol_error (s, t);
|
||
else if (!(na & FFESYMBOL_attrsANY))
|
||
{
|
||
ffesymbol_signal_change (s); /* May need to back up to previous
|
||
version. */
|
||
if (!ffeimplic_establish_symbol (s))
|
||
{
|
||
ffesymbol_error (s, t);
|
||
return s;
|
||
}
|
||
if (maybe_ambig
|
||
&& (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
|
||
return s; /* Still not sure, let caller deal with it
|
||
based on (...). */
|
||
|
||
ffesymbol_set_info (s,
|
||
ffeinfo_new (ffesymbol_basictype (s),
|
||
ffesymbol_kindtype (s),
|
||
ffesymbol_rank (s),
|
||
kind,
|
||
where,
|
||
ffesymbol_size (s)));
|
||
ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
|
||
ffesymbol_resolve_intrin (s);
|
||
s = ffecom_sym_learned (s);
|
||
ffesymbol_reference (s, t, FALSE);
|
||
ffesymbol_signal_unreported (s); /* For debugging purposes. */
|
||
}
|
||
|
||
return s;
|
||
}
|
||
|
||
/* ffeexpr_token_arguments_ -- OPEN_PAREN [expr COMMA]...expr
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle expression (which might be null) and COMMA or CLOSE_PAREN. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ procedure;
|
||
ffebld reduced;
|
||
ffeinfo info;
|
||
ffeexprContext ctx;
|
||
bool check_intrin = FALSE; /* Set TRUE if intrinsic is REAL(Z) or AIMAG(Z). */
|
||
|
||
procedure = ffeexpr_stack_->exprstack;
|
||
info = ffebld_info (procedure->u.operand);
|
||
|
||
/* Is there an expression to add? If the expression is nil,
|
||
it might still be an argument. It is if:
|
||
|
||
- The current token is comma, or
|
||
|
||
- The -fugly-comma flag was specified *and* the procedure
|
||
being invoked is external.
|
||
|
||
Otherwise, if neither of the above is the case, just
|
||
ignore this (nil) expression. */
|
||
|
||
if ((expr != NULL)
|
||
|| (ffelex_token_type (t) == FFELEX_typeCOMMA)
|
||
|| (ffe_is_ugly_comma ()
|
||
&& (ffeinfo_where (info) == FFEINFO_whereGLOBAL)))
|
||
{
|
||
/* This expression, even if nil, is apparently intended as an argument. */
|
||
|
||
/* Internal procedure (CONTAINS, or statement function)? */
|
||
|
||
if (ffeinfo_where (info) == FFEINFO_whereCONSTANT)
|
||
{
|
||
if ((expr == NULL)
|
||
&& ffebad_start (FFEBAD_NULL_ARGUMENT))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
if (expr == NULL)
|
||
;
|
||
else
|
||
{
|
||
if (ffeexpr_stack_->next_dummy == NULL)
|
||
{ /* Report later which was the first extra argument. */
|
||
if (ffeexpr_stack_->tokens[1] == NULL)
|
||
{
|
||
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
|
||
ffeexpr_stack_->num_args = 0;
|
||
}
|
||
++ffeexpr_stack_->num_args; /* Count # of extra arguments. */
|
||
}
|
||
else
|
||
{
|
||
if ((ffeinfo_rank (ffebld_info (expr)) != 0)
|
||
&& ffebad_start (FFEBAD_ARRAY_AS_SFARG))
|
||
{
|
||
ffebad_here (0,
|
||
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_here (1, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_string (ffesymbol_text (ffesymbol_sfdummyparent
|
||
(ffebld_symter (ffebld_head
|
||
(ffeexpr_stack_->next_dummy)))));
|
||
ffebad_finish ();
|
||
}
|
||
else
|
||
{
|
||
expr = ffeexpr_convert_expr (expr, ft,
|
||
ffebld_head (ffeexpr_stack_->next_dummy),
|
||
ffeexpr_stack_->tokens[0],
|
||
FFEEXPR_contextLET);
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
}
|
||
--ffeexpr_stack_->num_args; /* Count down # of args. */
|
||
ffeexpr_stack_->next_dummy
|
||
= ffebld_trail (ffeexpr_stack_->next_dummy);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((expr == NULL)
|
||
&& ffe_is_pedantic ()
|
||
&& ffebad_start (FFEBAD_NULL_ARGUMENT_W))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
}
|
||
}
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_:
|
||
ctx = FFEEXPR_contextSFUNCDEFACTUALARG_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
assert ("bad context" == NULL);
|
||
ctx = FFEEXPR_context;
|
||
break;
|
||
|
||
default:
|
||
ctx = FFEEXPR_contextACTUALARG_;
|
||
break;
|
||
}
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
|
||
ffeexpr_token_arguments_);
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ((ffeinfo_where (info) == FFEINFO_whereCONSTANT)
|
||
&& (ffeexpr_stack_->next_dummy != NULL))
|
||
{ /* Too few arguments. */
|
||
if (ffebad_start (FFEBAD_TOO_FEW_ARGUMENTS))
|
||
{
|
||
char num[10];
|
||
|
||
sprintf (num, "%" ffebldListLength_f "u", ffeexpr_stack_->num_args);
|
||
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_string (num);
|
||
ffebad_string (ffesymbol_text (ffesymbol_sfdummyparent (ffebld_symter
|
||
(ffebld_head (ffeexpr_stack_->next_dummy)))));
|
||
ffebad_finish ();
|
||
}
|
||
for (;
|
||
ffeexpr_stack_->next_dummy != NULL;
|
||
ffeexpr_stack_->next_dummy
|
||
= ffebld_trail (ffeexpr_stack_->next_dummy))
|
||
{
|
||
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (0));
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
}
|
||
}
|
||
|
||
if ((ffeinfo_where (info) == FFEINFO_whereCONSTANT)
|
||
&& (ffeexpr_stack_->tokens[1] != NULL))
|
||
{ /* Too many arguments to statement function. */
|
||
if (ffebad_start (FFEBAD_TOO_MANY_ARGUMENTS))
|
||
{
|
||
char num[10];
|
||
|
||
sprintf (num, "%" ffebldListLength_f "u", ffeexpr_stack_->num_args);
|
||
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_string (num);
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
|
||
if (ffebld_op (procedure->u.operand) == FFEBLD_opANY)
|
||
{
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF)
|
||
reduced = ffebld_new_funcref (procedure->u.operand,
|
||
ffeexpr_stack_->expr);
|
||
else
|
||
reduced = ffebld_new_subrref (procedure->u.operand,
|
||
ffeexpr_stack_->expr);
|
||
if (ffebld_symter_generic (procedure->u.operand) != FFEINTRIN_genNONE)
|
||
ffeintrin_fulfill_generic (&reduced, &info, ffeexpr_stack_->tokens[0]);
|
||
else if (ffebld_symter_specific (procedure->u.operand)
|
||
!= FFEINTRIN_specNONE)
|
||
ffeintrin_fulfill_specific (&reduced, &info, &check_intrin,
|
||
ffeexpr_stack_->tokens[0]);
|
||
else
|
||
ffeexpr_fulfill_call_ (&reduced, ffeexpr_stack_->tokens[0]);
|
||
|
||
if (ffebld_op (reduced) != FFEBLD_opANY)
|
||
ffebld_set_info (reduced,
|
||
ffeinfo_new (ffeinfo_basictype (info),
|
||
ffeinfo_kindtype (info),
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereFLEETING,
|
||
ffeinfo_size (info)));
|
||
else
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
}
|
||
if (ffebld_op (reduced) == FFEBLD_opFUNCREF)
|
||
reduced = ffeexpr_collapse_funcref (reduced, ffeexpr_stack_->tokens[0]);
|
||
ffeexpr_stack_->exprstack = procedure->previous; /* Pops
|
||
not-quite-operand off
|
||
stack. */
|
||
procedure->u.operand = reduced; /* Save the line/column ffewhere
|
||
info. */
|
||
ffeexpr_exprstack_push_operand_ (procedure); /* Push it back on stack. */
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
{
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
|
||
ffeexpr_is_substr_ok_ = FALSE; /* Nobody likes "FUNC(3)(1:1)".... */
|
||
|
||
/* If the intrinsic needs checking (is REAL(Z) or AIMAG(Z), where
|
||
Z is DOUBLE COMPLEX), and a command-line option doesn't already
|
||
establish interpretation, probably complain. */
|
||
|
||
if (check_intrin
|
||
&& !ffe_is_90 ()
|
||
&& !ffe_is_ugly_complex ())
|
||
{
|
||
/* If the outer expression is REAL(me...), issue diagnostic
|
||
only if next token isn't the close-paren for REAL(me). */
|
||
|
||
if ((ffeexpr_stack_->previous != NULL)
|
||
&& (ffeexpr_stack_->previous->exprstack != NULL)
|
||
&& (ffeexpr_stack_->previous->exprstack->type == FFEEXPR_exprtypeOPERAND_)
|
||
&& ((reduced = ffeexpr_stack_->previous->exprstack->u.operand) != NULL)
|
||
&& (ffebld_op (reduced) == FFEBLD_opSYMTER)
|
||
&& (ffebld_symter_implementation (reduced) == FFEINTRIN_impREAL))
|
||
return (ffelexHandler) ffeexpr_token_intrincheck_;
|
||
|
||
/* Diagnose the ambiguity now. */
|
||
|
||
if (ffebad_start (FFEBAD_INTRINSIC_CMPAMBIG))
|
||
{
|
||
ffebad_string (ffeintrin_name_implementation
|
||
(ffebld_symter_implementation
|
||
(ffebld_left
|
||
(ffeexpr_stack_->exprstack->u.operand))));
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->exprstack->token),
|
||
ffelex_token_where_column (ffeexpr_stack_->exprstack->token));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
return (ffelexHandler) ffeexpr_token_substrp_;
|
||
}
|
||
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
|
||
ffeexpr_is_substr_ok_ = FALSE;/* Nobody likes "FUNC(3)(1:1)".... */
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_token_substrp_);
|
||
}
|
||
|
||
/* ffeexpr_token_elements_ -- OPEN_PAREN [expr COMMA]...expr
|
||
|
||
Return a pointer to this array to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle expression and COMMA or CLOSE_PAREN. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_elements_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ array;
|
||
ffebld reduced;
|
||
ffeinfo info;
|
||
ffeinfoWhere where;
|
||
ffetargetIntegerDefault val;
|
||
ffetargetIntegerDefault lval = 0;
|
||
ffetargetIntegerDefault uval = 0;
|
||
ffebld lbound;
|
||
ffebld ubound;
|
||
bool lcheck;
|
||
bool ucheck;
|
||
|
||
array = ffeexpr_stack_->exprstack;
|
||
info = ffebld_info (array->u.operand);
|
||
|
||
if ((expr == NULL) /* && ((ffeexpr_stack_->rank != 0) ||
|
||
(ffelex_token_type(t) ==
|
||
FFELEX_typeCOMMA)) */ )
|
||
{
|
||
if (ffebad_start (FFEBAD_NULL_ELEMENT))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_here (1, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_finish ();
|
||
}
|
||
if (ffeexpr_stack_->rank < ffeinfo_rank (info))
|
||
{ /* Don't bother if we're going to complain
|
||
later! */
|
||
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
|
||
ffebld_set_info (expr, ffeinfo_new_any ());
|
||
}
|
||
}
|
||
|
||
if (expr == NULL)
|
||
;
|
||
else if (ffeinfo_rank (info) == 0)
|
||
{ /* In EQUIVALENCE context, ffeinfo_rank(info)
|
||
may == 0. */
|
||
++ffeexpr_stack_->rank; /* Track anyway, may need for new VXT
|
||
feature. */
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
}
|
||
else
|
||
{
|
||
++ffeexpr_stack_->rank;
|
||
if (ffeexpr_stack_->rank > ffeinfo_rank (info))
|
||
{ /* Report later which was the first extra
|
||
element. */
|
||
if (ffeexpr_stack_->rank == ffeinfo_rank (info) + 1)
|
||
ffeexpr_stack_->tokens[1] = ffelex_token_use (ft);
|
||
}
|
||
else
|
||
{
|
||
switch (ffeinfo_where (ffebld_info (expr)))
|
||
{
|
||
case FFEINFO_whereCONSTANT:
|
||
break;
|
||
|
||
case FFEINFO_whereIMMEDIATE:
|
||
ffeexpr_stack_->constant = FALSE;
|
||
break;
|
||
|
||
default:
|
||
ffeexpr_stack_->constant = FALSE;
|
||
ffeexpr_stack_->immediate = FALSE;
|
||
break;
|
||
}
|
||
if (ffebld_op (expr) == FFEBLD_opCONTER
|
||
&& ffebld_kindtype (expr) == FFEINFO_kindtypeINTEGERDEFAULT)
|
||
{
|
||
val = ffebld_constant_integerdefault (ffebld_conter (expr));
|
||
|
||
lbound = ffebld_left (ffebld_head (ffeexpr_stack_->bound_list));
|
||
if (lbound == NULL)
|
||
{
|
||
lcheck = TRUE;
|
||
lval = 1;
|
||
}
|
||
else if (ffebld_op (lbound) == FFEBLD_opCONTER)
|
||
{
|
||
lcheck = TRUE;
|
||
lval = ffebld_constant_integerdefault (ffebld_conter (lbound));
|
||
}
|
||
else
|
||
lcheck = FALSE;
|
||
|
||
ubound = ffebld_right (ffebld_head (ffeexpr_stack_->bound_list));
|
||
assert (ubound != NULL);
|
||
if (ffebld_op (ubound) == FFEBLD_opCONTER)
|
||
{
|
||
ucheck = TRUE;
|
||
uval = ffebld_constant_integerdefault (ffebld_conter (ubound));
|
||
}
|
||
else
|
||
ucheck = FALSE;
|
||
|
||
if ((lcheck && (val < lval)) || (ucheck && (val > uval)))
|
||
{
|
||
ffebad_start (FFEBAD_RANGE_ARRAY);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
ffeexpr_stack_->bound_list = ffebld_trail (ffeexpr_stack_->bound_list);
|
||
}
|
||
}
|
||
|
||
switch (ffelex_token_type (t))
|
||
{
|
||
case FFELEX_typeCOMMA:
|
||
switch (ffeexpr_context_outer_ (ffeexpr_stack_))
|
||
{
|
||
case FFEEXPR_contextDATAIMPDOITEM_:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextDATAIMPDOINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
case FFEEXPR_contextEQUIVALENCE:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextEQVINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextSFUNCDEFINDEX_,
|
||
ffeexpr_token_elements_);
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
assert ("bad context" == NULL);
|
||
break;
|
||
|
||
default:
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool,
|
||
FFEEXPR_contextINDEX_,
|
||
ffeexpr_token_elements_);
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ((ffeexpr_stack_->rank != ffeinfo_rank (info))
|
||
&& (ffeinfo_rank (info) != 0))
|
||
{
|
||
char num[10];
|
||
|
||
if (ffeexpr_stack_->rank < ffeinfo_rank (info))
|
||
{
|
||
if (ffebad_start (FFEBAD_TOO_FEW_ELEMENTS))
|
||
{
|
||
sprintf (num, "%d",
|
||
(int) (ffeinfo_rank (info) - ffeexpr_stack_->rank));
|
||
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1,
|
||
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_string (num);
|
||
ffebad_finish ();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (ffebad_start (FFEBAD_TOO_MANY_ELEMENTS))
|
||
{
|
||
sprintf (num, "%d",
|
||
(int) (ffeexpr_stack_->rank - ffeinfo_rank (info)));
|
||
|
||
ffebad_here (0,
|
||
ffelex_token_where_line (ffeexpr_stack_->tokens[1]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[1]));
|
||
ffebad_here (1,
|
||
ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_string (num);
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[1]);
|
||
}
|
||
while (ffeexpr_stack_->rank++ < ffeinfo_rank (info))
|
||
{
|
||
expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
|
||
ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0, FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_append_item (&ffeexpr_stack_->bottom, expr);
|
||
}
|
||
}
|
||
ffebld_end_list (&ffeexpr_stack_->bottom);
|
||
|
||
if (ffebld_op (array->u.operand) == FFEBLD_opANY)
|
||
{
|
||
reduced = ffebld_new_any ();
|
||
ffebld_set_info (reduced, ffeinfo_new_any ());
|
||
}
|
||
else
|
||
{
|
||
reduced = ffebld_new_arrayref (array->u.operand, ffeexpr_stack_->expr);
|
||
if (ffeexpr_stack_->constant)
|
||
where = FFEINFO_whereFLEETING_CADDR;
|
||
else if (ffeexpr_stack_->immediate)
|
||
where = FFEINFO_whereFLEETING_IADDR;
|
||
else
|
||
where = FFEINFO_whereFLEETING;
|
||
ffebld_set_info (reduced,
|
||
ffeinfo_new (ffeinfo_basictype (info),
|
||
ffeinfo_kindtype (info),
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
where,
|
||
ffeinfo_size (info)));
|
||
reduced = ffeexpr_collapse_arrayref (reduced, ffeexpr_stack_->tokens[0]);
|
||
}
|
||
|
||
ffeexpr_stack_->exprstack = array->previous; /* Pops not-quite-operand off
|
||
stack. */
|
||
array->u.operand = reduced; /* Save the line/column ffewhere info. */
|
||
ffeexpr_exprstack_push_operand_ (array); /* Push it back on stack. */
|
||
|
||
switch (ffeinfo_basictype (info))
|
||
{
|
||
case FFEINFO_basictypeCHARACTER:
|
||
ffeexpr_is_substr_ok_ = TRUE; /* Everyone likes "FOO(3)(1:1)".... */
|
||
break;
|
||
|
||
case FFEINFO_basictypeNONE:
|
||
ffeexpr_is_substr_ok_ = TRUE;
|
||
assert (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE);
|
||
break;
|
||
|
||
default:
|
||
ffeexpr_is_substr_ok_ = FALSE;
|
||
break;
|
||
}
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN)
|
||
{
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
|
||
return (ffelexHandler) ffeexpr_token_substrp_;
|
||
}
|
||
|
||
if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
ffelex_token_kill (ffeexpr_stack_->tokens[0]);
|
||
return
|
||
(ffelexHandler) ffeexpr_find_close_paren_ (t,
|
||
(ffelexHandler)
|
||
ffeexpr_token_substrp_);
|
||
}
|
||
|
||
/* ffeexpr_token_equivalence_ -- OPEN_PAREN expr
|
||
|
||
Return a pointer to this array to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
If token is COLON, pass off to _substr_, else init list and pass off
|
||
to _elements_. This handles the case "EQUIVALENCE (FOO(expr?", where
|
||
? marks the token, and where FOO's rank/type has not yet been established,
|
||
meaning we could be in a list of indices or in a substring
|
||
specification. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
return ffeexpr_token_substring_ (ft, expr, t);
|
||
|
||
ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom);
|
||
return ffeexpr_token_elements_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_token_substring_ -- NAME(of kindENTITY) OPEN_PAREN expr
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle expression (which may be null) and COLON. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_substring_ (ffelexToken ft, ffebld expr, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ string;
|
||
ffeinfo info;
|
||
ffetargetIntegerDefault i;
|
||
ffeexprContext ctx;
|
||
ffetargetCharacterSize size;
|
||
|
||
string = ffeexpr_stack_->exprstack;
|
||
info = ffebld_info (string->u.operand);
|
||
size = ffebld_size_max (string->u.operand);
|
||
|
||
if (ffelex_token_type (t) == FFELEX_typeCOLON)
|
||
{
|
||
if ((expr != NULL)
|
||
&& (ffebld_op (expr) == FFEBLD_opCONTER)
|
||
&& (((i = ffebld_constant_integerdefault (ffebld_conter (expr)))
|
||
< 1)
|
||
|| ((size != FFETARGET_charactersizeNONE) && (i > size))))
|
||
{
|
||
ffebad_start (FFEBAD_RANGE_SUBSTR);
|
||
ffebad_here (0, ffelex_token_where_line (ft),
|
||
ffelex_token_where_column (ft));
|
||
ffebad_finish ();
|
||
}
|
||
ffeexpr_stack_->expr = expr;
|
||
|
||
switch (ffeexpr_stack_->context)
|
||
{
|
||
case FFEEXPR_contextSFUNCDEF:
|
||
case FFEEXPR_contextSFUNCDEFINDEX_:
|
||
ctx = FFEEXPR_contextSFUNCDEFINDEX_;
|
||
break;
|
||
|
||
case FFEEXPR_contextSFUNCDEFACTUALARG_:
|
||
case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_:
|
||
assert ("bad context" == NULL);
|
||
ctx = FFEEXPR_context;
|
||
break;
|
||
|
||
default:
|
||
ctx = FFEEXPR_contextINDEX_;
|
||
break;
|
||
}
|
||
|
||
return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx,
|
||
ffeexpr_token_substring_1_);
|
||
}
|
||
|
||
if (ffest_ffebad_start (FFEBAD_MISSING_COLON_IN_SUBSTR))
|
||
{
|
||
ffebad_here (0, ffelex_token_where_line (t),
|
||
ffelex_token_where_column (t));
|
||
ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]),
|
||
ffelex_token_where_column (ffeexpr_stack_->tokens[0]));
|
||
ffebad_finish ();
|
||
}
|
||
|
||
ffeexpr_stack_->expr = NULL;
|
||
return (ffelexHandler) ffeexpr_token_substring_1_ (ft, expr, t);
|
||
}
|
||
|
||
/* ffeexpr_token_substring_1_ -- NAME OPEN_PAREN [expr COMMA]...expr
|
||
|
||
Return a pointer to this function to the lexer (ffelex), which will
|
||
invoke it for the next token.
|
||
|
||
Handle expression (which might be null) and CLOSE_PAREN. */
|
||
|
||
static ffelexHandler
|
||
ffeexpr_token_substring_1_ (ffelexToken ft, ffebld last, ffelexToken t)
|
||
{
|
||
ffeexprExpr_ string;
|
||
ffebld reduced;
|
||
ffebld substrlist;
|
||
ffebld first = ffeexpr_stack_->expr;
|
||
ffebld strop;
|
||
ffeinfo info;
|
||
ffeinfoWhere lwh;
|
||
ffeinfoWhere rwh;
|
||
ffeinfoWhere where;
|
||
ffeinfoKindtype first_kt;
|
||
ffeinfoKindtype last_kt;
|
||
ffetargetIntegerDefault first_val;
|
||
ffetargetIntegerDefault last_val;
|
||
ffetargetCharacterSize size;
|
||
ffetargetCharacterSize strop_size_max;
|
||
bool first_known;
|
||
|
||
string = ffeexpr_stack_->exprstack;
|
||
strop = string->u.operand;
|
||
info = ffebld_info (strop);
|
||
|
||
if (first == NULL
|
||
|| (ffebld_op (first) == FFEBLD_opCONTER
|
||
&& ffebld_kindtype (first) == FFEINFO_kindtypeINTEGERDEFAULT))
|
||
{ /* The starting point is known. */
|
||
first_val = (first == NULL) ? 1
|
||
: ffebld_constant_integerdefault (ffebld_conter (first));
|
||
first_known = TRUE;
|
||
}
|
||
else
|
||
{ /* Assume start of the entity. */
|
||
first_val = 1;
|
||
first_known = FALSE;
|
||
}
|
||
|
||
if (last != NULL
|
||
&& (ffebld_op (last) == FFEBLD_opCONTER
|
||
&& ffebld_kindtype (last) == FFEINFO_kindtypeINTEGERDEFAULT))
|
||
{ /* The ending point is known. */
|
||
last_val = ffebld_constant_integerdefault (ffebld_conter (last));
|
||
|
||
if (first_known)
|
||
{ /* 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);
|
||
}
|