| /* expr.c -- Implementation File (module.c template V1.0) |
| Copyright (C) 1995-1998 Free Software Foundation, Inc. |
| Contributed by James Craig Burley (burley@gnu.org). |
| |
| This file is part of GNU Fortran. |
| |
| GNU Fortran is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Fortran is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Fortran; see the file COPYING. If not, write to |
| the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| Related Modules: |
| None. |
| |
| Description: |
| Handles syntactic and semantic analysis of Fortran expressions. |
| |
| Modifications: |
| */ |
| |
| /* Include files. */ |
| |
| #include "proj.h" |
| #include "expr.h" |
| #include "bad.h" |
| #include "bld.h" |
| #include "com.h" |
| #include "global.h" |
| #include "implic.h" |
| #include "intrin.h" |
| #include "info.h" |
| #include "lex.h" |
| #include "malloc.h" |
| #include "src.h" |
| #include "st.h" |
| #include "symbol.h" |
| #include "str.h" |
| #include "target.h" |
| #include "where.h" |
| |
| /* Externals defined here. */ |
| |
| |
| /* Simple definitions and enumerations. */ |
| |
| typedef enum |
| { |
| FFEEXPR_exprtypeUNKNOWN_, |
| FFEEXPR_exprtypeOPERAND_, |
| FFEEXPR_exprtypeUNARY_, |
| FFEEXPR_exprtypeBINARY_, |
| FFEEXPR_exprtype_ |
| } ffeexprExprtype_; |
| |
| typedef enum |
| { |
| FFEEXPR_operatorPOWER_, |
| FFEEXPR_operatorMULTIPLY_, |
| FFEEXPR_operatorDIVIDE_, |
| FFEEXPR_operatorADD_, |
| FFEEXPR_operatorSUBTRACT_, |
| FFEEXPR_operatorCONCATENATE_, |
| FFEEXPR_operatorLT_, |
| FFEEXPR_operatorLE_, |
| FFEEXPR_operatorEQ_, |
| FFEEXPR_operatorNE_, |
| FFEEXPR_operatorGT_, |
| FFEEXPR_operatorGE_, |
| FFEEXPR_operatorNOT_, |
| FFEEXPR_operatorAND_, |
| FFEEXPR_operatorOR_, |
| FFEEXPR_operatorXOR_, |
| FFEEXPR_operatorEQV_, |
| FFEEXPR_operatorNEQV_, |
| FFEEXPR_operator_ |
| } ffeexprOperator_; |
| |
| typedef enum |
| { |
| FFEEXPR_operatorprecedenceHIGHEST_ = 1, |
| FFEEXPR_operatorprecedencePOWER_ = 1, |
| FFEEXPR_operatorprecedenceMULTIPLY_ = 2, |
| FFEEXPR_operatorprecedenceDIVIDE_ = 2, |
| FFEEXPR_operatorprecedenceADD_ = 3, |
| FFEEXPR_operatorprecedenceSUBTRACT_ = 3, |
| FFEEXPR_operatorprecedenceLOWARITH_ = 3, |
| FFEEXPR_operatorprecedenceCONCATENATE_ = 3, |
| FFEEXPR_operatorprecedenceLT_ = 4, |
| FFEEXPR_operatorprecedenceLE_ = 4, |
| FFEEXPR_operatorprecedenceEQ_ = 4, |
| FFEEXPR_operatorprecedenceNE_ = 4, |
| FFEEXPR_operatorprecedenceGT_ = 4, |
| FFEEXPR_operatorprecedenceGE_ = 4, |
| FFEEXPR_operatorprecedenceNOT_ = 5, |
| FFEEXPR_operatorprecedenceAND_ = 6, |
| FFEEXPR_operatorprecedenceOR_ = 7, |
| FFEEXPR_operatorprecedenceXOR_ = 8, |
| FFEEXPR_operatorprecedenceEQV_ = 8, |
| FFEEXPR_operatorprecedenceNEQV_ = 8, |
| FFEEXPR_operatorprecedenceLOWEST_ = 8, |
| FFEEXPR_operatorprecedence_ |
| } ffeexprOperatorPrecedence_; |
| |
| #define FFEEXPR_operatorassociativityL2R_ TRUE |
| #define FFEEXPR_operatorassociativityR2L_ FALSE |
| #define FFEEXPR_operatorassociativityPOWER_ FFEEXPR_operatorassociativityR2L_ |
| #define FFEEXPR_operatorassociativityMULTIPLY_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityDIVIDE_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityADD_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativitySUBTRACT_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityCONCATENATE_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityLT_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityLE_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityEQ_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityNE_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityGT_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityGE_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityNOT_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityAND_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityOR_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityXOR_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityEQV_ FFEEXPR_operatorassociativityL2R_ |
| #define FFEEXPR_operatorassociativityNEQV_ FFEEXPR_operatorassociativityL2R_ |
| |
| typedef enum |
| { |
| FFEEXPR_parentypeFUNCTION_, |
| FFEEXPR_parentypeSUBROUTINE_, |
| FFEEXPR_parentypeARRAY_, |
| FFEEXPR_parentypeSUBSTRING_, |
| FFEEXPR_parentypeFUNSUBSTR_,/* Ambig: check for colon after first expr. */ |
| FFEEXPR_parentypeEQUIVALENCE_, /* Ambig: ARRAY_ or SUBSTRING_. */ |
| FFEEXPR_parentypeANY_, /* Allow basically anything. */ |
| FFEEXPR_parentype_ |
| } ffeexprParenType_; |
| |
| typedef enum |
| { |
| FFEEXPR_percentNONE_, |
| FFEEXPR_percentLOC_, |
| FFEEXPR_percentVAL_, |
| FFEEXPR_percentREF_, |
| FFEEXPR_percentDESCR_, |
| FFEEXPR_percent_ |
| } ffeexprPercent_; |
| |
| /* Internal typedefs. */ |
| |
| typedef struct _ffeexpr_expr_ *ffeexprExpr_; |
| typedef bool ffeexprOperatorAssociativity_; |
| typedef struct _ffeexpr_stack_ *ffeexprStack_; |
| |
| /* Private include files. */ |
| |
| |
| /* Internal structure definitions. */ |
| |
| struct _ffeexpr_expr_ |
| { |
| ffeexprExpr_ previous; |
| ffelexToken token; |
| ffeexprExprtype_ type; |
| union |
| { |
| struct |
| { |
| ffeexprOperator_ op; |
| ffeexprOperatorPrecedence_ prec; |
| ffeexprOperatorAssociativity_ as; |
| } |
| operator; |
| ffebld operand; |
| } |
| u; |
| }; |
| |
| struct _ffeexpr_stack_ |
| { |
| ffeexprStack_ previous; |
| mallocPool pool; |
| ffeexprContext context; |
| ffeexprCallback callback; |
| ffelexToken first_token; |
| ffeexprExpr_ exprstack; |
| ffelexToken tokens[10]; /* Used in certain cases, like (unary) |
| open-paren. */ |
| ffebld expr; /* For first of |
| complex/implied-do/substring/array-elements |
| / actual-args expression. */ |
| ffebld bound_list; /* For tracking dimension bounds list of |
| array. */ |
| ffebldListBottom bottom; /* For building lists. */ |
| ffeinfoRank rank; /* For elements in an array reference. */ |
| bool constant; /* TRUE while elements seen so far are |
| constants. */ |
| bool immediate; /* TRUE while elements seen so far are |
| immediate/constants. */ |
| ffebld next_dummy; /* Next SFUNC dummy arg in arg list. */ |
| ffebldListLength num_args; /* Number of dummy args expected in arg list. */ |
| bool is_rhs; /* TRUE if rhs context, FALSE otherwise. */ |
| ffeexprPercent_ percent; /* Current %FOO keyword. */ |
| }; |
| |
| struct _ffeexpr_find_ |
| { |
| ffelexToken t; |
| ffelexHandler after; |
| int level; |
| }; |
| |
| /* Static objects accessed by functions in this module. */ |
| |
| static ffeexprStack_ ffeexpr_stack_; /* Expression stack for semantic. */ |
| static ffelexToken ffeexpr_tokens_[10]; /* Scratchpad tokens for syntactic. */ |
| static ffestrOther ffeexpr_current_dotdot_; /* Current .FOO. keyword. */ |
| static long ffeexpr_hollerith_count_; /* ffeexpr_token_number_ and caller. */ |
| static int ffeexpr_level_; /* Level of DATA implied-DO construct. */ |
| static bool ffeexpr_is_substr_ok_; /* If OPEN_PAREN as binary "op" ok. */ |
| static struct _ffeexpr_find_ ffeexpr_find_; |
| |
| /* Static functions (internal). */ |
| |
| static ffelexHandler ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_close_paren_ambig_ (ffelexToken ft, |
| ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t); |
| static ffelexHandler ffeexpr_cb_close_paren_c_ (ffelexToken ft, |
| ffebld expr, ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_close_paren_ci_ (ffelexToken ft, |
| ffebld expr, ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_ci_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_1_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_2_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_3_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_4_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_comma_i_5_ (ffelexToken t); |
| static ffelexHandler ffeexpr_cb_end_loc_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_end_notloc_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_cb_end_notloc_1_ (ffelexToken t); |
| static ffesymbol ffeexpr_check_impctrl_ (ffesymbol s); |
| static void ffeexpr_check_impdo_ (ffebld list, ffelexToken list_t, |
| ffebld dovar, ffelexToken dovar_t); |
| static void ffeexpr_update_impdo_ (ffebld expr, ffebld dovar); |
| static void ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar); |
| static ffeexprContext ffeexpr_context_outer_ (ffeexprStack_ s); |
| static ffeexprExpr_ ffeexpr_expr_new_ (void); |
| static void ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t); |
| static bool ffeexpr_isdigits_ (char *p); |
| static ffelexHandler ffeexpr_token_first_lhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_lhs_1_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_1_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_2_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_3_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_4_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_5_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_first_rhs_6_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_namelist_ (ffelexToken t); |
| static void ffeexpr_expr_kill_ (ffeexprExpr_ e); |
| static void ffeexpr_exprstack_push_ (ffeexprExpr_ e); |
| static void ffeexpr_exprstack_push_binary_ (ffeexprExpr_ e); |
| static void ffeexpr_exprstack_push_operand_ (ffeexprExpr_ e); |
| static void ffeexpr_exprstack_push_unary_ (ffeexprExpr_ e); |
| static void ffeexpr_reduce_ (void); |
| static ffebld ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op, |
| ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_eqop2_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op, |
| ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op, |
| ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffebld ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l, |
| ffeexprExpr_ op, ffeexprExpr_ r); |
| static ffelexHandler ffeexpr_find_close_paren_ (ffelexToken t, |
| ffelexHandler after); |
| static ffelexHandler ffeexpr_nil_finished_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_rhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_end_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_swallow_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_real_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_real_exponent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_real_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_exponent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_per_exp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_real_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_num_per_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_number_real_exp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_num_real_exp_sn_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_binary_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_binary_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_binary_end_per_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_binary_sw_per_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_quote_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_apostrophe_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_apos_char_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_name_rhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_name_apos_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_name_apos_name_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_percent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_percent_name_ (ffelexToken t); |
| static ffelexHandler ffeexpr_nil_substrp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_finished_ (ffelexToken t); |
| static ffebld ffeexpr_finished_ambig_ (ffelexToken t, ffebld expr); |
| static ffelexHandler ffeexpr_token_lhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_rhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_binary_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_end_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_swallow_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_real_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_real_exponent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_real_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_exponent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_per_exp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_real_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_num_per_exp_sign_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_number_real_exp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_num_real_exp_sn_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_binary_period_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_binary_end_per_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_binary_sw_per_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_quote_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_apostrophe_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_apos_char_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_name_lhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_name_arg_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_name_rhs_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_name_apos_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_name_apos_name_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_percent_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_percent_name_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_elements_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_substring_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_substring_1_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_substrp_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_intrincheck_ (ffelexToken t); |
| static ffelexHandler ffeexpr_token_funsubstr_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static ffelexHandler ffeexpr_token_anything_ (ffelexToken ft, ffebld expr, |
| ffelexToken t); |
| static void ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer, |
| ffelexToken decimal, ffelexToken fraction, ffelexToken exponent, |
| ffelexToken exponent_sign, ffelexToken exponent_digits); |
| static ffesymbol ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin); |
| static ffesymbol ffeexpr_sym_impdoitem_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t); |
| static ffesymbol ffeexpr_declare_parenthesized_ (ffelexToken t, |
| bool maybe_intrin, |
| ffeexprParenType_ *paren_type); |
| static ffesymbol ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t); |
| |
| /* Internal macros. */ |
| |
| #define ffeexpr_paren_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t) |
| #define ffeexpr_sym_lhs_let_(s,t) ffeexpr_sym_rhs_let_(s,t) |
| |
| /* ffeexpr_collapse_convert -- Collapse convert expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_convert(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_convert (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize sz; |
| ffetargetCharacterSize sz2; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| sz = FFETARGET_charactersizeNONE; |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_integer1_integer2 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_integer1_integer3 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_integer1_integer4 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER1/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer1_real1 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer1_real2 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer1_real3 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer1_real4 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER1/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer1_complex1 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer1_complex2 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer1_complex3 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer1_complex4 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER1/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_integer1_logical1 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_integer1_logical2 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_integer1_logical3 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_integer1_logical4 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER1/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_integer1_character1 |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_integer1_hollerith |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_integer1_typeless |
| (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("INTEGER1 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_integer2_integer1 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_integer2_integer3 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_integer2_integer4 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER2/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer2_real1 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer2_real2 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer2_real3 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer2_real4 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER2/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer2_complex1 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer2_complex2 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer2_complex3 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer2_complex4 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER2/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_integer2_logical1 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_integer2_logical2 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_integer2_logical3 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_integer2_logical4 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER2/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_integer2_character1 |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_integer2_hollerith |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_integer2_typeless |
| (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("INTEGER2 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_integer3_integer1 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_integer3_integer2 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_integer3_integer4 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER3/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer3_real1 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer3_real2 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer3_real3 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer3_real4 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER3/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer3_complex1 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer3_complex2 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer3_complex3 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer3_complex4 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER3/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_integer3_logical1 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_integer3_logical2 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_integer3_logical3 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_integer3_logical4 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER3/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_integer3_character1 |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_integer3_hollerith |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_integer3_typeless |
| (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("INTEGER3 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_integer4_integer1 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_integer4_integer2 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_integer4_integer3 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER4/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer4_real1 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer4_real2 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer4_real3 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer4_real4 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER4/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_integer4_complex1 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_integer4_complex2 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_integer4_complex3 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_integer4_complex4 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER3/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_integer4_logical1 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_integer4_logical2 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_integer4_logical3 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_integer4_logical4 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("INTEGER4/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_integer4_character1 |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_integer4_hollerith |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_integer4_typeless |
| (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("INTEGER4 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| sz = FFETARGET_charactersizeNONE; |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_logical1_logical2 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_logical1_logical3 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_logical1_logical4 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL1/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_logical1_integer1 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_logical1_integer2 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_logical1_integer3 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_logical1_integer4 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL1/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_logical1_character1 |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_logical1_hollerith |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_logical1_typeless |
| (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("LOGICAL1 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_logical2_logical1 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_logical2_logical3 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_logical2_logical4 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL2/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_logical2_integer1 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_logical2_integer2 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_logical2_integer3 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_logical2_integer4 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL2/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_logical2_character1 |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_logical2_hollerith |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_logical2_typeless |
| (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("LOGICAL2 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_logical3_logical1 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_logical3_logical2 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_convert_logical3_logical4 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL3/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_logical3_integer1 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_logical3_integer2 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_logical3_integer3 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_logical3_integer4 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL3/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_logical3_character1 |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_logical3_hollerith |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_logical3_typeless |
| (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("LOGICAL3 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_convert_logical4_logical1 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_convert_logical4_logical2 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_convert_logical4_logical3 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL4/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_logical4_integer1 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_logical4_integer2 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_logical4_integer3 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_logical4_integer4 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("LOGICAL4/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_logical4_character1 |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_logical4_hollerith |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_logical4_typeless |
| (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("LOGICAL4 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| sz = FFETARGET_charactersizeNONE; |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_real1_integer1 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_real1_integer2 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_real1_integer3 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_real1_integer4 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL1/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real1_real2 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real1_real3 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real1_real4 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL1/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real1_complex1 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real1_complex2 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real1_complex3 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real1_complex4 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL1/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_real1_character1 |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_real1_hollerith |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_real1_typeless |
| (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("REAL1 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_real2_integer1 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_real2_integer2 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_real2_integer3 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_real2_integer4 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL2/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real2_real1 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real2_real3 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real2_real4 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL2/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real2_complex1 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real2_complex2 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real2_complex3 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real2_complex4 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL2/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_real2_character1 |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_real2_hollerith |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_real2_typeless |
| (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("REAL2 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_real3_integer1 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_real3_integer2 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_real3_integer3 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_real3_integer4 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL3/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real3_real1 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real3_real2 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real3_real4 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL3/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real3_complex1 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real3_complex2 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real3_complex3 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real3_complex4 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL3/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_real3_character1 |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_real3_hollerith |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_real3_typeless |
| (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("REAL3 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_real4_integer1 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_real4_integer2 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_real4_integer3 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_real4_integer4 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL4/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real4_real1 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real4_real2 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real4_real3 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL4/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_real4_complex1 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_real4_complex2 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_real4_complex3 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_real4_complex4 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("REAL4/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_real4_character1 |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_real4_hollerith |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_real4_typeless |
| (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("REAL4 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| sz = FFETARGET_charactersizeNONE; |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_complex1_integer1 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_complex1_integer2 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_complex1_integer3 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_complex1_integer4 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX1/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex1_real1 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex1_real2 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex1_real3 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex1_real4 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX1/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex1_complex2 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex1_complex3 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex1_complex4 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX1/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_complex1_character1 |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_complex1_hollerith |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_complex1_typeless |
| (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("COMPLEX1 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_complex2_integer1 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_complex2_integer2 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_complex2_integer3 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_complex2_integer4 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX2/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex2_real1 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex2_real2 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex2_real3 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex2_real4 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX2/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex2_complex1 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex2_complex3 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex2_complex4 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX2/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_complex2_character1 |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_complex2_hollerith |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_complex2_typeless |
| (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("COMPLEX2 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_complex3_integer1 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_complex3_integer2 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_complex3_integer3 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_complex3_integer4 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX3/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex3_real1 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex3_real2 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex3_real3 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex3_real4 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX3/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex3_complex1 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex3_complex2 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex3_complex4 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX3/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_complex3_character1 |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_complex3_hollerith |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_complex3_typeless |
| (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("COMPLEX3 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_convert_complex4_integer1 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_integer1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_convert_complex4_integer2 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_integer2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_convert_complex4_integer3 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_integer3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_convert_complex4_integer4 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX4/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex4_real1 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_real1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex4_real2 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_real2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex4_real3 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_real3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_convert_complex4_real4 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_real4 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX4/REAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_convert_complex4_complex1 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex1 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_convert_complex4_complex2 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex2 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_convert_complex4_complex3 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex3 (ffebld_conter (l))); |
| break; |
| #endif |
| |
| default: |
| assert ("COMPLEX4/COMPLEX bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = ffetarget_convert_complex4_character1 |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_character1 (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error = ffetarget_convert_complex4_hollerith |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_hollerith (ffebld_conter (l))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error = ffetarget_convert_complex4_typeless |
| (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_typeless (ffebld_conter (l))); |
| break; |
| |
| default: |
| assert ("COMPLEX4 bad type" == NULL); |
| break; |
| } |
| |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| if ((sz = ffebld_size (expr)) == FFETARGET_charactersizeNONE) |
| return expr; |
| kt = ffeinfo_kindtype (ffebld_info (expr)); |
| switch (kt) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| switch (ffeinfo_basictype (ffebld_info (l))) |
| { |
| case FFEINFO_basictypeCHARACTER: |
| if ((sz2 = ffebld_size (l)) == FFETARGET_charactersizeNONE) |
| return expr; |
| assert (kt == ffeinfo_kindtype (ffebld_info (l))); |
| assert (sz2 == ffetarget_length_character1 |
| (ffebld_constant_character1 |
| (ffebld_conter (l)))); |
| error |
| = ffetarget_convert_character1_character1 |
| (ffebld_cu_ptr_character1 (u), sz, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error |
| = ffetarget_convert_character1_integer1 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error |
| = ffetarget_convert_character1_integer2 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error |
| = ffetarget_convert_character1_integer3 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error |
| = ffetarget_convert_character1_integer4 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| default: |
| assert ("CHARACTER1/INTEGER bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (ffeinfo_kindtype (ffebld_info (l))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error |
| = ffetarget_convert_character1_logical1 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error |
| = ffetarget_convert_character1_logical2 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error |
| = ffetarget_convert_character1_logical3 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error |
| = ffetarget_convert_character1_logical4 |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| #endif |
| |
| default: |
| assert ("CHARACTER1/LOGICAL bad source kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| error |
| = ffetarget_convert_character1_hollerith |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_hollerith (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| error |
| = ffetarget_convert_character1_typeless |
| (ffebld_cu_ptr_character1 (u), |
| sz, |
| ffebld_constant_typeless (ffebld_conter (l)), |
| ffebld_constant_pool ()); |
| break; |
| |
| default: |
| assert ("CHARACTER1 bad type" == NULL); |
| } |
| |
| expr |
| = ffebld_new_conter_with_orig |
| (ffebld_constant_new_character1_val |
| (ffebld_cu_val_character1 (u)), |
| expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| sz)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| assert (t != NULL); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_paren -- Collapse paren expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_paren(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_paren (ffebld expr, ffelexToken t UNUSED) |
| { |
| ffebld r; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize len; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| r = ffebld_left (expr); |
| |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| bt = ffeinfo_basictype (ffebld_info (r)); |
| kt = ffeinfo_kindtype (ffebld_info (r)); |
| len = ffebld_size (r); |
| |
| expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)), |
| expr); |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_uplus -- Collapse uplus expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_uplus(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_uplus (ffebld expr, ffelexToken t UNUSED) |
| { |
| ffebld r; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize len; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| r = ffebld_left (expr); |
| |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| bt = ffeinfo_basictype (ffebld_info (r)); |
| kt = ffeinfo_kindtype (ffebld_info (r)); |
| len = ffebld_size (r); |
| |
| expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)), |
| expr); |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_uminus -- Collapse uminus expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_uminus(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_uminus (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| r = ffebld_left (expr); |
| |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_uminus_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_uminus_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_uminus_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_uminus_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_uminus_real1 (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_uminus_real2 (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_uminus_real3 (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_uminus_real4 (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_uminus_complex1 (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_uminus_complex2 (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_uminus_complex3 (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_uminus_complex4 (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_not -- Collapse not expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_not(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_not (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| r = ffebld_left (expr); |
| |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_not_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_not_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_not_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_not_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_not_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_not_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_not_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_not_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_add -- Collapse add expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_add(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_add (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_add_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_add_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_add_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_add_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_add_real1 (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_add_real2 (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_add_real3 (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_add_real4 (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_add_complex1 (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_add_complex2 (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_add_complex3 (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_add_complex4 (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_subtract -- Collapse subtract expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_subtract(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_subtract (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_subtract_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_subtract_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_subtract_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_subtract_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_subtract_real1 (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_subtract_real2 (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_subtract_real3 (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_subtract_real4 (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_subtract_complex1 (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_subtract_complex2 (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_subtract_complex3 (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_subtract_complex4 (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_multiply -- Collapse multiply expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_multiply(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_multiply (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_multiply_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_multiply_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_multiply_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_multiply_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_multiply_real1 (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_multiply_real2 (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_multiply_real3 (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_multiply_real4 (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_multiply_complex1 (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_multiply_complex2 (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_multiply_complex3 (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_multiply_complex4 (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_divide -- Collapse divide expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_divide(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_divide (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_divide_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_divide_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_divide_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_divide_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_divide_real1 (ffebld_cu_ptr_real1 (u), |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real1_val |
| (ffebld_cu_val_real1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_divide_real2 (ffebld_cu_ptr_real2 (u), |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real2_val |
| (ffebld_cu_val_real2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_divide_real3 (ffebld_cu_ptr_real3 (u), |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real3_val |
| (ffebld_cu_val_real3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_divide_real4 (ffebld_cu_ptr_real4 (u), |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_real4_val |
| (ffebld_cu_val_real4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_divide_complex1 (ffebld_cu_ptr_complex1 (u), |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex1_val |
| (ffebld_cu_val_complex1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_divide_complex2 (ffebld_cu_ptr_complex2 (u), |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex2_val |
| (ffebld_cu_val_complex2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_divide_complex3 (ffebld_cu_ptr_complex3 (u), |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex3_val |
| (ffebld_cu_val_complex3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_divide_complex4 (ffebld_cu_ptr_complex4 (u), |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_complex4_val |
| (ffebld_cu_val_complex4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_power -- Collapse power expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_power(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_power (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| if ((ffeinfo_basictype (ffebld_info (r)) != FFEINFO_basictypeINTEGER) |
| || (ffeinfo_kindtype (ffebld_info (r)) != FFEINFO_kindtypeINTEGERDEFAULT)) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| case FFEINFO_kindtypeINTEGERDEFAULT: |
| error = ffetarget_power_integerdefault_integerdefault |
| (ffebld_cu_ptr_integerdefault (u), |
| ffebld_constant_integerdefault (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integerdefault_val |
| (ffebld_cu_val_integerdefault (u)), expr); |
| break; |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| case FFEINFO_kindtypeREALDEFAULT: |
| error = ffetarget_power_realdefault_integerdefault |
| (ffebld_cu_ptr_realdefault (u), |
| ffebld_constant_realdefault (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_realdefault_val |
| (ffebld_cu_val_realdefault (u)), expr); |
| break; |
| |
| case FFEINFO_kindtypeREALDOUBLE: |
| error = ffetarget_power_realdouble_integerdefault |
| (ffebld_cu_ptr_realdouble (u), |
| ffebld_constant_realdouble (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_realdouble_val |
| (ffebld_cu_val_realdouble (u)), expr); |
| break; |
| |
| #if FFETARGET_okREALQUAD |
| case FFEINFO_kindtypeREALQUAD: |
| error = ffetarget_power_realquad_integerdefault |
| (ffebld_cu_ptr_realquad (u), |
| ffebld_constant_realquad (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_realquad_val |
| (ffebld_cu_val_realquad (u)), expr); |
| break; |
| #endif |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| case FFEINFO_kindtypeREALDEFAULT: |
| error = ffetarget_power_complexdefault_integerdefault |
| (ffebld_cu_ptr_complexdefault (u), |
| ffebld_constant_complexdefault (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complexdefault_val |
| (ffebld_cu_val_complexdefault (u)), expr); |
| break; |
| |
| #if FFETARGET_okCOMPLEXDOUBLE |
| case FFEINFO_kindtypeREALDOUBLE: |
| error = ffetarget_power_complexdouble_integerdefault |
| (ffebld_cu_ptr_complexdouble (u), |
| ffebld_constant_complexdouble (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complexdouble_val |
| (ffebld_cu_val_complexdouble (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEXQUAD |
| case FFEINFO_kindtypeREALQUAD: |
| error = ffetarget_power_complexquad_integerdefault |
| (ffebld_cu_ptr_complexquad (u), |
| ffebld_constant_complexquad (ffebld_conter (l)), |
| ffebld_constant_integerdefault (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_complexquad_val |
| (ffebld_cu_val_complexquad (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_concatenate -- Collapse concatenate expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_concatenate(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_concatenate (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize len; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_concatenate_character1 (ffebld_cu_ptr_character1 (u), |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r)), |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val |
| (ffebld_cu_val_character1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_concatenate_character2 (ffebld_cu_ptr_character2 (u), |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r)), |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val |
| (ffebld_cu_val_character2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_concatenate_character3 (ffebld_cu_ptr_character3 (u), |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r)), |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val |
| (ffebld_cu_val_character3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_concatenate_character4 (ffebld_cu_ptr_character4 (u), |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r)), |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val |
| (ffebld_cu_val_character4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeCHARACTER, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_eq -- Collapse eq expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_eq(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_eq (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_eq_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_eq_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_eq_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_eq_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_eq_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_eq_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_eq_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_eq_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_eq_complex1 (&val, |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_eq_complex2 (&val, |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_eq_complex3 (&val, |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_eq_complex4 (&val, |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_eq_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_eq_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_eq_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_eq_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_ne -- Collapse ne expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_ne(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_ne (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_ne_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_ne_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_ne_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_ne_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_ne_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_ne_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_ne_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_ne_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCOMPLEX: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCOMPLEX1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_ne_complex1 (&val, |
| ffebld_constant_complex1 (ffebld_conter (l)), |
| ffebld_constant_complex1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_ne_complex2 (&val, |
| ffebld_constant_complex2 (ffebld_conter (l)), |
| ffebld_constant_complex2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_ne_complex3 (&val, |
| ffebld_constant_complex3 (ffebld_conter (l)), |
| ffebld_constant_complex3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCOMPLEX4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_ne_complex4 (&val, |
| ffebld_constant_complex4 (ffebld_conter (l)), |
| ffebld_constant_complex4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad complex kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_ne_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_ne_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_ne_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_ne_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_ge -- Collapse ge expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_ge(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_ge (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_ge_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_ge_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_ge_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_ge_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_ge_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_ge_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_ge_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_ge_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_ge_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_ge_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_ge_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_ge_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_gt -- Collapse gt expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_gt(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_gt (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_gt_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_gt_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_gt_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_gt_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_gt_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_gt_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_gt_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_gt_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_gt_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_gt_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_gt_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_gt_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_le -- Collapse le expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_le(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_le (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_le_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_le_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_le_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_le_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_le_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_le_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_le_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_le_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_le_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_le_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_le_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_le_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_lt -- Collapse lt expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_lt(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_lt (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| bool val; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_lt_integer1 (&val, |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_lt_integer2 (&val, |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_lt_integer3 (&val, |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_lt_integer4 (&val, |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okREAL1 |
| case FFEINFO_kindtypeREAL1: |
| error = ffetarget_lt_real1 (&val, |
| ffebld_constant_real1 (ffebld_conter (l)), |
| ffebld_constant_real1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL2 |
| case FFEINFO_kindtypeREAL2: |
| error = ffetarget_lt_real2 (&val, |
| ffebld_constant_real2 (ffebld_conter (l)), |
| ffebld_constant_real2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL3 |
| case FFEINFO_kindtypeREAL3: |
| error = ffetarget_lt_real3 (&val, |
| ffebld_constant_real3 (ffebld_conter (l)), |
| ffebld_constant_real3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okREAL4 |
| case FFEINFO_kindtypeREAL4: |
| error = ffetarget_lt_real4 (&val, |
| ffebld_constant_real4 (ffebld_conter (l)), |
| ffebld_constant_real4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad real kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffeinfo_kindtype (ffebld_info (ffebld_left (expr)))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_lt_character1 (&val, |
| ffebld_constant_character1 (ffebld_conter (l)), |
| ffebld_constant_character1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_lt_character2 (&val, |
| ffebld_constant_character2 (ffebld_conter (l)), |
| ffebld_constant_character2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_lt_character3 (&val, |
| ffebld_constant_character3 (ffebld_conter (l)), |
| ffebld_constant_character3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_lt_character4 (&val, |
| ffebld_constant_character4 (ffebld_conter (l)), |
| ffebld_constant_character4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig |
| (ffebld_constant_new_logicaldefault (val), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_and -- Collapse and expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_and(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_and (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_and_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_and_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_and_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_and_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_and_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_and_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_and_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_and_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_or -- Collapse or expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_or(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_or (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_or_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_or_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_or_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_or_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_or_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_or_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_or_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_or_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_xor -- Collapse xor expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_xor(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_xor (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_xor_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_xor_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_xor_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_xor_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_xor_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_xor_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_xor_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_xor_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_eqv -- Collapse eqv expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_eqv(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_eqv (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_eqv_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_eqv_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_eqv_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_eqv_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_eqv_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_eqv_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_eqv_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_eqv_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_neqv -- Collapse neqv expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_neqv(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_neqv (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebldConstantUnion u; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| if (ffebld_op (r) != FFEBLD_opCONTER) |
| return expr; |
| |
| switch (bt = ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okINTEGER1 |
| case FFEINFO_kindtypeINTEGER1: |
| error = ffetarget_neqv_integer1 (ffebld_cu_ptr_integer1 (u), |
| ffebld_constant_integer1 (ffebld_conter (l)), |
| ffebld_constant_integer1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer1_val |
| (ffebld_cu_val_integer1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER2 |
| case FFEINFO_kindtypeINTEGER2: |
| error = ffetarget_neqv_integer2 (ffebld_cu_ptr_integer2 (u), |
| ffebld_constant_integer2 (ffebld_conter (l)), |
| ffebld_constant_integer2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer2_val |
| (ffebld_cu_val_integer2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER3 |
| case FFEINFO_kindtypeINTEGER3: |
| error = ffetarget_neqv_integer3 (ffebld_cu_ptr_integer3 (u), |
| ffebld_constant_integer3 (ffebld_conter (l)), |
| ffebld_constant_integer3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer3_val |
| (ffebld_cu_val_integer3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okINTEGER4 |
| case FFEINFO_kindtypeINTEGER4: |
| error = ffetarget_neqv_integer4 (ffebld_cu_ptr_integer4 (u), |
| ffebld_constant_integer4 (ffebld_conter (l)), |
| ffebld_constant_integer4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_integer4_val |
| (ffebld_cu_val_integer4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad integer kind type" == NULL); |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okLOGICAL1 |
| case FFEINFO_kindtypeLOGICAL1: |
| error = ffetarget_neqv_logical1 (ffebld_cu_ptr_logical1 (u), |
| ffebld_constant_logical1 (ffebld_conter (l)), |
| ffebld_constant_logical1 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical1_val |
| (ffebld_cu_val_logical1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL2 |
| case FFEINFO_kindtypeLOGICAL2: |
| error = ffetarget_neqv_logical2 (ffebld_cu_ptr_logical2 (u), |
| ffebld_constant_logical2 (ffebld_conter (l)), |
| ffebld_constant_logical2 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical2_val |
| (ffebld_cu_val_logical2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL3 |
| case FFEINFO_kindtypeLOGICAL3: |
| error = ffetarget_neqv_logical3 (ffebld_cu_ptr_logical3 (u), |
| ffebld_constant_logical3 (ffebld_conter (l)), |
| ffebld_constant_logical3 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical3_val |
| (ffebld_cu_val_logical3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okLOGICAL4 |
| case FFEINFO_kindtypeLOGICAL4: |
| error = ffetarget_neqv_logical4 (ffebld_cu_ptr_logical4 (u), |
| ffebld_constant_logical4 (ffebld_conter (l)), |
| ffebld_constant_logical4 (ffebld_conter (r))); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_logical4_val |
| (ffebld_cu_val_logical4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad logical kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_symter -- Collapse symter expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_symter(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_symter (ffebld expr, ffelexToken t UNUSED) |
| { |
| ffebld r; |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize len; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| if ((r = ffesymbol_init (ffebld_symter (expr))) == NULL) |
| return expr; /* A PARAMETER lhs in progress. */ |
| |
| switch (ffebld_op (r)) |
| { |
| case FFEBLD_opCONTER: |
| break; |
| |
| case FFEBLD_opANY: |
| return r; |
| |
| default: |
| return expr; |
| } |
| |
| bt = ffeinfo_basictype (ffebld_info (r)); |
| kt = ffeinfo_kindtype (ffebld_info (r)); |
| len = ffebld_size (r); |
| |
| expr = ffebld_new_conter_with_orig (ffebld_constant_copy (ffebld_conter (r)), |
| expr); |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_funcref -- Collapse funcref expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_funcref(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_funcref (ffebld expr, ffelexToken t UNUSED) |
| { |
| return expr; /* ~~someday go ahead and collapse these, |
| though not required */ |
| } |
| |
| /* ffeexpr_collapse_arrayref -- Collapse arrayref expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_arrayref(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_arrayref (ffebld expr, ffelexToken t UNUSED) |
| { |
| return expr; |
| } |
| |
| /* ffeexpr_collapse_substr -- Collapse substr expr |
| |
| ffebld expr; |
| ffelexToken token; |
| expr = ffeexpr_collapse_substr(expr,token); |
| |
| If the result of the expr is a constant, replaces the expr with the |
| computed constant. */ |
| |
| ffebld |
| ffeexpr_collapse_substr (ffebld expr, ffelexToken t) |
| { |
| ffebad error = FFEBAD; |
| ffebld l; |
| ffebld r; |
| ffebld start; |
| ffebld stop; |
| ffebldConstantUnion u; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize len; |
| ffetargetIntegerDefault first; |
| ffetargetIntegerDefault last; |
| |
| if (ffeinfo_where (ffebld_info (expr)) != FFEINFO_whereCONSTANT) |
| return expr; |
| |
| l = ffebld_left (expr); |
| r = ffebld_right (expr); /* opITEM. */ |
| |
| if (ffebld_op (l) != FFEBLD_opCONTER) |
| return expr; |
| |
| kt = ffeinfo_kindtype (ffebld_info (l)); |
| len = ffebld_size (l); |
| |
| start = ffebld_head (r); |
| stop = ffebld_head (ffebld_trail (r)); |
| if (start == NULL) |
| first = 1; |
| else |
| { |
| if ((ffebld_op (start) != FFEBLD_opCONTER) |
| || (ffeinfo_basictype (ffebld_info (start)) != FFEINFO_basictypeINTEGER) |
| || (ffeinfo_kindtype (ffebld_info (start)) |
| != FFEINFO_kindtypeINTEGERDEFAULT)) |
| return expr; |
| first = ffebld_constant_integerdefault (ffebld_conter (start)); |
| } |
| if (stop == NULL) |
| last = len; |
| else |
| { |
| if ((ffebld_op (stop) != FFEBLD_opCONTER) |
| || (ffeinfo_basictype (ffebld_info (stop)) != FFEINFO_basictypeINTEGER) |
| || (ffeinfo_kindtype (ffebld_info (stop)) |
| != FFEINFO_kindtypeINTEGERDEFAULT)) |
| return expr; |
| last = ffebld_constant_integerdefault (ffebld_conter (stop)); |
| } |
| |
| /* Handle problems that should have already been diagnosed, but |
| left in the expression tree. */ |
| |
| if (first <= 0) |
| first = 1; |
| if (last < first) |
| last = first + len - 1; |
| |
| if ((first == 1) && (last == len)) |
| { /* Same as original. */ |
| expr = ffebld_new_conter_with_orig (ffebld_constant_copy |
| (ffebld_conter (l)), expr); |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeCHARACTER, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| return expr; |
| } |
| |
| switch (ffeinfo_basictype (ffebld_info (expr))) |
| { |
| case FFEINFO_basictypeANY: |
| return expr; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (kt = ffeinfo_kindtype (ffebld_info (expr))) |
| { |
| #if FFETARGET_okCHARACTER1 |
| case FFEINFO_kindtypeCHARACTER1: |
| error = ffetarget_substr_character1 (ffebld_cu_ptr_character1 (u), |
| ffebld_constant_character1 (ffebld_conter (l)), first, last, |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character1_val |
| (ffebld_cu_val_character1 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER2 |
| case FFEINFO_kindtypeCHARACTER2: |
| error = ffetarget_substr_character2 (ffebld_cu_ptr_character2 (u), |
| ffebld_constant_character2 (ffebld_conter (l)), first, last, |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character2_val |
| (ffebld_cu_val_character2 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER3 |
| case FFEINFO_kindtypeCHARACTER3: |
| error = ffetarget_substr_character3 (ffebld_cu_ptr_character3 (u), |
| ffebld_constant_character3 (ffebld_conter (l)), first, last, |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character3_val |
| (ffebld_cu_val_character3 (u)), expr); |
| break; |
| #endif |
| |
| #if FFETARGET_okCHARACTER4 |
| case FFEINFO_kindtypeCHARACTER4: |
| error = ffetarget_substr_character4 (ffebld_cu_ptr_character4 (u), |
| ffebld_constant_character4 (ffebld_conter (l)), first, last, |
| ffebld_constant_pool (), &len); |
| expr = ffebld_new_conter_with_orig (ffebld_constant_new_character4_val |
| (ffebld_cu_val_character4 (u)), expr); |
| break; |
| #endif |
| |
| default: |
| assert ("bad character kind type" == NULL); |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad type" == NULL); |
| return expr; |
| } |
| |
| ffebld_set_info (expr, ffeinfo_new |
| (FFEINFO_basictypeCHARACTER, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| len)); |
| |
| if ((error != FFEBAD) |
| && ffebad_start (error)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_convert -- Convert source expression to given type |
| |
| ffebld source; |
| ffelexToken source_token; |
| ffelexToken dest_token; // Any appropriate token for "destination". |
| ffeinfoBasictype bt; |
| ffeinfoKindtype kt; |
| ffetargetCharactersize sz; |
| ffeexprContext context; // Mainly LET or DATA. |
| source = ffeexpr_convert(source,source_token,dest_token,bt,kt,sz,context); |
| |
| If the expression conforms, returns the source expression. Otherwise |
| returns source wrapped in a convert node doing the conversion, or |
| ANY wrapped in convert if there is a conversion error (and issues an |
| error message). Be sensitive to the context for certain aspects of |
| the conversion. */ |
| |
| ffebld |
| ffeexpr_convert (ffebld source, ffelexToken source_token, ffelexToken dest_token, |
| ffeinfoBasictype bt, ffeinfoKindtype kt, ffeinfoRank rk, |
| ffetargetCharacterSize sz, ffeexprContext context) |
| { |
| bool bad; |
| ffeinfo info; |
| ffeinfoWhere wh; |
| |
| info = ffebld_info (source); |
| if ((bt != ffeinfo_basictype (info)) |
| || (kt != ffeinfo_kindtype (info)) |
| || (rk != 0) /* Can't convert from or to arrays yet. */ |
| || (ffeinfo_rank (info) != 0) |
| || (sz != ffebld_size_known (source))) |
| #if 0 /* Nobody seems to need this spurious CONVERT node. */ |
| || ((context != FFEEXPR_contextLET) |
| && (bt == FFEINFO_basictypeCHARACTER) |
| && (sz == FFETARGET_charactersizeNONE))) |
| #endif |
| { |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| switch (bt) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| bad = FALSE; |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| bad = !ffe_is_ugly_logint (); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| bad = ffe_is_pedantic () |
| || !(ffe_is_ugly_init () |
| && (context == FFEEXPR_contextDATA)); |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| switch (bt) |
| { |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| bad = FALSE; |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| bad = !ffe_is_ugly_logint (); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| bad = ffe_is_pedantic () |
| || !(ffe_is_ugly_init () |
| && (context == FFEEXPR_contextDATA)); |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| switch (bt) |
| { |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| bad = FALSE; |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| bad = TRUE; |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| bad = (bt != FFEINFO_basictypeCHARACTER) |
| && (ffe_is_pedantic () |
| || (bt != FFEINFO_basictypeINTEGER) |
| || !(ffe_is_ugly_init () |
| && (context == FFEEXPR_contextDATA))); |
| break; |
| |
| case FFEINFO_basictypeTYPELESS: |
| case FFEINFO_basictypeHOLLERITH: |
| bad = ffe_is_pedantic () |
| || !(ffe_is_ugly_init () |
| && ((context == FFEEXPR_contextDATA) |
| || (context == FFEEXPR_contextLET))); |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| |
| if (!bad && ((rk != 0) || (ffeinfo_rank (info) != 0))) |
| bad = TRUE; |
| |
| if (bad && (bt != FFEINFO_basictypeANY) && (kt != FFEINFO_kindtypeANY) |
| && (ffeinfo_basictype (info) != FFEINFO_basictypeANY) |
| && (ffeinfo_kindtype (info) != FFEINFO_kindtypeANY) |
| && (ffeinfo_where (info) != FFEINFO_whereANY)) |
| { |
| if (ffebad_start (FFEBAD_BAD_TYPES)) |
| { |
| if (dest_token == NULL) |
| ffebad_here (0, ffewhere_line_unknown (), |
| ffewhere_column_unknown ()); |
| else |
| ffebad_here (0, ffelex_token_where_line (dest_token), |
| ffelex_token_where_column (dest_token)); |
| assert (source_token != NULL); |
| ffebad_here (1, ffelex_token_where_line (source_token), |
| ffelex_token_where_column (source_token)); |
| ffebad_finish (); |
| } |
| |
| source = ffebld_new_any (); |
| ffebld_set_info (source, ffeinfo_new_any ()); |
| } |
| else |
| { |
| switch (ffeinfo_where (info)) |
| { |
| case FFEINFO_whereCONSTANT: |
| wh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| wh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| wh = FFEINFO_whereFLEETING; |
| break; |
| } |
| source = ffebld_new_convert (source); |
| ffebld_set_info (source, ffeinfo_new |
| (bt, |
| kt, |
| 0, |
| FFEINFO_kindENTITY, |
| wh, |
| sz)); |
| source = ffeexpr_collapse_convert (source, source_token); |
| } |
| } |
| |
| return source; |
| } |
| |
| /* ffeexpr_convert_expr -- Convert source expr to conform to dest expr |
| |
| ffebld source; |
| ffebld dest; |
| ffelexToken source_token; |
| ffelexToken dest_token; |
| ffeexprContext context; |
| source = ffeexpr_convert_expr(source,source_token,dest,dest_token,context); |
| |
| If the expressions conform, returns the source expression. Otherwise |
| returns source wrapped in a convert node doing the conversion, or |
| ANY wrapped in convert if there is a conversion error (and issues an |
| error message). Be sensitive to the context, such as LET or DATA. */ |
| |
| ffebld |
| ffeexpr_convert_expr (ffebld source, ffelexToken source_token, ffebld dest, |
| ffelexToken dest_token, ffeexprContext context) |
| { |
| ffeinfo info; |
| |
| info = ffebld_info (dest); |
| return ffeexpr_convert (source, source_token, dest_token, |
| ffeinfo_basictype (info), |
| ffeinfo_kindtype (info), |
| ffeinfo_rank (info), |
| ffebld_size_known (dest), |
| context); |
| } |
| |
| /* ffeexpr_convert_to_sym -- Convert source expression to conform to symbol |
| |
| ffebld source; |
| ffesymbol dest; |
| ffelexToken source_token; |
| ffelexToken dest_token; |
| source = ffeexpr_convert_to_sym(source,source_token,dest,dest_token); |
| |
| If the expressions conform, returns the source expression. Otherwise |
| returns source wrapped in a convert node doing the conversion, or |
| ANY wrapped in convert if there is a conversion error (and issues an |
| error message). */ |
| |
| ffebld |
| ffeexpr_convert_to_sym (ffebld source, ffelexToken source_token, |
| ffesymbol dest, ffelexToken dest_token) |
| { |
| return ffeexpr_convert (source, source_token, dest_token, ffesymbol_basictype (dest), |
| ffesymbol_kindtype (dest), ffesymbol_rank (dest), ffesymbol_size (dest), |
| FFEEXPR_contextLET); |
| } |
| |
| /* Initializes the module. */ |
| |
| void |
| ffeexpr_init_2 () |
| { |
| ffeexpr_stack_ = NULL; |
| ffeexpr_level_ = 0; |
| } |
| |
| /* ffeexpr_lhs -- Begin processing left-hand-side-context expression |
| |
| Prepares cluster for delivery of lexer tokens representing an expression |
| in a left-hand-side context (A in A=B, for example). ffebld is used |
| to build expressions in the given pool. The appropriate lexer-token |
| handling routine within ffeexpr is returned. When the end of the |
| expression is detected, mycallbackroutine is called with the resulting |
| single ffebld object specifying the entire expression and the first |
| lexer token that is not considered part of the expression. This caller- |
| supplied routine itself returns a lexer-token handling routine. Thus, |
| if necessary, ffeexpr can return several tokens as end-of-expression |
| tokens if it needs to scan forward more than one in any instance. */ |
| |
| ffelexHandler |
| ffeexpr_lhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback) |
| { |
| ffeexprStack_ s; |
| |
| ffebld_pool_push (pool); |
| s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s)); |
| s->previous = ffeexpr_stack_; |
| s->pool = pool; |
| s->context = context; |
| s->callback = callback; |
| s->first_token = NULL; |
| s->exprstack = NULL; |
| s->is_rhs = FALSE; |
| ffeexpr_stack_ = s; |
| return (ffelexHandler) ffeexpr_token_first_lhs_; |
| } |
| |
| /* ffeexpr_rhs -- Begin processing right-hand-side-context expression |
| |
| return ffeexpr_rhs(malloc_pool_image(),mycallbackroutine); // to lexer. |
| |
| Prepares cluster for delivery of lexer tokens representing an expression |
| in a right-hand-side context (B in A=B, for example). ffebld is used |
| to build expressions in the given pool. The appropriate lexer-token |
| handling routine within ffeexpr is returned. When the end of the |
| expression is detected, mycallbackroutine is called with the resulting |
| single ffebld object specifying the entire expression and the first |
| lexer token that is not considered part of the expression. This caller- |
| supplied routine itself returns a lexer-token handling routine. Thus, |
| if necessary, ffeexpr can return several tokens as end-of-expression |
| tokens if it needs to scan forward more than one in any instance. */ |
| |
| ffelexHandler |
| ffeexpr_rhs (mallocPool pool, ffeexprContext context, ffeexprCallback callback) |
| { |
| ffeexprStack_ s; |
| |
| ffebld_pool_push (pool); |
| s = malloc_new_ks (ffe_pool_program_unit (), "FFEEXPR stack", sizeof (*s)); |
| s->previous = ffeexpr_stack_; |
| s->pool = pool; |
| s->context = context; |
| s->callback = callback; |
| s->first_token = NULL; |
| s->exprstack = NULL; |
| s->is_rhs = TRUE; |
| ffeexpr_stack_ = s; |
| return (ffelexHandler) ffeexpr_token_first_rhs_; |
| } |
| |
| /* ffeexpr_cb_close_paren_ -- OPEN_PAREN expr |
| |
| Pass it to ffeexpr_rhs as the callback routine. |
| |
| Makes sure the end token is close-paren and swallows it, else issues |
| an error message and doesn't swallow the token (passing it along instead). |
| In either case wraps up subexpression construction by enclosing the |
| ffebld expression in a paren. */ |
| |
| static ffelexHandler |
| ffeexpr_cb_close_paren_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| |
| if (ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN) |
| { |
| /* Oops, naughty user didn't specify the close paren! */ |
| |
| if (ffest_ffebad_start (FFEBAD_MISSING_CLOSE_PAREN)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_finish (); |
| } |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| ffeexpr_exprstack_push_operand_ (e); |
| |
| return |
| (ffelexHandler) ffeexpr_find_close_paren_ (t, |
| (ffelexHandler) |
| ffeexpr_token_binary_); |
| } |
| |
| if (expr->op == FFEBLD_opIMPDO) |
| { |
| if (ffest_ffebad_start (FFEBAD_IMPDO_PAREN)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| expr = ffebld_new_paren (expr); |
| ffebld_set_info (expr, ffeinfo_use (ffebld_info (ffebld_left (expr)))); |
| } |
| |
| /* Now push the (parenthesized) expression as an operand onto the |
| expression stack. */ |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->u.operand = expr; |
| e->u.operand = ffeexpr_collapse_paren (e->u.operand, ft); |
| e->token = ffeexpr_stack_->tokens[0]; |
| ffeexpr_exprstack_push_operand_ (e); |
| |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_cb_close_paren_ambig_ -- OPEN_PAREN expr |
| |
| Pass it to ffeexpr_rhs as the callback routine. |
| |
| We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)" |
| with the next token in t. If the next token is possibly a binary |
| operator, continue processing the outer expression. If the next |
| token is COMMA, then the expression is a unit specifier, and |
| parentheses should not be added to it because it surrounds the |
| I/O control list that starts with the unit specifier (and continues |
| on from here -- we haven't seen the CLOSE_PAREN that matches the |
| OPEN_PAREN, it is up to the callback function to expect to see it |
| at some point). In this case, we notify the callback function that |
| the COMMA is inside, not outside, the parens by wrapping the expression |
| in an opITEM (with a NULL trail) -- the callback function presumably |
| unwraps it after seeing this kludgey indicator. |
| |
| If the next token is CLOSE_PAREN, then we go to the _1_ state to |
| decide what to do with the token after that. |
| |
| 15-Feb-91 JCB 1.1 |
| Use an extra state for the CLOSE_PAREN case to make READ &co really |
| work right. */ |
| |
| static ffelexHandler |
| ffeexpr_cb_close_paren_ambig_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeexprCallback callback; |
| ffeexprStack_ s; |
| |
| if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN) |
| { /* Need to see the next token before we |
| decide anything. */ |
| ffeexpr_stack_->expr = expr; |
| ffeexpr_tokens_[0] = ffelex_token_use (ft); |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_cb_close_paren_ambig_1_; |
| } |
| |
| expr = ffeexpr_finished_ambig_ (ft, expr); |
| |
| /* Let the callback function handle the case where t isn't COMMA. */ |
| |
| /* Here is a kludge whereby we tell the callback function the OPEN_PAREN |
| that preceded the expression starts a list of expressions, and the expr |
| hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN |
| node. The callback function should extract the real expr from the head |
| of this opITEM node after testing it. */ |
| |
| expr = ffebld_new_item (expr, NULL); |
| |
| ffebld_pool_pop (); |
| callback = ffeexpr_stack_->callback; |
| ffelex_token_kill (ffeexpr_stack_->first_token); |
| s = ffeexpr_stack_->previous; |
| malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_)); |
| ffeexpr_stack_ = s; |
| return (ffelexHandler) (*callback) (ft, expr, t); |
| } |
| |
| /* ffeexpr_cb_close_paren_ambig_1_ -- OPEN_PAREN expr CLOSE_PAREN |
| |
| See ffeexpr_cb_close_paren_ambig_. |
| |
| We get here in the READ/BACKEND/ENDFILE/REWIND case "READ(expr)" |
| with the next token in t. If the next token is possibly a binary |
| operator, continue processing the outer expression. If the next |
| token is COMMA, the expression is a parenthesized format specifier. |
| If the next token is not EOS or SEMICOLON, then because it is not a |
| binary operator (it is NAME, OPEN_PAREN, &c), the expression is |
| a unit specifier, and parentheses should not be added to it because |
| they surround the I/O control list that consists of only the unit |
| specifier. If the next token is EOS or SEMICOLON, the statement |
| must be disambiguated by looking at the type of the expression -- a |
| character expression is a parenthesized format specifier, while a |
| non-character expression is a unit specifier. |
| |
| Another issue is how to do the callback so the recipient of the |
| next token knows how to handle it if it is a COMMA. In all other |
| cases, disambiguation is straightforward: the same approach as the |
| above is used. |
| |
| EXTENSION: in COMMA case, if not pedantic, use same disambiguation |
| as for EOS/SEMICOLON case; f2c allows "READ (cilist) [[,]iolist]" |
| and apparently other compilers do, as well, and some code out there |
| uses this "feature". |
| |
| 19-Feb-91 JCB 1.1 |
| Extend to allow COMMA as nondisambiguating by itself. Remember |
| to not try and check info field for opSTAR, since that expr doesn't |
| have a valid info field. */ |
| |
| static ffelexHandler |
| ffeexpr_cb_close_paren_ambig_1_ (ffelexToken t) |
| { |
| ffeexprCallback callback; |
| ffeexprStack_ s; |
| ffelexHandler next; |
| ffelexToken orig_ft = ffeexpr_tokens_[0]; /* In case callback clobbers |
| these. */ |
| ffelexToken orig_t = ffeexpr_tokens_[1]; |
| ffebld expr = ffeexpr_stack_->expr; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeCOMMA: /* Subexpr is parenthesized format specifier. */ |
| if (ffe_is_pedantic ()) |
| goto pedantic_comma; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFELEX_typeEOS: /* Ambiguous; use type of expr to |
| disambiguate. */ |
| case FFELEX_typeSEMICOLON: |
| if ((expr == NULL) || (ffebld_op (expr) == FFEBLD_opANY) |
| || (ffebld_op (expr) == FFEBLD_opSTAR) |
| || (ffeinfo_basictype (ffebld_info (expr)) |
| != FFEINFO_basictypeCHARACTER)) |
| break; /* Not a valid CHARACTER entity, can't be a |
| format spec. */ |
| /* Fall through. */ |
| default: /* Binary op (we assume; error otherwise); |
| format specifier. */ |
| |
| pedantic_comma: /* :::::::::::::::::::: */ |
| |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFILENUMAMBIG: |
| ffeexpr_stack_->context = FFEEXPR_contextFILENUM; |
| break; |
| |
| case FFEEXPR_contextFILEUNITAMBIG: |
| ffeexpr_stack_->context = FFEEXPR_contextFILEFORMAT; |
| break; |
| |
| default: |
| assert ("bad context" == NULL); |
| break; |
| } |
| |
| ffeexpr_stack_->tokens[0] = ffelex_token_use (ffeexpr_stack_->first_token); |
| next = (ffelexHandler) ffeexpr_cb_close_paren_ (orig_ft, expr, orig_t); |
| ffelex_token_kill (orig_ft); |
| ffelex_token_kill (orig_t); |
| return (ffelexHandler) (*next) (t); |
| |
| case FFELEX_typeOPEN_PAREN:/* Non-binary op; beginning of I/O list. */ |
| case FFELEX_typeNAME: |
| break; |
| } |
| |
| expr = ffeexpr_finished_ambig_ (orig_ft, expr); |
| |
| /* Here is a kludge whereby we tell the callback function the OPEN_PAREN |
| that preceded the expression starts a list of expressions, and the expr |
| hasn't been wrapped in a corresponding (and possibly collapsed) opPAREN |
| node. The callback function should extract the real expr from the head |
| of this opITEM node after testing it. */ |
| |
| expr = ffebld_new_item (expr, NULL); |
| |
| ffebld_pool_pop (); |
| callback = ffeexpr_stack_->callback; |
| ffelex_token_kill (ffeexpr_stack_->first_token); |
| s = ffeexpr_stack_->previous; |
| malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, sizeof (*ffeexpr_stack_)); |
| ffeexpr_stack_ = s; |
| next = (ffelexHandler) (*callback) (orig_ft, expr, orig_t); |
| ffelex_token_kill (orig_ft); |
| ffelex_token_kill (orig_t); |
| return (ffelexHandler) (*next) (t); |
| } |
| |
| /* ffeexpr_cb_close_paren_c_ -- OPEN_PAREN expr (possible complex) |
| |
| Pass it to ffeexpr_rhs as the callback routine. |
| |
| Makes sure the end token is close-paren and swallows it, or a comma |
| and handles complex/implied-do possibilities, else issues |
| an error message and doesn't swallow the token (passing it along instead). */ |
| |
| static ffelexHandler |
| ffeexpr_cb_close_paren_c_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| /* First check to see if this is a possible complex entity. It is if the |
| token is a comma. */ |
| |
| if (ffelex_token_type (t) == FFELEX_typeCOMMA) |
| { |
| ffeexpr_stack_->tokens[1] = ffelex_token_use (ft); |
| ffeexpr_stack_->expr = expr; |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextPAREN_, ffeexpr_cb_comma_c_); |
| } |
| |
| return (ffelexHandler) ffeexpr_cb_close_paren_ (ft, expr, t); |
| } |
| |
| /* ffeexpr_cb_comma_c_ -- OPEN_PAREN expr COMMA expr |
| |
| Pass it to ffeexpr_rhs as the callback routine. |
| |
| If this token is not a comma, we have a complex constant (or an attempt |
| at one), so handle it accordingly, displaying error messages if the token |
| is not a close-paren. */ |
| |
| static ffelexHandler |
| ffeexpr_cb_comma_c_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffeinfoBasictype lty = (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) |
| { |
| 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_ (char *p) |
| { |
| for (; *p != '\0'; ++p) |
| if (! ISDIGIT (*p)) |
| return FALSE; |
| return TRUE; |
| } |
| |
| /* ffeexpr_exprstack_push_ -- Push an arbitrary expression object onto the stack |
| |
| ffeexprExpr_ e; |
| ffeexpr_exprstack_push_(e); |
| |
| Pushes the expression onto the stack without any analysis of the existing |
| contents of the stack. */ |
| |
| static void |
| ffeexpr_exprstack_push_ (ffeexprExpr_ e) |
| { |
| e->previous = ffeexpr_stack_->exprstack; |
| ffeexpr_stack_->exprstack = e; |
| } |
| |
| /* ffeexpr_exprstack_push_operand_ -- Push an operand onto the stack, reduce? |
| |
| ffeexprExpr_ e; |
| ffeexpr_exprstack_push_operand_(e); |
| |
| Pushes the expression already containing an operand (a constant, variable, |
| or more complicated expression that has already been fully resolved) after |
| analyzing the stack and checking for possible reduction (which will never |
| happen here since the highest precedence operator is ** and it has right- |
| to-left associativity). */ |
| |
| static void |
| ffeexpr_exprstack_push_operand_ (ffeexprExpr_ e) |
| { |
| ffeexpr_exprstack_push_ (e); |
| #ifdef WEIRD_NONFORTRAN_RULES |
| if ((ffeexpr_stack_->exprstack != NULL) |
| && (ffeexpr_stack_->exprstack->expr->type == FFEEXPR_exprtypeBINARY_) |
| && (ffeexpr_stack_->exprstack->expr->u.operator.prec |
| == FFEEXPR_operatorprecedenceHIGHEST_) |
| && (ffeexpr_stack_->exprstack->expr->u.operator.as |
| == FFEEXPR_operatorassociativityL2R_)) |
| ffeexpr_reduce_ (); |
| #endif |
| } |
| |
| /* ffeexpr_exprstack_push_unary_ -- Push a unary operator onto the stack |
| |
| ffeexprExpr_ e; |
| ffeexpr_exprstack_push_unary_(e); |
| |
| Pushes the expression already containing a unary operator. Reduction can |
| never happen since unary operators are themselves always R-L; that is, the |
| top of the expression stack is not an operand, in that it is either empty, |
| has a binary operator at the top, or a unary operator at the top. In any |
| of these cases, reduction is impossible. */ |
| |
| static void |
| ffeexpr_exprstack_push_unary_ (ffeexprExpr_ e) |
| { |
| if ((ffe_is_pedantic () |
| || ffe_is_warn_surprising ()) |
| && (ffeexpr_stack_->exprstack != NULL) |
| && (ffeexpr_stack_->exprstack->type != FFEEXPR_exprtypeOPERAND_) |
| && (ffeexpr_stack_->exprstack->u.operator.prec |
| <= FFEEXPR_operatorprecedenceLOWARITH_) |
| && (e->u.operator.prec <= FFEEXPR_operatorprecedenceLOWARITH_)) |
| { |
| ffebad_start_msg ("Two arithmetic operators in a row at %0 and %1 -- use parentheses", |
| ffe_is_pedantic () |
| ? FFEBAD_severityPEDANTIC |
| : FFEBAD_severityWARNING); |
| ffebad_here (0, |
| ffelex_token_where_line (ffeexpr_stack_->exprstack->token), |
| ffelex_token_where_column (ffeexpr_stack_->exprstack->token)); |
| ffebad_here (1, |
| ffelex_token_where_line (e->token), |
| ffelex_token_where_column (e->token)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_exprstack_push_ (e); |
| } |
| |
| /* ffeexpr_exprstack_push_binary_ -- Push a binary operator onto the stack, reduce? |
| |
| ffeexprExpr_ e; |
| ffeexpr_exprstack_push_binary_(e); |
| |
| Pushes the expression already containing a binary operator after checking |
| whether reduction is possible. If the stack is not empty, the top of the |
| stack must be an operand or syntactic analysis has failed somehow. If |
| the operand is preceded by a unary operator of higher (or equal and L-R |
| associativity) precedence than the new binary operator, then reduce that |
| preceding operator and its operand(s) before pushing the new binary |
| operator. */ |
| |
| static void |
| ffeexpr_exprstack_push_binary_ (ffeexprExpr_ e) |
| { |
| ffeexprExpr_ ce; |
| |
| if (ffe_is_warn_surprising () |
| /* These next two are always true (see assertions below). */ |
| && (ffeexpr_stack_->exprstack != NULL) |
| && (ffeexpr_stack_->exprstack->type == FFEEXPR_exprtypeOPERAND_) |
| /* If the previous operator is a unary minus, and the binary op |
| is of higher precedence, might not do what user expects, |
| e.g. "-2**2" is "-(2**2)", i.e. "-4", not "(-2)**2", which would |
| yield "4". */ |
| && (ffeexpr_stack_->exprstack->previous != NULL) |
| && (ffeexpr_stack_->exprstack->previous->type == FFEEXPR_exprtypeUNARY_) |
| && (ffeexpr_stack_->exprstack->previous->u.operator.op |
| == FFEEXPR_operatorSUBTRACT_) |
| && (e->u.operator.prec |
| < ffeexpr_stack_->exprstack->previous->u.operator.prec)) |
| { |
| ffebad_start_msg ("Operator at %0 has lower precedence than that at %1 -- use parentheses", FFEBAD_severityWARNING); |
| ffebad_here (0, |
| ffelex_token_where_line (ffeexpr_stack_->exprstack->previous->token), |
| ffelex_token_where_column (ffeexpr_stack_->exprstack->previous->token)); |
| ffebad_here (1, |
| ffelex_token_where_line (e->token), |
| ffelex_token_where_column (e->token)); |
| ffebad_finish (); |
| } |
| |
| again: |
| assert (ffeexpr_stack_->exprstack != NULL); |
| assert (ffeexpr_stack_->exprstack->type == FFEEXPR_exprtypeOPERAND_); |
| if ((ce = ffeexpr_stack_->exprstack->previous) != NULL) |
| { |
| assert (ce->type != FFEEXPR_exprtypeOPERAND_); |
| if ((ce->u.operator.prec < e->u.operator.prec) |
| || ((ce->u.operator.prec == e->u.operator.prec) |
| && (e->u.operator.as == FFEEXPR_operatorassociativityL2R_))) |
| { |
| ffeexpr_reduce_ (); |
| goto again; /* :::::::::::::::::::: */ |
| } |
| } |
| |
| ffeexpr_exprstack_push_ (e); |
| } |
| |
| /* ffeexpr_reduce_ -- Reduce highest operator w/operands on stack |
| |
| ffeexpr_reduce_(); |
| |
| Converts operand binop operand or unop operand at top of stack to a |
| single operand having the appropriate ffebld expression, and makes |
| sure that the expression is proper (like not trying to add two character |
| variables, not trying to concatenate two numbers). Also does the |
| requisite type-assignment. */ |
| |
| static void |
| ffeexpr_reduce_ () |
| { |
| ffeexprExpr_ operand; /* This is B in -B or A+B. */ |
| ffeexprExpr_ left_operand; /* When operator is binary, this is A in A+B. */ |
| ffeexprExpr_ operator; /* This is + in A+B. */ |
| ffebld reduced; /* This is +(A,B) in A+B or u-(B) in -B. */ |
| ffebldConstant constnode; /* For checking magical numbers (where mag == |
| -mag). */ |
| ffebld expr; |
| ffebld left_expr; |
| bool submag = FALSE; |
| |
| operand = ffeexpr_stack_->exprstack; |
| assert (operand != NULL); |
| assert (operand->type == FFEEXPR_exprtypeOPERAND_); |
| operator = operand->previous; |
| assert (operator != NULL); |
| assert (operator->type != FFEEXPR_exprtypeOPERAND_); |
| if (operator->type == FFEEXPR_exprtypeUNARY_) |
| { |
| expr = operand->u.operand; |
| switch (operator->u.operator.op) |
| { |
| case FFEEXPR_operatorADD_: |
| reduced = ffebld_new_uplus (expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand); |
| reduced = ffeexpr_reduced_math1_ (reduced, operator, operand); |
| reduced = ffeexpr_collapse_uplus (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorSUBTRACT_: |
| submag = TRUE; /* Ok to negate a magic number. */ |
| reduced = ffebld_new_uminus (expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly1_ (reduced, operator, operand); |
| reduced = ffeexpr_reduced_math1_ (reduced, operator, operand); |
| reduced = ffeexpr_collapse_uminus (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorNOT_: |
| reduced = ffebld_new_not (expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly1log_ (reduced, operator, operand); |
| reduced = ffeexpr_reduced_bool1_ (reduced, operator, operand); |
| reduced = ffeexpr_collapse_not (reduced, operator->token); |
| break; |
| |
| default: |
| assert ("unexpected unary op" != NULL); |
| reduced = NULL; |
| break; |
| } |
| if (!submag |
| && (ffebld_op (expr) == FFEBLD_opCONTER) |
| && (ffebld_conter_orig (expr) == NULL) |
| && ffebld_constant_is_magical (constnode = ffebld_conter (expr))) |
| { |
| ffetarget_integer_bad_magical (operand->token); |
| } |
| ffeexpr_stack_->exprstack = operator->previous; /* Pops unary-op operand |
| off stack. */ |
| ffeexpr_expr_kill_ (operand); |
| operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but |
| save */ |
| operator->u.operand = reduced; /* the line/column ffewhere info. */ |
| ffeexpr_exprstack_push_operand_ (operator); /* Push it back on |
| stack. */ |
| } |
| else |
| { |
| assert (operator->type == FFEEXPR_exprtypeBINARY_); |
| left_operand = operator->previous; |
| assert (left_operand != NULL); |
| assert (left_operand->type == FFEEXPR_exprtypeOPERAND_); |
| expr = operand->u.operand; |
| left_expr = left_operand->u.operand; |
| switch (operator->u.operator.op) |
| { |
| case FFEEXPR_operatorADD_: |
| reduced = ffebld_new_add (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_add (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorSUBTRACT_: |
| submag = TRUE; /* Just to pick the right error if magic |
| number. */ |
| reduced = ffebld_new_subtract (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_subtract (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorMULTIPLY_: |
| reduced = ffebld_new_multiply (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_multiply (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorDIVIDE_: |
| reduced = ffebld_new_divide (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_math2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_divide (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorPOWER_: |
| reduced = ffebld_new_power (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_power_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_power (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorCONCATENATE_: |
| reduced = ffebld_new_concatenate (left_expr, expr); |
| reduced = ffeexpr_reduced_concatenate_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_concatenate (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorLT_: |
| reduced = ffebld_new_lt (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_lt (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorLE_: |
| reduced = ffebld_new_le (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_le (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorEQ_: |
| reduced = ffebld_new_eq (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_eq (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorNE_: |
| reduced = ffebld_new_ne (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_eqop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_ne (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorGT_: |
| reduced = ffebld_new_gt (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_gt (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorGE_: |
| reduced = ffebld_new_ge (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_relop2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_ge (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorAND_: |
| reduced = ffebld_new_and (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_and (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorOR_: |
| reduced = ffebld_new_or (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_or (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorXOR_: |
| reduced = ffebld_new_xor (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_xor (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorEQV_: |
| reduced = ffebld_new_eqv (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_eqv (reduced, operator->token); |
| break; |
| |
| case FFEEXPR_operatorNEQV_: |
| reduced = ffebld_new_neqv (left_expr, expr); |
| if (ffe_is_ugly_logint ()) |
| reduced = ffeexpr_reduced_ugly2log_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_reduced_bool2_ (reduced, left_operand, operator, |
| operand); |
| reduced = ffeexpr_collapse_neqv (reduced, operator->token); |
| break; |
| |
| default: |
| assert ("bad bin op" == NULL); |
| reduced = expr; |
| break; |
| } |
| if ((ffebld_op (left_expr) == FFEBLD_opCONTER) |
| && (ffebld_conter_orig (expr) == NULL) |
| && ffebld_constant_is_magical (constnode = ffebld_conter (left_expr))) |
| { |
| if ((left_operand->previous != NULL) |
| && (left_operand->previous->type != FFEEXPR_exprtypeOPERAND_) |
| && (left_operand->previous->u.operator.op |
| == FFEEXPR_operatorSUBTRACT_)) |
| { |
| if (left_operand->previous->type == FFEEXPR_exprtypeUNARY_) |
| ffetarget_integer_bad_magical_precedence (left_operand->token, |
| left_operand->previous->token, |
| operator->token); |
| else |
| ffetarget_integer_bad_magical_precedence_binary |
| (left_operand->token, |
| left_operand->previous->token, |
| operator->token); |
| } |
| else |
| ffetarget_integer_bad_magical (left_operand->token); |
| } |
| if ((ffebld_op (expr) == FFEBLD_opCONTER) |
| && (ffebld_conter_orig (expr) == NULL) |
| && ffebld_constant_is_magical (constnode = ffebld_conter (expr))) |
| { |
| if (submag) |
| ffetarget_integer_bad_magical_binary (operand->token, |
| operator->token); |
| else |
| ffetarget_integer_bad_magical (operand->token); |
| } |
| ffeexpr_stack_->exprstack = left_operand->previous; /* Pops binary-op |
| operands off stack. */ |
| ffeexpr_expr_kill_ (left_operand); |
| ffeexpr_expr_kill_ (operand); |
| operator->type = FFEEXPR_exprtypeOPERAND_; /* Convert operator, but |
| save */ |
| operator->u.operand = reduced; /* the line/column ffewhere info. */ |
| ffeexpr_exprstack_push_operand_ (operator); /* Push it back on |
| stack. */ |
| } |
| } |
| |
| /* ffeexpr_reduced_bool1_ -- Wrap up reduction of NOT operator |
| |
| reduced = ffeexpr_reduced_bool1_(reduced,op,r); |
| |
| Makes sure the argument for reduced has basictype of |
| LOGICAL or (ugly) INTEGER. If |
| argument has where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_bool1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r) |
| { |
| ffeinfo rinfo, ninfo; |
| ffeinfoBasictype rbt; |
| ffeinfoKindtype rkt; |
| ffeinfoRank rrk; |
| ffeinfoKind rkd; |
| ffeinfoWhere rwh, nwh; |
| |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if (((rbt == FFEINFO_basictypeLOGICAL) |
| || (ffe_is_ugly_logint () && (rbt == FFEINFO_basictypeINTEGER))) |
| && (rrk == 0)) |
| { |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh, |
| FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| return reduced; |
| } |
| |
| if ((rbt != FFEINFO_basictypeLOGICAL) |
| && (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER))) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_NOT_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_NOT_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_bool2_ -- Wrap up reduction of boolean operators |
| |
| reduced = ffeexpr_reduced_bool2_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| LOGICAL or (ugly) INTEGER. Determine common basictype and |
| size for reduction (flag expression for combined hollerith/typeless |
| situations for later determination of effective basictype). If both left |
| and right arguments have where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. Create CONVERT ops for args where |
| needed. Convert typeless |
| constants to the desired type/size explicitly. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_bool2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token); |
| |
| if (((nbt == FFEINFO_basictypeLOGICAL) |
| || (ffe_is_ugly_logint () && (nbt == FFEINFO_basictypeINTEGER))) |
| && (lrk == 0) && (rrk == 0)) |
| { |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh, |
| FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| return reduced; |
| } |
| |
| if ((lbt != FFEINFO_basictypeLOGICAL) |
| && (!ffe_is_ugly_logint () || (lbt != FFEINFO_basictypeINTEGER))) |
| { |
| if ((rbt != FFEINFO_basictypeLOGICAL) |
| && (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER))) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_BOOL_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_BOOL_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else if ((rbt != FFEINFO_basictypeLOGICAL) |
| && (!ffe_is_ugly_logint () || (rbt != FFEINFO_basictypeINTEGER))) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_BOOL_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lrk != 0) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_BOOL_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_BOOL_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_concatenate_ -- Wrap up reduction of concatenate operator |
| |
| reduced = ffeexpr_reduced_concatenate_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| CHARACTER and kind of SCALAR, FUNCTION, or STATEMENT FUNCTION. Assign |
| basictype of CHARACTER and kind of SCALAR to reduced. Calculate effective |
| size of concatenation and assign that size to reduced. If both left and |
| right arguments have where of CONSTANT, assign where CONSTANT to reduced, |
| else assign where FLEETING. |
| |
| If these requirements cannot be met, generate error message using the |
| info in l, op, and r arguments and assign basictype, size, kind, and where |
| of ANY. */ |
| |
| static ffebld |
| ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd, nkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| ffetargetCharacterSize lszm, lszk, rszm, rszk, nszk; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| lszk = ffeinfo_size (linfo); /* Known size. */ |
| lszm = ffebld_size_max (ffebld_left (reduced)); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| rszk = ffeinfo_size (rinfo); /* Known size. */ |
| rszm = ffebld_size_max (ffebld_right (reduced)); |
| |
| if ((lbt == FFEINFO_basictypeCHARACTER) && (rbt == FFEINFO_basictypeCHARACTER) |
| && (lkt == rkt) && (lrk == 0) && (rrk == 0) |
| && (((lszm != FFETARGET_charactersizeNONE) |
| && (rszm != FFETARGET_charactersizeNONE)) |
| || (ffeexpr_context_outer_ (ffeexpr_stack_) |
| == FFEEXPR_contextLET) |
| || (ffeexpr_context_outer_ (ffeexpr_stack_) |
| == FFEEXPR_contextSFUNCDEF))) |
| { |
| nbt = FFEINFO_basictypeCHARACTER; |
| nkd = FFEINFO_kindENTITY; |
| if ((lszk == FFETARGET_charactersizeNONE) |
| || (rszk == FFETARGET_charactersizeNONE)) |
| nszk = FFETARGET_charactersizeNONE; /* Ok only in rhs of LET |
| stmt. */ |
| else |
| nszk = lszk + rszk; |
| |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| nkt = lkt; |
| ninfo = ffeinfo_new (nbt, nkt, 0, nkd, nwh, nszk); |
| ffebld_set_info (reduced, ninfo); |
| return reduced; |
| } |
| |
| if ((lbt != FFEINFO_basictypeCHARACTER) && (rbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_CONCAT_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lbt != FFEINFO_basictypeCHARACTER) |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_CONCAT_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (rbt != FFEINFO_basictypeCHARACTER) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_CONCAT_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if ((lrk != 0) || (lszm == FFETARGET_charactersizeNONE)) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_CONCAT_ARG_KIND)) |
| { |
| char *what; |
| |
| if (lrk != 0) |
| what = "an array"; |
| else |
| what = "of indeterminate length"; |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string (what); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if (ffebad_start (FFEBAD_CONCAT_ARG_KIND)) |
| { |
| char *what; |
| |
| if (rrk != 0) |
| what = "an array"; |
| else |
| what = "of indeterminate length"; |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string (what); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_eqop2_ -- Wrap up reduction of EQ and NE operators |
| |
| reduced = ffeexpr_reduced_eqop2_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| INTEGER, REAL, COMPLEX, or CHARACTER. Determine common basictype and |
| size for reduction. If both left |
| and right arguments have where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. Create CONVERT ops for args where |
| needed. Convert typeless |
| constants to the desired type/size explicitly. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_eqop2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| ffetargetCharacterSize lsz, rsz; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| lsz = ffebld_size_known (ffebld_left (reduced)); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| rsz = ffebld_size_known (ffebld_right (reduced)); |
| |
| ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token); |
| |
| if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL) |
| || (nbt == FFEINFO_basictypeCOMPLEX) || (nbt == FFEINFO_basictypeCHARACTER)) |
| && (lrk == 0) && (rrk == 0)) |
| { |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| if ((lsz != FFETARGET_charactersizeNONE) |
| && (rsz != FFETARGET_charactersizeNONE)) |
| lsz = rsz = (lsz > rsz) ? lsz : rsz; |
| |
| ninfo = ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, FFEINFO_kindENTITY, nwh, FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, nbt, nkt, 0, lsz, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, nbt, nkt, 0, rsz, |
| FFEEXPR_contextLET)); |
| return reduced; |
| } |
| |
| if ((lbt == FFEINFO_basictypeLOGICAL) |
| && (rbt == FFEINFO_basictypeLOGICAL)) |
| { |
| if (ffebad_start_msg ("Use .EQV./.NEQV. instead of .EQ./.NE. at %0 for LOGICAL operands at %1 and %2", |
| FFEBAD_severityFATAL)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL) |
| && (lbt != FFEINFO_basictypeCOMPLEX) && (lbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_EQOP_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_EQOP_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCOMPLEX) && (rbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_EQOP_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lrk != 0) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_EQOP_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_EQOP_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_math1_ -- Wrap up reduction of + - unary operators |
| |
| reduced = ffeexpr_reduced_math1_(reduced,op,r); |
| |
| Makes sure the argument for reduced has basictype of |
| INTEGER, REAL, or COMPLEX. If the argument has where of CONSTANT, |
| assign where CONSTANT to |
| reduced, else assign where FLEETING. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_math1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r) |
| { |
| ffeinfo rinfo, ninfo; |
| ffeinfoBasictype rbt; |
| ffeinfoKindtype rkt; |
| ffeinfoRank rrk; |
| ffeinfoKind rkd; |
| ffeinfoWhere rwh, nwh; |
| |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if (((rbt == FFEINFO_basictypeINTEGER) || (rbt == FFEINFO_basictypeREAL) |
| || (rbt == FFEINFO_basictypeCOMPLEX)) && (rrk == 0)) |
| { |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| ninfo = ffeinfo_new (rbt, rkt, 0, FFEINFO_kindENTITY, nwh, |
| FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| return reduced; |
| } |
| |
| if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_MATH_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_math2_ -- Wrap up reduction of + - * / operators |
| |
| reduced = ffeexpr_reduced_math2_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| INTEGER, REAL, or COMPLEX. Determine common basictype and |
| size for reduction (flag expression for combined hollerith/typeless |
| situations for later determination of effective basictype). If both left |
| and right arguments have where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. Create CONVERT ops for args where |
| needed. Convert typeless |
| constants to the desired type/size explicitly. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_math2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token); |
| |
| if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL) |
| || (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0)) |
| { |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh, |
| FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| return reduced; |
| } |
| |
| if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL) |
| && (lbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((rbt != FFEINFO_basictypeINTEGER) |
| && (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lrk != 0) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_MATH_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_MATH_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_power_ -- Wrap up reduction of ** operator |
| |
| reduced = ffeexpr_reduced_power_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| INTEGER, REAL, or COMPLEX. Determine common basictype and |
| size for reduction (flag expression for combined hollerith/typeless |
| situations for later determination of effective basictype). If both left |
| and right arguments have where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. Create CONVERT ops for args where |
| needed. Note that real**int or complex**int |
| comes out as int = real**int etc with no conversions. |
| |
| If these requirements cannot be met, generate error message using the |
| info in l, op, and r arguments and assign basictype, size, kind, and where |
| of ANY. */ |
| |
| static ffebld |
| ffeexpr_reduced_power_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if ((rbt == FFEINFO_basictypeINTEGER) |
| && ((lbt == FFEINFO_basictypeREAL) |
| || (lbt == FFEINFO_basictypeCOMPLEX))) |
| { |
| nbt = lbt; |
| nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDEFAULT); |
| if (nkt != FFEINFO_kindtypeREALDEFAULT) |
| { |
| nkt = ffeinfo_kindtype_max (nbt, lkt, FFEINFO_kindtypeREALDOUBLE); |
| if (nkt != FFEINFO_kindtypeREALDOUBLE) |
| nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */ |
| } |
| if (rkt == FFEINFO_kindtypeINTEGER4) |
| { |
| ffebad_start_msg ("Unsupported operand for ** at %1 -- converting to default INTEGER", |
| FFEBAD_severityWARNING); |
| ffebad_here (0, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| if (rkt != FFEINFO_kindtypeINTEGERDEFAULT) |
| { |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, |
| FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| rkt = FFEINFO_kindtypeINTEGERDEFAULT; |
| } |
| } |
| else |
| { |
| ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token); |
| |
| #if 0 /* INTEGER4**INTEGER4 works now. */ |
| if ((nbt == FFEINFO_basictypeINTEGER) |
| && (nkt != FFEINFO_kindtypeINTEGERDEFAULT)) |
| nkt = FFEINFO_kindtypeINTEGERDEFAULT; /* Highest kt we can power! */ |
| #endif |
| if (((nbt == FFEINFO_basictypeREAL) |
| || (nbt == FFEINFO_basictypeCOMPLEX)) |
| && (nkt != FFEINFO_kindtypeREALDEFAULT)) |
| { |
| nkt = ffeinfo_kindtype_max (nbt, nkt, FFEINFO_kindtypeREALDOUBLE); |
| if (nkt != FFEINFO_kindtypeREALDOUBLE) |
| nkt = FFEINFO_kindtypeREALDOUBLE; /* Highest kt we can power! */ |
| } |
| /* else Gonna turn into an error below. */ |
| } |
| |
| if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL) |
| || (nbt == FFEINFO_basictypeCOMPLEX)) && (lrk == 0) && (rrk == 0)) |
| { |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| ninfo = ffeinfo_new (nbt, nkt, 0, FFEINFO_kindENTITY, nwh, |
| FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| if (rbt != FFEINFO_basictypeINTEGER) |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, nbt, nkt, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| return reduced; |
| } |
| |
| if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL) |
| && (lbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((rbt != FFEINFO_basictypeINTEGER) |
| && (rbt != FFEINFO_basictypeREAL) && (rbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCOMPLEX)) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_MATH_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lrk != 0) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_MATH_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_MATH_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_relop2_ -- Wrap up reduction of LT, LE, GE, and GT operators |
| |
| reduced = ffeexpr_reduced_relop2_(reduced,l,op,r); |
| |
| Makes sure the left and right arguments for reduced have basictype of |
| INTEGER, REAL, or CHARACTER. Determine common basictype and |
| size for reduction. If both left |
| and right arguments have where of CONSTANT, assign where CONSTANT to |
| reduced, else assign where FLEETING. Create CONVERT ops for args where |
| needed. Convert typeless |
| constants to the desired type/size explicitly. |
| |
| If these requirements cannot be met, generate error message. */ |
| |
| static ffebld |
| ffeexpr_reduced_relop2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo, ninfo; |
| ffeinfoBasictype lbt, rbt, nbt; |
| ffeinfoKindtype lkt, rkt, nkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh, nwh; |
| ffetargetCharacterSize lsz, rsz; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| lsz = ffebld_size_known (ffebld_left (reduced)); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| rsz = ffebld_size_known (ffebld_right (reduced)); |
| |
| ffeexpr_type_combine (&nbt, &nkt, lbt, lkt, rbt, rkt, op->token); |
| |
| if (((nbt == FFEINFO_basictypeINTEGER) || (nbt == FFEINFO_basictypeREAL) |
| || (nbt == FFEINFO_basictypeCHARACTER)) |
| && (lrk == 0) && (rrk == 0)) |
| { |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| nwh = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| nwh = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| nwh = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| if ((lsz != FFETARGET_charactersizeNONE) |
| && (rsz != FFETARGET_charactersizeNONE)) |
| lsz = rsz = (lsz > rsz) ? lsz : rsz; |
| |
| ninfo = ffeinfo_new (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICALDEFAULT, |
| 0, FFEINFO_kindENTITY, nwh, FFETARGET_charactersizeNONE); |
| ffebld_set_info (reduced, ninfo); |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, nbt, nkt, 0, lsz, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, nbt, nkt, 0, rsz, |
| FFEEXPR_contextLET)); |
| return reduced; |
| } |
| |
| if ((lbt != FFEINFO_basictypeINTEGER) && (lbt != FFEINFO_basictypeREAL) |
| && (lbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((lbt != FFEINFO_basictypeANY) && (rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_RELOP_ARGS_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_here (2, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((lbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_RELOP_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else if ((rbt != FFEINFO_basictypeINTEGER) && (rbt != FFEINFO_basictypeREAL) |
| && (rbt != FFEINFO_basictypeCHARACTER)) |
| { |
| if ((rbt != FFEINFO_basictypeANY) |
| && ffebad_start (FFEBAD_RELOP_ARG_TYPE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_finish (); |
| } |
| } |
| else if (lrk != 0) |
| { |
| if ((lkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_RELOP_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (l->token), ffelex_token_where_column (l->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if ((rkd != FFEINFO_kindANY) |
| && ffebad_start (FFEBAD_RELOP_ARG_KIND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (op->token), ffelex_token_where_column (op->token)); |
| ffebad_here (1, ffelex_token_where_line (r->token), ffelex_token_where_column (r->token)); |
| ffebad_string ("an array"); |
| ffebad_finish (); |
| } |
| } |
| |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_ugly1_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL |
| |
| reduced = ffeexpr_reduced_ugly1_(reduced,op,r); |
| |
| Sigh. */ |
| |
| static ffebld |
| ffeexpr_reduced_ugly1_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r) |
| { |
| ffeinfo rinfo; |
| ffeinfoBasictype rbt; |
| ffeinfoKindtype rkt; |
| ffeinfoRank rrk; |
| ffeinfoKind rkd; |
| ffeinfoWhere rwh; |
| |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| r->token, op->token, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = FFEINFO_basictypeINTEGER; |
| rkt = FFEINFO_kindtypeINTEGERDEFAULT; |
| rrk = 0; |
| rkd = FFEINFO_kindENTITY; |
| rwh = ffeinfo_where (rinfo); |
| } |
| |
| if (rbt == FFEINFO_basictypeLOGICAL) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| r->token, op->token, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| } |
| |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_ugly1log_ -- Deal with TYPELESS and HOLLERITH |
| |
| reduced = ffeexpr_reduced_ugly1log_(reduced,op,r); |
| |
| Sigh. */ |
| |
| static ffebld |
| ffeexpr_reduced_ugly1log_ (ffebld reduced, ffeexprExpr_ op, ffeexprExpr_ r) |
| { |
| ffeinfo rinfo; |
| ffeinfoBasictype rbt; |
| ffeinfoKindtype rkt; |
| ffeinfoRank rrk; |
| ffeinfoKind rkd; |
| ffeinfoWhere rwh; |
| |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| r->token, op->token, FFEINFO_basictypeLOGICAL, 0, |
| FFEINFO_kindtypeLOGICALDEFAULT, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| rinfo = ffebld_info (ffebld_left (reduced)); |
| rbt = FFEINFO_basictypeLOGICAL; |
| rkt = FFEINFO_kindtypeLOGICALDEFAULT; |
| rrk = 0; |
| rkd = FFEINFO_kindENTITY; |
| rwh = ffeinfo_where (rinfo); |
| } |
| |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_ugly2_ -- Deal with TYPELESS, HOLLERITH, and LOGICAL |
| |
| reduced = ffeexpr_reduced_ugly2_(reduced,l,op,r); |
| |
| Sigh. */ |
| |
| static ffebld |
| ffeexpr_reduced_ugly2_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo; |
| ffeinfoBasictype lbt, rbt; |
| ffeinfoKindtype lkt, rkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if ((lbt == FFEINFO_basictypeTYPELESS) |
| || (lbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, FFEINFO_basictypeINTEGER, 0, |
| FFEINFO_kindtypeINTEGERDEFAULT, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| linfo = ffebld_info (ffebld_left (reduced)); |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| lbt = rbt = FFEINFO_basictypeINTEGER; |
| lkt = rkt = FFEINFO_kindtypeINTEGERDEFAULT; |
| lrk = rrk = 0; |
| lkd = rkd = FFEINFO_kindENTITY; |
| lwh = ffeinfo_where (linfo); |
| rwh = ffeinfo_where (rinfo); |
| } |
| else |
| { |
| ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced), |
| l->token, ffebld_right (reduced), r->token, |
| FFEEXPR_contextLET)); |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| } |
| } |
| else |
| { |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced), |
| r->token, ffebld_left (reduced), l->token, |
| FFEEXPR_contextLET)); |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| } |
| /* else Leave it alone. */ |
| } |
| |
| if (lbt == FFEINFO_basictypeLOGICAL) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| } |
| |
| if (rbt == FFEINFO_basictypeLOGICAL) |
| { |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| } |
| |
| return reduced; |
| } |
| |
| /* ffeexpr_reduced_ugly2log_ -- Deal with TYPELESS and HOLLERITH |
| |
| reduced = ffeexpr_reduced_ugly2log_(reduced,l,op,r); |
| |
| Sigh. */ |
| |
| static ffebld |
| ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op, |
| ffeexprExpr_ r) |
| { |
| ffeinfo linfo, rinfo; |
| ffeinfoBasictype lbt, rbt; |
| ffeinfoKindtype lkt, rkt; |
| ffeinfoRank lrk, rrk; |
| ffeinfoKind lkd, rkd; |
| ffeinfoWhere lwh, rwh; |
| |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| |
| if ((lbt == FFEINFO_basictypeTYPELESS) |
| || (lbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced), |
| l->token, op->token, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced), |
| r->token, op->token, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET)); |
| linfo = ffebld_info (ffebld_left (reduced)); |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| lbt = rbt = FFEINFO_basictypeLOGICAL; |
| lkt = rkt = FFEINFO_kindtypeLOGICALDEFAULT; |
| lrk = rrk = 0; |
| lkd = rkd = FFEINFO_kindENTITY; |
| lwh = ffeinfo_where (linfo); |
| rwh = ffeinfo_where (rinfo); |
| } |
| else |
| { |
| ffebld_set_left (reduced, ffeexpr_convert_expr (ffebld_left (reduced), |
| l->token, ffebld_right (reduced), r->token, |
| FFEEXPR_contextLET)); |
| linfo = ffebld_info (ffebld_left (reduced)); |
| lbt = ffeinfo_basictype (linfo); |
| lkt = ffeinfo_kindtype (linfo); |
| lrk = ffeinfo_rank (linfo); |
| lkd = ffeinfo_kind (linfo); |
| lwh = ffeinfo_where (linfo); |
| } |
| } |
| else |
| { |
| if ((rbt == FFEINFO_basictypeTYPELESS) |
| || (rbt == FFEINFO_basictypeHOLLERITH)) |
| { |
| ffebld_set_right (reduced, ffeexpr_convert_expr (ffebld_right (reduced), |
| r->token, ffebld_left (reduced), l->token, |
| FFEEXPR_contextLET)); |
| rinfo = ffebld_info (ffebld_right (reduced)); |
| rbt = ffeinfo_basictype (rinfo); |
| rkt = ffeinfo_kindtype (rinfo); |
| rrk = ffeinfo_rank (rinfo); |
| rkd = ffeinfo_kind (rinfo); |
| rwh = ffeinfo_where (rinfo); |
| } |
| /* else Leave it alone. */ |
| } |
| |
| return reduced; |
| } |
| |
| /* Fumble through tokens until a nonmatching CLOSE_PAREN, EOS, or SEMICOLON |
| is found. |
| |
| The idea is to process the tokens as they would be done by normal |
| expression processing, with the key things being telling the lexer |
| when hollerith/character constants are about to happen, until the |
| true closing token is found. */ |
| |
| static ffelexHandler |
| ffeexpr_find_close_paren_ (ffelexToken t, |
| ffelexHandler after) |
| { |
| ffeexpr_find_.after = after; |
| ffeexpr_find_.level = 1; |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_finished_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeCLOSE_PAREN: |
| if (--ffeexpr_find_.level == 0) |
| return (ffelexHandler) ffeexpr_find_.after; |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| |
| case FFELEX_typeCOMMA: |
| case FFELEX_typeCOLON: |
| case FFELEX_typeEQUALS: |
| case FFELEX_typePOINTS: |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| default: |
| if (--ffeexpr_find_.level == 0) |
| return (ffelexHandler) ffeexpr_find_.after (t); |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| } |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_rhs_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeQUOTE: |
| if (ffe_is_vxt ()) |
| return (ffelexHandler) ffeexpr_nil_quote_; |
| ffelex_set_expecting_hollerith (-1, '\"', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| return (ffelexHandler) ffeexpr_nil_apostrophe_; |
| |
| case FFELEX_typeAPOSTROPHE: |
| ffelex_set_expecting_hollerith (-1, '\'', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| return (ffelexHandler) ffeexpr_nil_apostrophe_; |
| |
| case FFELEX_typePERCENT: |
| return (ffelexHandler) ffeexpr_nil_percent_; |
| |
| case FFELEX_typeOPEN_PAREN: |
| ++ffeexpr_find_.level; |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| case FFELEX_typePLUS: |
| case FFELEX_typeMINUS: |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| case FFELEX_typePERIOD: |
| return (ffelexHandler) ffeexpr_nil_period_; |
| |
| case FFELEX_typeNUMBER: |
| ffeexpr_hollerith_count_ = atol (ffelex_token_text (t)); |
| if (ffeexpr_hollerith_count_ > 0) |
| ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_, |
| '\0', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| return (ffelexHandler) ffeexpr_nil_number_; |
| |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| return (ffelexHandler) ffeexpr_nil_name_rhs_; |
| |
| case FFELEX_typeASTERISK: |
| case FFELEX_typeSLASH: |
| case FFELEX_typePOWER: |
| case FFELEX_typeCONCAT: |
| case FFELEX_typeREL_EQ: |
| case FFELEX_typeREL_NE: |
| case FFELEX_typeREL_LE: |
| case FFELEX_typeREL_GE: |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_nil_finished_ (t); |
| } |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_period_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_current_dotdot_ = ffestr_other (t); |
| switch (ffeexpr_current_dotdot_) |
| { |
| case FFESTR_otherNone: |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| |
| case FFESTR_otherTRUE: |
| case FFESTR_otherFALSE: |
| case FFESTR_otherNOT: |
| return (ffelexHandler) ffeexpr_nil_end_period_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_nil_swallow_period_; |
| } |
| break; /* Nothing really reaches here. */ |
| |
| case FFELEX_typeNUMBER: |
| return (ffelexHandler) ffeexpr_nil_real_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| } |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_end_period_ (ffelexToken t) |
| { |
| switch (ffeexpr_current_dotdot_) |
| { |
| case FFESTR_otherNOT: |
| if (ffelex_token_type (t) != FFELEX_typePERIOD) |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| case FFESTR_otherTRUE: |
| case FFESTR_otherFALSE: |
| if (ffelex_token_type (t) != FFELEX_typePERIOD) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| |
| default: |
| assert ("Bad [nil] unary dotdot in ffeexpr_current_dotdot_" == NULL); |
| exit (0); |
| return NULL; |
| } |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_swallow_period_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typePERIOD) |
| return (ffelexHandler) ffeexpr_nil_rhs_ (t); |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_real_ (ffelexToken t) |
| { |
| char d; |
| char *p; |
| |
| if (((ffelex_token_type (t) != FFELEX_typeNAME) |
| && (ffelex_token_type (t) != FFELEX_typeNAMES)) |
| || !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q'))) |
| && ffeexpr_isdigits_ (++p))) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| |
| if (*p == '\0') |
| return (ffelexHandler) ffeexpr_nil_real_exponent_; |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_real_exponent_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| |
| return (ffelexHandler) ffeexpr_nil_real_exp_sign_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_real_exp_sign_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_number_ (ffelexToken t) |
| { |
| char d; |
| char *p; |
| |
| if (ffeexpr_hollerith_count_ > 0) |
| ffelex_set_expecting_hollerith (0, '\0', |
| ffewhere_line_unknown (), |
| ffewhere_column_unknown ()); |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q')) |
| && ffeexpr_isdigits_ (++p)) |
| { |
| if (*p == '\0') |
| { |
| ffeexpr_find_.t = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_nil_number_exponent_; |
| } |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| break; |
| |
| case FFELEX_typePERIOD: |
| ffeexpr_find_.t = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_nil_number_period_; |
| |
| case FFELEX_typeHOLLERITH: |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| |
| default: |
| break; |
| } |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| } |
| |
| /* Expects ffeexpr_find_.t. */ |
| |
| static ffelexHandler |
| ffeexpr_nil_number_exponent_ (ffelexToken t) |
| { |
| ffelexHandler nexthandler; |
| |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| { |
| nexthandler |
| = (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t); |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) (*nexthandler) (t); |
| } |
| |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) ffeexpr_nil_number_exp_sign_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_number_exp_sign_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| /* Expects ffeexpr_find_.t. */ |
| |
| static ffelexHandler |
| ffeexpr_nil_number_period_ (ffelexToken t) |
| { |
| ffelexHandler nexthandler; |
| char d; |
| char *p; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q')) |
| && ffeexpr_isdigits_ (++p)) |
| { |
| if (*p == '\0') |
| return (ffelexHandler) ffeexpr_nil_number_per_exp_; |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| nexthandler |
| = (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t); |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) (*nexthandler) (t); |
| |
| case FFELEX_typeNUMBER: |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) ffeexpr_nil_number_real_; |
| |
| default: |
| break; |
| } |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| } |
| |
| /* Expects ffeexpr_find_.t. */ |
| |
| static ffelexHandler |
| ffeexpr_nil_number_per_exp_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| { |
| ffelexHandler nexthandler; |
| |
| nexthandler |
| = (ffelexHandler) ffeexpr_nil_binary_ (ffeexpr_find_.t); |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) (*nexthandler) (t); |
| } |
| |
| ffelex_token_kill (ffeexpr_find_.t); |
| return (ffelexHandler) ffeexpr_nil_num_per_exp_sign_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_number_real_ (ffelexToken t) |
| { |
| char d; |
| char *p; |
| |
| if (((ffelex_token_type (t) != FFELEX_typeNAME) |
| && (ffelex_token_type (t) != FFELEX_typeNAMES)) |
| || !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q'))) |
| && ffeexpr_isdigits_ (++p))) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| |
| if (*p == '\0') |
| return (ffelexHandler) ffeexpr_nil_number_real_exp_; |
| |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_num_per_exp_sign_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_number_real_exp_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| return (ffelexHandler) ffeexpr_nil_num_real_exp_sn_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_num_real_exp_sn_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| return (ffelexHandler) ffeexpr_nil_binary_ (t); |
| return (ffelexHandler) ffeexpr_nil_binary_; |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_binary_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typePLUS: |
| case FFELEX_typeMINUS: |
| case FFELEX_typeASTERISK: |
| case FFELEX_typeSLASH: |
| case FFELEX_typePOWER: |
| case FFELEX_typeCONCAT: |
| case FFELEX_typeOPEN_ANGLE: |
| case FFELEX_typeCLOSE_ANGLE: |
| case FFELEX_typeREL_EQ: |
| case FFELEX_typeREL_NE: |
| case FFELEX_typeREL_GE: |
| case FFELEX_typeREL_LE: |
| return (ffelexHandler) ffeexpr_nil_rhs_; |
| |
| case FFELEX_typePERIOD: |
| return (ffelexHandler) ffeexpr_nil_binary_period_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_nil_finished_ (t); |
| } |
| } |
| |
| static ffelexHandler |
| ffeexpr_nil_binary_period_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_current_dotdot_ = 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_: |
| case FFEEXPR_contextRETURN: |
| if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0))) |
| break; |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeNONE: |
| error = FALSE; |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; /* expr==NULL ok for substring; element case |
| caught by callback. */ |
| |
| case FFEEXPR_contextDO: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| error = !ffe_is_ugly_logint (); |
| if (!ffeexpr_stack_->is_rhs) |
| break; /* Don't convert lhs variable. */ |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| ffeinfo_kindtype (ffebld_info (expr)), 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| if (!ffeexpr_stack_->is_rhs) |
| { |
| error = TRUE; |
| break; /* Don't convert lhs variable. */ |
| } |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeREAL: |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if (!ffeexpr_stack_->is_rhs |
| && (ffebld_op (expr) != FFEBLD_opSYMTER)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextIF: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeLOGICAL: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextAGOTO: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = (ffeinfo_kindtype (info) != ffecom_label_kind ()); |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| error = !ffe_is_ugly_logint () |
| || (ffeinfo_kindtype (info) != ffecom_label_kind ()); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0) |
| || (ffebld_op (expr) != FFEBLD_opSYMTER)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextFILENUM: /* See equiv code in _ambig_. */ |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextARITHIF: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeREAL: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextSTOP: |
| if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0))) |
| break; |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeNONE: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr != NULL) && ((ffebld_op (expr) != FFEBLD_opCONTER) |
| || (ffebld_conter_orig (expr) != NULL))) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextINCLUDE: |
| error = (expr == NULL) || (ffeinfo_rank (info) != 0) |
| || (ffeinfo_basictype (info) != FFEINFO_basictypeCHARACTER) |
| || (ffebld_op (expr) != FFEBLD_opCONTER) |
| || (ffebld_conter_orig (expr) != NULL); |
| break; |
| |
| case FFEEXPR_contextSELECTCASE: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeCHARACTER: |
| case FFEINFO_basictypeLOGICAL: |
| error = FALSE; |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextCASE: |
| if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0))) |
| break; |
| switch ((expr == NULL) ? FFEINFO_basictypeINTEGER |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeCHARACTER: |
| case FFEINFO_basictypeLOGICAL: |
| error = FALSE; |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0))) |
| break; |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextEQVINDEX_: |
| if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0))) |
| break; |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeNONE: |
| error = FALSE; |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr != NULL) && (ffebld_op (expr) != FFEBLD_opCONTER)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextPARAMETER: |
| if (ffeexpr_stack_->is_rhs) |
| error = (expr == NULL) || (ffeinfo_rank (info) != 0) |
| || (ffebld_op (expr) != FFEBLD_opCONTER); |
| else |
| error = (expr == NULL) || (ffeinfo_rank (info) != 0) |
| || (ffebld_op (expr) != FFEBLD_opSYMTER); |
| break; |
| |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| ffeexpr_stack_->context = FFEEXPR_contextINDEX_; |
| else |
| ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_; |
| goto again; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| ffeexpr_stack_->context = FFEEXPR_contextINDEX_; |
| else |
| ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_; |
| goto again; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_; |
| else |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_; |
| goto again; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFINDEX_; |
| else |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_; |
| goto again; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextIMPDOCTRL_: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| if (!ffeexpr_stack_->is_rhs |
| && (ffebld_op (expr) != FFEBLD_opSYMTER)) |
| error = TRUE; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| error = error && !ffe_is_ugly_logint (); |
| if (!ffeexpr_stack_->is_rhs) |
| break; /* Don't convert lhs variable. */ |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| ffeinfo_kindtype (ffebld_info (expr)), 0, |
| FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| if (!ffeexpr_stack_->is_rhs |
| && ffe_is_warn_surprising () |
| && !error) |
| { |
| ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */ |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_string (ffelex_token_text (ft)); |
| ffebad_finish (); |
| } |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOCTRL_: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| if (ffeexpr_stack_->is_rhs) |
| { |
| if ((ffebld_op (expr) != FFEBLD_opCONTER) |
| && (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE)) |
| error = TRUE; |
| } |
| else if ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| || (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE)) |
| error = TRUE; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| error = error |
| && (ffeinfo_kindtype (info) != FFEINFO_kindtypeLOGICALDEFAULT); |
| if (!ffeexpr_stack_->is_rhs) |
| break; /* Don't convert lhs variable. */ |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| error = error && |
| (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT); |
| break; |
| |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeREAL: |
| if (!ffeexpr_stack_->is_rhs |
| && ffe_is_warn_surprising () |
| && !error) |
| { |
| ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */ |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_string (ffelex_token_text (ft)); |
| ffebad_finish (); |
| } |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextIMPDOITEM_: |
| if (ffelex_token_type (t) == FFELEX_typeEQUALS) |
| { |
| ffeexpr_stack_->is_rhs = FALSE; |
| ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_; |
| goto again; /* :::::::::::::::::::: */ |
| } |
| /* Fall through. */ |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| break; |
| } |
| error = (expr == NULL) |
| || ((ffeinfo_rank (info) != 0) |
| && ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| || (ffesymbol_arraysize (ffebld_symter (expr)) == NULL) |
| || (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr))) |
| == FFEBLD_opSTAR))); /* Bad if null expr, or if |
| array that is not a SYMTER |
| (can't happen yet, I |
| think) or has a NULL or |
| STAR (assumed) array |
| size. */ |
| break; |
| |
| case FFEEXPR_contextIMPDOITEMDF_: |
| if (ffelex_token_type (t) == FFELEX_typeEQUALS) |
| { |
| ffeexpr_stack_->is_rhs = FALSE; |
| ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_; |
| goto again; /* :::::::::::::::::::: */ |
| } |
| /* Fall through. */ |
| case FFEEXPR_contextIOLISTDF: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| break; |
| } |
| error |
| = (expr == NULL) |
| || ((ffeinfo_basictype (info) == FFEINFO_basictypeCHARACTER) |
| && (ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT)) |
| || ((ffeinfo_rank (info) != 0) |
| && ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| || (ffesymbol_arraysize (ffebld_symter (expr)) == NULL) |
| || (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr))) |
| == FFEBLD_opSTAR))); /* Bad if null expr, |
| non-default-kindtype |
| character expr, or if |
| array that is not a SYMTER |
| (can't happen yet, I |
| think) or has a NULL or |
| STAR (assumed) array |
| size. */ |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| error = (expr == NULL) |
| || (ffebld_op (expr) != FFEBLD_opARRAYREF) |
| || ((ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR) |
| && (ffeinfo_where (info) != FFEINFO_whereFLEETING_IADDR)); |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOINDEX_: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((ffeinfo_where (info) != FFEINFO_whereCONSTANT) |
| && (ffeinfo_where (info) != FFEINFO_whereIMMEDIATE)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextDATA: |
| if (expr == NULL) |
| error = TRUE; |
| else if (ffeexpr_stack_->is_rhs) |
| error = (ffebld_op (expr) != FFEBLD_opCONTER); |
| else if (ffebld_op (expr) == FFEBLD_opSYMTER) |
| error = FALSE; |
| else |
| error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR); |
| break; |
| |
| case FFEEXPR_contextINITVAL: |
| error = (expr == NULL) || (ffebld_op (expr) != FFEBLD_opCONTER); |
| break; |
| |
| case FFEEXPR_contextEQUIVALENCE: |
| if (expr == NULL) |
| error = TRUE; |
| else if (ffebld_op (expr) == FFEBLD_opSYMTER) |
| error = FALSE; |
| else |
| error = (ffeinfo_where (info) != FFEINFO_whereFLEETING_CADDR); |
| break; |
| |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILEDFINT: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILELOG: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILECHAR: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeCHARACTER: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILENUMCHAR: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeCHARACTER: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextFILEDFCHAR: |
| if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0))) |
| break; |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeCHARACTER: |
| error |
| = (ffeinfo_kindtype (info) |
| != FFEINFO_kindtypeCHARACTERDEFAULT); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if (!ffeexpr_stack_->is_rhs |
| && (ffebld_op (expr) == FFEBLD_opSUBSTR)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILEUNIT: /* See equiv code in _ambig_. */ |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| if ((error = (ffeinfo_rank (info) != 0))) |
| break; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if ((error = (ffeinfo_rank (info) != 0))) |
| break; |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| if ((error = (ffeinfo_rank (info) != 0))) |
| break; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffebld_op (expr)) |
| { /* As if _lhs had been called instead of |
| _rhs. */ |
| case FFEBLD_opSYMTER: |
| error |
| = (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT); |
| break; |
| |
| case FFEBLD_opSUBSTR: |
| error = (ffeinfo_where (ffebld_info (expr)) |
| == FFEINFO_whereCONSTANT_SUBOBJECT); |
| break; |
| |
| case FFEBLD_opARRAYREF: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if (!error |
| && ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT) |
| || ((ffeinfo_rank (info) != 0) |
| && ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| || (ffesymbol_arraysize (ffebld_symter (expr)) == NULL) |
| || (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr))) |
| == FFEBLD_opSTAR))))) /* Bad if |
| non-default-kindtype |
| character expr, or if |
| array that is not a SYMTER |
| (can't happen yet, I |
| think), or has a NULL or |
| STAR (assumed) array |
| size. */ |
| error = TRUE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextFILEFORMAT: |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeINTEGER: |
| error = (expr == NULL) |
| || ((ffeinfo_rank (info) != 0) ? |
| ffe_is_pedantic () /* F77 C5. */ |
| : (ffeinfo_kindtype (info) != ffecom_label_kind ())) |
| || (ffebld_op (expr) != FFEBLD_opSYMTER); |
| break; |
| |
| case FFEINFO_basictypeLOGICAL: |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| /* F77 C5 -- must be an array of hollerith. */ |
| error |
| = ffe_is_pedantic () |
| || (ffeinfo_rank (info) == 0); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| if ((ffeinfo_kindtype (info) != FFEINFO_kindtypeCHARACTERDEFAULT) |
| || ((ffeinfo_rank (info) != 0) |
| && ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| || (ffesymbol_arraysize (ffebld_symter (expr)) == NULL) |
| || (ffebld_op (ffesymbol_arraysize (ffebld_symter (expr))) |
| == FFEBLD_opSTAR)))) /* Bad if |
| non-default-kindtype |
| character expr, or if |
| array that is not a SYMTER |
| (can't happen yet, I |
| think), or has a NULL or |
| STAR (assumed) array |
| size. */ |
| error = TRUE; |
| else |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextLOC_: |
| /* See also ffeintrin_check_loc_. */ |
| if ((expr == NULL) |
| || (ffeinfo_kind (info) != FFEINFO_kindENTITY) |
| || ((ffebld_op (expr) != FFEBLD_opSYMTER) |
| && (ffebld_op (expr) != FFEBLD_opSUBSTR) |
| && (ffebld_op (expr) != FFEBLD_opARRAYREF))) |
| error = TRUE; |
| break; |
| |
| default: |
| error = FALSE; |
| break; |
| } |
| |
| if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY))) |
| { |
| ffebad_start (FFEBAD_EXPR_WRONG); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| expr = ffebld_new_any (); |
| ffebld_set_info (expr, ffeinfo_new_any ()); |
| } |
| |
| callback = ffeexpr_stack_->callback; |
| s = ffeexpr_stack_->previous; |
| malloc_kill_ks (ffe_pool_program_unit (), ffeexpr_stack_, |
| sizeof (*ffeexpr_stack_)); |
| ffeexpr_stack_ = s; |
| next = (ffelexHandler) (*callback) (ft, expr, t); |
| ffelex_token_kill (ft); |
| return (ffelexHandler) next; |
| } |
| |
| /* ffeexpr_finished_ambig_ -- Check validity of ambiguous unit/form spec |
| |
| ffebld expr; |
| expr = ffeexpr_finished_ambig_(expr); |
| |
| Replicates a bit of ffeexpr_finished_'s task when in a context |
| of UNIT or FORMAT. */ |
| |
| static ffebld |
| ffeexpr_finished_ambig_ (ffelexToken ft, ffebld expr) |
| { |
| ffeinfo info = ffebld_info (expr); |
| bool error; |
| |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFILENUMAMBIG: /* Same as FILENUM in _finished_. */ |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = FALSE; |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| if ((expr == NULL) || (ffeinfo_rank (info) != 0)) |
| error = TRUE; |
| break; |
| |
| case FFEEXPR_contextFILEUNITAMBIG: /* Same as FILEUNIT in _finished_. */ |
| if ((expr != NULL) && (ffebld_op (expr) == FFEBLD_opSTAR)) |
| { |
| error = FALSE; |
| break; |
| } |
| switch ((expr == NULL) ? FFEINFO_basictypeNONE |
| : ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeLOGICAL: |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL, |
| FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| /* Fall through. */ |
| case FFEINFO_basictypeREAL: |
| case FFEINFO_basictypeCOMPLEX: |
| if (ffe_is_pedantic ()) |
| { |
| error = TRUE; |
| break; |
| } |
| /* Fall through. */ |
| case FFEINFO_basictypeINTEGER: |
| case FFEINFO_basictypeHOLLERITH: |
| case FFEINFO_basictypeTYPELESS: |
| error = (ffeinfo_rank (info) != 0); |
| expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE, |
| FFEEXPR_contextLET); |
| break; |
| |
| case FFEINFO_basictypeCHARACTER: |
| switch (ffebld_op (expr)) |
| { /* As if _lhs had been called instead of |
| _rhs. */ |
| case FFEBLD_opSYMTER: |
| error |
| = (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereCONSTANT); |
| break; |
| |
| case FFEBLD_opSUBSTR: |
| error = (ffeinfo_where (ffebld_info (expr)) |
| == FFEINFO_whereCONSTANT_SUBOBJECT); |
| break; |
| |
| case FFEBLD_opARRAYREF: |
| error = FALSE; |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| default: |
| error = TRUE; |
| break; |
| } |
| break; |
| |
| default: |
| assert ("bad context" == NULL); |
| error = TRUE; |
| break; |
| } |
| |
| if (error && ((expr == NULL) || (ffebld_op (expr) != FFEBLD_opANY))) |
| { |
| ffebad_start (FFEBAD_EXPR_WRONG); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| expr = ffebld_new_any (); |
| ffebld_set_info (expr, ffeinfo_new_any ()); |
| } |
| |
| return expr; |
| } |
| |
| /* ffeexpr_token_lhs_ -- Initial state for lhs expression |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Basically a smaller version of _rhs_; keep them both in sync, of course. */ |
| |
| static ffelexHandler |
| ffeexpr_token_lhs_ (ffelexToken t) |
| { |
| |
| /* When changing the list of valid initial lhs tokens, check whether to |
| update a corresponding list in ffeexpr_cb_close_paren_ambig_1_ for the |
| READ (expr) <token> case -- it assumes it knows which tokens <token> can |
| be to indicate an lhs (or implied DO), which right now is the set |
| {NAME,OPEN_PAREN}. |
| |
| This comment also appears in ffeexpr_token_first_lhs_. */ |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_name_lhs_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_rhs_ -- Initial state for rhs expression |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| The initial state and the post-binary-operator state are the same and |
| both handled here, with the expression stack used to distinguish |
| between them. Binary operators are invalid here; unary operators, |
| constants, subexpressions, and name references are valid. */ |
| |
| static ffelexHandler |
| ffeexpr_token_rhs_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeQUOTE: |
| if (ffe_is_vxt ()) |
| { |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_quote_; |
| } |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| ffelex_set_expecting_hollerith (-1, '\"', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| /* Don't have to unset this one. */ |
| return (ffelexHandler) ffeexpr_token_apostrophe_; |
| |
| case FFELEX_typeAPOSTROPHE: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| ffelex_set_expecting_hollerith (-1, '\'', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| /* Don't have to unset this one. */ |
| return (ffelexHandler) ffeexpr_token_apostrophe_; |
| |
| case FFELEX_typePERCENT: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_percent_; |
| |
| case FFELEX_typeOPEN_PAREN: |
| ffeexpr_stack_->tokens[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextPAREN_, |
| ffeexpr_cb_close_paren_c_); |
| |
| case FFELEX_typePLUS: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeUNARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorADD_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceADD_; |
| e->u.operator.as = FFEEXPR_operatorassociativityADD_; |
| ffeexpr_exprstack_push_unary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeMINUS: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeUNARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorSUBTRACT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_; |
| e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_; |
| ffeexpr_exprstack_push_unary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typePERIOD: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_period_; |
| |
| case FFELEX_typeNUMBER: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| ffeexpr_hollerith_count_ = atol (ffelex_token_text (t)); |
| if (ffeexpr_hollerith_count_ > 0) |
| ffelex_set_expecting_hollerith (ffeexpr_hollerith_count_, |
| '\0', |
| ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| return (ffelexHandler) ffeexpr_token_number_; |
| |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextACTUALARG_: |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| return (ffelexHandler) ffeexpr_token_name_arg_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_token_name_rhs_; |
| } |
| |
| case FFELEX_typeASTERISK: |
| case FFELEX_typeSLASH: |
| case FFELEX_typePOWER: |
| case FFELEX_typeCONCAT: |
| case FFELEX_typeREL_EQ: |
| case FFELEX_typeREL_NE: |
| case FFELEX_typeREL_LE: |
| case FFELEX_typeREL_GE: |
| if (ffest_ffebad_start (FFEBAD_MISSING_FIRST_BINARY_OPERAND)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| #if 0 |
| case FFELEX_typeEQUALS: |
| case FFELEX_typePOINTS: |
| case FFELEX_typeCLOSE_ANGLE: |
| case FFELEX_typeCLOSE_PAREN: |
| case FFELEX_typeCOMMA: |
| case FFELEX_typeCOLON: |
| case FFELEX_typeEOS: |
| case FFELEX_typeSEMICOLON: |
| #endif |
| default: |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_period_ -- Rhs PERIOD |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle a period detected at rhs (expecting unary op or operand) state. |
| Must begin a floating-point value (as in .12) or a dot-dot name, of |
| which only .NOT., .TRUE., and .FALSE. are truly valid. Other sort-of- |
| valid names represent binary operators, which are invalid here because |
| there isn't an operand at the top of the stack. */ |
| |
| static ffelexHandler |
| ffeexpr_token_period_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_current_dotdot_ = 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; |
| char *p; |
| |
| if (((ffelex_token_type (t) != FFELEX_typeNAME) |
| && (ffelex_token_type (t) != FFELEX_typeNAMES)) |
| || !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q'))) |
| && ffeexpr_isdigits_ (++p))) |
| { |
| #if 0 |
| /* This code has been removed because it seems inconsistent to |
| produce a diagnostic in this case, but not all of the other |
| ones that look for an exponent and cannot recognize one. */ |
| if (((ffelex_token_type (t) == FFELEX_typeNAME) |
| || (ffelex_token_type (t) == FFELEX_typeNAMES)) |
| && ffest_ffebad_start (FFEBAD_INVALID_EXPONENT)) |
| { |
| char bad[2]; |
| |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| bad[0] = *(p - 1); |
| bad[1] = '\0'; |
| ffebad_string (bad); |
| ffebad_finish (); |
| } |
| #endif |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL, |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| /* Just exponent character by itself? In which case, PLUS or MINUS must |
| surely be next, followed by a NUMBER token. */ |
| |
| if (*p == '\0') |
| { |
| ffeexpr_tokens_[2] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_real_exponent_; |
| } |
| |
| ffeexpr_make_float_const_ (d, NULL, ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| t, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_real_exponent_ -- Rhs PERIOD NUMBER NAME(D, E, or Q) |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Ensures this token is PLUS or MINUS, preserves it, goes to final state |
| for real number (exponent digits). Else issues diagnostic, assumes a |
| zero exponent field for number, passes token on to binary state as if |
| previous token had been "E0" instead of "E", for example. */ |
| |
| static ffelexHandler |
| ffeexpr_token_real_exponent_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| { |
| if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]), |
| ffelex_token_where_column (ffeexpr_tokens_[2])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL, |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| ffeexpr_tokens_[3] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_real_exp_sign_; |
| } |
| |
| /* ffeexpr_token_real_exp_sign_ -- Rhs PERIOD NUMBER NAME(D,E,Q) PLUS/MINUS |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Make sure token is a NUMBER, make a real constant out of all we have and |
| push it onto the expression stack. Else issue diagnostic and pretend |
| exponent field was a zero. */ |
| |
| static ffelexHandler |
| ffeexpr_token_real_exp_sign_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| { |
| if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]), |
| ffelex_token_where_column (ffeexpr_tokens_[2])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), NULL, |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0], NULL, |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], ffeexpr_tokens_[2], |
| ffeexpr_tokens_[3], t); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_number_ -- Rhs NUMBER |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| If the token is a period, we may have a floating-point number, or an |
| integer followed by a dotdot binary operator. If the token is a name |
| beginning with D, E, or Q, we definitely have a floating-point number. |
| If the token is a hollerith constant, that's what we've got, so push |
| it onto the expression stack and continue with the binary state. |
| |
| Otherwise, we have an integer followed by something the binary state |
| should be able to swallow. */ |
| |
| static ffelexHandler |
| ffeexpr_token_number_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffeinfo ni; |
| char d; |
| char *p; |
| |
| if (ffeexpr_hollerith_count_ > 0) |
| ffelex_set_expecting_hollerith (0, '\0', |
| ffewhere_line_unknown (), |
| ffewhere_column_unknown ()); |
| |
| /* See if we've got a floating-point number here. */ |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q')) |
| && ffeexpr_isdigits_ (++p)) |
| { |
| |
| /* Just exponent character by itself? In which case, PLUS or MINUS |
| must surely be next, followed by a NUMBER token. */ |
| |
| if (*p == '\0') |
| { |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_number_exponent_; |
| } |
| ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], NULL, NULL, t, |
| NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| break; |
| |
| case FFELEX_typePERIOD: |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_number_period_; |
| |
| case FFELEX_typeHOLLERITH: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_hollerith (t)); |
| ni = ffeinfo_new (FFEINFO_basictypeHOLLERITH, FFEINFO_kindtypeNONE, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, |
| ffelex_token_length (t)); |
| ffebld_set_info (e->u.operand, ni); |
| ffeexpr_exprstack_push_operand_ (e); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| |
| default: |
| break; |
| } |
| |
| /* Nothing specific we were looking for, so make an integer and pass the |
| current token to the binary state. */ |
| |
| 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; |
| char *p; |
| char d; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| if ((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q')) |
| && ffeexpr_isdigits_ (++p)) |
| { |
| |
| /* Just exponent character by itself? In which case, PLUS or MINUS |
| must surely be next, followed by a NUMBER token. */ |
| |
| if (*p == '\0') |
| { |
| ffeexpr_tokens_[2] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_number_per_exp_; |
| } |
| ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], |
| ffeexpr_tokens_[1], NULL, t, NULL, |
| NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| /* A name not representing an exponent, so assume it will be something |
| like EQ, make an integer from the number, pass the period to binary |
| state and the current token to the resulting state. */ |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault |
| (ffeexpr_tokens_[0])); |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| ffeexpr_exprstack_push_operand_ (e); |
| nexthandler = (ffelexHandler) ffeexpr_token_binary_ |
| (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) (*nexthandler) (t); |
| |
| case FFELEX_typeNUMBER: |
| ffeexpr_tokens_[2] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_number_real_; |
| |
| default: |
| break; |
| } |
| |
| /* Nothing specific we were looking for, so make a real number and pass the |
| period and then the current token to the binary state. */ |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| /* ffeexpr_token_number_per_exp_ -- Rhs NUMBER PERIOD NAME(D, E, or Q) |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Ensures this token is PLUS or MINUS, preserves it, goes to final state |
| for real number (exponent digits). Else treats number as real, passes |
| name to binary, passes current token to subsequent handler. */ |
| |
| static ffelexHandler |
| ffeexpr_token_number_per_exp_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| { |
| ffelexHandler nexthandler; |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| nexthandler = (ffelexHandler) ffeexpr_token_binary_ (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) (*nexthandler) (t); |
| } |
| |
| ffeexpr_tokens_[3] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_num_per_exp_sign_; |
| } |
| |
| /* ffeexpr_token_number_real_ -- Rhs NUMBER PERIOD NUMBER |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| After a number, period, and number, check next token for possible |
| exponent designation (D, E, or Q as first/only character) and continue |
| real-number handling accordingly. Else form basic real constant, push |
| onto expression stack, and enter binary state using current token (which, |
| if it is a name not beginning with D, E, or Q, will certainly result |
| in an error, but that's not for this routine to deal with). */ |
| |
| static ffelexHandler |
| ffeexpr_token_number_real_ (ffelexToken t) |
| { |
| char d; |
| char *p; |
| |
| if (((ffelex_token_type (t) != FFELEX_typeNAME) |
| && (ffelex_token_type (t) != FFELEX_typeNAMES)) |
| || !(((ffesrc_char_match_init ((d = *(p = ffelex_token_text (t))), |
| 'D', 'd') |
| || ffesrc_char_match_init (d, 'E', 'e') |
| || ffesrc_char_match_init (d, 'Q', 'q'))) |
| && ffeexpr_isdigits_ (++p))) |
| { |
| #if 0 |
| /* This code has been removed because it seems inconsistent to |
| produce a diagnostic in this case, but not all of the other |
| ones that look for an exponent and cannot recognize one. */ |
| if (((ffelex_token_type (t) == FFELEX_typeNAME) |
| || (ffelex_token_type (t) == FFELEX_typeNAMES)) |
| && ffest_ffebad_start (FFEBAD_INVALID_EXPONENT)) |
| { |
| char bad[2]; |
| |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| bad[0] = *(p - 1); |
| bad[1] = '\0'; |
| ffebad_string (bad); |
| ffebad_finish (); |
| } |
| #endif |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| ffeexpr_tokens_[2], NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| /* Just exponent character by itself? In which case, PLUS or MINUS must |
| surely be next, followed by a NUMBER token. */ |
| |
| if (*p == '\0') |
| { |
| ffeexpr_tokens_[3] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_number_real_exp_; |
| } |
| |
| ffeexpr_make_float_const_ (d, ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| ffeexpr_tokens_[2], t, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_num_per_exp_sign_ -- Rhs NUMBER PERIOD NAME(D,E,Q) PLUS/MINUS |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Make sure token is a NUMBER, make a real constant out of all we have and |
| push it onto the expression stack. Else issue diagnostic and pretend |
| exponent field was a zero. */ |
| |
| static ffelexHandler |
| ffeexpr_token_num_per_exp_sign_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| { |
| if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[2]), |
| ffelex_token_where_column (ffeexpr_tokens_[2])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| NULL, NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[2])[0], |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], NULL, |
| ffeexpr_tokens_[2], ffeexpr_tokens_[3], t); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_number_real_exp_ -- Rhs NUMBER PERIOD NUMBER NAME(D, E, or Q) |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Ensures this token is PLUS or MINUS, preserves it, goes to final state |
| for real number (exponent digits). Else issues diagnostic, assumes a |
| zero exponent field for number, passes token on to binary state as if |
| previous token had been "E0" instead of "E", for example. */ |
| |
| static ffelexHandler |
| ffeexpr_token_number_real_exp_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typePLUS) |
| && (ffelex_token_type (t) != FFELEX_typeMINUS)) |
| { |
| if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]), |
| ffelex_token_where_column (ffeexpr_tokens_[3])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| ffeexpr_tokens_[2], NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| ffeexpr_tokens_[4] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_num_real_exp_sn_; |
| } |
| |
| /* ffeexpr_token_num_real_exp_sn_ -- Rhs NUMBER PERIOD NUMBER NAME(D,E,Q) |
| PLUS/MINUS |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Make sure token is a NUMBER, make a real constant out of all we have and |
| push it onto the expression stack. Else issue diagnostic and pretend |
| exponent field was a zero. */ |
| |
| static ffelexHandler |
| ffeexpr_token_num_real_exp_sn_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| { |
| if (ffest_ffebad_start (FFEBAD_MISSING_EXPONENT_VALUE)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[3]), |
| ffelex_token_where_column (ffeexpr_tokens_[3])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_make_float_const_ (ffesrc_char_internal_init ('E', 'e'), |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| ffeexpr_tokens_[2], NULL, NULL, NULL); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| ffelex_token_kill (ffeexpr_tokens_[4]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| ffeexpr_make_float_const_ (ffelex_token_text (ffeexpr_tokens_[3])[0], |
| ffeexpr_tokens_[0], ffeexpr_tokens_[1], |
| ffeexpr_tokens_[2], ffeexpr_tokens_[3], |
| ffeexpr_tokens_[4], t); |
| |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| ffelex_token_kill (ffeexpr_tokens_[3]); |
| ffelex_token_kill (ffeexpr_tokens_[4]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_binary_ -- Handle binary operator possibility |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| The possibility of a binary operator is handled here, meaning the previous |
| token was an operand. */ |
| |
| static ffelexHandler |
| ffeexpr_token_binary_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| |
| if (!ffeexpr_stack_->is_rhs) |
| return (ffelexHandler) ffeexpr_finished_ (t); /* For now. */ |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typePLUS: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorADD_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceADD_; |
| e->u.operator.as = FFEEXPR_operatorassociativityADD_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeMINUS: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorSUBTRACT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceSUBTRACT_; |
| e->u.operator.as = FFEEXPR_operatorassociativitySUBTRACT_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeASTERISK: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextDATA: |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorMULTIPLY_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceMULTIPLY_; |
| e->u.operator.as = FFEEXPR_operatorassociativityMULTIPLY_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeSLASH: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextDATA: |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorDIVIDE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceDIVIDE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityDIVIDE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typePOWER: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorPOWER_; |
| e->u.operator.prec = FFEEXPR_operatorprecedencePOWER_; |
| e->u.operator.as = FFEEXPR_operatorassociativityPOWER_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeCONCAT: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorCONCATENATE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeOPEN_ANGLE: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorLT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceLT_; |
| e->u.operator.as = FFEEXPR_operatorassociativityLT_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeCLOSE_ANGLE: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| return ffeexpr_finished_ (t); |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorGT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceGT_; |
| e->u.operator.as = FFEEXPR_operatorassociativityGT_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeREL_EQ: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorEQ_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_; |
| e->u.operator.as = FFEEXPR_operatorassociativityEQ_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeREL_NE: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorNE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceNE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityNE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeREL_LE: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorLE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceLE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityLE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typeREL_GE: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextFORMAT: |
| ffebad_start (FFEBAD_FORMAT_EXPR_TOKEN); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorGE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceGE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityGE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| |
| case FFELEX_typePERIOD: |
| ffeexpr_tokens_[0] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_binary_period_; |
| |
| #if 0 |
| case FFELEX_typeOPEN_PAREN: |
| case FFELEX_typeCLOSE_PAREN: |
| case FFELEX_typeEQUALS: |
| case FFELEX_typePOINTS: |
| case FFELEX_typeCOMMA: |
| case FFELEX_typeCOLON: |
| case FFELEX_typeEOS: |
| case FFELEX_typeSEMICOLON: |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| #endif |
| default: |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_binary_period_ -- Binary PERIOD |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle a period detected at binary (expecting binary op or end) state. |
| Must begin a dot-dot name, of which .NOT., .TRUE., and .FALSE. are not |
| valid. */ |
| |
| static ffelexHandler |
| ffeexpr_token_binary_period_ (ffelexToken t) |
| { |
| ffeexprExpr_ operand; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_current_dotdot_ = ffestr_other (t); |
| switch (ffeexpr_current_dotdot_) |
| { |
| case FFESTR_otherTRUE: |
| case FFESTR_otherFALSE: |
| case FFESTR_otherNOT: |
| if (ffest_ffebad_start (FFEBAD_MISSING_BINARY_OPERATOR)) |
| { |
| operand = ffeexpr_stack_->exprstack; |
| assert (operand != NULL); |
| assert (operand->type == FFEEXPR_exprtypeOPERAND_); |
| ffebad_here (0, ffelex_token_where_line (operand->token), ffelex_token_where_column (operand->token)); |
| ffebad_here (1, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| return (ffelexHandler) ffeexpr_token_binary_sw_per_; |
| |
| default: |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_binary_end_per_; |
| } |
| break; /* Nothing really reaches here. */ |
| |
| default: |
| if (ffest_ffebad_start (FFEBAD_IGNORING_PERIOD)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_binary_end_per_ -- Binary PERIOD NAME(not NOT, TRUE, or FALSE) |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Expecting a period to close a dot-dot at binary (binary op |
| or operator) state. If period isn't found, issue a diagnostic but |
| pretend we saw one. ffeexpr_current_dotdot_ must already contained the |
| dotdot representation of the name in between the two PERIOD tokens. */ |
| |
| static ffelexHandler |
| ffeexpr_token_binary_end_per_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffeexpr_tokens_[0]; |
| |
| switch (ffeexpr_current_dotdot_) |
| { |
| case FFESTR_otherAND: |
| e->u.operator.op = FFEEXPR_operatorAND_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceAND_; |
| e->u.operator.as = FFEEXPR_operatorassociativityAND_; |
| break; |
| |
| case FFESTR_otherOR: |
| e->u.operator.op = FFEEXPR_operatorOR_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceOR_; |
| e->u.operator.as = FFEEXPR_operatorassociativityOR_; |
| break; |
| |
| case FFESTR_otherXOR: |
| e->u.operator.op = FFEEXPR_operatorXOR_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceXOR_; |
| e->u.operator.as = FFEEXPR_operatorassociativityXOR_; |
| break; |
| |
| case FFESTR_otherEQV: |
| e->u.operator.op = FFEEXPR_operatorEQV_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceEQV_; |
| e->u.operator.as = FFEEXPR_operatorassociativityEQV_; |
| break; |
| |
| case FFESTR_otherNEQV: |
| e->u.operator.op = FFEEXPR_operatorNEQV_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceNEQV_; |
| e->u.operator.as = FFEEXPR_operatorassociativityNEQV_; |
| break; |
| |
| case FFESTR_otherLT: |
| e->u.operator.op = FFEEXPR_operatorLT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceLT_; |
| e->u.operator.as = FFEEXPR_operatorassociativityLT_; |
| break; |
| |
| case FFESTR_otherLE: |
| e->u.operator.op = FFEEXPR_operatorLE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceLE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityLE_; |
| break; |
| |
| case FFESTR_otherEQ: |
| e->u.operator.op = FFEEXPR_operatorEQ_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_; |
| e->u.operator.as = FFEEXPR_operatorassociativityEQ_; |
| break; |
| |
| case FFESTR_otherNE: |
| e->u.operator.op = FFEEXPR_operatorNE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceNE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityNE_; |
| break; |
| |
| case FFESTR_otherGT: |
| e->u.operator.op = FFEEXPR_operatorGT_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceGT_; |
| e->u.operator.as = FFEEXPR_operatorassociativityGT_; |
| break; |
| |
| case FFESTR_otherGE: |
| e->u.operator.op = FFEEXPR_operatorGE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceGE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityGE_; |
| break; |
| |
| default: |
| if (ffest_ffebad_start (FFEBAD_INVALID_DOTDOT)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_string (ffelex_token_text (ffeexpr_tokens_[1])); |
| ffebad_finish (); |
| } |
| e->u.operator.op = FFEEXPR_operatorEQ_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceEQ_; |
| e->u.operator.as = FFEEXPR_operatorassociativityEQ_; |
| break; |
| } |
| |
| ffeexpr_exprstack_push_binary_ (e); |
| |
| if (ffelex_token_type (t) != FFELEX_typePERIOD) |
| { |
| if (ffest_ffebad_start (FFEBAD_INSERTING_PERIOD)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_string (ffelex_token_text (ffeexpr_tokens_[1])); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */ |
| return (ffelexHandler) ffeexpr_token_rhs_ (t); |
| } |
| |
| ffelex_token_kill (ffeexpr_tokens_[1]); /* Kill dot-dot token. */ |
| return (ffelexHandler) ffeexpr_token_rhs_; |
| } |
| |
| /* ffeexpr_token_binary_sw_per_ -- Rhs PERIOD NAME(NOT, TRUE, or FALSE) |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| A diagnostic has already been issued; just swallow a period if there is |
| one, then continue with ffeexpr_token_binary_. */ |
| |
| static ffelexHandler |
| ffeexpr_token_binary_sw_per_ (ffelexToken t) |
| { |
| if (ffelex_token_type (t) != FFELEX_typePERIOD) |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_quote_ -- Rhs QUOTE |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Expecting a NUMBER that we'll treat as an octal integer. */ |
| |
| static ffelexHandler |
| ffeexpr_token_quote_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffebld anyexpr; |
| |
| if (ffelex_token_type (t) != FFELEX_typeNUMBER) |
| { |
| if (ffest_ffebad_start (FFEBAD_QUOTE_MISSES_DIGITS)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| return (ffelexHandler) ffeexpr_token_rhs_ (t); |
| } |
| |
| /* This is kind of a kludge to prevent any whining about magical numbers |
| that start out as these octal integers, so "20000000000 (on a 32-bit |
| 2's-complement machine) by itself won't produce an error. */ |
| |
| anyexpr = ffebld_new_any (); |
| ffebld_set_info (anyexpr, ffeinfo_new_any ()); |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| e->u.operand = ffebld_new_conter_with_orig |
| (ffebld_constant_new_integeroctal (t), anyexpr); |
| ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE)); |
| ffeexpr_exprstack_push_operand_ (e); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| /* ffeexpr_token_apostrophe_ -- Rhs APOSTROPHE |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle an open-apostrophe, which begins either a character ('char-const'), |
| typeless octal ('octal-const'O), or typeless hexadecimal ('hex-const'Z or |
| 'hex-const'X) constant. */ |
| |
| static ffelexHandler |
| ffeexpr_token_apostrophe_ (ffelexToken t) |
| { |
| assert (ffelex_token_type (t) == FFELEX_typeCHARACTER); |
| if (ffe_is_pedantic_not_90 () && (ffelex_token_length (t) == 0)) |
| { |
| ffebad_start (FFEBAD_NULL_CHAR_CONST); |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_apos_char_; |
| } |
| |
| /* ffeexpr_token_apos_char_ -- Rhs APOSTROPHE CHARACTER |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Close-apostrophe is implicit; if this token is NAME, it is a possible |
| typeless-constant radix specifier. */ |
| |
| static ffelexHandler |
| ffeexpr_token_apos_char_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffeinfo ni; |
| char c; |
| ffetargetCharacterSize size; |
| |
| if ((ffelex_token_type (t) == FFELEX_typeNAME) |
| || (ffelex_token_type (t) == FFELEX_typeNAMES)) |
| { |
| if ((ffelex_token_length (t) == 1) |
| && (ffesrc_char_match_init ((c = ffelex_token_text (t)[0]), 'B', |
| 'b') |
| || ffesrc_char_match_init (c, 'O', 'o') |
| || ffesrc_char_match_init (c, 'X', 'x') |
| || ffesrc_char_match_init (c, 'Z', 'z'))) |
| { |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| switch (c) |
| { |
| case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match): |
| e->u.operand = ffebld_new_conter |
| (ffebld_constant_new_typeless_bv (ffeexpr_tokens_[1])); |
| size = ffetarget_size_typeless_binary (ffeexpr_tokens_[1]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match): |
| e->u.operand = ffebld_new_conter |
| (ffebld_constant_new_typeless_ov (ffeexpr_tokens_[1])); |
| size = ffetarget_size_typeless_octal (ffeexpr_tokens_[1]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match): |
| e->u.operand = ffebld_new_conter |
| (ffebld_constant_new_typeless_hxv (ffeexpr_tokens_[1])); |
| size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match): |
| e->u.operand = ffebld_new_conter |
| (ffebld_constant_new_typeless_hzv (ffeexpr_tokens_[1])); |
| size = ffetarget_size_typeless_hex (ffeexpr_tokens_[1]); |
| break; |
| |
| default: |
| no_match: /* :::::::::::::::::::: */ |
| assert ("not BOXZ!" == NULL); |
| size = 0; |
| break; |
| } |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size)); |
| ffeexpr_exprstack_push_operand_ (e); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_characterdefault |
| (ffeexpr_tokens_[1])); |
| ni = ffeinfo_new (FFEINFO_basictypeCHARACTER, FFEINFO_kindtypeCHARACTERDEFAULT, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, |
| ffelex_token_length (ffeexpr_tokens_[1])); |
| ffebld_set_info (e->u.operand, ni); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffeexpr_exprstack_push_operand_ (e); |
| if ((ffelex_token_type (t) == FFELEX_typeNAME) |
| || (ffelex_token_type (t) == FFELEX_typeNAMES)) |
| { |
| if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER)) |
| { |
| ffebad_string (ffelex_token_text (t)); |
| ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_finish (); |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeBINARY_; |
| e->token = ffelex_token_use (t); |
| e->u.operator.op = FFEEXPR_operatorCONCATENATE_; |
| e->u.operator.prec = FFEEXPR_operatorprecedenceCONCATENATE_; |
| e->u.operator.as = FFEEXPR_operatorassociativityCONCATENATE_; |
| ffeexpr_exprstack_push_binary_ (e); |
| return (ffelexHandler) ffeexpr_token_rhs_ (t); |
| } |
| ffeexpr_is_substr_ok_ = !ffe_is_pedantic_not_90 (); /* Allow "'hello'(3:5)". */ |
| return (ffelexHandler) ffeexpr_token_substrp_ (t); |
| } |
| |
| /* ffeexpr_token_name_lhs_ -- Lhs NAME |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle a name followed by open-paren, period (RECORD.MEMBER), percent |
| (RECORD%MEMBER), or nothing at all. */ |
| |
| static ffelexHandler |
| ffeexpr_token_name_lhs_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffeexprParenType_ paren_type; |
| ffesymbol s; |
| ffebld expr; |
| ffeinfo info; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeOPEN_PAREN: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextFILEUNIT_DF: |
| goto just_name; /* :::::::::::::::::::: */ |
| |
| default: |
| break; |
| } |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffelex_token_use (ffeexpr_tokens_[0]); |
| s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], FALSE, |
| &paren_type); |
| |
| switch (ffesymbol_where (s)) |
| { |
| case FFEINFO_whereLOCAL: |
| if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recursion. */ |
| break; |
| |
| case FFEINFO_whereINTRINSIC: |
| case FFEINFO_whereGLOBAL: |
| if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */ |
| break; |
| |
| case FFEINFO_whereCOMMON: |
| case FFEINFO_whereDUMMY: |
| case FFEINFO_whereRESULT: |
| break; |
| |
| case FFEINFO_whereNONE: |
| case FFEINFO_whereANY: |
| break; |
| |
| default: |
| ffesymbol_error (s, ffeexpr_tokens_[0]); |
| break; |
| } |
| |
| if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY) |
| { |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| } |
| else |
| { |
| e->u.operand = ffebld_new_symter (s, |
| ffesymbol_generic (s), |
| ffesymbol_specific (s), |
| ffesymbol_implementation (s)); |
| ffebld_set_info (e->u.operand, ffesymbol_info (s)); |
| } |
| ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */ |
| ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0]; |
| switch (paren_type) |
| { |
| case FFEEXPR_parentypeSUBROUTINE_: |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextACTUALARG_, |
| ffeexpr_token_arguments_); |
| |
| case FFEEXPR_parentypeARRAY_: |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| ffeexpr_stack_->bound_list = ffesymbol_dims (s); |
| ffeexpr_stack_->rank = 0; |
| ffeexpr_stack_->constant = TRUE; |
| ffeexpr_stack_->immediate = TRUE; |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextDATAIMPDOINDEX_, |
| ffeexpr_token_elements_); |
| |
| case FFEEXPR_contextEQUIVALENCE: |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextEQVINDEX_, |
| ffeexpr_token_elements_); |
| |
| default: |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextINDEX_, |
| ffeexpr_token_elements_); |
| } |
| |
| case FFEEXPR_parentypeSUBSTRING_: |
| e->u.operand = ffeexpr_collapse_symter (e->u.operand, |
| ffeexpr_tokens_[0]); |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextINDEX_, |
| ffeexpr_token_substring_); |
| |
| case FFEEXPR_parentypeEQUIVALENCE_: |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| ffeexpr_stack_->bound_list = ffesymbol_dims (s); |
| ffeexpr_stack_->rank = 0; |
| ffeexpr_stack_->constant = TRUE; |
| ffeexpr_stack_->immediate = TRUE; |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextEQVINDEX_, |
| ffeexpr_token_equivalence_); |
| |
| case FFEEXPR_parentypeFUNCTION_: /* Invalid case. */ |
| case FFEEXPR_parentypeFUNSUBSTR_: /* Invalid case. */ |
| ffesymbol_error (s, ffeexpr_tokens_[0]); |
| /* Fall through. */ |
| case FFEEXPR_parentypeANY_: |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextACTUALARG_, |
| ffeexpr_token_anything_); |
| |
| default: |
| assert ("bad paren type" == NULL); |
| break; |
| } |
| |
| case FFELEX_typeEQUALS: /* As in "VAR=". */ |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextIMPDOITEM_: /* within |
| "(,VAR=start,end[,incr])". */ |
| case FFEEXPR_contextIMPDOITEMDF_: |
| ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_; |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| ffeexpr_stack_->context = FFEEXPR_contextDATAIMPDOCTRL_; |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| #if 0 |
| case FFELEX_typePERIOD: |
| case FFELEX_typePERCENT: |
| assert ("FOO%, FOO. not yet supported!~~" == NULL); |
| break; |
| #endif |
| |
| default: |
| break; |
| } |
| |
| just_name: /* :::::::::::::::::::: */ |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0], |
| (ffeexpr_stack_->context |
| == FFEEXPR_contextSUBROUTINEREF)); |
| |
| switch (ffesymbol_where (s)) |
| { |
| case FFEINFO_whereCONSTANT: |
| if ((ffeexpr_stack_->context != FFEEXPR_contextPARAMETER) |
| || (ffesymbol_kind (s) != FFEINFO_kindENTITY)) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| if ((ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOCTRL_) |
| && (ffeexpr_stack_->context != FFEEXPR_contextDATAIMPDOINDEX_)) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); |
| break; |
| |
| case FFEINFO_whereLOCAL: |
| if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); /* Recurse!. */ |
| break; |
| |
| case FFEINFO_whereINTRINSIC: |
| if (ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF) |
| ffesymbol_error (s, ffeexpr_tokens_[0]); /* Can call intrin. */ |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY) |
| { |
| expr = ffebld_new_any (); |
| info = ffeinfo_new_any (); |
| ffebld_set_info (expr, info); |
| } |
| else |
| { |
| expr = ffebld_new_symter (s, |
| ffesymbol_generic (s), |
| ffesymbol_specific (s), |
| ffesymbol_implementation (s)); |
| info = ffesymbol_info (s); |
| ffebld_set_info (expr, info); |
| if (ffesymbol_is_doiter (s)) |
| { |
| ffebad_start (FFEBAD_DOITER); |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffest_ffebad_here_doiter (1, s); |
| ffebad_string (ffesymbol_text (s)); |
| ffebad_finish (); |
| } |
| expr = ffeexpr_collapse_symter (expr, ffeexpr_tokens_[0]); |
| } |
| |
| if (ffeexpr_stack_->context == FFEEXPR_contextSUBROUTINEREF) |
| { |
| if (ffebld_op (expr) == FFEBLD_opANY) |
| { |
| expr = ffebld_new_any (); |
| ffebld_set_info (expr, ffeinfo_new_any ()); |
| } |
| else |
| { |
| expr = ffebld_new_subrref (expr, NULL); /* No argument list. */ |
| if (ffesymbol_generic (s) != FFEINTRIN_genNONE) |
| ffeintrin_fulfill_generic (&expr, &info, e->token); |
| else if (ffesymbol_specific (s) != FFEINTRIN_specNONE) |
| ffeintrin_fulfill_specific (&expr, &info, NULL, e->token); |
| else |
| ffeexpr_fulfill_call_ (&expr, e->token); |
| |
| if (ffebld_op (expr) != FFEBLD_opANY) |
| ffebld_set_info (expr, |
| ffeinfo_new (ffeinfo_basictype (info), |
| ffeinfo_kindtype (info), |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereFLEETING, |
| ffeinfo_size (info))); |
| else |
| ffebld_set_info (expr, ffeinfo_new_any ()); |
| } |
| } |
| |
| e->u.operand = expr; |
| ffeexpr_exprstack_push_operand_ (e); |
| return (ffelexHandler) ffeexpr_finished_ (t); |
| } |
| |
| /* ffeexpr_token_name_arg_ -- Rhs NAME |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle first token in an actual-arg (or possible actual-arg) context |
| being a NAME, and use second token to refine the context. */ |
| |
| static ffelexHandler |
| ffeexpr_token_name_arg_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeCLOSE_PAREN: |
| case FFELEX_typeCOMMA: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| ffeexpr_stack_->context = FFEEXPR_contextACTUALARG_; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARG_; |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| default: |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextACTUALARG_: |
| ffeexpr_stack_->context = FFEEXPR_contextACTUALARGEXPR_; |
| break; |
| |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| ffeexpr_stack_->context = FFEEXPR_contextINDEXORACTUALARGEXPR_; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| ffeexpr_stack_->context = FFEEXPR_contextSFUNCDEFACTUALARGEXPR_; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| ffeexpr_stack_->context |
| = FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_; |
| break; |
| |
| default: |
| assert ("bad context in _name_arg_" == NULL); |
| break; |
| } |
| break; |
| } |
| |
| return (ffelexHandler) ffeexpr_token_name_rhs_ (t); |
| } |
| |
| /* ffeexpr_token_name_rhs_ -- Rhs NAME |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle a name followed by open-paren, apostrophe (O'octal-const', |
| Z'hex-const', or X'hex-const'), period (RECORD.MEMBER). |
| |
| 26-Nov-91 JCB 1.2 |
| When followed by apostrophe or quote, set lex hexnum flag on so |
| [0-9] as first char of next token seen as starting a potentially |
| hex number (NAME). |
| 04-Oct-91 JCB 1.1 |
| In case of intrinsic, decorate its SYMTER with the type info for |
| the specific intrinsic. */ |
| |
| static ffelexHandler |
| ffeexpr_token_name_rhs_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| ffeexprParenType_ paren_type; |
| ffesymbol s; |
| bool sfdef; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeQUOTE: |
| case FFELEX_typeAPOSTROPHE: |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| ffelex_set_hexnum (TRUE); |
| return (ffelexHandler) ffeexpr_token_name_apos_; |
| |
| case FFELEX_typeOPEN_PAREN: |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffelex_token_use (ffeexpr_tokens_[0]); |
| s = ffeexpr_declare_parenthesized_ (ffeexpr_tokens_[0], TRUE, |
| &paren_type); |
| if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY) |
| e->u.operand = ffebld_new_any (); |
| else |
| e->u.operand = ffebld_new_symter (s, ffesymbol_generic (s), |
| ffesymbol_specific (s), |
| ffesymbol_implementation (s)); |
| ffeexpr_exprstack_push_ (e); /* Not a complete operand yet. */ |
| ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0]; |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| sfdef = TRUE; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| assert ("weird context!" == NULL); |
| sfdef = FALSE; |
| break; |
| |
| default: |
| sfdef = FALSE; |
| break; |
| } |
| switch (paren_type) |
| { |
| case FFEEXPR_parentypeFUNCTION_: |
| ffebld_set_info (e->u.operand, ffesymbol_info (s)); |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) |
| { /* A statement function. */ |
| ffeexpr_stack_->num_args |
| = ffebld_list_length |
| (ffeexpr_stack_->next_dummy |
| = ffesymbol_dummyargs (s)); |
| ffeexpr_stack_->tokens[1] = NULL; /* !=NULL when > num_args. */ |
| } |
| else if ((ffesymbol_where (s) == FFEINFO_whereINTRINSIC) |
| && !ffe_is_pedantic_not_90 () |
| && ((ffesymbol_implementation (s) |
| == FFEINTRIN_impICHAR) |
| || (ffesymbol_implementation (s) |
| == FFEINTRIN_impIACHAR) |
| || (ffesymbol_implementation (s) |
| == FFEINTRIN_impLEN))) |
| { /* Allow arbitrary concatenations. */ |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEF |
| : FFEEXPR_contextLET, |
| ffeexpr_token_arguments_); |
| } |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEFACTUALARG_ |
| : FFEEXPR_contextACTUALARG_, |
| ffeexpr_token_arguments_); |
| |
| case FFEEXPR_parentypeARRAY_: |
| ffebld_set_info (e->u.operand, |
| ffesymbol_info (ffebld_symter (e->u.operand))); |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| ffeexpr_stack_->bound_list = ffesymbol_dims (s); |
| ffeexpr_stack_->rank = 0; |
| ffeexpr_stack_->constant = TRUE; |
| ffeexpr_stack_->immediate = TRUE; |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEFINDEX_ |
| : FFEEXPR_contextINDEX_, |
| ffeexpr_token_elements_); |
| |
| case FFEEXPR_parentypeSUBSTRING_: |
| ffebld_set_info (e->u.operand, |
| ffesymbol_info (ffebld_symter (e->u.operand))); |
| e->u.operand = ffeexpr_collapse_symter (e->u.operand, |
| ffeexpr_tokens_[0]); |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEFINDEX_ |
| : FFEEXPR_contextINDEX_, |
| ffeexpr_token_substring_); |
| |
| case FFEEXPR_parentypeFUNSUBSTR_: |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_ |
| : FFEEXPR_contextINDEXORACTUALARG_, |
| ffeexpr_token_funsubstr_); |
| |
| case FFEEXPR_parentypeANY_: |
| ffebld_set_info (e->u.operand, ffesymbol_info (s)); |
| return |
| (ffelexHandler) |
| ffeexpr_rhs (ffeexpr_stack_->pool, |
| sfdef |
| ? FFEEXPR_contextSFUNCDEFACTUALARG_ |
| : FFEEXPR_contextACTUALARG_, |
| ffeexpr_token_anything_); |
| |
| default: |
| assert ("bad paren type" == NULL); |
| break; |
| } |
| |
| case FFELEX_typeEQUALS: /* As in "VAR=". */ |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextIMPDOITEM_: /* "(,VAR=start,end[,incr])". */ |
| case FFEEXPR_contextIMPDOITEMDF_: |
| ffeexpr_stack_->is_rhs = FALSE; /* Really an lhs construct. */ |
| ffeexpr_stack_->context = FFEEXPR_contextIMPDOCTRL_; |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| #if 0 |
| case FFELEX_typePERIOD: |
| case FFELEX_typePERCENT: |
| ~~Support these two someday, though not required |
| assert ("FOO%, FOO. not yet supported!~~" == NULL); |
| break; |
| #endif |
| |
| default: |
| break; |
| } |
| |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| assert ("strange context" == NULL); |
| break; |
| |
| default: |
| break; |
| } |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| s = ffeexpr_declare_unadorned_ (ffeexpr_tokens_[0], FALSE); |
| if (ffesymbol_attrs (s) & FFESYMBOL_attrsANY) |
| { |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| } |
| else |
| { |
| e->u.operand = ffebld_new_symter (s, FFEINTRIN_genNONE, |
| ffesymbol_specific (s), |
| ffesymbol_implementation (s)); |
| if (ffesymbol_specific (s) == FFEINTRIN_specNONE) |
| ffebld_set_info (e->u.operand, ffeinfo_use (ffesymbol_info (s))); |
| else |
| { /* Decorate the SYMTER with the actual type |
| of the intrinsic. */ |
| ffebld_set_info (e->u.operand, ffeinfo_new |
| (ffeintrin_basictype (ffesymbol_specific (s)), |
| ffeintrin_kindtype (ffesymbol_specific (s)), |
| 0, |
| ffesymbol_kind (s), |
| ffesymbol_where (s), |
| FFETARGET_charactersizeNONE)); |
| } |
| if (ffesymbol_is_doiter (s)) |
| ffebld_symter_set_is_doiter (e->u.operand, TRUE); |
| e->u.operand = ffeexpr_collapse_symter (e->u.operand, |
| ffeexpr_tokens_[0]); |
| } |
| ffeexpr_exprstack_push_operand_ (e); |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| /* ffeexpr_token_name_apos_ -- Rhs NAME APOSTROPHE |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Expecting a NAME token, analyze the previous NAME token to see what kind, |
| if any, typeless constant we've got. |
| |
| 01-Sep-90 JCB 1.1 |
| Expect a NAME instead of CHARACTER in this situation. */ |
| |
| static ffelexHandler |
| ffeexpr_token_name_apos_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| |
| ffelex_set_hexnum (FALSE); |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| ffeexpr_tokens_[2] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_name_apos_name_; |
| |
| default: |
| break; |
| } |
| |
| if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER)) |
| { |
| ffebad_string (ffelex_token_text (ffeexpr_tokens_[0])); |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| e->token = ffeexpr_tokens_[0]; |
| ffeexpr_exprstack_push_operand_ (e); |
| |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| |
| /* ffeexpr_token_name_apos_name_ -- Rhs NAME APOSTROPHE NAME |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Expecting an APOSTROPHE token, analyze the previous NAME token to see |
| what kind, if any, typeless constant we've got. */ |
| |
| static ffelexHandler |
| ffeexpr_token_name_apos_name_ (ffelexToken t) |
| { |
| ffeexprExpr_ e; |
| char c; |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->token = ffeexpr_tokens_[0]; |
| |
| if ((ffelex_token_type (t) == ffelex_token_type (ffeexpr_tokens_[1])) |
| && (ffelex_token_length (ffeexpr_tokens_[0]) == 1) |
| && (ffesrc_char_match_init ((c = ffelex_token_text (ffeexpr_tokens_[0])[0]), |
| 'B', 'b') |
| || ffesrc_char_match_init (c, 'O', 'o') |
| || ffesrc_char_match_init (c, 'X', 'x') |
| || ffesrc_char_match_init (c, 'Z', 'z'))) |
| { |
| ffetargetCharacterSize size; |
| |
| if (!ffe_is_typeless_boz ()) { |
| |
| switch (c) |
| { |
| case FFESRC_CASE_MATCH_INIT ('B', 'b', imatch_b, no_imatch): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integerbinary |
| (ffeexpr_tokens_[2])); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('O', 'o', imatch_o, no_imatch): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integeroctal |
| (ffeexpr_tokens_[2])); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('X', 'x', imatch_x, no_imatch): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex |
| (ffeexpr_tokens_[2])); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('Z', 'z', imatch_z, no_imatch): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integerhex |
| (ffeexpr_tokens_[2])); |
| break; |
| |
| default: |
| no_imatch: /* :::::::::::::::::::: */ |
| assert ("not BOXZ!" == NULL); |
| abort (); |
| } |
| |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| ffeexpr_exprstack_push_operand_ (e); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| switch (c) |
| { |
| case FFESRC_CASE_MATCH_INIT ('B', 'b', match_b, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_bm |
| (ffeexpr_tokens_[2])); |
| size = ffetarget_size_typeless_binary (ffeexpr_tokens_[2]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('O', 'o', match_o, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_om |
| (ffeexpr_tokens_[2])); |
| size = ffetarget_size_typeless_octal (ffeexpr_tokens_[2]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('X', 'x', match_x, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hxm |
| (ffeexpr_tokens_[2])); |
| size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('Z', 'z', match_z, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm |
| (ffeexpr_tokens_[2])); |
| size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]); |
| break; |
| |
| default: |
| no_match: /* :::::::::::::::::::: */ |
| assert ("not BOXZ!" == NULL); |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_typeless_hzm |
| (ffeexpr_tokens_[2])); |
| size = ffetarget_size_typeless_hex (ffeexpr_tokens_[2]); |
| break; |
| } |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeTYPELESS, FFEINFO_kindtypeNONE, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, size)); |
| ffeexpr_exprstack_push_operand_ (e); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| return (ffelexHandler) ffeexpr_token_binary_; |
| } |
| |
| if (ffest_ffebad_start (FFEBAD_INVALID_RADIX_SPECIFIER)) |
| { |
| ffebad_string (ffelex_token_text (ffeexpr_tokens_[0])); |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (t), ffelex_token_where_column (t)); |
| ffebad_finish (); |
| } |
| |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[2]); |
| |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| e->token = ffeexpr_tokens_[0]; |
| ffeexpr_exprstack_push_operand_ (e); |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeAPOSTROPHE: |
| case FFELEX_typeQUOTE: |
| return (ffelexHandler) ffeexpr_token_binary_; |
| |
| default: |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_percent_ -- Rhs PERCENT |
| |
| Handle a percent sign possibly followed by "LOC". If followed instead |
| by "VAL", "REF", or "DESCR", issue an error message and substitute |
| "LOC". If followed by something else, treat the percent sign as a |
| spurious incorrect token and reprocess the token via _rhs_. */ |
| |
| static ffelexHandler |
| ffeexpr_token_percent_ (ffelexToken t) |
| { |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeNAME: |
| case FFELEX_typeNAMES: |
| ffeexpr_stack_->percent = ffeexpr_percent_ (t); |
| ffeexpr_tokens_[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_token_percent_name_; |
| |
| default: |
| if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token), |
| ffelex_token_where_column (ffeexpr_stack_->first_token)); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| return (ffelexHandler) ffeexpr_token_rhs_ (t); |
| } |
| } |
| |
| /* ffeexpr_token_percent_name_ -- Rhs PERCENT NAME |
| |
| Make sure the token is OPEN_PAREN and prepare for the one-item list of |
| LHS expressions. Else display an error message. */ |
| |
| static ffelexHandler |
| ffeexpr_token_percent_name_ (ffelexToken t) |
| { |
| ffelexHandler nexthandler; |
| |
| if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN) |
| { |
| if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->first_token), |
| ffelex_token_where_column (ffeexpr_stack_->first_token)); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_tokens_[0]); |
| nexthandler = (ffelexHandler) ffeexpr_token_rhs_ (ffeexpr_tokens_[1]); |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| return (ffelexHandler) (*nexthandler) (t); |
| } |
| |
| switch (ffeexpr_stack_->percent) |
| { |
| default: |
| if (ffest_ffebad_start (FFEBAD_INVALID_PERCENT)) |
| { |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_tokens_[0]), |
| ffelex_token_where_column (ffeexpr_tokens_[0])); |
| ffebad_string (ffelex_token_text (ffeexpr_tokens_[1])); |
| ffebad_finish (); |
| } |
| ffeexpr_stack_->percent = FFEEXPR_percentLOC_; |
| /* Fall through. */ |
| case FFEEXPR_percentLOC_: |
| ffeexpr_stack_->tokens[0] = ffeexpr_tokens_[0]; |
| ffelex_token_kill (ffeexpr_tokens_[1]); |
| ffeexpr_stack_->tokens[1] = ffelex_token_use (t); |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextLOC_, |
| ffeexpr_cb_end_loc_); |
| } |
| } |
| |
| /* ffeexpr_make_float_const_ -- Make a floating-point constant |
| |
| See prototype. |
| |
| Pass 'E', 'D', or 'Q' for exponent letter. */ |
| |
| static void |
| ffeexpr_make_float_const_ (char exp_letter, ffelexToken integer, |
| ffelexToken decimal, ffelexToken fraction, |
| ffelexToken exponent, ffelexToken exponent_sign, |
| ffelexToken exponent_digits) |
| { |
| ffeexprExpr_ e; |
| |
| e = ffeexpr_expr_new_ (); |
| e->type = FFEEXPR_exprtypeOPERAND_; |
| if (integer != NULL) |
| e->token = ffelex_token_use (integer); |
| else |
| { |
| assert (decimal != NULL); |
| e->token = ffelex_token_use (decimal); |
| } |
| |
| switch (exp_letter) |
| { |
| #if !FFETARGET_okREALQUAD |
| case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match): |
| if (ffebad_start (FFEBAD_QUAD_UNSUPPORTED)) |
| { |
| ffebad_here (0, ffelex_token_where_line (e->token), |
| ffelex_token_where_column (e->token)); |
| ffebad_finish (); |
| } |
| goto match_d; /* The FFESRC_CASE_* macros don't |
| allow fall-through! */ |
| #endif |
| |
| case FFESRC_CASE_MATCH_INIT ('D', 'd', match_d, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_realdouble |
| (integer, decimal, fraction, exponent, exponent_sign, exponent_digits)); |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE)); |
| break; |
| |
| case FFESRC_CASE_MATCH_INIT ('E', 'e', match_e, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_realdefault |
| (integer, decimal, fraction, exponent, exponent_sign, exponent_digits)); |
| ffebld_set_info (e->u.operand, ffeinfo_new (FFEINFO_basictypeREAL, |
| FFEINFO_kindtypeREALDEFAULT, 0, FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE)); |
| break; |
| |
| #if FFETARGET_okREALQUAD |
| case FFESRC_CASE_MATCH_INIT ('Q', 'q', match_q, no_match): |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_realquad |
| (integer, decimal, fraction, exponent, exponent_sign, exponent_digits)); |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALQUAD, |
| 0, FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, FFETARGET_charactersizeNONE)); |
| break; |
| #endif |
| |
| case 'I': /* Make an integer. */ |
| e->u.operand = ffebld_new_conter (ffebld_constant_new_integerdefault |
| (ffeexpr_tokens_[0])); |
| ffebld_set_info (e->u.operand, |
| ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, 0, |
| FFEINFO_kindENTITY, FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| break; |
| |
| default: |
| no_match: /* :::::::::::::::::::: */ |
| assert ("Lost the exponent letter!" == NULL); |
| } |
| |
| ffeexpr_exprstack_push_operand_ (e); |
| } |
| |
| /* Just like ffesymbol_declare_local, except performs any implicit info |
| assignment necessary. */ |
| |
| static ffesymbol |
| ffeexpr_declare_unadorned_ (ffelexToken t, bool maybe_intrin) |
| { |
| ffesymbol s; |
| ffeinfoKind k; |
| bool bad; |
| |
| s = ffesymbol_declare_local (t, maybe_intrin); |
| |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| /* Special-case these since they can involve a different concept |
| of "state" (in the stmtfunc name space). */ |
| { |
| case FFEEXPR_contextDATAIMPDOINDEX_: |
| case FFEEXPR_contextDATAIMPDOCTRL_: |
| if (ffeexpr_context_outer_ (ffeexpr_stack_) |
| == FFEEXPR_contextDATAIMPDOINDEX_) |
| s = ffeexpr_sym_impdoitem_ (s, t); |
| else |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_sym_impdoitem_ (s, t); |
| else |
| s = ffeexpr_sym_lhs_impdoctrl_ (s, t); |
| bad = (ffesymbol_kind (s) != FFEINFO_kindENTITY) |
| || ((ffesymbol_where (s) != FFEINFO_whereCONSTANT) |
| && (ffesymbol_where (s) != FFEINFO_whereIMMEDIATE)); |
| if (bad && (ffesymbol_kind (s) != FFEINFO_kindANY)) |
| ffesymbol_error (s, t); |
| return s; |
| |
| default: |
| break; |
| } |
| |
| switch ((ffesymbol_sfdummyparent (s) == NULL) |
| ? ffesymbol_state (s) |
| : FFESYMBOL_stateUNDERSTOOD) |
| { |
| case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr |
| context. */ |
| if (!ffest_seen_first_exec ()) |
| goto seen; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */ |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextSUBROUTINEREF: |
| s = ffeexpr_sym_lhs_call_ (s, t); |
| break; |
| |
| case FFEEXPR_contextFILEEXTFUNC: |
| s = ffeexpr_sym_lhs_extfunc_ (s, t); |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFEEXPR_contextACTUALARG_: |
| s = ffeexpr_sym_rhs_actualarg_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDATA: |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_sym_rhs_let_ (s, t); |
| else |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| break; |
| |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFEEXPR_contextLET: |
| case FFEEXPR_contextPAREN_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextIOLISTDF: |
| case FFEEXPR_contextDO: |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextIF: |
| case FFEEXPR_contextARITHIF: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextSTOP: |
| case FFEEXPR_contextRETURN: |
| case FFEEXPR_contextSELECTCASE: |
| case FFEEXPR_contextCASE: |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| case FFEEXPR_contextFILEDFINT: |
| case FFEEXPR_contextFILELOG: |
| case FFEEXPR_contextFILENUM: |
| case FFEEXPR_contextFILENUMAMBIG: |
| case FFEEXPR_contextFILECHAR: |
| case FFEEXPR_contextFILENUMCHAR: |
| case FFEEXPR_contextFILEDFCHAR: |
| case FFEEXPR_contextFILEKEY: |
| case FFEEXPR_contextFILEUNIT: |
| case FFEEXPR_contextFILEUNIT_DF: |
| case FFEEXPR_contextFILEUNITAMBIG: |
| case FFEEXPR_contextFILEFORMAT: |
| case FFEEXPR_contextFILENAMELIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextIMPDOITEM_: |
| case FFEEXPR_contextIMPDOITEMDF_: |
| case FFEEXPR_contextIMPDOCTRL_: |
| case FFEEXPR_contextLOC_: |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_sym_rhs_let_ (s, t); |
| else |
| s = ffeexpr_sym_lhs_let_ (s, t); |
| break; |
| |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextEQUIVALENCE: |
| case FFEEXPR_contextINCLUDE: |
| case FFEEXPR_contextPARAMETER: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| break; /* Will turn into errors below. */ |
| |
| default: |
| ffesymbol_error (s, t); |
| break; |
| } |
| /* Fall through. */ |
| case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */ |
| understood: /* :::::::::::::::::::: */ |
| k = ffesymbol_kind (s); |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextSUBROUTINEREF: |
| bad = ((k != FFEINFO_kindSUBROUTINE) |
| && ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC) |
| || (k != FFEINFO_kindNONE))); |
| break; |
| |
| case FFEEXPR_contextFILEEXTFUNC: |
| bad = (k != FFEINFO_kindFUNCTION) |
| || (ffesymbol_where (s) != FFEINFO_whereGLOBAL); |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextACTUALARG_: |
| switch (k) |
| { |
| case FFEINFO_kindENTITY: |
| bad = FALSE; |
| break; |
| |
| case FFEINFO_kindFUNCTION: |
| case FFEINFO_kindSUBROUTINE: |
| bad |
| = ((ffesymbol_where (s) != FFEINFO_whereGLOBAL) |
| && (ffesymbol_where (s) != FFEINFO_whereDUMMY) |
| && ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC) |
| || !ffeintrin_is_actualarg (ffesymbol_specific (s)))); |
| break; |
| |
| case FFEINFO_kindNONE: |
| if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC) |
| { |
| bad = !(ffeintrin_is_actualarg (ffesymbol_specific (s))); |
| break; |
| } |
| |
| /* If state is UNDERSTOOD here, it's CHAR*(*) or attrsANY, |
| and in the former case, attrsTYPE is set, so we |
| see this as an error as we should, since CHAR*(*) |
| cannot be actually referenced in a main/block data |
| program unit. */ |
| |
| if ((ffesymbol_attrs (s) & (FFESYMBOL_attrsANY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE)) |
| == FFESYMBOL_attrsEXTERNAL) |
| bad = FALSE; |
| else |
| bad = TRUE; |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| break; |
| |
| case FFEEXPR_contextDATA: |
| if (ffeexpr_stack_->is_rhs) |
| bad = (k != FFEINFO_kindENTITY) |
| || (ffesymbol_where (s) != FFEINFO_whereCONSTANT); |
| else |
| bad = (k != FFEINFO_kindENTITY) |
| || ((ffesymbol_where (s) != FFEINFO_whereNONE) |
| && (ffesymbol_where (s) != FFEINFO_whereLOCAL) |
| && (ffesymbol_where (s) != FFEINFO_whereCOMMON)); |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| bad = TRUE; /* Unadorned item never valid. */ |
| break; |
| |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextLET: |
| case FFEEXPR_contextPAREN_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextIOLISTDF: |
| case FFEEXPR_contextDO: |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextIF: |
| case FFEEXPR_contextARITHIF: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextSTOP: |
| case FFEEXPR_contextRETURN: |
| case FFEEXPR_contextSELECTCASE: |
| case FFEEXPR_contextCASE: |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| case FFEEXPR_contextFILEDFINT: |
| case FFEEXPR_contextFILELOG: |
| case FFEEXPR_contextFILENUM: |
| case FFEEXPR_contextFILENUMAMBIG: |
| case FFEEXPR_contextFILECHAR: |
| case FFEEXPR_contextFILENUMCHAR: |
| case FFEEXPR_contextFILEDFCHAR: |
| case FFEEXPR_contextFILEKEY: |
| case FFEEXPR_contextFILEUNIT: |
| case FFEEXPR_contextFILEUNIT_DF: |
| case FFEEXPR_contextFILEUNITAMBIG: |
| case FFEEXPR_contextFILEFORMAT: |
| case FFEEXPR_contextFILENAMELIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextIMPDOITEM_: |
| case FFEEXPR_contextIMPDOITEMDF_: |
| case FFEEXPR_contextIMPDOCTRL_: |
| case FFEEXPR_contextLOC_: |
| bad = (k != FFEINFO_kindENTITY); /* This catches "SUBROUTINE |
| X(A);EXTERNAL A;CALL |
| Y(A);B=A", for example. */ |
| break; |
| |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextEQUIVALENCE: |
| case FFEEXPR_contextPARAMETER: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| bad = (k != FFEINFO_kindENTITY) |
| || (ffesymbol_where (s) != FFEINFO_whereCONSTANT); |
| break; |
| |
| case FFEEXPR_contextINCLUDE: |
| bad = TRUE; |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| if (bad && (k != FFEINFO_kindANY)) |
| ffesymbol_error (s, t); |
| return s; |
| |
| case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */ |
| seen: /* :::::::::::::::::::: */ |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextPARAMETER: |
| if (ffeexpr_stack_->is_rhs) |
| ffesymbol_error (s, t); |
| else |
| s = ffeexpr_sym_lhs_parameter_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDATA: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| if (ffeexpr_stack_->is_rhs) |
| ffesymbol_error (s, t); |
| else |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextEQUIVALENCE: |
| s = ffeexpr_sym_lhs_equivalence_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDIMLIST: |
| s = ffeexpr_sym_rhs_dimlist_ (s, t); |
| break; |
| |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| ffesymbol_error (s, t); |
| break; |
| |
| case FFEEXPR_contextINCLUDE: |
| ffesymbol_error (s, t); |
| break; |
| |
| case FFEEXPR_contextACTUALARG_: /* E.g. I in REAL A(Y(I)). */ |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| s = ffeexpr_sym_rhs_actualarg_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| assert (ffeexpr_stack_->is_rhs); |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| s = ffeexpr_sym_rhs_let_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| default: |
| ffesymbol_error (s, t); |
| break; |
| } |
| return s; |
| |
| default: |
| assert ("bad symbol state" == NULL); |
| return NULL; |
| break; |
| } |
| } |
| |
| /* Have FOO in DATA (XYZ(FOO),...)/.../ or DATA (...,XYZ=FOO,BAR,BLETCH). |
| Could be found via the "statement-function" name space (in which case |
| it should become an iterator) or the local name space (in which case |
| it should be either a named constant, or a variable that will have an |
| sfunc name space sibling that should become an iterator). */ |
| |
| static ffesymbol |
| ffeexpr_sym_impdoitem_ (ffesymbol sp, ffelexToken t) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffesymbolState ss; |
| ffesymbolState ns; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| |
| ss = ffesymbol_state (sp); |
| |
| if (ffesymbol_sfdummyparent (sp) != NULL) |
| { /* Have symbol in sfunc name space. */ |
| switch (ss) |
| { |
| case FFESYMBOL_stateNONE: /* Used as iterator already. */ |
| if (ffeexpr_level_ < ffesymbol_maxentrynum (sp)) |
| ffesymbol_error (sp, t); /* Can't use dead iterator. */ |
| else |
| { /* Can use dead iterator because we're at at |
| least an innermore (higher-numbered) level |
| than the iterator's outermost |
| (lowest-numbered) level. */ |
| ffesymbol_signal_change (sp); |
| ffesymbol_set_state (sp, FFESYMBOL_stateSEEN); |
| ffesymbol_set_maxentrynum (sp, ffeexpr_level_); |
| ffesymbol_signal_unreported (sp); |
| } |
| break; |
| |
| case FFESYMBOL_stateSEEN: /* Seen already in this or other |
| implied-DO. Set symbol level |
| number to outermost value, as that |
| tells us we can see it as iterator |
| at that level at the innermost. */ |
| if (ffeexpr_level_ < ffesymbol_maxentrynum (sp)) |
| { |
| ffesymbol_signal_change (sp); |
| ffesymbol_set_maxentrynum (sp, ffeexpr_level_); |
| ffesymbol_signal_unreported (sp); |
| } |
| break; |
| |
| case FFESYMBOL_stateUNCERTAIN: /* Iterator. */ |
| assert (ffeexpr_level_ == ffesymbol_maxentrynum (sp)); |
| ffesymbol_error (sp, t); /* (,,,I=I,10). */ |
| break; |
| |
| case FFESYMBOL_stateUNDERSTOOD: |
| break; /* ANY. */ |
| |
| default: |
| assert ("Foo Bar!!" == NULL); |
| break; |
| } |
| |
| return sp; |
| } |
| |
| /* Got symbol in local name space, so we haven't seen it in impdo yet. |
| First, if it is brand-new and we're in executable statements, set the |
| attributes and exec-transition it to set state UNCERTAIN or UNDERSTOOD. |
| Second, if it is now a constant (PARAMETER), then just return it, it |
| can't be an implied-do iterator. If it is understood, complain if it is |
| not a valid variable, but make the inner name space iterator anyway and |
| return that. If it is not understood, improve understanding of the |
| symbol accordingly, complain accordingly, in either case make the inner |
| name space iterator and return that. */ |
| |
| sa = ffesymbol_attrs (sp); |
| |
| if (ffesymbol_state_is_specable (ss) |
| && ffest_seen_first_exec ()) |
| { |
| assert (sa == FFESYMBOL_attrsetNONE); |
| ffesymbol_signal_change (sp); |
| ffesymbol_set_state (sp, FFESYMBOL_stateSEEN); |
| ffesymbol_resolve_intrin (sp); |
| if (ffeimplic_establish_symbol (sp)) |
| ffesymbol_set_attr (sp, FFESYMBOL_attrSFARG); |
| else |
| ffesymbol_error (sp, t); |
| |
| /* After the exec transition, the state will either be UNCERTAIN (could |
| be a dummy or local var) or UNDERSTOOD (local var, because this is a |
| PROGRAM/BLOCKDATA program unit). */ |
| |
| sp = ffecom_sym_exec_transition (sp); |
| sa = ffesymbol_attrs (sp); |
| ss = ffesymbol_state (sp); |
| } |
| |
| ns = ss; |
| kind = ffesymbol_kind (sp); |
| where = ffesymbol_where (sp); |
| |
| if (ss == FFESYMBOL_stateUNDERSTOOD) |
| { |
| if (kind != FFEINFO_kindENTITY) |
| ffesymbol_error (sp, t); |
| if (where == FFEINFO_whereCONSTANT) |
| return sp; |
| } |
| else |
| { |
| /* Enhance understanding of local symbol. This used to imply exec |
| transition, but that doesn't seem necessary, since the local symbol |
| doesn't actually get put into an ffebld tree here -- we just learn |
| more about it, just like when we see a local symbol's name in the |
| dummy-arg list of a statement function. */ |
| |
| if (ss != FFESYMBOL_stateUNCERTAIN) |
| { |
| /* Figure out what kind of object we've got based on previous |
| declarations of or references to the object. */ |
| |
| ns = FFESYMBOL_stateSEEN; |
| |
| if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsANY |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsRESULT |
| | FFESYMBOL_attrsSAVE |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsSFARG; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| } |
| else |
| { /* stateUNCERTAIN. */ |
| na = sa | FFESYMBOL_attrsSFARG; |
| ns = FFESYMBOL_stateUNDERSTOOD; |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| na = FFESYMBOL_attrsetNONE; |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = FFEINFO_kindENTITY; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| na = FFESYMBOL_attrsetNONE; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| ns = FFESYMBOL_stateUNCERTAIN; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| kind = FFEINFO_kindENTITY; |
| |
| if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN)) |
| na = FFESYMBOL_attrsetNONE; |
| else if (ffest_is_entry_valid ()) |
| ns = FFESYMBOL_stateUNCERTAIN; /* Could be DUMMY or LOCAL. */ |
| else |
| where = FFEINFO_whereLOCAL; |
| } |
| else |
| na = FFESYMBOL_attrsetNONE; /* Error. */ |
| } |
| |
| /* Now see what we've got for a new object: NONE means a new error |
| cropped up; ANY means an old error to be ignored; otherwise, |
| everything's ok, update the object (symbol) and continue on. */ |
| |
| if (na == FFESYMBOL_attrsetNONE) |
| ffesymbol_error (sp, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (sp); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (sp)) |
| ffesymbol_error (sp, t); |
| else |
| { |
| ffesymbol_set_info (sp, |
| ffeinfo_new (ffesymbol_basictype (sp), |
| ffesymbol_kindtype (sp), |
| ffesymbol_rank (sp), |
| kind, |
| where, |
| ffesymbol_size (sp))); |
| ffesymbol_set_attrs (sp, na); |
| ffesymbol_set_state (sp, ns); |
| ffesymbol_resolve_intrin (sp); |
| if (!ffesymbol_state_is_specable (ns)) |
| sp = ffecom_sym_learned (sp); |
| ffesymbol_signal_unreported (sp); /* For debugging purposes. */ |
| } |
| } |
| } |
| |
| /* Here we create the sfunc-name-space symbol representing what should |
| become an iterator in this name space at this or an outermore (lower- |
| numbered) expression level, else the implied-DO construct is in error. */ |
| |
| s = ffesymbol_declare_sfdummy (t); /* Sets maxentrynum to 0 for new obj; |
| also sets sfa_dummy_parent to |
| parent symbol. */ |
| assert (sp == ffesymbol_sfdummyparent (s)); |
| |
| ffesymbol_signal_change (s); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_maxentrynum (s, ffeexpr_level_); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereIMMEDIATE, |
| FFETARGET_charactersizeNONE)); |
| ffesymbol_signal_unreported (s); |
| |
| if (((ffesymbol_basictype (sp) != FFEINFO_basictypeINTEGER) |
| && (ffesymbol_basictype (sp) != FFEINFO_basictypeANY)) |
| || ((ffesymbol_kindtype (sp) != FFEINFO_kindtypeINTEGERDEFAULT) |
| && (ffesymbol_kindtype (sp) != FFEINFO_kindtypeANY))) |
| ffesymbol_error (s, t); |
| |
| return s; |
| } |
| |
| /* Have FOO in CALL FOO. Local name space, executable context only. */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_call_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| ffeintrinGen gen; |
| ffeintrinSpec spec; |
| ffeintrinImp imp; |
| bool error = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsTYPE) |
| error = TRUE; |
| else |
| /* Not TYPE. */ |
| { |
| kind = FFEINFO_kindSUBROUTINE; |
| |
| if (sa & FFESYMBOL_attrsDUMMY) |
| ; /* Not TYPE. */ |
| else if (sa & FFESYMBOL_attrsACTUALARG) |
| ; /* Not DUMMY or TYPE. */ |
| else /* Not ACTUALARG, DUMMY, or TYPE. */ |
| where = FFEINFO_whereGLOBAL; |
| } |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsTYPE) |
| error = TRUE; |
| else |
| kind = FFEINFO_kindSUBROUTINE; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| error = TRUE; |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| |
| if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE, |
| &gen, &spec, &imp)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| ffesymbol_set_generic (s, gen); |
| ffesymbol_set_specific (s, spec); |
| ffesymbol_set_implementation (s, imp); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindSUBROUTINE, |
| FFEINFO_whereINTRINSIC, |
| FFETARGET_charactersizeNONE)); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_reference (s, t, FALSE); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| |
| return s; |
| } |
| |
| kind = FFEINFO_kindSUBROUTINE; |
| where = FFEINFO_whereGLOBAL; |
| } |
| else |
| error = TRUE; |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (error) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* SUBROUTINE. */ |
| where, /* GLOBAL or DUMMY. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_reference (s, t, FALSE); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in DATA FOO/.../. Local name space and executable context |
| only. (This will change in the future when DATA FOO may be followed |
| by COMMON FOO or even INTEGER FOO(10), etc.) */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_data_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| bool error = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsADJUSTABLE) |
| error = TRUE; |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN)) |
| error = TRUE; |
| else |
| { |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| else |
| error = TRUE; |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (error) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* ENTITY. */ |
| where, /* LOCAL. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in EQUIVALENCE (...,FOO,...). Does not include |
| EQUIVALENCE (...,BAR(FOO),...). */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_equivalence_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| |
| na = sa = ffesymbol_attrs (s); |
| kind = FFEINFO_kindENTITY; |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSAVE |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsEQUIV; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* Don't know why we're bothering to set kind and where in this code, but |
| added the following to make it complete, in case it's really important. |
| Generally this is left up to symbol exec transition. */ |
| |
| if (where == FFEINFO_whereNONE) |
| { |
| if (na & (FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsCOMMON)) |
| where = FFEINFO_whereCOMMON; |
| else if (na & FFESYMBOL_attrsSAVE) |
| where = FFEINFO_whereLOCAL; |
| } |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (na == FFESYMBOL_attrsetNONE) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* Always ENTITY. */ |
| where, /* NONE, COMMON, or LOCAL. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in OPEN(...,USEROPEN=FOO,...). Executable context only. |
| |
| Note that I think this should be considered semantically similar to |
| doing CALL XYZ(FOO), in that it should be considered like an |
| ACTUALARG context. In particular, without EXTERNAL being specified, |
| it should not be allowed. */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_extfunc_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| bool needs_type = FALSE; |
| bool error = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsTYPE) |
| where = FFEINFO_whereGLOBAL; |
| else |
| /* Not TYPE. */ |
| { |
| kind = FFEINFO_kindFUNCTION; |
| needs_type = TRUE; |
| |
| if (sa & FFESYMBOL_attrsDUMMY) |
| ; /* Not TYPE. */ |
| else if (sa & FFESYMBOL_attrsACTUALARG) |
| ; /* Not DUMMY or TYPE. */ |
| else /* Not ACTUALARG, DUMMY, or TYPE. */ |
| where = FFEINFO_whereGLOBAL; |
| } |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = FFEINFO_kindFUNCTION; |
| if (!(sa & FFESYMBOL_attrsTYPE)) |
| needs_type = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| if (sa & (FFESYMBOL_attrsADJUSTABLE | FFESYMBOL_attrsANYLEN)) |
| error = TRUE; |
| else |
| { |
| kind = FFEINFO_kindFUNCTION; |
| where = FFEINFO_whereGLOBAL; |
| } |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| kind = FFEINFO_kindFUNCTION; |
| where = FFEINFO_whereGLOBAL; |
| needs_type = TRUE; |
| } |
| else |
| error = TRUE; |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (error) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (needs_type && !ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| if (!ffesymbol_explicitwhere (s)) |
| { |
| ffebad_start (FFEBAD_NEED_EXTERNAL); |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_string (ffesymbol_text (s)); |
| ffebad_finish (); |
| ffesymbol_set_explicitwhere (s, TRUE); |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* FUNCTION. */ |
| where, /* GLOBAL or DUMMY. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_reference (s, t, FALSE); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in DATA (stuff,FOO=1,10)/.../. */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_impdoctrl_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolState ss; |
| |
| /* If the symbol isn't in the sfunc name space, pretend as though we saw a |
| reference to it already within the imp-DO construct at this level, so as |
| to get a symbol that is in the sfunc name space. But this is an |
| erroneous construct, and should be caught elsewhere. */ |
| |
| if (ffesymbol_sfdummyparent (s) == NULL) |
| { |
| s = ffeexpr_sym_impdoitem_ (s, t); |
| if (ffesymbol_sfdummyparent (s) == NULL) |
| { /* PARAMETER FOO...DATA (A(I),FOO=...). */ |
| ffesymbol_error (s, t); |
| return s; |
| } |
| } |
| |
| ss = ffesymbol_state (s); |
| |
| switch (ss) |
| { |
| case FFESYMBOL_stateNONE: /* Used as iterator already. */ |
| if (ffeexpr_level_ < ffesymbol_maxentrynum (s)) |
| ffesymbol_error (s, t); /* Can't reuse dead iterator. F90 disallows |
| this; F77 allows it but it is a stupid |
| feature. */ |
| else |
| { /* Can use dead iterator because we're at at |
| least a innermore (higher-numbered) level |
| than the iterator's outermost |
| (lowest-numbered) level. This should be |
| diagnosed later, because it means an item |
| in this list didn't reference this |
| iterator. */ |
| #if 1 |
| ffesymbol_error (s, t); /* For now, complain. */ |
| #else /* Someday will detect all cases where initializer doesn't reference |
| all applicable iterators, in which case reenable this code. */ |
| ffesymbol_signal_change (s); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN); |
| ffesymbol_set_maxentrynum (s, ffeexpr_level_); |
| ffesymbol_signal_unreported (s); |
| #endif |
| } |
| break; |
| |
| case FFESYMBOL_stateSEEN: /* Seen already in this or other implied-DO. |
| If seen in outermore level, can't be an |
| iterator here, so complain. If not seen |
| at current level, complain for now, |
| because that indicates something F90 |
| rejects (though we currently don't detect |
| all such cases for now). */ |
| if (ffeexpr_level_ <= ffesymbol_maxentrynum (s)) |
| { |
| ffesymbol_signal_change (s); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNCERTAIN); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, t); |
| break; |
| |
| case FFESYMBOL_stateUNCERTAIN: /* Already iterator! */ |
| assert ("DATA implied-DO control var seen twice!!" == NULL); |
| ffesymbol_error (s, t); |
| break; |
| |
| case FFESYMBOL_stateUNDERSTOOD: |
| break; /* ANY. */ |
| |
| default: |
| assert ("Foo Bletch!!" == NULL); |
| break; |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in PARAMETER (FOO=...). */ |
| |
| static ffesymbol |
| ffeexpr_sym_lhs_parameter_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & ~(FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsTYPE)) |
| { |
| if (!(sa & FFESYMBOL_attrsANY)) |
| ffesymbol_error (s, t); |
| } |
| else |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in CALL XYZ(...,FOO,...). Does not include any other |
| embedding of FOO, such as CALL XYZ((FOO)) or CALL XYZ(FOO+1). */ |
| |
| static ffesymbol |
| ffeexpr_sym_rhs_actualarg_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| ffesymbolState ns; |
| bool needs_type = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| ns = FFESYMBOL_stateUNDERSTOOD; |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsTYPE) |
| where = FFEINFO_whereGLOBAL; |
| else |
| /* Not TYPE. */ |
| { |
| ns = FFESYMBOL_stateUNCERTAIN; |
| |
| if (sa & FFESYMBOL_attrsDUMMY) |
| assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */ |
| else if (sa & FFESYMBOL_attrsACTUALARG) |
| ; /* Not DUMMY or TYPE. */ |
| else |
| /* Not ACTUALARG, DUMMY, or TYPE. */ |
| { |
| assert (kind == FFEINFO_kindNONE); /* FUNCTION, SUBROUTINE. */ |
| na |= FFESYMBOL_attrsACTUALARG; |
| where = FFEINFO_whereGLOBAL; |
| } |
| } |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = FFEINFO_kindENTITY; |
| if (!(sa & FFESYMBOL_attrsTYPE)) |
| needs_type = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| if (sa & FFESYMBOL_attrsANYLEN) |
| ns = FFESYMBOL_stateNONE; |
| else |
| { |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| /* New state is left empty because there isn't any state flag to |
| set for this case, and it's UNDERSTOOD after all. */ |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| needs_type = TRUE; |
| } |
| else |
| ns = FFESYMBOL_stateNONE; /* Error. */ |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (ns == FFESYMBOL_stateNONE) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (needs_type && !ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, |
| where, |
| ffesymbol_size (s))); |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, ns); |
| s = ffecom_sym_learned (s); |
| ffesymbol_reference (s, t, FALSE); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in DIMENSION XYZ(FOO) or any array declarator containing |
| a reference to FOO. */ |
| |
| static ffesymbol |
| ffeexpr_sym_rhs_dimlist_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| |
| na = sa = ffesymbol_attrs (s); |
| kind = FFEINFO_kindENTITY; |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsADJUSTS; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* Since this symbol definitely is going into an expression (the |
| dimension-list for some dummy array, presumably), figure out WHERE if |
| possible. */ |
| |
| if (where == FFEINFO_whereNONE) |
| { |
| if (na & (FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST)) |
| where = FFEINFO_whereCOMMON; |
| else if (na & FFESYMBOL_attrsDUMMY) |
| where = FFEINFO_whereDUMMY; |
| } |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (na == FFESYMBOL_attrsetNONE) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* Always ENTITY. */ |
| where, /* NONE, COMMON, or DUMMY. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* Have FOO in XYZ = ...FOO.... Does not include cases like FOO in |
| XYZ = BAR(FOO), as such cases are handled elsewhere. */ |
| |
| static ffesymbol |
| ffeexpr_sym_rhs_let_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| bool error = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| error = TRUE; |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = FFEINFO_kindENTITY; |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| if (sa & FFESYMBOL_attrsANYLEN) |
| error = TRUE; |
| else |
| { |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| else |
| error = TRUE; |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (error) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, /* ENTITY. */ |
| where, /* LOCAL. */ |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* ffeexpr_declare_parenthesized_ -- ffesymbol wrapper for NAME(...) operand |
| |
| ffelexToken t; |
| bool maybe_intrin; |
| ffeexprParenType_ paren_type; |
| ffesymbol s; |
| s = ffeexpr_declare_parenthesized_ (t, maybe_intrin, &paren_type); |
| |
| Just like ffesymbol_declare_local, except performs any implicit info |
| assignment necessary, and it returns the type of the parenthesized list |
| (list of function args, list of array args, or substring spec). */ |
| |
| static ffesymbol |
| ffeexpr_declare_parenthesized_ (ffelexToken t, bool maybe_intrin, |
| ffeexprParenType_ *paren_type) |
| { |
| ffesymbol s; |
| ffesymbolState st; /* Effective state. */ |
| ffeinfoKind k; |
| bool bad; |
| |
| if (maybe_intrin && ffesrc_check_symbol ()) |
| { /* Knock off some easy cases. */ |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextSUBROUTINEREF: |
| case FFEEXPR_contextDATA: |
| case FFEEXPR_contextDATAIMPDOINDEX_: |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextLET: |
| case FFEEXPR_contextPAREN_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextIOLISTDF: |
| case FFEEXPR_contextDO: |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextACTUALARG_: |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextIF: |
| case FFEEXPR_contextARITHIF: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextSTOP: |
| case FFEEXPR_contextRETURN: |
| case FFEEXPR_contextSELECTCASE: |
| case FFEEXPR_contextCASE: |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| case FFEEXPR_contextFILEDFINT: |
| case FFEEXPR_contextFILELOG: |
| case FFEEXPR_contextFILENUM: |
| case FFEEXPR_contextFILENUMAMBIG: |
| case FFEEXPR_contextFILECHAR: |
| case FFEEXPR_contextFILENUMCHAR: |
| case FFEEXPR_contextFILEDFCHAR: |
| case FFEEXPR_contextFILEKEY: |
| case FFEEXPR_contextFILEUNIT: |
| case FFEEXPR_contextFILEUNIT_DF: |
| case FFEEXPR_contextFILEUNITAMBIG: |
| case FFEEXPR_contextFILEFORMAT: |
| case FFEEXPR_contextFILENAMELIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextIMPDOITEM_: |
| case FFEEXPR_contextIMPDOITEMDF_: |
| case FFEEXPR_contextIMPDOCTRL_: |
| case FFEEXPR_contextDATAIMPDOCTRL_: |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextPARAMETER: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| break; /* These could be intrinsic invocations. */ |
| |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextFILEFORMATNML: |
| case FFEEXPR_contextALLOCATE: |
| case FFEEXPR_contextDEALLOCATE: |
| case FFEEXPR_contextHEAPSTAT: |
| case FFEEXPR_contextNULLIFY: |
| case FFEEXPR_contextINCLUDE: |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| case FFEEXPR_contextLOC_: |
| case FFEEXPR_contextINDEXORACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| case FFEEXPR_contextPARENFILENUM_: |
| case FFEEXPR_contextPARENFILEUNIT_: |
| maybe_intrin = FALSE; |
| break; /* Can't be intrinsic invocation. */ |
| |
| default: |
| assert ("blah! blah! waaauuggh!" == NULL); |
| break; |
| } |
| } |
| |
| s = ffesymbol_declare_local (t, maybe_intrin); |
| |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| /* Special-case these since they can involve a different concept |
| of "state" (in the stmtfunc name space). */ |
| { |
| case FFEEXPR_contextDATAIMPDOINDEX_: |
| case FFEEXPR_contextDATAIMPDOCTRL_: |
| if (ffeexpr_context_outer_ (ffeexpr_stack_) |
| == FFEEXPR_contextDATAIMPDOINDEX_) |
| s = ffeexpr_sym_impdoitem_ (s, t); |
| else |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_sym_impdoitem_ (s, t); |
| else |
| s = ffeexpr_sym_lhs_impdoctrl_ (s, t); |
| if (ffesymbol_kind (s) != FFEINFO_kindANY) |
| ffesymbol_error (s, t); |
| return s; |
| |
| default: |
| break; |
| } |
| |
| switch ((ffesymbol_sfdummyparent (s) == NULL) |
| ? ffesymbol_state (s) |
| : FFESYMBOL_stateUNDERSTOOD) |
| { |
| case FFESYMBOL_stateNONE: /* Before first exec, not seen in expr |
| context. */ |
| if (!ffest_seen_first_exec ()) |
| goto seen; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFESYMBOL_stateUNCERTAIN: /* Unseen since first exec. */ |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextSUBROUTINEREF: |
| s = ffeexpr_sym_lhs_call_ (s, t); /* "CALL FOO"=="CALL |
| FOO(...)". */ |
| break; |
| |
| case FFEEXPR_contextDATA: |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_sym_rhs_let_ (s, t); |
| else |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| break; |
| |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| /* Fall through. */ |
| case FFEEXPR_contextLET: |
| case FFEEXPR_contextPAREN_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextIOLISTDF: |
| case FFEEXPR_contextDO: |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextACTUALARG_: |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextIF: |
| case FFEEXPR_contextARITHIF: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextSTOP: |
| case FFEEXPR_contextRETURN: |
| case FFEEXPR_contextSELECTCASE: |
| case FFEEXPR_contextCASE: |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| case FFEEXPR_contextFILEDFINT: |
| case FFEEXPR_contextFILELOG: |
| case FFEEXPR_contextFILENUM: |
| case FFEEXPR_contextFILENUMAMBIG: |
| case FFEEXPR_contextFILECHAR: |
| case FFEEXPR_contextFILENUMCHAR: |
| case FFEEXPR_contextFILEDFCHAR: |
| case FFEEXPR_contextFILEKEY: |
| case FFEEXPR_contextFILEUNIT: |
| case FFEEXPR_contextFILEUNIT_DF: |
| case FFEEXPR_contextFILEUNITAMBIG: |
| case FFEEXPR_contextFILEFORMAT: |
| case FFEEXPR_contextFILENAMELIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextIMPDOITEM_: |
| case FFEEXPR_contextIMPDOITEMDF_: |
| case FFEEXPR_contextIMPDOCTRL_: |
| case FFEEXPR_contextLOC_: |
| if (ffeexpr_stack_->is_rhs) |
| s = ffeexpr_paren_rhs_let_ (s, t); |
| else |
| s = ffeexpr_paren_lhs_let_ (s, t); |
| break; |
| |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextEQUIVALENCE: |
| case FFEEXPR_contextINCLUDE: |
| case FFEEXPR_contextPARAMETER: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| break; /* Will turn into errors below. */ |
| |
| default: |
| ffesymbol_error (s, t); |
| break; |
| } |
| /* Fall through. */ |
| case FFESYMBOL_stateUNDERSTOOD: /* Nothing much more to learn. */ |
| understood: /* :::::::::::::::::::: */ |
| |
| /* State might have changed, update it. */ |
| st = ((ffesymbol_sfdummyparent (s) == NULL) |
| ? ffesymbol_state (s) |
| : FFESYMBOL_stateUNDERSTOOD); |
| |
| k = ffesymbol_kind (s); |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextSUBROUTINEREF: |
| bad = ((k != FFEINFO_kindSUBROUTINE) |
| && ((ffesymbol_where (s) != FFEINFO_whereINTRINSIC) |
| || (k != FFEINFO_kindNONE))); |
| break; |
| |
| case FFEEXPR_contextDATA: |
| if (ffeexpr_stack_->is_rhs) |
| bad = (k != FFEINFO_kindENTITY) |
| || (ffesymbol_where (s) != FFEINFO_whereCONSTANT); |
| else |
| bad = (k != FFEINFO_kindENTITY) |
| || ((ffesymbol_where (s) != FFEINFO_whereNONE) |
| && (ffesymbol_where (s) != FFEINFO_whereLOCAL) |
| && (ffesymbol_where (s) != FFEINFO_whereCOMMON)); |
| break; |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| bad = (k != FFEINFO_kindENTITY) || (ffesymbol_rank (s) == 0) |
| || ((ffesymbol_where (s) != FFEINFO_whereNONE) |
| && (ffesymbol_where (s) != FFEINFO_whereLOCAL) |
| && (ffesymbol_where (s) != FFEINFO_whereCOMMON)); |
| break; |
| |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextLET: |
| case FFEEXPR_contextPAREN_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextIOLIST: |
| case FFEEXPR_contextIOLISTDF: |
| case FFEEXPR_contextDO: |
| case FFEEXPR_contextDOWHILE: |
| case FFEEXPR_contextACTUALARG_: |
| case FFEEXPR_contextCGOTO: |
| case FFEEXPR_contextIF: |
| case FFEEXPR_contextARITHIF: |
| case FFEEXPR_contextFORMAT: |
| case FFEEXPR_contextSTOP: |
| case FFEEXPR_contextRETURN: |
| case FFEEXPR_contextSELECTCASE: |
| case FFEEXPR_contextCASE: |
| case FFEEXPR_contextFILEASSOC: |
| case FFEEXPR_contextFILEINT: |
| case FFEEXPR_contextFILEDFINT: |
| case FFEEXPR_contextFILELOG: |
| case FFEEXPR_contextFILENUM: |
| case FFEEXPR_contextFILENUMAMBIG: |
| case FFEEXPR_contextFILECHAR: |
| case FFEEXPR_contextFILENUMCHAR: |
| case FFEEXPR_contextFILEDFCHAR: |
| case FFEEXPR_contextFILEKEY: |
| case FFEEXPR_contextFILEUNIT: |
| case FFEEXPR_contextFILEUNIT_DF: |
| case FFEEXPR_contextFILEUNITAMBIG: |
| case FFEEXPR_contextFILEFORMAT: |
| case FFEEXPR_contextFILENAMELIST: |
| case FFEEXPR_contextFILEVXTCODE: |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextIMPDOITEM_: |
| case FFEEXPR_contextIMPDOITEMDF_: |
| case FFEEXPR_contextIMPDOCTRL_: |
| case FFEEXPR_contextLOC_: |
| bad = FALSE; /* Let paren-switch handle the cases. */ |
| break; |
| |
| case FFEEXPR_contextASSIGN: |
| case FFEEXPR_contextAGOTO: |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextEQUIVALENCE: |
| case FFEEXPR_contextPARAMETER: |
| case FFEEXPR_contextDIMLIST: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| bad = (k != FFEINFO_kindENTITY) |
| || (ffesymbol_where (s) != FFEINFO_whereCONSTANT); |
| break; |
| |
| case FFEEXPR_contextINCLUDE: |
| bad = TRUE; |
| break; |
| |
| default: |
| bad = TRUE; |
| break; |
| } |
| |
| switch (bad ? FFEINFO_kindANY : k) |
| { |
| case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */ |
| if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC) |
| { |
| if (ffeexpr_context_outer_ (ffeexpr_stack_) |
| == FFEEXPR_contextSUBROUTINEREF) |
| *paren_type = FFEEXPR_parentypeSUBROUTINE_; |
| else |
| *paren_type = FFEEXPR_parentypeFUNCTION_; |
| break; |
| } |
| if (st == FFESYMBOL_stateUNDERSTOOD) |
| { |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| } |
| else |
| *paren_type = FFEEXPR_parentypeFUNSUBSTR_; |
| break; |
| |
| case FFEINFO_kindFUNCTION: |
| *paren_type = FFEEXPR_parentypeFUNCTION_; |
| switch (ffesymbol_where (s)) |
| { |
| case FFEINFO_whereLOCAL: |
| bad = TRUE; /* Attempt to recurse! */ |
| break; |
| |
| case FFEINFO_whereCONSTANT: |
| bad = ((ffesymbol_sfexpr (s) == NULL) |
| || (ffebld_op (ffesymbol_sfexpr (s)) |
| == FFEBLD_opANY)); /* Attempt to recurse! */ |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| case FFEINFO_kindSUBROUTINE: |
| if ((ffeexpr_stack_->context != FFEEXPR_contextSUBROUTINEREF) |
| || (ffeexpr_stack_->previous != NULL)) |
| { |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| break; |
| } |
| |
| *paren_type = FFEEXPR_parentypeSUBROUTINE_; |
| switch (ffesymbol_where (s)) |
| { |
| case FFEINFO_whereLOCAL: |
| case FFEINFO_whereCONSTANT: |
| bad = TRUE; /* Attempt to recurse! */ |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| case FFEINFO_kindENTITY: |
| if (ffesymbol_rank (s) == 0) |
| { |
| if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER) |
| *paren_type = FFEEXPR_parentypeSUBSTRING_; |
| else |
| { |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| } |
| } |
| else |
| *paren_type = FFEEXPR_parentypeARRAY_; |
| break; |
| |
| default: |
| case FFEINFO_kindANY: |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| break; |
| } |
| |
| if (bad) |
| { |
| if (k == FFEINFO_kindANY) |
| ffest_shutdown (); |
| else |
| ffesymbol_error (s, t); |
| } |
| |
| return s; |
| |
| case FFESYMBOL_stateSEEN: /* Seen but not yet in exec portion. */ |
| seen: /* :::::::::::::::::::: */ |
| bad = TRUE; |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextPARAMETER: |
| if (ffeexpr_stack_->is_rhs) |
| ffesymbol_error (s, t); |
| else |
| s = ffeexpr_sym_lhs_parameter_ (s, t); |
| break; |
| |
| case FFEEXPR_contextDATA: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| if (ffeexpr_stack_->is_rhs) |
| ffesymbol_error (s, t); |
| else |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| s = ffeexpr_sym_lhs_data_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| case FFEEXPR_contextEQUIVALENCE: |
| s = ffeexpr_sym_lhs_equivalence_ (s, t); |
| bad = FALSE; |
| break; |
| |
| case FFEEXPR_contextDIMLIST: |
| s = ffeexpr_sym_rhs_dimlist_ (s, t); |
| break; |
| |
| case FFEEXPR_contextCHARACTERSIZE: |
| case FFEEXPR_contextKINDTYPE: |
| case FFEEXPR_contextDIMLISTCOMMON: |
| case FFEEXPR_contextINITVAL: |
| case FFEEXPR_contextEQVINDEX_: |
| break; |
| |
| case FFEEXPR_contextINCLUDE: |
| break; |
| |
| case FFEEXPR_contextINDEX_: |
| case FFEEXPR_contextACTUALARGEXPR_: |
| case FFEEXPR_contextINDEXORACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| case FFEEXPR_contextSFUNCDEFACTUALARGEXPR_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARGEXPR_: |
| assert (ffeexpr_stack_->is_rhs); |
| s = ffecom_sym_exec_transition (s); |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| goto understood; /* :::::::::::::::::::: */ |
| s = ffeexpr_paren_rhs_let_ (s, t); |
| goto understood; /* :::::::::::::::::::: */ |
| |
| default: |
| break; |
| } |
| k = ffesymbol_kind (s); |
| switch (bad ? FFEINFO_kindANY : k) |
| { |
| case FFEINFO_kindNONE: /* Case "CHARACTER X,Y; Y=X(?". */ |
| *paren_type = FFEEXPR_parentypeFUNSUBSTR_; |
| break; |
| |
| case FFEINFO_kindFUNCTION: |
| *paren_type = FFEEXPR_parentypeFUNCTION_; |
| switch (ffesymbol_where (s)) |
| { |
| case FFEINFO_whereLOCAL: |
| bad = TRUE; /* Attempt to recurse! */ |
| break; |
| |
| case FFEINFO_whereCONSTANT: |
| bad = ((ffesymbol_sfexpr (s) == NULL) |
| || (ffebld_op (ffesymbol_sfexpr (s)) |
| == FFEBLD_opANY)); /* Attempt to recurse! */ |
| break; |
| |
| default: |
| break; |
| } |
| break; |
| |
| case FFEINFO_kindSUBROUTINE: |
| *paren_type = FFEEXPR_parentypeANY_; |
| bad = TRUE; /* Cannot possibly be in |
| contextSUBROUTINEREF. */ |
| break; |
| |
| case FFEINFO_kindENTITY: |
| if (ffesymbol_rank (s) == 0) |
| { |
| if (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE) |
| *paren_type = FFEEXPR_parentypeEQUIVALENCE_; |
| else if (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER) |
| *paren_type = FFEEXPR_parentypeSUBSTRING_; |
| else |
| { |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| } |
| } |
| else |
| *paren_type = FFEEXPR_parentypeARRAY_; |
| break; |
| |
| default: |
| case FFEINFO_kindANY: |
| bad = TRUE; |
| *paren_type = FFEEXPR_parentypeANY_; |
| break; |
| } |
| |
| if (bad) |
| { |
| if (k == FFEINFO_kindANY) |
| ffest_shutdown (); |
| else |
| ffesymbol_error (s, t); |
| } |
| |
| return s; |
| |
| default: |
| assert ("bad symbol state" == NULL); |
| return NULL; |
| } |
| } |
| |
| /* Have FOO in XYZ = ...FOO(...).... Executable context only. */ |
| |
| static ffesymbol |
| ffeexpr_paren_rhs_let_ (ffesymbol s, ffelexToken t) |
| { |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| ffeintrinGen gen; |
| ffeintrinSpec spec; |
| ffeintrinImp imp; |
| bool maybe_ambig = FALSE; |
| bool error = FALSE; |
| |
| assert ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN)); |
| |
| na = sa = ffesymbol_attrs (s); |
| |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (sa & FFESYMBOL_attrsEXTERNAL) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsACTUALARG |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| if (sa & FFESYMBOL_attrsTYPE) |
| where = FFEINFO_whereGLOBAL; |
| else |
| /* Not TYPE. */ |
| { |
| kind = FFEINFO_kindFUNCTION; |
| |
| if (sa & FFESYMBOL_attrsDUMMY) |
| ; /* Not TYPE. */ |
| else if (sa & FFESYMBOL_attrsACTUALARG) |
| ; /* Not DUMMY or TYPE. */ |
| else /* Not ACTUALARG, DUMMY, or TYPE. */ |
| where = FFEINFO_whereGLOBAL; |
| } |
| } |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| assert (!(sa & FFESYMBOL_attrsEXTERNAL)); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsTYPE))); |
| |
| kind = FFEINFO_kindFUNCTION; |
| maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure; kind |
| could be ENTITY w/substring ref. */ |
| } |
| else if (sa & FFESYMBOL_attrsARRAY) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; |
| } |
| else if (sa & FFESYMBOL_attrsSFARG) |
| { |
| assert (!(sa & ~(FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))); |
| |
| where = FFEINFO_whereLOCAL; /* Actually an error, but at least we |
| know it's a local var. */ |
| } |
| else if (sa & FFESYMBOL_attrsTYPE) |
| { |
| assert (!(sa & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); /* Handled above. */ |
| assert (!(sa & ~(FFESYMBOL_attrsTYPE |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG))); |
| |
| if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE, |
| &gen, &spec, &imp)) |
| { |
| if (!(sa & FFESYMBOL_attrsANYLEN) |
| && (ffeimplic_peek_symbol_type (s, NULL) |
| == FFEINFO_basictypeCHARACTER)) |
| return s; /* Haven't learned anything yet. */ |
| |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| ffesymbol_set_generic (s, gen); |
| ffesymbol_set_specific (s, spec); |
| ffesymbol_set_implementation (s, imp); |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| FFEINFO_kindFUNCTION, |
| FFEINFO_whereINTRINSIC, |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| ffesymbol_reference (s, t, FALSE); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| |
| return s; |
| } |
| if (sa & FFESYMBOL_attrsANYLEN) |
| error = TRUE; /* Error, since the only way we can, |
| given CHARACTER*(*) FOO, accept |
| FOO(...) is for FOO to be a dummy |
| arg or constant, but it can't |
| become either now. */ |
| else if (sa & FFESYMBOL_attrsADJUSTABLE) |
| { |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereLOCAL; |
| } |
| else |
| { |
| kind = FFEINFO_kindFUNCTION; |
| where = FFEINFO_whereGLOBAL; |
| maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure; |
| could be ENTITY/LOCAL w/substring ref. */ |
| } |
| } |
| else if (sa == FFESYMBOL_attrsetNONE) |
| { |
| assert (ffesymbol_state (s) == FFESYMBOL_stateNONE); |
| |
| if (ffeintrin_is_intrinsic (ffesymbol_text (s), t, FALSE, |
| &gen, &spec, &imp)) |
| { |
| if (ffeimplic_peek_symbol_type (s, NULL) |
| == FFEINFO_basictypeCHARACTER) |
| return s; /* Haven't learned anything yet. */ |
| |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| ffesymbol_set_generic (s, gen); |
| ffesymbol_set_specific (s, spec); |
| ffesymbol_set_implementation (s, imp); |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| FFEINFO_kindFUNCTION, |
| FFEINFO_whereINTRINSIC, |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_reference (s, t, FALSE); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| return s; |
| } |
| |
| kind = FFEINFO_kindFUNCTION; |
| where = FFEINFO_whereGLOBAL; |
| maybe_ambig = TRUE; /* If basictypeCHARACTER, can't be sure; |
| could be ENTITY/LOCAL w/substring ref. */ |
| } |
| else |
| error = TRUE; |
| |
| /* Now see what we've got for a new object: NONE means a new error cropped |
| up; ANY means an old error to be ignored; otherwise, everything's ok, |
| update the object (symbol) and continue on. */ |
| |
| if (error) |
| ffesymbol_error (s, t); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_signal_change (s); /* May need to back up to previous |
| version. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return s; |
| } |
| if (maybe_ambig |
| && (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)) |
| return s; /* Still not sure, let caller deal with it |
| based on (...). */ |
| |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, |
| where, |
| ffesymbol_size (s))); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_reference (s, t, FALSE); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| } |
| |
| return s; |
| } |
| |
| /* ffeexpr_token_arguments_ -- OPEN_PAREN [expr COMMA]...expr |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle expression (which might be null) and COMMA or CLOSE_PAREN. */ |
| |
| static ffelexHandler |
| ffeexpr_token_arguments_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeexprExpr_ procedure; |
| ffebld reduced; |
| ffeinfo info; |
| ffeexprContext ctx; |
| bool check_intrin = FALSE; /* Set TRUE if intrinsic is REAL(Z) or AIMAG(Z). */ |
| |
| procedure = ffeexpr_stack_->exprstack; |
| info = ffebld_info (procedure->u.operand); |
| |
| /* 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) |
| { |
| val = ffebld_constant_integerdefault (ffebld_conter (expr)); |
| |
| lbound = ffebld_left (ffebld_head (ffeexpr_stack_->bound_list)); |
| if (lbound == NULL) |
| { |
| lcheck = TRUE; |
| lval = 1; |
| } |
| else if (ffebld_op (lbound) == FFEBLD_opCONTER) |
| { |
| lcheck = TRUE; |
| lval = ffebld_constant_integerdefault (ffebld_conter (lbound)); |
| } |
| else |
| lcheck = FALSE; |
| |
| ubound = ffebld_right (ffebld_head (ffeexpr_stack_->bound_list)); |
| assert (ubound != NULL); |
| if (ffebld_op (ubound) == FFEBLD_opCONTER) |
| { |
| ucheck = TRUE; |
| uval = ffebld_constant_integerdefault (ffebld_conter (ubound)); |
| } |
| else |
| ucheck = FALSE; |
| |
| if ((lcheck && (val < lval)) || (ucheck && (val > uval))) |
| { |
| ffebad_start (FFEBAD_RANGE_ARRAY); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| } |
| } |
| ffebld_append_item (&ffeexpr_stack_->bottom, expr); |
| ffeexpr_stack_->bound_list = ffebld_trail (ffeexpr_stack_->bound_list); |
| } |
| } |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeCOMMA: |
| switch (ffeexpr_context_outer_ (ffeexpr_stack_)) |
| { |
| case FFEEXPR_contextDATAIMPDOITEM_: |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextDATAIMPDOINDEX_, |
| ffeexpr_token_elements_); |
| |
| case FFEEXPR_contextEQUIVALENCE: |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextEQVINDEX_, |
| ffeexpr_token_elements_); |
| |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextSFUNCDEFINDEX_, |
| ffeexpr_token_elements_); |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| assert ("bad context" == NULL); |
| break; |
| |
| default: |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextINDEX_, |
| ffeexpr_token_elements_); |
| } |
| |
| default: |
| break; |
| } |
| |
| if ((ffeexpr_stack_->rank != ffeinfo_rank (info)) |
| && (ffeinfo_rank (info) != 0)) |
| { |
| char num[10]; |
| |
| if (ffeexpr_stack_->rank < ffeinfo_rank (info)) |
| { |
| if (ffebad_start (FFEBAD_TOO_FEW_ELEMENTS)) |
| { |
| sprintf (num, "%d", |
| (int) (ffeinfo_rank (info) - ffeexpr_stack_->rank)); |
| |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_here (1, |
| ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_string (num); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if (ffebad_start (FFEBAD_TOO_MANY_ELEMENTS)) |
| { |
| sprintf (num, "%d", |
| (int) (ffeexpr_stack_->rank - ffeinfo_rank (info))); |
| |
| ffebad_here (0, |
| ffelex_token_where_line (ffeexpr_stack_->tokens[1]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[1])); |
| ffebad_here (1, |
| ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_string (num); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_stack_->tokens[1]); |
| } |
| while (ffeexpr_stack_->rank++ < ffeinfo_rank (info)) |
| { |
| expr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1)); |
| ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, |
| 0, FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| ffebld_append_item (&ffeexpr_stack_->bottom, expr); |
| } |
| } |
| ffebld_end_list (&ffeexpr_stack_->bottom); |
| |
| if (ffebld_op (array->u.operand) == FFEBLD_opANY) |
| { |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| } |
| else |
| { |
| reduced = ffebld_new_arrayref (array->u.operand, ffeexpr_stack_->expr); |
| if (ffeexpr_stack_->constant) |
| where = FFEINFO_whereFLEETING_CADDR; |
| else if (ffeexpr_stack_->immediate) |
| where = FFEINFO_whereFLEETING_IADDR; |
| else |
| where = FFEINFO_whereFLEETING; |
| ffebld_set_info (reduced, |
| ffeinfo_new (ffeinfo_basictype (info), |
| ffeinfo_kindtype (info), |
| 0, |
| FFEINFO_kindENTITY, |
| where, |
| ffeinfo_size (info))); |
| reduced = ffeexpr_collapse_arrayref (reduced, ffeexpr_stack_->tokens[0]); |
| } |
| |
| ffeexpr_stack_->exprstack = array->previous; /* Pops not-quite-operand off |
| stack. */ |
| array->u.operand = reduced; /* Save the line/column ffewhere info. */ |
| ffeexpr_exprstack_push_operand_ (array); /* Push it back on stack. */ |
| |
| switch (ffeinfo_basictype (info)) |
| { |
| case FFEINFO_basictypeCHARACTER: |
| ffeexpr_is_substr_ok_ = TRUE; /* Everyone likes "FOO(3)(1:1)".... */ |
| break; |
| |
| case FFEINFO_basictypeNONE: |
| ffeexpr_is_substr_ok_ = TRUE; |
| assert (ffeexpr_stack_->context == FFEEXPR_contextEQUIVALENCE); |
| break; |
| |
| default: |
| ffeexpr_is_substr_ok_ = FALSE; |
| break; |
| } |
| |
| if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN) |
| { |
| ffelex_token_kill (ffeexpr_stack_->tokens[0]); |
| return (ffelexHandler) ffeexpr_token_substrp_; |
| } |
| |
| if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_finish (); |
| } |
| ffelex_token_kill (ffeexpr_stack_->tokens[0]); |
| return |
| (ffelexHandler) ffeexpr_find_close_paren_ (t, |
| (ffelexHandler) |
| ffeexpr_token_substrp_); |
| } |
| |
| /* ffeexpr_token_equivalence_ -- OPEN_PAREN expr |
| |
| Return a pointer to this array to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| If token is COLON, pass off to _substr_, else init list and pass off |
| to _elements_. This handles the case "EQUIVALENCE (FOO(expr?", where |
| ? marks the token, and where FOO's rank/type has not yet been established, |
| meaning we could be in a list of indices or in a substring |
| specification. */ |
| |
| static ffelexHandler |
| ffeexpr_token_equivalence_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| return ffeexpr_token_substring_ (ft, expr, t); |
| |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| return ffeexpr_token_elements_ (ft, expr, t); |
| } |
| |
| /* ffeexpr_token_substring_ -- NAME(of kindENTITY) OPEN_PAREN expr |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle expression (which may be null) and COLON. */ |
| |
| static ffelexHandler |
| ffeexpr_token_substring_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeexprExpr_ string; |
| ffeinfo info; |
| ffetargetIntegerDefault i; |
| ffeexprContext ctx; |
| ffetargetCharacterSize size; |
| |
| string = ffeexpr_stack_->exprstack; |
| info = ffebld_info (string->u.operand); |
| size = ffebld_size_max (string->u.operand); |
| |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| { |
| if ((expr != NULL) |
| && (ffebld_op (expr) == FFEBLD_opCONTER) |
| && (((i = ffebld_constant_integerdefault (ffebld_conter (expr))) |
| < 1) |
| || ((size != FFETARGET_charactersizeNONE) && (i > size)))) |
| { |
| ffebad_start (FFEBAD_RANGE_SUBSTR); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| } |
| ffeexpr_stack_->expr = expr; |
| |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| ctx = FFEEXPR_contextSFUNCDEFINDEX_; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| assert ("bad context" == NULL); |
| ctx = FFEEXPR_context; |
| break; |
| |
| default: |
| ctx = FFEEXPR_contextINDEX_; |
| break; |
| } |
| |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx, |
| ffeexpr_token_substring_1_); |
| } |
| |
| if (ffest_ffebad_start (FFEBAD_MISSING_COLON_IN_SUBSTR)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_finish (); |
| } |
| |
| ffeexpr_stack_->expr = NULL; |
| return (ffelexHandler) ffeexpr_token_substring_1_ (ft, expr, t); |
| } |
| |
| /* ffeexpr_token_substring_1_ -- NAME OPEN_PAREN [expr COMMA]...expr |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| Handle expression (which might be null) and CLOSE_PAREN. */ |
| |
| static ffelexHandler |
| ffeexpr_token_substring_1_ (ffelexToken ft, ffebld last, ffelexToken t) |
| { |
| ffeexprExpr_ string; |
| ffebld reduced; |
| ffebld substrlist; |
| ffebld first = ffeexpr_stack_->expr; |
| ffebld strop; |
| ffeinfo info; |
| ffeinfoWhere lwh; |
| ffeinfoWhere rwh; |
| ffeinfoWhere where; |
| ffeinfoKindtype first_kt; |
| ffeinfoKindtype last_kt; |
| ffetargetIntegerDefault first_val; |
| ffetargetIntegerDefault last_val; |
| ffetargetCharacterSize size; |
| ffetargetCharacterSize strop_size_max; |
| |
| string = ffeexpr_stack_->exprstack; |
| strop = string->u.operand; |
| info = ffebld_info (strop); |
| |
| if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER)) |
| { /* The starting point is known. */ |
| first_val = (first == NULL) ? 1 |
| : ffebld_constant_integerdefault (ffebld_conter (first)); |
| } |
| else |
| { /* Assume start of the entity. */ |
| first_val = 1; |
| } |
| |
| if ((last != NULL) && (ffebld_op (last) == FFEBLD_opCONTER)) |
| { /* The ending point is known. */ |
| last_val = ffebld_constant_integerdefault (ffebld_conter (last)); |
| |
| if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER)) |
| { /* The beginning point is a constant. */ |
| if (first_val <= last_val) |
| size = last_val - first_val + 1; |
| else |
| { |
| if (0 && ffe_is_90 ()) |
| size = 0; |
| else |
| { |
| size = 1; |
| ffebad_start (FFEBAD_ZERO_SIZE); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| } |
| } |
| } |
| else |
| size = FFETARGET_charactersizeNONE; |
| |
| strop_size_max = ffebld_size_max (strop); |
| |
| if ((strop_size_max != FFETARGET_charactersizeNONE) |
| && (last_val > strop_size_max)) |
| { /* Beyond maximum possible end of string. */ |
| ffebad_start (FFEBAD_RANGE_SUBSTR); |
| ffebad_here (0, ffelex_token_where_line (ft), |
| ffelex_token_where_column (ft)); |
| ffebad_finish (); |
| } |
| } |
| else |
| size = FFETARGET_charactersizeNONE; /* The size is not known. */ |
| |
| #if 0 /* Don't do this, or "is size of target |
| known?" would no longer be easily |
| answerable. To see if there is a max |
| size, use ffebld_size_max; to get only the |
| known size, else NONE, use |
| ffebld_size_known; use ffebld_size if |
| values are sure to be the same (not |
| opSUBSTR or opCONCATENATE or known to have |
| known length). By getting rid of this |
| "useful info" stuff, we don't end up |
| blank-padding the constant in the |
| assignment "A(I:J)='XYZ'" to the known |
| length of A. */ |
| if (size == FFETARGET_charactersizeNONE) |
| size = strop_size_max; /* Assume we use the entire string. */ |
| #endif |
| |
| substrlist |
| = ffebld_new_item |
| (first, |
| ffebld_new_item |
| (last, |
| NULL |
| ) |
| ) |
| ; |
| |
| if (first == NULL) |
| lwh = FFEINFO_whereCONSTANT; |
| else |
| lwh = ffeinfo_where (ffebld_info (first)); |
| if (last == NULL) |
| rwh = FFEINFO_whereCONSTANT; |
| else |
| rwh = ffeinfo_where (ffebld_info (last)); |
| |
| switch (lwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| where = FFEINFO_whereCONSTANT; |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| where = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| where = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (rwh) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: |
| where = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| where = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| |
| default: |
| where = FFEINFO_whereFLEETING; |
| break; |
| } |
| |
| if (first == NULL) |
| first_kt = FFEINFO_kindtypeINTEGERDEFAULT; |
| else |
| first_kt = ffeinfo_kindtype (ffebld_info (first)); |
| if (last == NULL) |
| last_kt = FFEINFO_kindtypeINTEGERDEFAULT; |
| else |
| last_kt = ffeinfo_kindtype (ffebld_info (last)); |
| |
| switch (where) |
| { |
| case FFEINFO_whereCONSTANT: |
| switch (ffeinfo_where (info)) |
| { |
| case FFEINFO_whereCONSTANT: |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */ |
| where = FFEINFO_whereIMMEDIATE; |
| break; |
| |
| default: |
| where = FFEINFO_whereFLEETING_CADDR; |
| break; |
| } |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: |
| switch (ffeinfo_where (info)) |
| { |
| case FFEINFO_whereCONSTANT: |
| case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */ |
| break; |
| |
| default: |
| where = FFEINFO_whereFLEETING_IADDR; |
| break; |
| } |
| break; |
| |
| default: |
| switch (ffeinfo_where (info)) |
| { |
| case FFEINFO_whereCONSTANT: |
| where = FFEINFO_whereCONSTANT_SUBOBJECT; /* An F90 concept. */ |
| break; |
| |
| case FFEINFO_whereIMMEDIATE: /* Not possible, actually. */ |
| default: |
| where = FFEINFO_whereFLEETING; |
| break; |
| } |
| break; |
| } |
| |
| if (ffebld_op (strop) == FFEBLD_opANY) |
| { |
| reduced = ffebld_new_any (); |
| ffebld_set_info (reduced, ffeinfo_new_any ()); |
| } |
| else |
| { |
| reduced = ffebld_new_substr (strop, substrlist); |
| ffebld_set_info (reduced, ffeinfo_new |
| (FFEINFO_basictypeCHARACTER, |
| ffeinfo_kindtype (info), |
| 0, |
| FFEINFO_kindENTITY, |
| where, |
| size)); |
| reduced = ffeexpr_collapse_substr (reduced, ffeexpr_stack_->tokens[0]); |
| } |
| |
| ffeexpr_stack_->exprstack = string->previous; /* Pops not-quite-operand off |
| stack. */ |
| string->u.operand = reduced; /* Save the line/column ffewhere info. */ |
| ffeexpr_exprstack_push_operand_ (string); /* Push it back on stack. */ |
| |
| if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN) |
| { |
| ffelex_token_kill (ffeexpr_stack_->tokens[0]); |
| ffeexpr_is_substr_ok_ = FALSE; /* Nobody likes "FOO(3:5)(1:1)".... */ |
| return (ffelexHandler) ffeexpr_token_substrp_; |
| } |
| |
| if (ffest_ffebad_start (FFEBAD_INVALID_TOKEN_IN_EXPRESSION)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->tokens[0]), |
| ffelex_token_where_column (ffeexpr_stack_->tokens[0])); |
| ffebad_finish (); |
| } |
| |
| ffelex_token_kill (ffeexpr_stack_->tokens[0]); |
| ffeexpr_is_substr_ok_ = FALSE;/* Nobody likes "FOO(3:5)(1:1)".... */ |
| return |
| (ffelexHandler) ffeexpr_find_close_paren_ (t, |
| (ffelexHandler) |
| ffeexpr_token_substrp_); |
| } |
| |
| /* ffeexpr_token_substrp_ -- Rhs <character entity> |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| If OPEN_PAREN, treat as start of a substring ("(3:4)") construct, and |
| issue error message if flag (serves as argument) is set. Else, just |
| forward token to binary_. */ |
| |
| static ffelexHandler |
| ffeexpr_token_substrp_ (ffelexToken t) |
| { |
| ffeexprContext ctx; |
| |
| if (ffelex_token_type (t) != FFELEX_typeOPEN_PAREN) |
| return (ffelexHandler) ffeexpr_token_binary_ (t); |
| |
| ffeexpr_stack_->tokens[0] = ffelex_token_use (t); |
| |
| switch (ffeexpr_stack_->context) |
| { |
| case FFEEXPR_contextSFUNCDEF: |
| case FFEEXPR_contextSFUNCDEFINDEX_: |
| ctx = FFEEXPR_contextSFUNCDEFINDEX_; |
| break; |
| |
| case FFEEXPR_contextSFUNCDEFACTUALARG_: |
| case FFEEXPR_contextSFUNCDEFINDEXORACTUALARG_: |
| assert ("bad context" == NULL); |
| ctx = FFEEXPR_context; |
| break; |
| |
| default: |
| ctx = FFEEXPR_contextINDEX_; |
| break; |
| } |
| |
| if (!ffeexpr_is_substr_ok_) |
| { |
| if (ffebad_start (FFEBAD_BAD_SUBSTR)) |
| { |
| ffebad_here (0, ffelex_token_where_line (t), |
| ffelex_token_where_column (t)); |
| ffebad_here (1, ffelex_token_where_line (ffeexpr_stack_->exprstack->token), |
| ffelex_token_where_column (ffeexpr_stack_->exprstack->token)); |
| ffebad_finish (); |
| } |
| |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx, |
| ffeexpr_token_anything_); |
| } |
| |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, ctx, |
| ffeexpr_token_substring_); |
| } |
| |
| static ffelexHandler |
| ffeexpr_token_intrincheck_ (ffelexToken t) |
| { |
| if ((ffelex_token_type (t) != FFELEX_typeCLOSE_PAREN) |
| && ffebad_start (FFEBAD_INTRINSIC_CMPAMBIG)) |
| { |
| ffebad_string (ffeintrin_name_implementation |
| (ffebld_symter_implementation |
| (ffebld_left |
| (ffeexpr_stack_->exprstack->u.operand)))); |
| ffebad_here (0, ffelex_token_where_line (ffeexpr_stack_->exprstack->token), |
| ffelex_token_where_column (ffeexpr_stack_->exprstack->token)); |
| ffebad_finish (); |
| } |
| |
| return (ffelexHandler) ffeexpr_token_substrp_ (t); |
| } |
| |
| /* ffeexpr_token_funsubstr_ -- NAME OPEN_PAREN expr |
| |
| Return a pointer to this function to the lexer (ffelex), which will |
| invoke it for the next token. |
| |
| If COLON, do everything we would have done since _parenthesized_ if |
| we had known NAME represented a kindENTITY instead of a kindFUNCTION. |
| If not COLON, do likewise for kindFUNCTION instead. */ |
| |
| static ffelexHandler |
| ffeexpr_token_funsubstr_ (ffelexToken ft, ffebld expr, ffelexToken t) |
| { |
| ffeinfoWhere where; |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffebld symter = ffeexpr_stack_->exprstack->u.operand; |
| bool needs_type; |
| ffeintrinGen gen; |
| ffeintrinSpec spec; |
| ffeintrinImp imp; |
| |
| s = ffebld_symter (symter); |
| sa = ffesymbol_attrs (s); |
| where = ffesymbol_where (s); |
| |
| /* We get here only if we don't already know enough about FOO when seeing a |
| FOO(stuff) reference, and FOO might turn out to be a CHARACTER type. If |
| "stuff" is a substring reference, then FOO is a CHARACTER scalar type. |
| Else FOO is a function, either intrinsic or external. If intrinsic, it |
| wouldn't necessarily be CHARACTER type, so unless it has already been |
| declared DUMMY, it hasn't had its type established yet. It can't be |
| CHAR*(*) in any case, though it can have an explicit CHAR*n type. */ |
| |
| assert (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsTYPE))); |
| |
| needs_type = !(ffesymbol_attrs (s) & FFESYMBOL_attrsDUMMY); |
| |
| ffesymbol_signal_change (s); /* Probably already done, but in case.... */ |
| |
| if (ffelex_token_type (t) == FFELEX_typeCOLON) |
| { /* Definitely an ENTITY (char substring). */ |
| if (needs_type && !ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, ffeexpr_stack_->tokens[0]); |
| return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t); |
| } |
| |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| FFEINFO_kindENTITY, |
| (where == FFEINFO_whereNONE) |
| ? FFEINFO_whereLOCAL |
| : where, |
| ffesymbol_size (s))); |
| ffebld_set_info (symter, ffeinfo_use (ffesymbol_info (s))); |
| |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| |
| ffeexpr_stack_->exprstack->u.operand |
| = ffeexpr_collapse_symter (symter, ffeexpr_tokens_[0]); |
| |
| return (ffelexHandler) ffeexpr_token_substring_ (ft, expr, t); |
| } |
| |
| /* The "stuff" isn't a substring notation, so we now know the overall |
| reference is to a function. */ |
| |
| if (ffeintrin_is_intrinsic (ffesymbol_text (s), ffeexpr_stack_->tokens[0], |
| FALSE, &gen, &spec, &imp)) |
| { |
| ffebld_symter_set_generic (symter, gen); |
| ffebld_symter_set_specific (symter, spec); |
| ffebld_symter_set_implementation (symter, imp); |
| ffesymbol_set_generic (s, gen); |
| ffesymbol_set_specific (s, spec); |
| ffesymbol_set_implementation (s, imp); |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| FFEINFO_kindFUNCTION, |
| FFEINFO_whereINTRINSIC, |
| ffesymbol_size (s))); |
| } |
| else |
| { /* Not intrinsic, now needs CHAR type. */ |
| if (!ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, ffeexpr_stack_->tokens[0]); |
| return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t); |
| } |
| |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| FFEINFO_kindFUNCTION, |
| (where == FFEINFO_whereNONE) |
| ? FFEINFO_whereGLOBAL |
| : where, |
| ffesymbol_size (s))); |
| } |
| |
| ffebld_set_info (symter, ffeinfo_use (ffesymbol_info (s))); |
| |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_resolve_intrin (s); |
| s = ffecom_sym_learned (s); |
| ffesymbol_reference (s, ffeexpr_stack_->tokens[0], FALSE); |
| ffesymbol_signal_unreported (s); /* For debugging purposes. */ |
| ffebld_init_list (&ffeexpr_stack_->expr, &ffeexpr_stack_->bottom); |
| return (ffelexHandler) ffeexpr_token_arguments_ (ft, expr, t); |
| } |
| |
| /* ffeexpr_token_anything_ -- NAME OPEN_PAREN any-expr |
| |
| Handle basically any expression, looking for CLOSE_PAREN. */ |
| |
| static ffelexHandler |
| ffeexpr_token_anything_ (ffelexToken ft UNUSED, ffebld expr UNUSED, |
| ffelexToken t) |
| { |
| ffeexprExpr_ e = ffeexpr_stack_->exprstack; |
| |
| switch (ffelex_token_type (t)) |
| { |
| case FFELEX_typeCOMMA: |
| case FFELEX_typeCOLON: |
| return (ffelexHandler) ffeexpr_rhs (ffeexpr_stack_->pool, |
| FFEEXPR_contextACTUALARG_, |
| ffeexpr_token_anything_); |
| |
| default: |
| e->u.operand = ffebld_new_any (); |
| ffebld_set_info (e->u.operand, ffeinfo_new_any ()); |
| ffelex_token_kill (ffeexpr_stack_->tokens[0]); |
| ffeexpr_is_substr_ok_ = FALSE; |
| if (ffelex_token_type (t) == FFELEX_typeCLOSE_PAREN) |
| return (ffelexHandler) ffeexpr_token_substrp_; |
| return (ffelexHandler) ffeexpr_token_substrp_ (t); |
| } |
| } |
| |
| /* Terminate module. */ |
| |
| void |
| ffeexpr_terminate_2 () |
| { |
| assert (ffeexpr_stack_ == NULL); |
| assert (ffeexpr_level_ == 0); |
| } |