| /* stc.c -- Implementation File (module.c template V1.0) |
| Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. |
| Contributed by James Craig Burley. |
| |
| This file is part of GNU Fortran. |
| |
| GNU Fortran is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Fortran is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Fortran; see the file COPYING. If not, write to |
| the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| Related Modules: |
| st.c |
| |
| Description: |
| Verifies the proper semantics for statements, checking expressions already |
| semantically analyzed individually, collectively, checking label defs and |
| refs, and so on. Uses ffebad to indicate errors in semantics. |
| |
| In many cases, both a token and a keyword (ffestrFirst, ffestrSecond, |
| or ffestrOther) is provided. ONLY USE THE TOKEN as a pointer to the |
| source-code location for an error message or similar; use the keyword |
| as the semantic matching for the token, since the token's text might |
| not match the keyword's code. For example, INTENT(IN OUT) A in free |
| source form passes to ffestc_R519_start the token "IN" but the keyword |
| FFESTR_otherINOUT, and the latter is correct. |
| |
| Generally, either a single ffestc function handles an entire statement, |
| in which case its name is ffestc_xyz_, or more than one function is |
| needed, in which case its names are ffestc_xyz_start_, |
| ffestc_xyz_item_ or ffestc_xyz_item_abc_, and ffestc_xyz_finish_. |
| The caller must call _start_ before calling any _item_ functions, and |
| must call _finish_ afterwards. If it is clearly a syntactic matter as |
| to restrictions on the number and variety of _item_ calls, then the caller |
| should report any errors and ffestc_ should presume it has been taken |
| care of and handle any semantic problems with grace and no error messages. |
| If the permitted number and variety of _item_ calls has some basis in |
| semantics, then the caller should not generate any messages and ffestc |
| should do all the checking. |
| |
| A few ffestc functions have names rather than grammar numbers, like |
| ffestc_elsewhere and ffestc_end. These are cases where the actual |
| statement depends on its context rather than just its form; ELSE WHERE |
| may be the obvious (WHERE...ELSE WHERE...END WHERE) or something a little |
| more subtle (WHERE: IF THEN...ELSE WHERE...END IF WHERE). The actual |
| ffestc functions do exist and do work, but may or may not be invoked |
| by ffestb depending on whether some form of resolution is possible. |
| For example, ffestc_R1103 end-program-stmt is reachable directly when |
| END PROGRAM [name] is specified, or via ffestc_end when END is specified |
| and the context is a main program. So ffestc_xyz_ should make a quick |
| determination of the context and pick the appropriate ffestc_Nxyz_ |
| function to invoke, without a lot of ceremony. |
| |
| Modifications: |
| */ |
| |
| /* Include files. */ |
| |
| #include "proj.h" |
| #include "stc.h" |
| #include "bad.h" |
| #include "bld.h" |
| #include "data.h" |
| #include "expr.h" |
| #include "global.h" |
| #include "implic.h" |
| #include "lex.h" |
| #include "malloc.h" |
| #include "src.h" |
| #include "sta.h" |
| #include "std.h" |
| #include "stp.h" |
| #include "str.h" |
| #include "stt.h" |
| #include "stw.h" |
| |
| /* Externals defined here. */ |
| |
| ffeexprContext ffestc_iolist_context_ = FFEEXPR_contextIOLIST; |
| /* Valid only from READ/WRITE start to finish. */ |
| |
| /* Simple definitions and enumerations. */ |
| |
| typedef enum |
| { |
| FFESTC_orderOK_, /* Statement ok in this context, process. */ |
| FFESTC_orderBAD_, /* Statement not ok in this context, don't |
| process. */ |
| FFESTC_orderBADOK_, /* Don't process but push block if |
| applicable. */ |
| FFESTC |
| } ffestcOrder_; |
| |
| typedef enum |
| { |
| FFESTC_stateletSIMPLE_, /* Expecting simple/start. */ |
| FFESTC_stateletATTRIB_, /* Expecting attrib/item/itemstart. */ |
| FFESTC_stateletITEM_, /* Expecting item/itemstart/finish. */ |
| FFESTC_stateletITEMVALS_, /* Expecting itemvalue/itemendvals. */ |
| FFESTC_ |
| } ffestcStatelet_; |
| |
| /* Internal typedefs. */ |
| |
| |
| /* Private include files. */ |
| |
| |
| /* Internal structure definitions. */ |
| |
| union ffestc_local_u_ |
| { |
| struct |
| { |
| ffebld initlist; /* For list of one sym in INTEGER I/3/ case. */ |
| ffetargetCharacterSize stmt_size; |
| ffetargetCharacterSize size; |
| ffeinfoBasictype basic_type; |
| ffeinfoKindtype stmt_kind_type; |
| ffeinfoKindtype kind_type; |
| bool per_var_kind_ok; |
| char is_R426; /* 1=R426, 2=R501. */ |
| } |
| decl; |
| struct |
| { |
| ffebld objlist; /* For list of target objects. */ |
| ffebldListBottom list_bottom; /* For building lists. */ |
| } |
| data; |
| struct |
| { |
| ffebldListBottom list_bottom; /* For building lists. */ |
| int entry_num; |
| } |
| dummy; |
| struct |
| { |
| ffesymbol symbol; /* NML symbol. */ |
| } |
| namelist; |
| struct |
| { |
| ffelexToken t; /* First token in list. */ |
| ffeequiv eq; /* Current equivalence being built up. */ |
| ffebld list; /* List of expressions in equivalence. */ |
| ffebldListBottom bottom; |
| bool ok; /* TRUE while current list still being |
| processed. */ |
| bool save; /* TRUE if any var in list is SAVEd. */ |
| } |
| equiv; |
| struct |
| { |
| ffesymbol symbol; /* BCB/NCB symbol. */ |
| } |
| common; |
| struct |
| { |
| ffesymbol symbol; /* SFN symbol. */ |
| } |
| sfunc; |
| #if FFESTR_VXT |
| struct |
| { |
| char list_state; /* 0=>no field names allowed, 1=>error |
| reported already, 2=>field names req'd, |
| 3=>have a field name. */ |
| } |
| V003; |
| #endif |
| }; /* Merge with the one in ffestc later. */ |
| |
| /* Static objects accessed by functions in this module. */ |
| |
| static bool ffestc_ok_; /* _start_ fn's send this to _xyz_ fn's. */ |
| static bool ffestc_parent_ok_; /* Parent sym for baby sym fn's ok. */ |
| static char ffestc_namelist_; /* 0=>not namelist, 1=>namelist, 2=>error. */ |
| static union ffestc_local_u_ ffestc_local_; |
| static ffestcStatelet_ ffestc_statelet_ = FFESTC_stateletSIMPLE_; |
| static ffestwShriek ffestc_shriek_after1_ = NULL; |
| static unsigned long ffestc_blocknum_ = 0; /* Next block# to assign. */ |
| static int ffestc_entry_num_; |
| static int ffestc_sfdummy_argno_; |
| static int ffestc_saved_entry_num_; |
| static ffelab ffestc_label_; |
| |
| /* Static functions (internal). */ |
| |
| static void ffestc_R544_equiv_ (ffebld expr, ffelexToken t); |
| static void ffestc_establish_declinfo_ (ffebld kind, ffelexToken kindt, |
| ffebld len, ffelexToken lent); |
| static void ffestc_establish_declstmt_ (ffestpType type, ffelexToken typet, |
| ffebld kind, ffelexToken kindt, |
| ffebld len, ffelexToken lent); |
| static void ffestc_establish_impletter_ (ffelexToken first, ffelexToken last); |
| static ffeinfoKindtype ffestc_kindtype_kind_ (ffeinfoBasictype bt, |
| ffetargetCharacterSize val); |
| static ffeinfoKindtype ffestc_kindtype_star_ (ffeinfoBasictype bt, |
| ffetargetCharacterSize val); |
| static void ffestc_labeldef_any_ (void); |
| static bool ffestc_labeldef_begin_ (void); |
| static void ffestc_labeldef_branch_begin_ (void); |
| static void ffestc_labeldef_branch_end_ (void); |
| static void ffestc_labeldef_endif_ (void); |
| static void ffestc_labeldef_format_ (void); |
| static void ffestc_labeldef_invalid_ (void); |
| static void ffestc_labeldef_notloop_ (void); |
| static void ffestc_labeldef_notloop_begin_ (void); |
| static void ffestc_labeldef_useless_ (void); |
| static bool ffestc_labelref_is_assignable_ (ffelexToken label_token, |
| ffelab *label); |
| static bool ffestc_labelref_is_branch_ (ffelexToken label_token, |
| ffelab *label); |
| static bool ffestc_labelref_is_format_ (ffelexToken label_token, |
| ffelab *label); |
| static bool ffestc_labelref_is_loopend_ (ffelexToken label_token, |
| ffelab *label); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_access_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_actiondo_ (void); |
| static ffestcOrder_ ffestc_order_actionif_ (void); |
| static ffestcOrder_ ffestc_order_actionwhere_ (void); |
| static void ffestc_order_any_ (void); |
| static void ffestc_order_bad_ (void); |
| static ffestcOrder_ ffestc_order_blockdata_ (void); |
| static ffestcOrder_ ffestc_order_blockspec_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_component_ (void); |
| #endif |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_contains_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_data_ (void); |
| static ffestcOrder_ ffestc_order_data77_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_derivedtype_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_do_ (void); |
| static ffestcOrder_ ffestc_order_entry_ (void); |
| static ffestcOrder_ ffestc_order_exec_ (void); |
| static ffestcOrder_ ffestc_order_format_ (void); |
| static ffestcOrder_ ffestc_order_function_ (void); |
| static ffestcOrder_ ffestc_order_iface_ (void); |
| static ffestcOrder_ ffestc_order_ifthen_ (void); |
| static ffestcOrder_ ffestc_order_implicit_ (void); |
| static ffestcOrder_ ffestc_order_implicitnone_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_interface_ (void); |
| #endif |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_map_ (void); |
| #endif |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_module_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_parameter_ (void); |
| static ffestcOrder_ ffestc_order_program_ (void); |
| static ffestcOrder_ ffestc_order_progspec_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_record_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_selectcase_ (void); |
| static ffestcOrder_ ffestc_order_sfunc_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_spec_ (void); |
| #endif |
| #if FFESTR_VXT |
| static ffestcOrder_ ffestc_order_structure_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_subroutine_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_type_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_typedecl_ (void); |
| #if FFESTR_VXT |
| static ffestcOrder_ ffestc_order_union_ (void); |
| #endif |
| static ffestcOrder_ ffestc_order_unit_ (void); |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_use_ (void); |
| #endif |
| #if FFESTR_VXT |
| static ffestcOrder_ ffestc_order_vxtstructure_ (void); |
| #endif |
| #if FFESTR_F90 |
| static ffestcOrder_ ffestc_order_where_ (void); |
| #endif |
| static void ffestc_promote_dummy_ (ffelexToken t); |
| static void ffestc_promote_execdummy_ (ffelexToken t); |
| static void ffestc_promote_sfdummy_ (ffelexToken t); |
| static void ffestc_shriek_begin_program_ (void); |
| #if FFESTR_F90 |
| static void ffestc_shriek_begin_uses_ (void); |
| #endif |
| static void ffestc_shriek_blockdata_ (bool ok); |
| static void ffestc_shriek_do_ (bool ok); |
| static void ffestc_shriek_end_program_ (bool ok); |
| #if FFESTR_F90 |
| static void ffestc_shriek_end_uses_ (bool ok); |
| #endif |
| static void ffestc_shriek_function_ (bool ok); |
| static void ffestc_shriek_if_ (bool ok); |
| static void ffestc_shriek_ifthen_ (bool ok); |
| #if FFESTR_F90 |
| static void ffestc_shriek_interface_ (bool ok); |
| #endif |
| #if FFESTR_F90 |
| static void ffestc_shriek_map_ (bool ok); |
| #endif |
| #if FFESTR_F90 |
| static void ffestc_shriek_module_ (bool ok); |
| #endif |
| static void ffestc_shriek_select_ (bool ok); |
| #if FFESTR_VXT |
| static void ffestc_shriek_structure_ (bool ok); |
| #endif |
| static void ffestc_shriek_subroutine_ (bool ok); |
| #if FFESTR_F90 |
| static void ffestc_shriek_type_ (bool ok); |
| #endif |
| #if FFESTR_VXT |
| static void ffestc_shriek_union_ (bool ok); |
| #endif |
| #if FFESTR_F90 |
| static void ffestc_shriek_where_ (bool ok); |
| #endif |
| #if FFESTR_F90 |
| static void ffestc_shriek_wherethen_ (bool ok); |
| #endif |
| static int ffestc_subr_binsrch_ (const char *const *list, int size, |
| ffestpFile *spec, const char *whine); |
| static ffestvFormat ffestc_subr_format_ (ffestpFile *spec); |
| static bool ffestc_subr_is_branch_ (ffestpFile *spec); |
| static bool ffestc_subr_is_format_ (ffestpFile *spec); |
| static bool ffestc_subr_is_present_ (const char *name, ffestpFile *spec); |
| static int ffestc_subr_speccmp_ (const char *string, ffestpFile *spec, |
| const char **target, int *length); |
| static ffestvUnit ffestc_subr_unit_ (ffestpFile *spec); |
| static void ffestc_try_shriek_do_ (void); |
| |
| /* Internal macros. */ |
| |
| #define ffestc_check_simple_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletSIMPLE_) |
| #define ffestc_check_start_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletSIMPLE_); \ |
| ffestc_statelet_ = FFESTC_stateletATTRIB_ |
| #define ffestc_check_attrib_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletATTRIB_) |
| #define ffestc_check_item_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletATTRIB_ \ |
| || ffestc_statelet_ == FFESTC_stateletITEM_); \ |
| ffestc_statelet_ = FFESTC_stateletITEM_ |
| #define ffestc_check_item_startvals_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletATTRIB_ \ |
| || ffestc_statelet_ == FFESTC_stateletITEM_); \ |
| ffestc_statelet_ = FFESTC_stateletITEMVALS_ |
| #define ffestc_check_item_value_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletITEMVALS_) |
| #define ffestc_check_item_endvals_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletITEMVALS_); \ |
| ffestc_statelet_ = FFESTC_stateletITEM_ |
| #define ffestc_check_finish_() \ |
| assert(ffestc_statelet_ == FFESTC_stateletATTRIB_ \ |
| || ffestc_statelet_ == FFESTC_stateletITEM_); \ |
| ffestc_statelet_ = FFESTC_stateletSIMPLE_ |
| #define ffestc_order_action_() ffestc_order_exec_() |
| #if FFESTR_F90 |
| #define ffestc_order_interfacespec_() ffestc_order_derivedtype_() |
| #endif |
| #define ffestc_shriek_if_lost_ ffestc_shriek_if_ |
| #if FFESTR_F90 |
| #define ffestc_shriek_where_lost_ ffestc_shriek_where_ |
| #endif |
| |
| /* ffestc_establish_declinfo_ -- Determine specific type/params info for entity |
| |
| ffestc_establish_declinfo_(kind,kind_token,len,len_token); |
| |
| Must be called after _declstmt_ called to establish base type. */ |
| |
| static void |
| ffestc_establish_declinfo_ (ffebld kind, ffelexToken kindt, ffebld len, |
| ffelexToken lent) |
| { |
| ffeinfoBasictype bt = ffestc_local_.decl.basic_type; |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize val; |
| |
| if (kindt == NULL) |
| kt = ffestc_local_.decl.stmt_kind_type; |
| else if (!ffestc_local_.decl.per_var_kind_ok) |
| { |
| ffebad_start (FFEBAD_KINDTYPE); |
| ffebad_here (0, ffelex_token_where_line (kindt), |
| ffelex_token_where_column (kindt)); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| kt = ffestc_local_.decl.stmt_kind_type; |
| } |
| else |
| { |
| if (kind == NULL) |
| { |
| assert (ffelex_token_type (kindt) == FFELEX_typeNUMBER); |
| val = atol (ffelex_token_text (kindt)); |
| kt = ffestc_kindtype_star_ (bt, val); |
| } |
| else if (ffebld_op (kind) == FFEBLD_opANY) |
| kt = ffestc_local_.decl.stmt_kind_type; |
| else |
| { |
| assert (ffebld_op (kind) == FFEBLD_opCONTER); |
| assert (ffeinfo_basictype (ffebld_info (kind)) |
| == FFEINFO_basictypeINTEGER); |
| assert (ffeinfo_kindtype (ffebld_info (kind)) |
| == FFEINFO_kindtypeINTEGERDEFAULT); |
| val = ffebld_constant_integerdefault (ffebld_conter (kind)); |
| kt = ffestc_kindtype_kind_ (bt, val); |
| } |
| |
| if (kt == FFEINFO_kindtypeNONE) |
| { /* Not valid kind type. */ |
| ffebad_start (FFEBAD_KINDTYPE); |
| ffebad_here (0, ffelex_token_where_line (kindt), |
| ffelex_token_where_column (kindt)); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| kt = ffestc_local_.decl.stmt_kind_type; |
| } |
| } |
| |
| ffestc_local_.decl.kind_type = kt; |
| |
| /* Now check length specification for CHARACTER data type. */ |
| |
| if (((len == NULL) && (lent == NULL)) |
| || (bt != FFEINFO_basictypeCHARACTER)) |
| val = ffestc_local_.decl.stmt_size; |
| else |
| { |
| if (len == NULL) |
| { |
| assert (ffelex_token_type (lent) == FFELEX_typeNUMBER); |
| val = atol (ffelex_token_text (lent)); |
| } |
| else if (ffebld_op (len) == FFEBLD_opSTAR) |
| val = FFETARGET_charactersizeNONE; |
| else if (ffebld_op (len) == FFEBLD_opANY) |
| val = FFETARGET_charactersizeNONE; |
| else |
| { |
| assert (ffebld_op (len) == FFEBLD_opCONTER); |
| assert (ffeinfo_basictype (ffebld_info (len)) |
| == FFEINFO_basictypeINTEGER); |
| assert (ffeinfo_kindtype (ffebld_info (len)) |
| == FFEINFO_kindtypeINTEGERDEFAULT); |
| val = ffebld_constant_integerdefault (ffebld_conter (len)); |
| } |
| } |
| |
| if ((val == 0) && !(0 && ffe_is_90 ())) |
| { |
| val = 1; |
| ffebad_start (FFEBAD_ZERO_SIZE); |
| ffebad_here (0, ffelex_token_where_line (lent), ffelex_token_where_column (lent)); |
| ffebad_finish (); |
| } |
| ffestc_local_.decl.size = val; |
| } |
| |
| /* ffestc_establish_declstmt_ -- Establish host-specific type/params info |
| |
| ffestc_establish_declstmt_(type,type_token,kind,kind_token,len, |
| len_token); */ |
| |
| static void |
| ffestc_establish_declstmt_ (ffestpType type, ffelexToken typet, ffebld kind, |
| ffelexToken kindt, ffebld len, ffelexToken lent) |
| { |
| ffeinfoBasictype bt; |
| ffeinfoKindtype ktd; /* Default kindtype. */ |
| ffeinfoKindtype kt; |
| ffetargetCharacterSize val; |
| bool per_var_kind_ok = TRUE; |
| |
| /* Determine basictype and default kindtype. */ |
| |
| switch (type) |
| { |
| case FFESTP_typeINTEGER: |
| bt = FFEINFO_basictypeINTEGER; |
| ktd = FFEINFO_kindtypeINTEGERDEFAULT; |
| break; |
| |
| case FFESTP_typeBYTE: |
| bt = FFEINFO_basictypeINTEGER; |
| ktd = FFEINFO_kindtypeINTEGER2; |
| break; |
| |
| case FFESTP_typeWORD: |
| bt = FFEINFO_basictypeINTEGER; |
| ktd = FFEINFO_kindtypeINTEGER3; |
| break; |
| |
| case FFESTP_typeREAL: |
| bt = FFEINFO_basictypeREAL; |
| ktd = FFEINFO_kindtypeREALDEFAULT; |
| break; |
| |
| case FFESTP_typeCOMPLEX: |
| bt = FFEINFO_basictypeCOMPLEX; |
| ktd = FFEINFO_kindtypeREALDEFAULT; |
| break; |
| |
| case FFESTP_typeLOGICAL: |
| bt = FFEINFO_basictypeLOGICAL; |
| ktd = FFEINFO_kindtypeLOGICALDEFAULT; |
| break; |
| |
| case FFESTP_typeCHARACTER: |
| bt = FFEINFO_basictypeCHARACTER; |
| ktd = FFEINFO_kindtypeCHARACTERDEFAULT; |
| break; |
| |
| case FFESTP_typeDBLPRCSN: |
| bt = FFEINFO_basictypeREAL; |
| ktd = FFEINFO_kindtypeREALDOUBLE; |
| per_var_kind_ok = FALSE; |
| break; |
| |
| case FFESTP_typeDBLCMPLX: |
| bt = FFEINFO_basictypeCOMPLEX; |
| #if FFETARGET_okCOMPLEX2 |
| ktd = FFEINFO_kindtypeREALDOUBLE; |
| #else |
| ktd = FFEINFO_kindtypeREALDEFAULT; |
| ffebad_start (FFEBAD_BAD_DBLCMPLX); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| #endif |
| per_var_kind_ok = FALSE; |
| break; |
| |
| default: |
| assert ("Unexpected type (F90 TYPE?)!" == NULL); |
| bt = FFEINFO_basictypeNONE; |
| ktd = FFEINFO_kindtypeNONE; |
| break; |
| } |
| |
| if (kindt == NULL) |
| kt = ktd; |
| else |
| { /* Not necessarily default kind type. */ |
| if (kind == NULL) |
| { /* Shouldn't happen for CHARACTER. */ |
| assert (ffelex_token_type (kindt) == FFELEX_typeNUMBER); |
| val = atol (ffelex_token_text (kindt)); |
| kt = ffestc_kindtype_star_ (bt, val); |
| } |
| else if (ffebld_op (kind) == FFEBLD_opANY) |
| kt = ktd; |
| else |
| { |
| assert (ffebld_op (kind) == FFEBLD_opCONTER); |
| assert (ffeinfo_basictype (ffebld_info (kind)) |
| == FFEINFO_basictypeINTEGER); |
| assert (ffeinfo_kindtype (ffebld_info (kind)) |
| == FFEINFO_kindtypeINTEGERDEFAULT); |
| val = ffebld_constant_integerdefault (ffebld_conter (kind)); |
| kt = ffestc_kindtype_kind_ (bt, val); |
| } |
| |
| if (kt == FFEINFO_kindtypeNONE) |
| { /* Not valid kind type. */ |
| ffebad_start (FFEBAD_KINDTYPE); |
| ffebad_here (0, ffelex_token_where_line (kindt), |
| ffelex_token_where_column (kindt)); |
| ffebad_here (1, ffelex_token_where_line (typet), |
| ffelex_token_where_column (typet)); |
| ffebad_finish (); |
| kt = ktd; |
| } |
| } |
| |
| ffestc_local_.decl.basic_type = bt; |
| ffestc_local_.decl.stmt_kind_type = kt; |
| ffestc_local_.decl.per_var_kind_ok = per_var_kind_ok; |
| |
| /* Now check length specification for CHARACTER data type. */ |
| |
| if (((len == NULL) && (lent == NULL)) |
| || (type != FFESTP_typeCHARACTER)) |
| val = (type == FFESTP_typeCHARACTER) ? 1 : FFETARGET_charactersizeNONE; |
| else |
| { |
| if (len == NULL) |
| { |
| assert (ffelex_token_type (lent) == FFELEX_typeNUMBER); |
| val = atol (ffelex_token_text (lent)); |
| } |
| else if (ffebld_op (len) == FFEBLD_opSTAR) |
| val = FFETARGET_charactersizeNONE; |
| else if (ffebld_op (len) == FFEBLD_opANY) |
| val = FFETARGET_charactersizeNONE; |
| else |
| { |
| assert (ffebld_op (len) == FFEBLD_opCONTER); |
| assert (ffeinfo_basictype (ffebld_info (len)) |
| == FFEINFO_basictypeINTEGER); |
| assert (ffeinfo_kindtype (ffebld_info (len)) |
| == FFEINFO_kindtypeINTEGERDEFAULT); |
| val = ffebld_constant_integerdefault (ffebld_conter (len)); |
| } |
| } |
| |
| if ((val == 0) && !(0 && ffe_is_90 ())) |
| { |
| val = 1; |
| ffebad_start (FFEBAD_ZERO_SIZE); |
| ffebad_here (0, ffelex_token_where_line (lent), ffelex_token_where_column (lent)); |
| ffebad_finish (); |
| } |
| ffestc_local_.decl.stmt_size = val; |
| } |
| |
| /* ffestc_establish_impletter_ -- Establish type/params for IMPLICIT letter(s) |
| |
| ffestc_establish_impletter_(first_letter_token,last_letter_token); */ |
| |
| static void |
| ffestc_establish_impletter_ (ffelexToken first, ffelexToken last) |
| { |
| bool ok = FALSE; /* Stays FALSE if first letter > last. */ |
| char c; |
| |
| if (last == NULL) |
| ok = ffeimplic_establish_initial (c = *(ffelex_token_text (first)), |
| ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| ffestc_local_.decl.size); |
| else |
| { |
| for (c = *(ffelex_token_text (first)); |
| c <= *(ffelex_token_text (last)); |
| c++) |
| { |
| ok = ffeimplic_establish_initial (c, |
| ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| ffestc_local_.decl.size); |
| if (!ok) |
| break; |
| } |
| } |
| |
| if (!ok) |
| { |
| char cs[2]; |
| |
| cs[0] = c; |
| cs[1] = '\0'; |
| |
| ffebad_start (FFEBAD_BAD_IMPLICIT); |
| ffebad_here (0, ffelex_token_where_line (first), ffelex_token_where_column (first)); |
| ffebad_string (cs); |
| ffebad_finish (); |
| } |
| } |
| |
| /* ffestc_init_3 -- Initialize ffestc for new program unit |
| |
| ffestc_init_3(); */ |
| |
| void |
| ffestc_init_3 () |
| { |
| ffestv_save_state_ = FFESTV_savestateNONE; |
| ffestc_entry_num_ = 0; |
| ffestv_num_label_defines_ = 0; |
| } |
| |
| /* ffestc_init_4 -- Initialize ffestc for new scoping unit |
| |
| ffestc_init_4(); |
| |
| For SUBROUTINEs/FUNCTIONs within INTERFACE/END INTERFACE, derived-TYPE- |
| defs, and statement function defs. */ |
| |
| void |
| ffestc_init_4 () |
| { |
| ffestc_saved_entry_num_ = ffestc_entry_num_; |
| ffestc_entry_num_ = 0; |
| } |
| |
| /* ffestc_kindtype_kind_ -- Determine kindtype from basictype and KIND= value |
| |
| ffeinfoKindtype kt; |
| ffeinfoBasictype bt; |
| ffetargetCharacterSize val; |
| kt = ffestc_kindtype_kind_(bt,val); |
| if (kt == FFEINFO_kindtypeNONE) |
| // unsupported/invalid KIND= value for type */ |
| |
| static ffeinfoKindtype |
| ffestc_kindtype_kind_ (ffeinfoBasictype bt, ffetargetCharacterSize val) |
| { |
| ffetype type; |
| ffetype base_type; |
| ffeinfoKindtype kt; |
| |
| base_type = ffeinfo_type (bt, 1); /* ~~ */ |
| assert (base_type != NULL); |
| |
| type = ffetype_lookup_kind (base_type, (int) val); |
| if (type == NULL) |
| return FFEINFO_kindtypeNONE; |
| |
| for (kt = 1; kt < FFEINFO_kindtype; ++kt) |
| if (ffeinfo_type (bt, kt) == type) |
| return kt; |
| |
| return FFEINFO_kindtypeNONE; |
| } |
| |
| /* ffestc_kindtype_star_ -- Determine kindtype from basictype and * value |
| |
| ffeinfoKindtype kt; |
| ffeinfoBasictype bt; |
| ffetargetCharacterSize val; |
| kt = ffestc_kindtype_star_(bt,val); |
| if (kt == FFEINFO_kindtypeNONE) |
| // unsupported/invalid * value for type */ |
| |
| static ffeinfoKindtype |
| ffestc_kindtype_star_ (ffeinfoBasictype bt, ffetargetCharacterSize val) |
| { |
| ffetype type; |
| ffetype base_type; |
| ffeinfoKindtype kt; |
| |
| base_type = ffeinfo_type (bt, 1); /* ~~ */ |
| assert (base_type != NULL); |
| |
| type = ffetype_lookup_star (base_type, (int) val); |
| if (type == NULL) |
| return FFEINFO_kindtypeNONE; |
| |
| for (kt = 1; kt < FFEINFO_kindtype; ++kt) |
| if (ffeinfo_type (bt, kt) == type) |
| return kt; |
| |
| return FFEINFO_kindtypeNONE; |
| } |
| |
| /* Define label as usable for anything without complaint. */ |
| |
| static void |
| ffestc_labeldef_any_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_labeldef_begin_ -- Define label as unknown, initially |
| |
| ffestc_labeldef_begin_(); */ |
| |
| static bool |
| ffestc_labeldef_begin_ () |
| { |
| ffelabValue label_value; |
| ffelab label; |
| |
| label_value = (ffelabValue) atol (ffelex_token_text (ffesta_label_token)); |
| if ((label_value == 0) || (label_value > FFELAB_valueMAX)) |
| { |
| ffebad_start (FFEBAD_LABEL_NUMBER_INVALID); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| } |
| |
| label = ffelab_find (label_value); |
| if (label == NULL) |
| { |
| label = ffestc_label_ = ffelab_new (label_value); |
| ffestv_num_label_defines_++; |
| ffelab_set_definition_line (label, |
| ffewhere_line_use (ffelex_token_where_line (ffesta_label_token))); |
| ffelab_set_definition_column (label, |
| ffewhere_column_use (ffelex_token_where_column (ffesta_label_token))); |
| |
| return TRUE; |
| } |
| |
| if (ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { |
| ffestv_num_label_defines_++; |
| ffestc_label_ = label; |
| ffelab_set_definition_line (label, |
| ffewhere_line_use (ffelex_token_where_line (ffesta_label_token))); |
| ffelab_set_definition_column (label, |
| ffewhere_column_use (ffelex_token_where_column (ffesta_label_token))); |
| |
| return TRUE; |
| } |
| |
| ffebad_start (FFEBAD_LABEL_ALREADY_DEFINED); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_definition_line (label), |
| ffelab_definition_column (label)); |
| ffebad_string (ffelex_token_text (ffesta_label_token)); |
| ffebad_finish (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| return FALSE; |
| } |
| |
| /* ffestc_labeldef_branch_begin_ -- Define label as a branch target one |
| |
| ffestc_labeldef_branch_begin_(); */ |
| |
| static void |
| ffestc_labeldef_branch_begin_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (ffestc_label_, FFELAB_typeNOTLOOP); |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_branch (ffestc_label_); |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| if (ffelab_blocknum (ffestc_label_) |
| < ffestw_blocknum (ffestw_stack_top ())) |
| { |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| } |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_branch (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffestd_labeldef_branch (ffestc_label_); |
| /* Leave something around for _branch_end_() to handle. */ |
| return; |
| |
| case FFELAB_typeFORMAT: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* Define possible end of labeled-DO-loop. Call only after calling |
| ffestc_labeldef_branch_begin_, or when other branch_* functions |
| recognize that a label might also be serving as a branch end (in |
| which case they must issue a diagnostic). */ |
| |
| static void |
| ffestc_labeldef_branch_end_ () |
| { |
| if (ffesta_label_token == NULL) |
| return; |
| |
| assert (ffestc_label_ != NULL); |
| assert ((ffelab_type (ffestc_label_) == FFELAB_typeLOOPEND) |
| || (ffelab_type (ffestc_label_) == FFELAB_typeANY)); |
| |
| while ((ffestw_state (ffestw_stack_top ()) == FFESTV_stateDO) |
| && (ffestw_label (ffestw_stack_top ()) == ffestc_label_)) |
| ffestc_shriek_do_ (TRUE); |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* ffestc_labeldef_endif_ -- Define label as an END IF one |
| |
| ffestc_labeldef_endif_(); */ |
| |
| static void |
| ffestc_labeldef_endif_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (ffestc_label_, FFELAB_typeENDIF); |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_previous (ffestw_stack_top ()))); |
| ffestd_labeldef_endif (ffestc_label_); |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| if (ffelab_blocknum (ffestc_label_) |
| < ffestw_blocknum (ffestw_previous (ffestw_stack_top ()))) |
| { |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| } |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_previous (ffestw_stack_top ()))); |
| ffestd_labeldef_endif (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffestd_labeldef_endif (ffestc_label_); |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_finish (); |
| ffestc_labeldef_branch_end_ (); |
| return; |
| |
| case FFELAB_typeFORMAT: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* ffestc_labeldef_format_ -- Define label as a FORMAT one |
| |
| ffestc_labeldef_format_(); */ |
| |
| static void |
| ffestc_labeldef_format_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL)) |
| { |
| ffebad_start (FFEBAD_FORMAT_NO_LABEL_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| return; |
| } |
| |
| if (!ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (ffestc_label_, FFELAB_typeFORMAT); |
| ffestd_labeldef_format (ffestc_label_); |
| break; |
| |
| case FFELAB_typeFORMAT: |
| ffestd_labeldef_format (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffestd_labeldef_format (ffestc_label_); |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_finish (); |
| ffestc_labeldef_branch_end_ (); |
| return; |
| |
| case FFELAB_typeNOTLOOP: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* ffestc_labeldef_invalid_ -- Label definition invalid, complain if present |
| |
| ffestc_labeldef_invalid_(); */ |
| |
| static void |
| ffestc_labeldef_invalid_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| ffebad_start (FFEBAD_INVALID_LABEL_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* Define label as a non-loop-ending one on a statement that can't |
| be in the "then" part of a logical IF, such as a block-IF statement. */ |
| |
| static void |
| ffestc_labeldef_notloop_ () |
| { |
| if (ffesta_label_token == NULL) |
| return; |
| |
| assert (ffestc_shriek_after1_ == NULL); |
| |
| if (!ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (ffestc_label_, FFELAB_typeNOTLOOP); |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_notloop (ffestc_label_); |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| if (ffelab_blocknum (ffestc_label_) |
| < ffestw_blocknum (ffestw_stack_top ())) |
| { |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| } |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_notloop (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffestd_labeldef_notloop (ffestc_label_); |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_finish (); |
| ffestc_labeldef_branch_end_ (); |
| return; |
| |
| case FFELAB_typeFORMAT: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* Define label as a non-loop-ending one. Use this when it is |
| possible that the pending label is inhibited because we're in |
| the midst of a logical-IF, and thus _branch_end_ is going to |
| be called after the current statement to resolve a potential |
| loop-ending label. */ |
| |
| static void |
| ffestc_labeldef_notloop_begin_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (ffestc_label_, FFELAB_typeNOTLOOP); |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_notloop (ffestc_label_); |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| if (ffelab_blocknum (ffestc_label_) |
| < ffestw_blocknum (ffestw_stack_top ())) |
| { |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| } |
| ffelab_set_blocknum (ffestc_label_, |
| ffestw_blocknum (ffestw_stack_top ())); |
| ffestd_labeldef_notloop (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffestd_labeldef_branch (ffestc_label_); |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_finish (); |
| return; |
| |
| case FFELAB_typeFORMAT: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* ffestc_labeldef_useless_ -- Define label as a useless one |
| |
| ffestc_labeldef_useless_(); */ |
| |
| static void |
| ffestc_labeldef_useless_ () |
| { |
| if ((ffesta_label_token == NULL) |
| || (ffestc_shriek_after1_ != NULL) |
| || !ffestc_labeldef_begin_ ()) |
| return; |
| |
| switch (ffelab_type (ffestc_label_)) |
| { |
| case FFELAB_typeUNKNOWN: |
| ffelab_set_type (ffestc_label_, FFELAB_typeUSELESS); |
| ffestd_labeldef_useless (ffestc_label_); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != ffestc_label_)) |
| { /* Unterminated block. */ |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_END); |
| ffebad_here (0, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_doref_line (ffestc_label_), |
| ffelab_doref_column (ffestc_label_)); |
| ffebad_finish (); |
| ffestc_labeldef_branch_end_ (); |
| return; |
| |
| case FFELAB_typeASSIGNABLE: |
| case FFELAB_typeFORMAT: |
| case FFELAB_typeNOTLOOP: |
| ffelab_set_type (ffestc_label_, FFELAB_typeANY); |
| ffestd_labeldef_any (ffestc_label_); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelex_token_where_line (ffesta_label_token), |
| ffelex_token_where_column (ffesta_label_token)); |
| ffebad_here (1, ffelab_firstref_line (ffestc_label_), |
| ffelab_firstref_column (ffestc_label_)); |
| ffebad_finish (); |
| break; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| ffelex_token_kill (ffesta_label_token); |
| ffesta_label_token = NULL; |
| } |
| |
| /* ffestc_labelref_is_assignable_ -- Reference to label in ASSIGN stmt |
| |
| if (ffestc_labelref_is_assignable_(label_token,&label)) |
| // label ref is ok, label is filled in with ffelab object */ |
| |
| static bool |
| ffestc_labelref_is_assignable_ (ffelexToken label_token, ffelab *x_label) |
| { |
| ffelab label; |
| ffelabValue label_value; |
| |
| label_value = (ffelabValue) atol (ffelex_token_text (label_token)); |
| if ((label_value == 0) || (label_value > FFELAB_valueMAX)) |
| { |
| ffebad_start (FFEBAD_LABEL_NUMBER_INVALID); |
| ffebad_here (0, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| return FALSE; |
| } |
| |
| label = ffelab_find (label_value); |
| if (label == NULL) |
| { |
| label = ffelab_new (label_value); |
| ffelab_set_firstref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_firstref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| } |
| |
| switch (ffelab_type (label)) |
| { |
| case FFELAB_typeUNKNOWN: |
| ffelab_set_type (label, FFELAB_typeASSIGNABLE); |
| break; |
| |
| case FFELAB_typeASSIGNABLE: |
| case FFELAB_typeLOOPEND: |
| case FFELAB_typeFORMAT: |
| case FFELAB_typeNOTLOOP: |
| case FFELAB_typeENDIF: |
| break; |
| |
| case FFELAB_typeUSELESS: |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelab_firstref_line (label), ffelab_firstref_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| *x_label = label; |
| return TRUE; |
| } |
| |
| /* ffestc_labelref_is_branch_ -- Reference to label in branch stmt |
| |
| if (ffestc_labelref_is_branch_(label_token,&label)) |
| // label ref is ok, label is filled in with ffelab object */ |
| |
| static bool |
| ffestc_labelref_is_branch_ (ffelexToken label_token, ffelab *x_label) |
| { |
| ffelab label; |
| ffelabValue label_value; |
| ffestw block; |
| unsigned long blocknum; |
| |
| label_value = (ffelabValue) atol (ffelex_token_text (label_token)); |
| if ((label_value == 0) || (label_value > FFELAB_valueMAX)) |
| { |
| ffebad_start (FFEBAD_LABEL_NUMBER_INVALID); |
| ffebad_here (0, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| return FALSE; |
| } |
| |
| label = ffelab_find (label_value); |
| if (label == NULL) |
| { |
| label = ffelab_new (label_value); |
| ffelab_set_firstref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_firstref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| } |
| |
| switch (ffelab_type (label)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (label, FFELAB_typeNOTLOOP); |
| ffelab_set_blocknum (label, ffestw_blocknum (ffestw_stack_top ())); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if (ffelab_blocknum (label) != 0) |
| break; /* Already taken care of. */ |
| for (block = ffestw_top_do (ffestw_stack_top ()); |
| (block != NULL) && (ffestw_label (block) != label); |
| block = ffestw_top_do (ffestw_previous (block))) |
| ; /* Find most recent DO <label> ancestor. */ |
| if (block == NULL) |
| { /* Reference to within a (dead) block. */ |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelab_definition_line (label), |
| ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffelab_set_blocknum (label, ffestw_blocknum (block)); |
| ffelab_set_firstref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_firstref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| case FFELAB_typeENDIF: |
| if (ffelab_blocknum (label) == ffestw_blocknum (ffestw_stack_top ())) |
| break; |
| blocknum = ffelab_blocknum (label); |
| for (block = ffestw_stack_top (); |
| ffestw_blocknum (block) > blocknum; |
| block = ffestw_previous (block)) |
| ; /* Find most recent common ancestor. */ |
| if (ffelab_blocknum (label) == ffestw_blocknum (block)) |
| break; /* Check again. */ |
| if (!ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { /* Reference to within a (dead) block. */ |
| ffebad_start (FFEBAD_LABEL_BLOCK); |
| ffebad_here (0, ffelab_definition_line (label), |
| ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| break; |
| } |
| ffelab_set_blocknum (label, ffestw_blocknum (block)); |
| break; |
| |
| case FFELAB_typeFORMAT: |
| if (ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_USE); |
| ffebad_here (0, ffelab_firstref_line (label), ffelab_firstref_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| /* Fall through. */ |
| case FFELAB_typeUSELESS: |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelab_definition_line (label), ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| *x_label = label; |
| return TRUE; |
| } |
| |
| /* ffestc_labelref_is_format_ -- Reference to label in [FMT=] specification |
| |
| if (ffestc_labelref_is_format_(label_token,&label)) |
| // label ref is ok, label is filled in with ffelab object */ |
| |
| static bool |
| ffestc_labelref_is_format_ (ffelexToken label_token, ffelab *x_label) |
| { |
| ffelab label; |
| ffelabValue label_value; |
| |
| label_value = (ffelabValue) atol (ffelex_token_text (label_token)); |
| if ((label_value == 0) || (label_value > FFELAB_valueMAX)) |
| { |
| ffebad_start (FFEBAD_LABEL_NUMBER_INVALID); |
| ffebad_here (0, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| return FALSE; |
| } |
| |
| label = ffelab_find (label_value); |
| if (label == NULL) |
| { |
| label = ffelab_new (label_value); |
| ffelab_set_firstref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_firstref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| } |
| |
| switch (ffelab_type (label)) |
| { |
| case FFELAB_typeUNKNOWN: |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_type (label, FFELAB_typeFORMAT); |
| break; |
| |
| case FFELAB_typeFORMAT: |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| case FFELAB_typeNOTLOOP: |
| if (ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_USE); |
| ffebad_here (0, ffelab_firstref_line (label), ffelab_firstref_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| /* Fall through. */ |
| case FFELAB_typeUSELESS: |
| case FFELAB_typeENDIF: |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelab_definition_line (label), ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| ffestc_try_shriek_do_ (); |
| |
| *x_label = label; |
| return TRUE; |
| } |
| |
| /* ffestc_labelref_is_loopend_ -- Reference to label in DO stmt |
| |
| if (ffestc_labelref_is_loopend_(label_token,&label)) |
| // label ref is ok, label is filled in with ffelab object */ |
| |
| static bool |
| ffestc_labelref_is_loopend_ (ffelexToken label_token, ffelab *x_label) |
| { |
| ffelab label; |
| ffelabValue label_value; |
| |
| label_value = (ffelabValue) atol (ffelex_token_text (label_token)); |
| if ((label_value == 0) || (label_value > FFELAB_valueMAX)) |
| { |
| ffebad_start (FFEBAD_LABEL_NUMBER_INVALID); |
| ffebad_here (0, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| return FALSE; |
| } |
| |
| label = ffelab_find (label_value); |
| if (label == NULL) |
| { |
| label = ffelab_new (label_value); |
| ffelab_set_doref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_doref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| } |
| |
| switch (ffelab_type (label)) |
| { |
| case FFELAB_typeASSIGNABLE: |
| ffelab_set_doref_line (label, |
| ffewhere_line_use (ffelex_token_where_line (label_token))); |
| ffelab_set_doref_column (label, |
| ffewhere_column_use (ffelex_token_where_column (label_token))); |
| ffewhere_line_kill (ffelab_firstref_line (label)); |
| ffelab_set_firstref_line (label, ffewhere_line_unknown ()); |
| ffewhere_column_kill (ffelab_firstref_column (label)); |
| ffelab_set_firstref_column (label, ffewhere_column_unknown ()); |
| /* Fall through. */ |
| case FFELAB_typeUNKNOWN: |
| ffelab_set_type (label, FFELAB_typeLOOPEND); |
| ffelab_set_blocknum (label, 0); |
| break; |
| |
| case FFELAB_typeLOOPEND: |
| if (!ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { /* Def must follow all refs. */ |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_DEF_DO); |
| ffebad_here (0, ffelab_definition_line (label), |
| ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| if (ffelab_blocknum (label) != 0) |
| { /* Had a branch ref earlier, can't go inside |
| this new block! */ |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_USE); |
| ffebad_here (0, ffelab_firstref_line (label), |
| ffelab_firstref_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| if ((ffestw_state (ffestw_stack_top ()) != FFESTV_stateDO) |
| || (ffestw_label (ffestw_stack_top ()) != label)) |
| { /* Top of stack interrupts flow between two |
| DOs specifying label. */ |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_DO_BLOCK_DO); |
| ffebad_here (0, ffelab_doref_line (label), |
| ffelab_doref_column (label)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_here (2, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| break; |
| |
| case FFELAB_typeNOTLOOP: |
| case FFELAB_typeFORMAT: |
| if (ffewhere_line_is_unknown (ffelab_definition_line (label))) |
| { |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_USE); |
| ffebad_here (0, ffelab_firstref_line (label), ffelab_firstref_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| } |
| /* Fall through. */ |
| case FFELAB_typeUSELESS: |
| case FFELAB_typeENDIF: |
| ffelab_set_type (label, FFELAB_typeANY); |
| ffestd_labeldef_any (label); |
| |
| ffebad_start (FFEBAD_LABEL_USE_DEF); |
| ffebad_here (0, ffelab_definition_line (label), ffelab_definition_column (label)); |
| ffebad_here (1, ffelex_token_where_line (label_token), |
| ffelex_token_where_column (label_token)); |
| ffebad_finish (); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return FALSE; |
| |
| default: |
| assert ("bad label" == NULL); |
| /* Fall through. */ |
| case FFELAB_typeANY: |
| break; |
| } |
| |
| *x_label = label; |
| return TRUE; |
| } |
| |
| /* ffestc_order_access_ -- Check ordering on <access> statement |
| |
| if (ffestc_order_access_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_access_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_actiondo_ -- Check ordering on <actiondo> statement |
| |
| if (ffestc_order_actiondo_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_actiondo_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateDO: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateSELECT1: |
| if (ffestw_top_do (ffestw_stack_top ()) == NULL) |
| break; |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateIF: |
| if (ffestw_top_do (ffestw_stack_top ()) == NULL) |
| break; |
| ffestc_shriek_after1_ = ffestc_shriek_if_; |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| default: |
| break; |
| } |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| /* ffestc_order_actionif_ -- Check ordering on <actionif> statement |
| |
| if (ffestc_order_actionif_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_actionif_ () |
| { |
| bool update; |
| |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| update = FALSE; |
| break; |
| |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateIF: |
| ffestc_shriek_after1_ = ffestc_shriek_if_; |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateINTERFACE0: |
| ffestc_order_bad_ (); |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderBAD_; |
| |
| default: |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderOK_; |
| } |
| } |
| |
| /* ffestc_order_actionwhere_ -- Check ordering on <actionwhere> statement |
| |
| if (ffestc_order_actionwhere_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_actionwhere_ () |
| { |
| bool update; |
| |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| update = FALSE; |
| break; |
| |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| #if FFESTR_F90 |
| ffestc_shriek_after1_ = ffestc_shriek_where_; |
| #endif |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateIF: |
| ffestc_shriek_after1_ = ffestc_shriek_if_; |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateINTERFACE0: |
| ffestc_order_bad_ (); |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderBAD_; |
| |
| default: |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderOK_; |
| } |
| } |
| |
| /* Check ordering on "any" statement. Like _actionwhere_, but |
| doesn't produce any diagnostics. */ |
| |
| static void |
| ffestc_order_any_ () |
| { |
| bool update; |
| |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| update = FALSE; |
| break; |
| |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT1: |
| return; |
| |
| case FFESTV_stateWHERE: |
| #if FFESTR_F90 |
| ffestc_shriek_after1_ = ffestc_shriek_where_; |
| #endif |
| return; |
| |
| case FFESTV_stateIF: |
| ffestc_shriek_after1_ = ffestc_shriek_if_; |
| return; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| default: |
| return; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateINTERFACE0: |
| if (update) |
| ffestw_update (NULL); |
| return; |
| |
| default: |
| if (update) |
| ffestw_update (NULL); |
| return; |
| } |
| } |
| |
| /* ffestc_order_bad_ -- Whine about statement ordering violation |
| |
| ffestc_order_bad_(); |
| |
| Uses current ffesta_tokens[0] and, if available, info on where current |
| state started to produce generic message. Someday we should do |
| fancier things than this, but this just gets things creaking along for |
| now. */ |
| |
| static void |
| ffestc_order_bad_ () |
| { |
| if (ffewhere_line_is_unknown (ffestw_line (ffestw_stack_top ()))) |
| { |
| ffebad_start (FFEBAD_ORDER_1); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| } |
| else |
| { |
| ffebad_start (FFEBAD_ORDER_2); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| ffestc_labeldef_useless_ (); /* Any label definition is useless. */ |
| } |
| |
| /* ffestc_order_blockdata_ -- Check ordering on <blockdata> statement |
| |
| if (ffestc_order_blockdata_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_blockdata_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateBLOCKDATA4: |
| case FFESTV_stateBLOCKDATA5: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_blockspec_ -- Check ordering on <blockspec> statement |
| |
| if (ffestc_order_blockspec_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_blockspec_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_component_ -- Check ordering on <component-decl> statement |
| |
| if (ffestc_order_component_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_component_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateTYPE: |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_contains_ -- Check ordering on CONTAINS statement |
| |
| if (ffestc_order_contains_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_contains_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_statePROGRAM4: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM5); |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateSUBROUTINE4: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE5); |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateFUNCTION4: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION5); |
| break; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateMODULE4: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE5); |
| break; |
| |
| case FFESTV_stateUSE: |
| ffestc_shriek_end_uses_ (TRUE); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateNIL: |
| ffestw_update (NULL); |
| return FFESTC_orderOK_; |
| |
| default: |
| ffestc_order_bad_ (); |
| ffestw_update (NULL); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_data_ -- Check ordering on DATA statement |
| |
| if (ffestc_order_data_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_data_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateBLOCKDATA4: |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT0: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_data77_ -- Check ordering on pedantic-F77 DATA statement |
| |
| if (ffestc_order_data77_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_data77_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM4); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE4); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION4); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_stateBLOCKDATA3: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA4); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateBLOCKDATA4: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT0: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_derivedtype_ -- Check ordering on derived TYPE statement |
| |
| if (ffestc_order_derivedtype_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_derivedtype_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| ffestc_shriek_end_uses_ (TRUE); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_do_ -- Check ordering on <do> statement |
| |
| if (ffestc_order_do_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_do_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateDO: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_entry_ -- Check ordering on ENTRY statement |
| |
| if (ffestc_order_entry_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_entry_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateSUBROUTINE0: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE1); |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION1); |
| break; |
| |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| break; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateNIL: |
| case FFESTV_stateMODULE5: |
| ffestw_update (NULL); |
| return FFESTC_orderOK_; |
| |
| default: |
| ffestc_order_bad_ (); |
| ffestw_update (NULL); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_exec_ -- Check ordering on <exec> statement |
| |
| if (ffestc_order_exec_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_exec_ () |
| { |
| bool update; |
| |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION4); |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| update = FALSE; |
| break; |
| |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| |
| switch (ffestw_state (ffestw_previous (ffestw_stack_top ()))) |
| { |
| case FFESTV_stateINTERFACE0: |
| ffestc_order_bad_ (); |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderBAD_; |
| |
| default: |
| if (update) |
| ffestw_update (NULL); |
| return FFESTC_orderOK_; |
| } |
| } |
| |
| /* ffestc_order_format_ -- Check ordering on FORMAT statement |
| |
| if (ffestc_order_format_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_format_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM1); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE1); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION1); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT0: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_function_ -- Check ordering on <function> statement |
| |
| if (ffestc_order_function_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_function_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateFUNCTION5: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_iface_ -- Check ordering on <iface> statement |
| |
| if (ffestc_order_iface_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_iface_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| case FFESTV_statePROGRAM5: |
| case FFESTV_stateSUBROUTINE5: |
| case FFESTV_stateFUNCTION5: |
| case FFESTV_stateMODULE5: |
| case FFESTV_stateINTERFACE0: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_ifthen_ -- Check ordering on <ifthen> statement |
| |
| if (ffestc_order_ifthen_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_ifthen_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateIFTHEN: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_implicit_ -- Check ordering on IMPLICIT statement |
| |
| if (ffestc_order_implicit_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_implicit_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateBLOCKDATA2: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_implicitnone_ -- Check ordering on IMPLICIT NONE statement |
| |
| if (ffestc_order_implicitnone_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_implicitnone_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_interface_ -- Check ordering on <interface> statement |
| |
| if (ffestc_order_interface_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_interface_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateINTERFACE0: |
| case FFESTV_stateINTERFACE1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_map_ -- Check ordering on <map> statement |
| |
| if (ffestc_order_map_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_VXT |
| static ffestcOrder_ |
| ffestc_order_map_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateMAP: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_module_ -- Check ordering on <module> statement |
| |
| if (ffestc_order_module_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_module_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateMODULE4: |
| case FFESTV_stateMODULE5: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| ffestc_shriek_end_uses_ (TRUE); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_parameter_ -- Check ordering on <parameter> statement |
| |
| if (ffestc_order_parameter_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_parameter_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA2); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateTYPE: /* GNU extension here! */ |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateUNION: |
| case FFESTV_stateMAP: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_program_ -- Check ordering on <program> statement |
| |
| if (ffestc_order_program_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_program_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_statePROGRAM4: |
| case FFESTV_statePROGRAM5: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_progspec_ -- Check ordering on <progspec> statement |
| |
| if (ffestc_order_progspec_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_progspec_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA2); |
| if (ffe_is_pedantic ()) |
| { |
| ffebad_start (FFEBAD_BLOCKDATA_STMT); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_record_ -- Check ordering on RECORD statement |
| |
| if (ffestc_order_record_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_VXT |
| static ffestcOrder_ |
| ffestc_order_record_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_selectcase_ -- Check ordering on <selectcase> statement |
| |
| if (ffestc_order_selectcase_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_selectcase_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSELECT0: |
| case FFESTV_stateSELECT1: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_sfunc_ -- Check ordering on statement-function definition |
| |
| if (ffestc_order_sfunc_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_sfunc_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_spec_ -- Check ordering on <spec> statement |
| |
| if (ffestc_order_spec_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_spec_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_structure_ -- Check ordering on <structure> statement |
| |
| if (ffestc_order_structure_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_VXT |
| static ffestcOrder_ |
| ffestc_order_structure_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSTRUCTURE: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_subroutine_ -- Check ordering on <subroutine> statement |
| |
| if (ffestc_order_subroutine_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_subroutine_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateSUBROUTINE5: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_type_ -- Check ordering on <type> statement |
| |
| if (ffestc_order_type_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_type_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateTYPE: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_typedecl_ -- Check ordering on <typedecl> statement |
| |
| if (ffestc_order_typedecl_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_typedecl_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_union_ -- Check ordering on <union> statement |
| |
| if (ffestc_order_union_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_VXT |
| static ffestcOrder_ |
| ffestc_order_union_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateUNION: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_unit_ -- Check ordering on <unit> statement |
| |
| if (ffestc_order_unit_() != FFESTC_orderOK_) |
| return; */ |
| |
| static ffestcOrder_ |
| ffestc_order_unit_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| /* ffestc_order_use_ -- Check ordering on USE statement |
| |
| if (ffestc_order_use_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_use_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM1); |
| ffestc_shriek_begin_uses_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateSUBROUTINE0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE1); |
| ffestc_shriek_begin_uses_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateFUNCTION0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION1); |
| ffestc_shriek_begin_uses_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateMODULE0: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE1); |
| ffestc_shriek_begin_uses_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateUSE: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_vxtstructure_ -- Check ordering on STRUCTURE statement |
| |
| if (ffestc_order_vxtstructure_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_VXT |
| static ffestcOrder_ |
| ffestc_order_vxtstructure_ () |
| { |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_statePROGRAM2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_statePROGRAM3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSUBROUTINE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateFUNCTION3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateMODULE3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_update (NULL); |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateBLOCKDATA3); |
| return FFESTC_orderOK_; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| #if FFESTR_F90 |
| ffestc_shriek_where_ (FALSE); |
| #endif |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* ffestc_order_where_ -- Check ordering on <where> statement |
| |
| if (ffestc_order_where_() != FFESTC_orderOK_) |
| return; */ |
| |
| #if FFESTR_F90 |
| static ffestcOrder_ |
| ffestc_order_where_ () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateWHERETHEN: |
| return FFESTC_orderOK_; |
| |
| case FFESTV_stateWHERE: |
| ffestc_order_bad_ (); |
| ffestc_shriek_where_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| case FFESTV_stateIF: |
| ffestc_order_bad_ (); |
| ffestc_shriek_if_ (FALSE); |
| return FFESTC_orderBAD_; |
| |
| default: |
| ffestc_order_bad_ (); |
| return FFESTC_orderBAD_; |
| } |
| } |
| |
| #endif |
| /* Invoked for each token in dummy arg list of FUNCTION, SUBROUTINE, and |
| ENTRY (prior to the first executable statement). */ |
| |
| static void |
| ffestc_promote_dummy_ (ffelexToken t) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffebld e; |
| bool sfref_ok; |
| |
| assert (t != NULL); |
| |
| if (ffelex_token_type (t) == FFELEX_typeASTERISK) |
| { |
| ffebld_append_item (&ffestc_local_.dummy.list_bottom, |
| ffebld_new_star ()); |
| return; /* Don't bother with alternate returns! */ |
| } |
| |
| s = ffesymbol_declare_local (t, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| sfref_ok = FALSE; |
| |
| if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if (sa & FFESYMBOL_attrsDUMMY) |
| { |
| if (ffestc_entry_num_ == ffesymbol_maxentrynum (s)) |
| { /* Seen this one twice in this list! */ |
| na = FFESYMBOL_attrsetNONE; |
| } |
| else |
| na = sa; |
| sfref_ok = TRUE; /* Ok for sym to be ref'd in sfuncdef |
| previously, since already declared as a |
| dummy arg. */ |
| } |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsANY |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsANYSIZE |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsDUMMY; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| if (!ffesymbol_is_specable (s) |
| && (!sfref_ok |
| || (ffesymbol_where (s) != FFEINFO_whereDUMMY))) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| |
| /* 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_set_attrs (s, na); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_maxentrynum (s, ffestc_entry_num_); |
| ffesymbol_set_numentries (s, ffesymbol_numentries (s) + 1); |
| e = ffebld_new_symter (s, FFEINTRIN_genNONE, FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| ffebld_set_info (e, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindNONE, |
| FFEINFO_whereNONE, |
| FFETARGET_charactersizeNONE)); |
| ffebld_append_item (&ffestc_local_.dummy.list_bottom, e); |
| ffesymbol_signal_unreported (s); |
| } |
| } |
| |
| /* ffestc_promote_execdummy_ -- Declare token as dummy variable in exec context |
| |
| ffestc_promote_execdummy_(t); |
| |
| Invoked for each token in dummy arg list of ENTRY when the statement |
| follows the first executable statement. */ |
| |
| static void |
| ffestc_promote_execdummy_ (ffelexToken t) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffesymbolState ss; |
| ffesymbolState ns; |
| ffeinfoKind kind; |
| ffeinfoWhere where; |
| ffebld e; |
| |
| assert (t != NULL); |
| |
| if (ffelex_token_type (t) == FFELEX_typeASTERISK) |
| { |
| ffebld_append_item (&ffestc_local_.dummy.list_bottom, |
| ffebld_new_star ()); |
| return; /* Don't bother with alternate returns! */ |
| } |
| |
| s = ffesymbol_declare_local (t, FALSE); |
| na = sa = ffesymbol_attrs (s); |
| ss = ffesymbol_state (s); |
| kind = ffesymbol_kind (s); |
| where = ffesymbol_where (s); |
| |
| if (ffestc_entry_num_ == ffesymbol_maxentrynum (s)) |
| { /* Seen this one twice in this list! */ |
| na = FFESYMBOL_attrsetNONE; |
| } |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| ns = FFESYMBOL_stateUNDERSTOOD; /* Assume we know it all know. */ |
| |
| switch (kind) |
| { |
| case FFEINFO_kindENTITY: |
| case FFEINFO_kindFUNCTION: |
| case FFEINFO_kindSUBROUTINE: |
| break; /* These are fine, as far as we know. */ |
| |
| case FFEINFO_kindNONE: |
| if (sa & FFESYMBOL_attrsDUMMY) |
| ns = FFESYMBOL_stateUNCERTAIN; /* Learned nothing new. */ |
| else if (sa & FFESYMBOL_attrsANYLEN) |
| { |
| kind = FFEINFO_kindENTITY; |
| where = FFEINFO_whereDUMMY; |
| } |
| else if (sa & FFESYMBOL_attrsACTUALARG) |
| na = FFESYMBOL_attrsetNONE; |
| else |
| { |
| na = sa | FFESYMBOL_attrsDUMMY; |
| ns = FFESYMBOL_stateUNCERTAIN; |
| } |
| break; |
| |
| default: |
| na = FFESYMBOL_attrsetNONE; /* Error. */ |
| break; |
| } |
| |
| switch (where) |
| { |
| case FFEINFO_whereDUMMY: |
| break; /* This is fine. */ |
| |
| case FFEINFO_whereNONE: |
| where = FFEINFO_whereDUMMY; |
| break; |
| |
| default: |
| na = FFESYMBOL_attrsetNONE; /* Error. */ |
| break; |
| } |
| |
| /* 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_set_attrs (s, na); |
| ffesymbol_set_state (s, ns); |
| ffesymbol_set_maxentrynum (s, ffestc_entry_num_); |
| ffesymbol_set_numentries (s, ffesymbol_numentries (s) + 1); |
| if ((ns == FFESYMBOL_stateUNDERSTOOD) |
| && (kind != FFEINFO_kindSUBROUTINE) |
| && !ffeimplic_establish_symbol (s)) |
| { |
| ffesymbol_error (s, t); |
| return; |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| ffesymbol_rank (s), |
| kind, |
| where, |
| ffesymbol_size (s))); |
| e = ffebld_new_symter (s, FFEINTRIN_genNONE, FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| ffebld_set_info (e, ffeinfo_use (ffesymbol_info (s))); |
| ffebld_append_item (&ffestc_local_.dummy.list_bottom, e); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| } |
| |
| /* ffestc_promote_sfdummy_ -- Declare token as stmt-func dummy variable |
| |
| ffestc_promote_sfdummy_(t); |
| |
| Invoked for each token in dummy arg list of statement function. |
| |
| 22-Oct-91 JCB 1.1 |
| Reject arg if CHARACTER*(*). */ |
| |
| static void |
| ffestc_promote_sfdummy_ (ffelexToken t) |
| { |
| ffesymbol s; |
| ffesymbol sp; /* Parent symbol. */ |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffebld e; |
| |
| assert (t != NULL); |
| |
| s = ffesymbol_declare_sfdummy (t); /* Sets maxentrynum to 0 for new obj; |
| also sets sfa_dummy_parent to |
| parent symbol. */ |
| if (ffesymbol_state (s) != FFESYMBOL_stateNONE) |
| { |
| ffesymbol_error (s, t); /* Dummy already in list. */ |
| return; |
| } |
| |
| sp = ffesymbol_sfdummyparent (s); /* Now flag dummy's parent as used |
| for dummy. */ |
| sa = ffesymbol_attrs (sp); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (sp) |
| && ((ffesymbol_kind (sp) != FFEINFO_kindENTITY) |
| || ((ffesymbol_where (sp) != FFEINFO_whereLOCAL) |
| && (ffesymbol_where (sp) != FFEINFO_whereCOMMON) |
| && (ffesymbol_where (sp) != FFEINFO_whereDUMMY) |
| && (ffesymbol_where (sp) != FFEINFO_whereNONE)))) |
| na = FFESYMBOL_attrsetNONE; /* Can't be PARAMETER etc., must be a var. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | 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; |
| |
| /* 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); |
| ffesymbol_set_info (s, ffeinfo_new_any ()); |
| } |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_state (sp, FFESYMBOL_stateSEEN); |
| ffesymbol_set_attrs (sp, na); |
| if (!ffeimplic_establish_symbol (sp) |
| || ((ffesymbol_basictype (sp) == FFEINFO_basictypeCHARACTER) |
| && (ffesymbol_size (sp) == FFETARGET_charactersizeNONE))) |
| ffesymbol_error (sp, t); |
| else |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (sp), |
| ffesymbol_kindtype (sp), |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereDUMMY, |
| ffesymbol_size (sp))); |
| |
| ffesymbol_signal_unreported (sp); |
| } |
| |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_maxentrynum (s, ffestc_sfdummy_argno_++); |
| ffesymbol_signal_unreported (s); |
| e = ffebld_new_symter (s, FFEINTRIN_genNONE, FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| ffebld_set_info (e, ffeinfo_use (ffesymbol_info (s))); |
| ffebld_append_item (&ffestc_local_.dummy.list_bottom, e); |
| } |
| |
| /* ffestc_shriek_begin_program_ -- Implicit PROGRAM statement |
| |
| ffestc_shriek_begin_program_(); |
| |
| Invoked only when a PROGRAM statement is NOT present at the beginning |
| of a main program unit. */ |
| |
| static void |
| ffestc_shriek_begin_program_ () |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| ffestc_blocknum_ = 0; |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_statePROGRAM0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_end_program_); |
| ffestw_set_name (b, NULL); |
| |
| s = ffesymbol_declare_programunit (NULL, |
| ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| |
| /* Special case: this is one symbol that won't go through |
| ffestu_exec_transition_ when the first statement in a main program is |
| executable, because the transition happens in ffest before ffestc is |
| reached and triggers the implicit generation of a main program. So we |
| do the exec transition for the implicit main program right here, just |
| for cleanliness' sake (at the very least). */ |
| |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindPROGRAM, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| |
| ffesymbol_signal_unreported (s); |
| |
| ffestd_R1102 (s, NULL); |
| } |
| |
| /* ffestc_shriek_begin_uses_ -- Start a bunch of USE statements |
| |
| ffestc_shriek_begin_uses_(); |
| |
| Invoked before handling the first USE statement in a block of one or |
| more USE statements. _end_uses_(bool ok) is invoked before handling |
| the first statement after the block (there are no BEGIN USE and END USE |
| statements, but the semantics of USE statements effectively requires |
| handling them as a single block rather than one statement at a time). */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_begin_uses_ () |
| { |
| ffestw b; |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateUSE); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_end_uses_); |
| |
| ffestd_begin_uses (); |
| } |
| |
| #endif |
| /* ffestc_shriek_blockdata_ -- End a BLOCK DATA |
| |
| ffestc_shriek_blockdata_(TRUE); */ |
| |
| static void |
| ffestc_shriek_blockdata_ (bool ok) |
| { |
| if (!ffesta_seen_first_exec) |
| { |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| } |
| |
| ffestd_R1112 (ok); |
| |
| ffestd_exec_end (); |
| |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| |
| ffe_terminate_2 (); |
| ffe_init_2 (); |
| } |
| |
| /* ffestc_shriek_do_ -- End of statement following DO-term-stmt etc |
| |
| ffestc_shriek_do_(TRUE); |
| |
| Also invoked by _labeldef_branch_end_ (or, in cases |
| of errors, other _labeldef_ functions) when the label definition is |
| for a DO-target (LOOPEND) label, once per matching/outstanding DO |
| block on the stack. These cases invoke this function with ok==TRUE, so |
| only forced stack popping (via ffestc_eof()) invokes it with ok==FALSE. */ |
| |
| static void |
| ffestc_shriek_do_ (bool ok) |
| { |
| ffelab l; |
| |
| if (((l = ffestw_label (ffestw_stack_top ())) != NULL) |
| && (ffewhere_line_is_unknown (ffelab_definition_line (l)))) |
| { /* DO target is label that is still |
| undefined. */ |
| assert ((ffelab_type (l) == FFELAB_typeLOOPEND) |
| || (ffelab_type (l) == FFELAB_typeANY)); |
| if (ffelab_type (l) != FFELAB_typeANY) |
| { |
| ffelab_set_definition_line (l, |
| ffewhere_line_use (ffelab_doref_line (l))); |
| ffelab_set_definition_column (l, |
| ffewhere_column_use (ffelab_doref_column (l))); |
| ffestv_num_label_defines_++; |
| } |
| ffestd_labeldef_branch (l); |
| } |
| |
| ffestd_do (ok); |
| |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| if (ffestw_do_iter_var_t (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_do_iter_var_t (ffestw_stack_top ())); |
| if (ffestw_do_iter_var (ffestw_stack_top ()) != NULL) |
| ffesymbol_set_is_doiter (ffestw_do_iter_var (ffestw_stack_top ()), FALSE); |
| ffestw_kill (ffestw_pop ()); |
| } |
| |
| /* ffestc_shriek_end_program_ -- End a PROGRAM |
| |
| ffestc_shriek_end_program_(); */ |
| |
| static void |
| ffestc_shriek_end_program_ (bool ok) |
| { |
| if (!ffesta_seen_first_exec) |
| { |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| } |
| |
| ffestd_R1103 (ok); |
| |
| ffestd_exec_end (); |
| |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| |
| ffe_terminate_2 (); |
| ffe_init_2 (); |
| } |
| |
| /* ffestc_shriek_end_uses_ -- End a bunch of USE statements |
| |
| ffestc_shriek_end_uses_(TRUE); |
| |
| ok==TRUE means simply not popping due to ffestc_eof() |
| being called, because there is no formal END USES statement in Fortran. */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_end_uses_ (bool ok) |
| { |
| ffestd_end_uses (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| } |
| |
| #endif |
| /* ffestc_shriek_function_ -- End a FUNCTION |
| |
| ffestc_shriek_function_(TRUE); */ |
| |
| static void |
| ffestc_shriek_function_ (bool ok) |
| { |
| if (!ffesta_seen_first_exec) |
| { |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| } |
| |
| ffestd_R1221 (ok); |
| |
| ffestd_exec_end (); |
| |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| ffesta_is_entry_valid = FALSE; |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffe_terminate_2 (); |
| ffe_init_2 (); |
| break; |
| |
| default: |
| ffe_terminate_3 (); |
| ffe_init_3 (); |
| break; |
| |
| case FFESTV_stateINTERFACE0: |
| ffe_terminate_4 (); |
| ffe_init_4 (); |
| break; |
| } |
| } |
| |
| /* ffestc_shriek_if_ -- End of statement following logical IF |
| |
| ffestc_shriek_if_(TRUE); |
| |
| Applies ONLY to logical IF, not to IF-THEN. For example, does not |
| ffelex_token_kill the construct name for an IF-THEN block (the name |
| field is invalid for logical IF). ok==TRUE iff statement following |
| logical IF (substatement) is valid; else, statement is invalid or |
| stack forcibly popped due to ffestc_eof(). */ |
| |
| static void |
| ffestc_shriek_if_ (bool ok) |
| { |
| ffestd_end_R807 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| ffestc_shriek_after1_ = NULL; |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| /* ffestc_shriek_ifthen_ -- End an IF-THEN |
| |
| ffestc_shriek_ifthen_(TRUE); */ |
| |
| static void |
| ffestc_shriek_ifthen_ (bool ok) |
| { |
| ffestd_R806 (ok); |
| |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| /* ffestc_shriek_interface_ -- End an INTERFACE |
| |
| ffestc_shriek_interface_(TRUE); */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_interface_ (bool ok) |
| { |
| ffestd_R1203 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_map_ -- End a MAP |
| |
| ffestc_shriek_map_(TRUE); */ |
| |
| #if FFESTR_VXT |
| static void |
| ffestc_shriek_map_ (bool ok) |
| { |
| ffestd_V013 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_module_ -- End a MODULE |
| |
| ffestc_shriek_module_(TRUE); */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_module_ (bool ok) |
| { |
| if (!ffesta_seen_first_exec) |
| { |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| } |
| |
| ffestd_R1106 (ok); |
| |
| ffestd_exec_end (); |
| |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| |
| ffe_terminate_2 (); |
| ffe_init_2 (); |
| } |
| |
| #endif |
| /* ffestc_shriek_select_ -- End a SELECT |
| |
| ffestc_shriek_select_(TRUE); */ |
| |
| static void |
| ffestc_shriek_select_ (bool ok) |
| { |
| ffestwSelect s; |
| ffestwCase c; |
| |
| ffestd_R811 (ok); |
| |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| s = ffestw_select (ffestw_stack_top ()); |
| ffelex_token_kill (s->t); |
| for (c = s->first_rel; c != (ffestwCase) &s->first_rel; c = c->next_rel) |
| ffelex_token_kill (c->t); |
| malloc_pool_kill (s->pool); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| /* ffestc_shriek_structure_ -- End a STRUCTURE |
| |
| ffestc_shriek_structure_(TRUE); */ |
| |
| #if FFESTR_VXT |
| static void |
| ffestc_shriek_structure_ (bool ok) |
| { |
| ffestd_V004 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_subroutine_ -- End a SUBROUTINE |
| |
| ffestc_shriek_subroutine_(TRUE); */ |
| |
| static void |
| ffestc_shriek_subroutine_ (bool ok) |
| { |
| if (!ffesta_seen_first_exec) |
| { |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| } |
| |
| ffestd_R1225 (ok); |
| |
| ffestd_exec_end (); |
| |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| ffesta_is_entry_valid = FALSE; |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffe_terminate_2 (); |
| ffe_init_2 (); |
| break; |
| |
| default: |
| ffe_terminate_3 (); |
| ffe_init_3 (); |
| break; |
| |
| case FFESTV_stateINTERFACE0: |
| ffe_terminate_4 (); |
| ffe_init_4 (); |
| break; |
| } |
| } |
| |
| /* ffestc_shriek_type_ -- End a TYPE |
| |
| ffestc_shriek_type_(TRUE); */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_type_ (bool ok) |
| { |
| ffestd_R425 (ok); |
| |
| ffe_terminate_4 (); |
| |
| ffelex_token_kill (ffestw_name (ffestw_stack_top ())); |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_union_ -- End a UNION |
| |
| ffestc_shriek_union_(TRUE); */ |
| |
| #if FFESTR_VXT |
| static void |
| ffestc_shriek_union_ (bool ok) |
| { |
| ffestd_V010 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_where_ -- Implicit END WHERE statement |
| |
| ffestc_shriek_where_(TRUE); |
| |
| Implement the end of the current WHERE "block". ok==TRUE iff statement |
| following WHERE (substatement) is valid; else, statement is invalid |
| or stack forcibly popped due to ffestc_eof(). */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_where_ (bool ok) |
| { |
| ffestd_R745 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| ffestc_shriek_after1_ = NULL; |
| if (ffestw_state (ffestw_stack_top ()) == FFESTV_stateIF) |
| ffestc_shriek_if_ (TRUE); /* "IF (x) WHERE (y) stmt" is only valid |
| case. */ |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_shriek_wherethen_ -- End a WHERE(-THEN) |
| |
| ffestc_shriek_wherethen_(TRUE); */ |
| |
| #if FFESTR_F90 |
| static void |
| ffestc_shriek_wherethen_ (bool ok) |
| { |
| ffestd_end_R740 (ok); |
| |
| ffestw_kill (ffestw_pop ()); |
| |
| ffestc_try_shriek_do_ (); |
| } |
| |
| #endif |
| /* ffestc_subr_binsrch_ -- Binary search of char const in list of strings |
| |
| i = ffestc_subr_binsrch_(search_list,search_list_size,&spec,"etc"); |
| |
| search_list contains search_list_size char *'s, spec is checked to see |
| if it is a char constant and, if so, is binary-searched against the list. |
| 0 is returned if not found, else the "classic" index (beginning with 1) |
| is returned. Before returning 0 where the search was performed but |
| fruitless, if "etc" is a non-NULL char *, an error message is displayed |
| using "etc" as the pick-one-of-these string. */ |
| |
| static int |
| ffestc_subr_binsrch_ (const char *const *list, int size, ffestpFile *spec, |
| const char *whine) |
| { |
| int lowest_tested; |
| int highest_tested; |
| int halfway; |
| int offset; |
| int c; |
| const char *str; |
| int len; |
| |
| if (size == 0) |
| return 0; /* Nobody should pass size == 0, but for |
| elegance.... */ |
| |
| lowest_tested = -1; |
| highest_tested = size; |
| halfway = size >> 1; |
| |
| list += halfway; |
| |
| c = ffestc_subr_speccmp_ (*list, spec, &str, &len); |
| if (c == 2) |
| return 0; |
| c = -c; /* Sigh. */ |
| |
| next: /* :::::::::::::::::::: */ |
| switch (c) |
| { |
| case -1: |
| offset = (halfway - lowest_tested) >> 1; |
| if (offset == 0) |
| goto nope; /* :::::::::::::::::::: */ |
| highest_tested = halfway; |
| list -= offset; |
| halfway -= offset; |
| c = ffesrc_strcmp_1ns2i (ffe_case_match (), str, len, *list); |
| goto next; /* :::::::::::::::::::: */ |
| |
| case 0: |
| return halfway + 1; |
| |
| case 1: |
| offset = (highest_tested - halfway) >> 1; |
| if (offset == 0) |
| goto nope; /* :::::::::::::::::::: */ |
| lowest_tested = halfway; |
| list += offset; |
| halfway += offset; |
| c = ffesrc_strcmp_1ns2i (ffe_case_match (), str, len, *list); |
| goto next; /* :::::::::::::::::::: */ |
| |
| default: |
| assert ("unexpected return from ffesrc_strcmp_1ns2i" == NULL); |
| break; |
| } |
| |
| nope: /* :::::::::::::::::::: */ |
| ffebad_start (FFEBAD_SPEC_VALUE); |
| ffebad_here (0, ffelex_token_where_line (spec->value), |
| ffelex_token_where_column (spec->value)); |
| ffebad_string (whine); |
| ffebad_finish (); |
| return 0; |
| } |
| |
| /* ffestc_subr_format_ -- Return summary of format specifier |
| |
| ffestc_subr_format_(&specifier); */ |
| |
| static ffestvFormat |
| ffestc_subr_format_ (ffestpFile *spec) |
| { |
| if (!spec->kw_or_val_present) |
| return FFESTV_formatNONE; |
| assert (spec->value_present); |
| if (spec->value_is_label) |
| return FFESTV_formatLABEL; /* Ok if not a label. */ |
| |
| assert (spec->value != NULL); |
| if (ffebld_op (spec->u.expr) == FFEBLD_opSTAR) |
| return FFESTV_formatASTERISK; |
| |
| if (ffeinfo_kind (ffebld_info (spec->u.expr)) == FFEINFO_kindNAMELIST) |
| return FFESTV_formatNAMELIST; |
| |
| if (ffeinfo_rank (ffebld_info (spec->u.expr)) != 0) |
| return FFESTV_formatCHAREXPR; /* F77 C5. */ |
| |
| switch (ffeinfo_basictype (ffebld_info (spec->u.expr))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| return FFESTV_formatINTEXPR; |
| |
| case FFEINFO_basictypeCHARACTER: |
| return FFESTV_formatCHAREXPR; |
| |
| case FFEINFO_basictypeANY: |
| return FFESTV_formatASTERISK; |
| |
| default: |
| assert ("bad basictype" == NULL); |
| return FFESTV_formatINTEXPR; |
| } |
| } |
| |
| /* ffestc_subr_is_branch_ -- Handle specifier as branch target label |
| |
| ffestc_subr_is_branch_(&specifier); */ |
| |
| static bool |
| ffestc_subr_is_branch_ (ffestpFile *spec) |
| { |
| if (!spec->kw_or_val_present) |
| return TRUE; |
| assert (spec->value_present); |
| assert (spec->value_is_label); |
| spec->value_is_label++; /* For checking purposes only; 1=>2. */ |
| return ffestc_labelref_is_branch_ (spec->value, &spec->u.label); |
| } |
| |
| /* ffestc_subr_is_format_ -- Handle specifier as format target label |
| |
| ffestc_subr_is_format_(&specifier); */ |
| |
| static bool |
| ffestc_subr_is_format_ (ffestpFile *spec) |
| { |
| if (!spec->kw_or_val_present) |
| return TRUE; |
| assert (spec->value_present); |
| if (!spec->value_is_label) |
| return TRUE; /* Ok if not a label. */ |
| |
| spec->value_is_label++; /* For checking purposes only; 1=>2. */ |
| return ffestc_labelref_is_format_ (spec->value, &spec->u.label); |
| } |
| |
| /* ffestc_subr_is_present_ -- Ensure specifier is present, else error |
| |
| ffestc_subr_is_present_("SPECIFIER",&specifier); */ |
| |
| static bool |
| ffestc_subr_is_present_ (const char *name, ffestpFile *spec) |
| { |
| if (spec->kw_or_val_present) |
| { |
| assert (spec->value_present); |
| return TRUE; |
| } |
| |
| ffebad_start (FFEBAD_MISSING_SPECIFIER); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_string (name); |
| ffebad_finish (); |
| return FALSE; |
| } |
| |
| /* ffestc_subr_speccmp_ -- Compare string to constant expression, if present |
| |
| if (ffestc_subr_speccmp_("Constant",&specifier,NULL,NULL) == 0) |
| // specifier value is present and is a char constant "CONSTANT" |
| |
| Like strcmp, except the return values are defined as: -1 returned in place |
| of strcmp's generic negative value, 1 in place of it's generic positive |
| value, and 2 when there is no character constant string to compare. Also, |
| a case-insensitive comparison is performed, where string is assumed to |
| already be in InitialCaps form. |
| |
| If a non-NULL pointer is provided as the char **target, then *target is |
| written with NULL if 2 is returned, a pointer to the constant string |
| value of the specifier otherwise. Similarly, length is written with |
| 0 if 2 is returned, the length of the constant string value otherwise. */ |
| |
| static int |
| ffestc_subr_speccmp_ (const char *string, ffestpFile *spec, const char **target, |
| int *length) |
| { |
| ffebldConstant c; |
| int i; |
| |
| if (!spec->kw_or_val_present || !spec->value_present |
| || (spec->u.expr == NULL) |
| || (ffebld_op (spec->u.expr) != FFEBLD_opCONTER)) |
| { |
| if (target != NULL) |
| *target = NULL; |
| if (length != NULL) |
| *length = 0; |
| return 2; |
| } |
| |
| if (ffebld_constant_type (c = ffebld_conter (spec->u.expr)) |
| != FFEBLD_constCHARACTERDEFAULT) |
| { |
| if (target != NULL) |
| *target = NULL; |
| if (length != NULL) |
| *length = 0; |
| return 2; |
| } |
| |
| if (target != NULL) |
| *target = ffebld_constant_characterdefault (c).text; |
| if (length != NULL) |
| *length = ffebld_constant_characterdefault (c).length; |
| |
| i = ffesrc_strcmp_1ns2i (ffe_case_match (), |
| ffebld_constant_characterdefault (c).text, |
| ffebld_constant_characterdefault (c).length, |
| string); |
| if (i == 0) |
| return 0; |
| if (i > 0) |
| return -1; /* Yes indeed, we reverse the strings to |
| _strcmpin_. */ |
| return 1; |
| } |
| |
| /* ffestc_subr_unit_ -- Return summary of unit specifier |
| |
| ffestc_subr_unit_(&specifier); */ |
| |
| static ffestvUnit |
| ffestc_subr_unit_ (ffestpFile *spec) |
| { |
| if (!spec->kw_or_val_present) |
| return FFESTV_unitNONE; |
| assert (spec->value_present); |
| assert (spec->value != NULL); |
| |
| if (ffebld_op (spec->u.expr) == FFEBLD_opSTAR) |
| return FFESTV_unitASTERISK; |
| |
| switch (ffeinfo_basictype (ffebld_info (spec->u.expr))) |
| { |
| case FFEINFO_basictypeINTEGER: |
| return FFESTV_unitINTEXPR; |
| |
| case FFEINFO_basictypeCHARACTER: |
| return FFESTV_unitCHAREXPR; |
| |
| case FFEINFO_basictypeANY: |
| return FFESTV_unitASTERISK; |
| |
| default: |
| assert ("bad basictype" == NULL); |
| return FFESTV_unitINTEXPR; |
| } |
| } |
| |
| /* Call this function whenever it's possible that one or more top |
| stack items are label-targeting DO blocks that have had their |
| labels defined, but at a time when they weren't at the top of the |
| stack. This prevents uninformative diagnostics for programs |
| like "DO 10", "IF (...) THEN", "10 ELSE", "END IF", "END". */ |
| |
| static void |
| ffestc_try_shriek_do_ () |
| { |
| ffelab lab; |
| ffelabType ty; |
| |
| while ((ffestw_state (ffestw_stack_top ()) == FFESTV_stateDO) |
| && ((lab = (ffestw_label (ffestw_stack_top ()))) != NULL) |
| && (((ty = (ffelab_type (lab))) |
| == FFELAB_typeANY) |
| || (ty == FFELAB_typeUSELESS) |
| || (ty == FFELAB_typeFORMAT) |
| || (ty == FFELAB_typeNOTLOOP) |
| || (ty == FFELAB_typeENDIF))) |
| ffestc_shriek_do_ (FALSE); |
| } |
| |
| /* ffestc_decl_start -- R426 or R501 |
| |
| ffestc_decl_start(...); |
| |
| Verify that R426 component-def-stmt or R501 type-declaration-stmt are |
| valid here, figure out which one, and implement. */ |
| |
| void |
| ffestc_decl_start (ffestpType type, ffelexToken typet, ffebld kind, |
| ffelexToken kindt, ffebld len, ffelexToken lent) |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| case FFESTV_statePROGRAM0: |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_statePROGRAM1: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateUSE: |
| ffestc_local_.decl.is_R426 = 2; |
| break; |
| |
| case FFESTV_stateTYPE: |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| ffestc_local_.decl.is_R426 = 1; |
| break; |
| |
| default: |
| ffestc_order_bad_ (); |
| ffestc_labeldef_useless_ (); |
| ffestc_local_.decl.is_R426 = 0; |
| return; |
| } |
| |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_start (type, typet, kind, kindt, len, lent); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_start (type, typet, kind, kindt, len, lent); |
| break; |
| |
| default: |
| ffestc_labeldef_useless_ (); |
| break; |
| } |
| } |
| |
| /* ffestc_decl_attrib -- R426 or R501 type attribute |
| |
| ffestc_decl_attrib(...); |
| |
| Verify that R426 component-def-stmt or R501 type-declaration-stmt attribute |
| is valid here and implement. */ |
| |
| void |
| ffestc_decl_attrib (ffestpAttrib attrib UNUSED, |
| ffelexToken attribt UNUSED, |
| ffestrOther intent_kw UNUSED, |
| ffesttDimList dims UNUSED) |
| { |
| #if FFESTR_F90 |
| switch (ffestc_local_.decl.is_R426) |
| { |
| case 1: |
| ffestc_R426_attrib (attrib, attribt, intent_kw, dims); |
| break; |
| |
| case 2: |
| ffestc_R501_attrib (attrib, attribt, intent_kw, dims); |
| break; |
| |
| default: |
| break; |
| } |
| #else |
| ffebad_start (FFEBAD_F90); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| return; |
| #endif |
| } |
| |
| /* ffestc_decl_item -- R426 or R501 |
| |
| ffestc_decl_item(...); |
| |
| Establish type for a particular object. */ |
| |
| void |
| ffestc_decl_item (ffelexToken name, ffebld kind, ffelexToken kindt, |
| ffesttDimList dims, ffebld len, ffelexToken lent, ffebld init, |
| ffelexToken initt, bool clist) |
| { |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_item (name, kind, kindt, dims, len, lent, init, initt, |
| clist); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_item (name, kind, kindt, dims, len, lent, init, initt, |
| clist); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* ffestc_decl_itemstartvals -- R426 or R501 start list of values |
| |
| ffestc_decl_itemstartvals(); |
| |
| Gonna specify values for the object now. */ |
| |
| void |
| ffestc_decl_itemstartvals () |
| { |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_itemstartvals (); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_itemstartvals (); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* ffestc_decl_itemvalue -- R426 or R501 source value |
| |
| ffestc_decl_itemvalue(repeat,repeat_token,value,value_token); |
| |
| Make sure repeat and value are valid for the object being initialized. */ |
| |
| void |
| ffestc_decl_itemvalue (ffebld repeat, ffelexToken repeat_token, |
| ffebld value, ffelexToken value_token) |
| { |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_itemvalue (repeat, repeat_token, value, value_token); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_itemvalue (repeat, repeat_token, value, value_token); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* ffestc_decl_itemendvals -- R426 or R501 end list of values |
| |
| ffelexToken t; // the SLASH token that ends the list. |
| ffestc_decl_itemendvals(t); |
| |
| No more values, might specify more objects now. */ |
| |
| void |
| ffestc_decl_itemendvals (ffelexToken t) |
| { |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_itemendvals (t); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_itemendvals (t); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* ffestc_decl_finish -- R426 or R501 |
| |
| ffestc_decl_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_decl_finish () |
| { |
| switch (ffestc_local_.decl.is_R426) |
| { |
| #if FFESTR_F90 |
| case 1: |
| ffestc_R426_finish (); |
| break; |
| #endif |
| |
| case 2: |
| ffestc_R501_finish (); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /* ffestc_elsewhere -- Generic ELSE WHERE statement |
| |
| ffestc_end(); |
| |
| Decide whether ELSEWHERE or ELSE w/if-construct-name=="WHERE" is meant. */ |
| |
| void |
| ffestc_elsewhere (ffelexToken where) |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateIFTHEN: |
| ffestc_R805 (where); |
| break; |
| |
| default: |
| #if FFESTR_F90 |
| ffestc_R744 (); |
| #endif |
| break; |
| } |
| } |
| |
| /* ffestc_end -- Generic END statement |
| |
| ffestc_end(); |
| |
| Make sure a generic END is valid in the current context, and implement |
| it. */ |
| |
| void |
| ffestc_end () |
| { |
| ffestw b; |
| |
| b = ffestw_stack_top (); |
| |
| recurse: |
| |
| switch (ffestw_state (b)) |
| { |
| case FFESTV_stateBLOCKDATA0: |
| case FFESTV_stateBLOCKDATA1: |
| case FFESTV_stateBLOCKDATA2: |
| case FFESTV_stateBLOCKDATA3: |
| case FFESTV_stateBLOCKDATA4: |
| case FFESTV_stateBLOCKDATA5: |
| ffestc_R1112 (NULL); |
| break; |
| |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateFUNCTION5: |
| if ((ffestw_state (ffestw_previous (b)) != FFESTV_stateNIL) |
| && (ffestw_state (ffestw_previous (b)) != FFESTV_stateINTERFACE0)) |
| { |
| ffebad_start (FFEBAD_END_WO); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_previous (b)), ffestw_col (ffestw_previous (b))); |
| ffebad_string ("FUNCTION"); |
| ffebad_finish (); |
| } |
| ffestc_R1221 (NULL); |
| break; |
| |
| case FFESTV_stateMODULE0: |
| case FFESTV_stateMODULE1: |
| case FFESTV_stateMODULE2: |
| case FFESTV_stateMODULE3: |
| case FFESTV_stateMODULE4: |
| case FFESTV_stateMODULE5: |
| #if FFESTR_F90 |
| ffestc_R1106 (NULL); |
| #endif |
| break; |
| |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateSUBROUTINE5: |
| if ((ffestw_state (ffestw_previous (b)) != FFESTV_stateNIL) |
| && (ffestw_state (ffestw_previous (b)) != FFESTV_stateINTERFACE0)) |
| { |
| ffebad_start (FFEBAD_END_WO); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_previous (b)), ffestw_col (ffestw_previous (b))); |
| ffebad_string ("SUBROUTINE"); |
| ffebad_finish (); |
| } |
| ffestc_R1225 (NULL); |
| break; |
| |
| case FFESTV_stateUSE: |
| b = ffestw_previous (ffestw_stack_top ()); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| default: |
| ffestc_R1103 (NULL); |
| break; |
| } |
| } |
| |
| /* ffestc_eof -- Generic EOF |
| |
| ffestc_eof(); |
| |
| Make sure we're at state NIL, or issue an error message and use each |
| block's shriek function to clean up to state NIL. */ |
| |
| void |
| ffestc_eof () |
| { |
| if (ffestw_state (ffestw_stack_top ()) != FFESTV_stateNIL) |
| { |
| ffebad_start (FFEBAD_EOF_BEFORE_BLOCK_END); |
| ffebad_here (0, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| do |
| (*ffestw_shriek (ffestw_stack_top ()))(FALSE); |
| while (ffestw_state (ffestw_stack_top ()) != FFESTV_stateNIL); |
| } |
| } |
| |
| /* ffestc_exec_transition -- Check if ok and move stmt state to executable |
| |
| if (ffestc_exec_transition()) |
| // Transition successful (kind of like a CONTINUE stmt was seen). |
| |
| If the current statement state is a non-nested specification state in |
| which, say, a CONTINUE statement would be valid, then enter the state |
| we'd be in after seeing CONTINUE (without, of course, generating any |
| CONTINUE code), call ffestd_exec_begin, and return TRUE. Otherwise |
| return FALSE. |
| |
| This function cannot be invoked once the first executable statement |
| is seen. This function may choose to always return TRUE by shrieking |
| away any interceding state stack entries to reach the base level of |
| specification state, but right now it doesn't, and it is (or should |
| be) purely an issue of how one wishes errors to be handled (for example, |
| an unrecognized statement in the middle of a STRUCTURE construct: after |
| the error message, should subsequent statements still be interpreted as |
| being within the construct, or should the construct be terminated upon |
| seeing the unrecognized statement? we do the former at the moment). */ |
| |
| bool |
| ffestc_exec_transition () |
| { |
| bool update; |
| |
| recurse: |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| ffestc_shriek_begin_program_ (); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| case FFESTV_statePROGRAM0: |
| case FFESTV_stateSUBROUTINE0: |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateBLOCKDATA0: |
| ffestw_state (ffestw_stack_top ()) += 4; /* To state UNIT4. */ |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM1: |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateBLOCKDATA1: |
| ffestw_state (ffestw_stack_top ()) += 3; /* To state UNIT4. */ |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM2: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateBLOCKDATA2: |
| ffestw_state (ffestw_stack_top ()) += 2; /* To state UNIT4. */ |
| update = TRUE; |
| break; |
| |
| case FFESTV_statePROGRAM3: |
| case FFESTV_stateSUBROUTINE3: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateBLOCKDATA3: |
| ffestw_state (ffestw_stack_top ()) += 1; /* To state UNIT4. */ |
| update = TRUE; |
| break; |
| |
| case FFESTV_stateUSE: |
| #if FFESTR_F90 |
| ffestc_shriek_end_uses_ (TRUE); |
| #endif |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| default: |
| return FALSE; |
| } |
| |
| if (update) |
| ffestw_update (NULL); /* Update state line/col info. */ |
| |
| ffesta_seen_first_exec = TRUE; |
| ffestd_exec_begin (); |
| |
| return TRUE; |
| } |
| |
| /* ffestc_ffebad_here_doiter -- Calls ffebad_here with ptr to DO iter var |
| |
| ffesymbol s; |
| // call ffebad_start first, of course. |
| ffestc_ffebad_here_doiter(0,s); |
| // call ffebad_finish afterwards, naturally. |
| |
| Searches the stack of blocks backwards for a DO loop that has s |
| as its iteration variable, then calls ffebad_here with pointers to |
| that particular reference to the variable. Crashes if the DO loop |
| can't be found. */ |
| |
| void |
| ffestc_ffebad_here_doiter (ffebadIndex i, ffesymbol s) |
| { |
| ffestw block; |
| |
| for (block = ffestw_top_do (ffestw_stack_top ()); |
| (block != NULL) && (ffestw_blocknum (block) != 0); |
| block = ffestw_top_do (ffestw_previous (block))) |
| { |
| if (ffestw_do_iter_var (block) == s) |
| { |
| ffebad_here (i, ffelex_token_where_line (ffestw_do_iter_var_t (block)), |
| ffelex_token_where_column (ffestw_do_iter_var_t (block))); |
| return; |
| } |
| } |
| assert ("no do block found" == NULL); |
| } |
| |
| /* ffestc_is_decl_not_R1219 -- Context information for FFESTB |
| |
| if (ffestc_is_decl_not_R1219()) ... |
| |
| When a statement with the form "type[RECURSIVE]FUNCTIONname(name-list)" |
| is seen, call this function. It returns TRUE if the statement's context |
| is such that it is a declaration of an object named |
| "[RECURSIVE]FUNCTIONname" with an array-decl spec of "name-list", FALSE |
| if the statement's context is such that it begins the definition of a |
| function named "name" havin the dummy argument list "name-list" (this |
| is the R1219 function-stmt case). */ |
| |
| bool |
| ffestc_is_decl_not_R1219 () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateNIL: |
| case FFESTV_statePROGRAM5: |
| case FFESTV_stateSUBROUTINE5: |
| case FFESTV_stateFUNCTION5: |
| case FFESTV_stateMODULE5: |
| case FFESTV_stateINTERFACE0: |
| return FALSE; |
| |
| default: |
| return TRUE; |
| } |
| } |
| |
| /* ffestc_is_entry_in_subr -- Context information for FFESTB |
| |
| if (ffestc_is_entry_in_subr()) ... |
| |
| When a statement with the form "ENTRY name(name-list)" |
| is seen, call this function. It returns TRUE if the statement's context |
| is such that it may have "*", meaning alternate return, in place of |
| names in the name list (i.e. if the ENTRY is in a subroutine context). |
| It also returns TRUE if the ENTRY is not in a function context (invalid |
| but prevents extra complaints about "*", if present). It returns FALSE |
| if the ENTRY is in a function context. */ |
| |
| bool |
| ffestc_is_entry_in_subr () |
| { |
| ffestvState s; |
| |
| s = ffestw_state (ffestw_stack_top ()); |
| |
| recurse: |
| |
| switch (s) |
| { |
| case FFESTV_stateFUNCTION0: |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| case FFESTV_stateFUNCTION4: |
| return FALSE; |
| |
| case FFESTV_stateUSE: |
| s = ffestw_state (ffestw_previous (ffestw_stack_top ())); |
| goto recurse; /* :::::::::::::::::::: */ |
| |
| default: |
| return TRUE; |
| } |
| } |
| |
| /* ffestc_is_let_not_V027 -- Context information for FFESTB |
| |
| if (ffestc_is_let_not_V027()) ... |
| |
| When a statement with the form "PARAMETERname=expr" |
| is seen, call this function. It returns TRUE if the statement's context |
| is such that it is an assignment to an object named "PARAMETERname", FALSE |
| if the statement's context is such that it is a V-extension PARAMETER |
| statement that is like a PARAMETER(name=expr) statement except that the |
| type of name is determined by the type of expr, not the implicit or |
| explicit typing of name. */ |
| |
| bool |
| ffestc_is_let_not_V027 () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| case FFESTV_stateWHERETHEN: |
| case FFESTV_stateIFTHEN: |
| case FFESTV_stateDO: |
| case FFESTV_stateSELECT0: |
| case FFESTV_stateSELECT1: |
| case FFESTV_stateWHERE: |
| case FFESTV_stateIF: |
| return TRUE; |
| |
| default: |
| return FALSE; |
| } |
| } |
| |
| /* ffestc_module -- MODULE or MODULE PROCEDURE statement |
| |
| ffestc_module(module_name_token,procedure_name_token); |
| |
| Decide which is intended, and implement it by calling _R1105_ or |
| _R1205_. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_module (ffelexToken module, ffelexToken procedure) |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateINTERFACE0: |
| case FFESTV_stateINTERFACE1: |
| ffestc_R1205_start (); |
| ffestc_R1205_item (procedure); |
| ffestc_R1205_finish (); |
| break; |
| |
| default: |
| ffestc_R1105 (module); |
| break; |
| } |
| } |
| |
| #endif |
| /* ffestc_private -- Generic PRIVATE statement |
| |
| ffestc_end(); |
| |
| This is either a PRIVATE within R422 derived-type statement or an |
| R521 PRIVATE statement. Figure it out based on context and implement |
| it, or produce an error. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_private () |
| { |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateTYPE: |
| ffestc_R423A (); |
| break; |
| |
| default: |
| ffestc_R521B (); |
| break; |
| } |
| } |
| |
| #endif |
| /* ffestc_terminate_4 -- Terminate ffestc after scoping unit |
| |
| ffestc_terminate_4(); |
| |
| For SUBROUTINEs/FUNCTIONs within INTERFACE/END INTERFACE, derived-TYPE- |
| defs, and statement function defs. */ |
| |
| void |
| ffestc_terminate_4 () |
| { |
| ffestc_entry_num_ = ffestc_saved_entry_num_; |
| } |
| |
| /* ffestc_R423A -- PRIVATE statement (in R422 derived-type statement) |
| |
| ffestc_R423A(); */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R423A () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_type_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_DERIVTYP_ACCESS_FIRST); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| return; |
| } |
| |
| if (ffestw_state (ffestw_previous (ffestw_stack_top ())) != FFESTV_stateMODULE3) |
| { |
| ffebad_start (FFEBAD_DERIVTYP_ACCESS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| return; |
| } |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen |
| private-sequence-stmt. */ |
| |
| ffestd_R423A (); |
| } |
| |
| /* ffestc_R423B -- SEQUENCE statement (in R422 derived-type-stmt) |
| |
| ffestc_R423B(); */ |
| |
| void |
| ffestc_R423B () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_type_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_DERIVTYP_ACCESS_FIRST); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| return; |
| } |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen |
| private-sequence-stmt. */ |
| |
| ffestd_R423B (); |
| } |
| |
| /* ffestc_R424 -- derived-TYPE-def statement |
| |
| ffestc_R424(access_token,access_kw,name_token); |
| |
| Handle a derived-type definition. */ |
| |
| void |
| ffestc_R424 (ffelexToken access, ffestrOther access_kw, ffelexToken name) |
| { |
| ffestw b; |
| |
| assert (name != NULL); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_derivedtype_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if ((access != NULL) |
| && (ffestw_state (ffestw_stack_top ()) != FFESTV_stateMODULE3)) |
| { |
| ffebad_start (FFEBAD_DERIVTYP_ACCESS); |
| ffebad_here (0, ffelex_token_where_line (access), |
| ffelex_token_where_column (access)); |
| ffebad_finish (); |
| access = NULL; |
| } |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateTYPE); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_type_); |
| ffestw_set_name (b, ffelex_token_use (name)); |
| ffestw_set_substate (b, 0); /* Awaiting private-sequence-stmt and one |
| component-def-stmt. */ |
| |
| ffestd_R424 (access, access_kw, name); |
| |
| ffe_init_4 (); |
| } |
| |
| /* ffestc_R425 -- END TYPE statement |
| |
| ffestc_R425(name_token); |
| |
| Make sure ffestc_kind_ identifies a TYPE definition. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the type definition. */ |
| |
| void |
| ffestc_R425 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_type_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 2) |
| { |
| ffebad_start (FFEBAD_DERIVTYP_NO_COMPONENTS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| if ((name != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0)) |
| { |
| ffebad_start (FFEBAD_TYPE_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_type_ (TRUE); |
| } |
| |
| /* ffestc_R426_start -- component-declaration-stmt |
| |
| ffestc_R426_start(...); |
| |
| Verify that R426 component-declaration-stmt is |
| valid here and implement. */ |
| |
| void |
| ffestc_R426_start (ffestpType type, ffelexToken typet, ffebld kind, |
| ffelexToken kindt, ffebld len, ffelexToken lent) |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_component_ () != FFESTC_orderOK_) |
| { |
| ffestc_local_.decl.is_R426 = 0; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen at least one |
| member. */ |
| break; |
| |
| case FFESTV_stateTYPE: |
| ffestw_set_substate (ffestw_stack_top (), 2); |
| break; |
| |
| default: |
| assert ("Component parent state invalid" == NULL); |
| break; |
| } |
| } |
| |
| /* ffestc_R426_attrib -- type attribute |
| |
| ffestc_R426_attrib(...); |
| |
| Verify that R426 component-declaration-stmt attribute |
| is valid here and implement. */ |
| |
| void |
| ffestc_R426_attrib (ffestpAttrib attrib, ffelexToken attribt, |
| ffestrOther intent_kw, ffesttDimList dims) |
| { |
| ffestc_check_attrib_ (); |
| } |
| |
| /* ffestc_R426_item -- declared object |
| |
| ffestc_R426_item(...); |
| |
| Establish type for a particular object. */ |
| |
| void |
| ffestc_R426_item (ffelexToken name, ffebld kind, ffelexToken kindt, |
| ffesttDimList dims, ffebld len, ffelexToken lent, ffebld init, |
| ffelexToken initt, bool clist) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| assert (ffelex_token_type (name) == FFELEX_typeNAME); /* Not NAMES. */ |
| assert (kind == NULL); /* No way an expression should get here. */ |
| |
| if ((dims != NULL) || (init != NULL) || clist) |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| } |
| |
| /* ffestc_R426_itemstartvals -- Start list of values |
| |
| ffestc_R426_itemstartvals(); |
| |
| Gonna specify values for the object now. */ |
| |
| void |
| ffestc_R426_itemstartvals () |
| { |
| ffestc_check_item_startvals_ (); |
| } |
| |
| /* ffestc_R426_itemvalue -- Source value |
| |
| ffestc_R426_itemvalue(repeat,repeat_token,value,value_token); |
| |
| Make sure repeat and value are valid for the object being initialized. */ |
| |
| void |
| ffestc_R426_itemvalue (ffebld repeat, ffelexToken repeat_token, |
| ffebld value, ffelexToken value_token) |
| { |
| ffestc_check_item_value_ (); |
| } |
| |
| /* ffestc_R426_itemendvals -- End list of values |
| |
| ffelexToken t; // the SLASH token that ends the list. |
| ffestc_R426_itemendvals(t); |
| |
| No more values, might specify more objects now. */ |
| |
| void |
| ffestc_R426_itemendvals (ffelexToken t) |
| { |
| ffestc_check_item_endvals_ (); |
| } |
| |
| /* ffestc_R426_finish -- Done |
| |
| ffestc_R426_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R426_finish () |
| { |
| ffestc_check_finish_ (); |
| } |
| |
| #endif |
| /* ffestc_R501_start -- type-declaration-stmt |
| |
| ffestc_R501_start(...); |
| |
| Verify that R501 type-declaration-stmt is |
| valid here and implement. */ |
| |
| void |
| ffestc_R501_start (ffestpType type, ffelexToken typet, ffebld kind, |
| ffelexToken kindt, ffebld len, ffelexToken lent) |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_typedecl_ () != FFESTC_orderOK_) |
| { |
| ffestc_local_.decl.is_R426 = 0; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_establish_declstmt_ (type, typet, kind, kindt, len, lent); |
| } |
| |
| /* ffestc_R501_attrib -- type attribute |
| |
| ffestc_R501_attrib(...); |
| |
| Verify that R501 type-declaration-stmt attribute |
| is valid here and implement. */ |
| |
| void |
| ffestc_R501_attrib (ffestpAttrib attrib, ffelexToken attribt, |
| ffestrOther intent_kw UNUSED, |
| ffesttDimList dims UNUSED) |
| { |
| ffestc_check_attrib_ (); |
| |
| switch (attrib) |
| { |
| #if FFESTR_F90 |
| case FFESTP_attribALLOCATABLE: |
| break; |
| #endif |
| |
| case FFESTP_attribDIMENSION: |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| break; |
| |
| case FFESTP_attribEXTERNAL: |
| break; |
| |
| #if FFESTR_F90 |
| case FFESTP_attribINTENT: |
| break; |
| #endif |
| |
| case FFESTP_attribINTRINSIC: |
| break; |
| |
| #if FFESTR_F90 |
| case FFESTP_attribOPTIONAL: |
| break; |
| #endif |
| |
| case FFESTP_attribPARAMETER: |
| break; |
| |
| #if FFESTR_F90 |
| case FFESTP_attribPOINTER: |
| break; |
| #endif |
| |
| #if FFESTR_F90 |
| case FFESTP_attribPRIVATE: |
| break; |
| |
| case FFESTP_attribPUBLIC: |
| break; |
| #endif |
| |
| case FFESTP_attribSAVE: |
| switch (ffestv_save_state_) |
| { |
| case FFESTV_savestateNONE: |
| ffestv_save_state_ = FFESTV_savestateSPECIFIC; |
| ffestv_save_line_ |
| = ffewhere_line_use (ffelex_token_where_line (attribt)); |
| ffestv_save_col_ |
| = ffewhere_column_use (ffelex_token_where_column (attribt)); |
| break; |
| |
| case FFESTV_savestateSPECIFIC: |
| case FFESTV_savestateANY: |
| break; |
| |
| case FFESTV_savestateALL: |
| if (ffe_is_pedantic ()) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SAVES); |
| ffebad_here (0, ffestv_save_line_, ffestv_save_col_); |
| ffebad_here (1, ffelex_token_where_line (attribt), |
| ffelex_token_where_column (attribt)); |
| ffebad_finish (); |
| } |
| ffestv_save_state_ = FFESTV_savestateANY; |
| break; |
| |
| default: |
| assert ("unexpected save state" == NULL); |
| break; |
| } |
| break; |
| |
| #if FFESTR_F90 |
| case FFESTP_attribTARGET: |
| break; |
| #endif |
| |
| default: |
| assert ("unexpected attribute" == NULL); |
| break; |
| } |
| } |
| |
| /* ffestc_R501_item -- declared object |
| |
| ffestc_R501_item(...); |
| |
| Establish type for a particular object. */ |
| |
| void |
| ffestc_R501_item (ffelexToken name, ffebld kind, ffelexToken kindt, |
| ffesttDimList dims, ffebld len, ffelexToken lent, |
| ffebld init, ffelexToken initt, bool clist) |
| { |
| ffesymbol s; |
| ffesymbol sfn; /* FUNCTION symbol. */ |
| ffebld array_size; |
| ffebld extents; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffestpDimtype nd; |
| bool is_init = (init != NULL) || clist; |
| bool is_assumed; |
| bool is_ugly_assumed; |
| ffeinfoRank rank; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| assert (ffelex_token_type (name) == FFELEX_typeNAME); /* Not NAMES. */ |
| assert (kind == NULL); /* No way an expression should get here. */ |
| |
| ffestc_establish_declinfo_ (kind, kindt, len, lent); |
| |
| is_assumed = (ffestc_local_.decl.basic_type == FFEINFO_basictypeCHARACTER) |
| && (ffestc_local_.decl.size == FFETARGET_charactersizeNONE); |
| |
| if ((dims != NULL) || is_init) |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| s = ffesymbol_declare_local (name, TRUE); |
| sa = ffesymbol_attrs (s); |
| |
| /* First figure out what kind of object this is based solely on the current |
| object situation (type params, dimension list, and initialization). */ |
| |
| na = FFESYMBOL_attrsTYPE; |
| |
| if (is_assumed) |
| na |= FFESYMBOL_attrsANYLEN; |
| |
| is_ugly_assumed = (ffe_is_ugly_assumed () |
| && ((sa & FFESYMBOL_attrsDUMMY) |
| || (ffesymbol_where (s) == FFEINFO_whereDUMMY))); |
| |
| nd = ffestt_dimlist_type (dims, is_ugly_assumed); |
| switch (nd) |
| { |
| case FFESTP_dimtypeNONE: |
| break; |
| |
| case FFESTP_dimtypeKNOWN: |
| na |= FFESYMBOL_attrsARRAY; |
| break; |
| |
| case FFESTP_dimtypeADJUSTABLE: |
| na |= FFESYMBOL_attrsARRAY | FFESYMBOL_attrsADJUSTABLE; |
| break; |
| |
| case FFESTP_dimtypeASSUMED: |
| na |= FFESYMBOL_attrsARRAY | FFESYMBOL_attrsANYSIZE; |
| break; |
| |
| case FFESTP_dimtypeADJUSTABLEASSUMED: |
| na |= FFESYMBOL_attrsARRAY | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYSIZE; |
| break; |
| |
| default: |
| assert ("unexpected dimtype" == NULL); |
| na = FFESYMBOL_attrsetNONE; |
| break; |
| } |
| |
| if (!ffesta_is_entry_valid |
| && (((na & (FFESYMBOL_attrsANYLEN | FFESYMBOL_attrsARRAY)) |
| == (FFESYMBOL_attrsANYLEN | FFESYMBOL_attrsARRAY)))) |
| na = FFESYMBOL_attrsetNONE; |
| |
| if (is_init) |
| { |
| if (na == FFESYMBOL_attrsetNONE) |
| ; |
| else if (na & (FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYSIZE)) |
| na = FFESYMBOL_attrsetNONE; |
| else |
| na |= FFESYMBOL_attrsINIT; |
| } |
| |
| /* Now figure out what kind of object we've got based on previous |
| declarations of or references to the object. */ |
| |
| if (na == FFESYMBOL_attrsetNONE) |
| ; |
| else if (!ffesymbol_is_specable (s) |
| && (((ffesymbol_where (s) != FFEINFO_whereCONSTANT) |
| && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)) |
| || (na & (FFESYMBOL_attrsARRAY | FFESYMBOL_attrsINIT)))) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef, and can't |
| dimension/init UNDERSTOODs. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if ((sa & na) |
| || ((sa & (FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsADJUSTS)) |
| && (na & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsANYLEN))) |
| || ((sa & FFESYMBOL_attrsRESULT) |
| && (na & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsINIT))) |
| || ((sa & (FFESYMBOL_attrsSFUNC |
| | FFESYMBOL_attrsEXTERNAL |
| | FFESYMBOL_attrsINTRINSIC |
| | FFESYMBOL_attrsINIT)) |
| && (na & (FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsINIT))) |
| || ((sa & FFESYMBOL_attrsARRAY) |
| && !ffesta_is_entry_valid |
| && (na & FFESYMBOL_attrsANYLEN)) |
| || ((sa & (FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsANYSIZE |
| | FFESYMBOL_attrsDUMMY)) |
| && (na & FFESYMBOL_attrsINIT)) |
| || ((sa & (FFESYMBOL_attrsSAVE |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsEQUIV)) |
| && (na & (FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsANYSIZE)))) |
| na = FFESYMBOL_attrsetNONE; |
| else if ((ffesymbol_kind (s) == FFEINFO_kindENTITY) |
| && (ffesymbol_where (s) == FFEINFO_whereCONSTANT) |
| && (na & FFESYMBOL_attrsANYLEN)) |
| { /* If CHARACTER*(*) FOO after PARAMETER FOO. */ |
| na |= FFESYMBOL_attrsTYPE; |
| ffestc_local_.decl.size = ffebld_size (ffesymbol_init (s)); |
| } |
| else |
| na |= sa; |
| |
| /* 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, name); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else if (na & FFESYMBOL_attrsANY) |
| ffestc_parent_ok_ = FALSE; |
| else |
| { |
| ffesymbol_set_attrs (s, na); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| rank = ffesymbol_rank (s); |
| if (dims != NULL) |
| { |
| ffesymbol_set_dims (s, ffestt_dimlist_as_expr (dims, &rank, |
| &array_size, |
| &extents, |
| is_ugly_assumed)); |
| ffesymbol_set_arraysize (s, array_size); |
| ffesymbol_set_extents (s, extents); |
| if (!(0 && ffe_is_90 ()) |
| && (ffebld_op (array_size) == FFEBLD_opCONTER) |
| && (ffebld_constant_integerdefault (ffebld_conter (array_size)) |
| == 0)) |
| { |
| ffebad_start (FFEBAD_ZERO_ARRAY); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| } |
| if (init != NULL) |
| { |
| ffesymbol_set_init (s, |
| ffeexpr_convert (init, initt, name, |
| ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| rank, |
| ffestc_local_.decl.size, |
| FFEEXPR_contextDATA)); |
| ffecom_notify_init_symbol (s); |
| ffesymbol_update_init (s); |
| #if FFEGLOBAL_ENABLED |
| if (ffesymbol_common (s) != NULL) |
| ffeglobal_init_common (ffesymbol_common (s), initt); |
| #endif |
| } |
| else if (clist) |
| { |
| ffebld symter; |
| |
| symter = ffebld_new_symter (s, FFEINTRIN_genNONE, |
| FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| |
| ffebld_set_info (symter, |
| ffeinfo_new (ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| rank, |
| FFEINFO_kindNONE, |
| FFEINFO_whereNONE, |
| ffestc_local_.decl.size)); |
| ffestc_local_.decl.initlist = ffebld_new_item (symter, NULL); |
| } |
| if (ffesymbol_basictype (s) == FFEINFO_basictypeNONE) |
| { |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| rank, |
| ffesymbol_kind (s), |
| ffesymbol_where (s), |
| ffestc_local_.decl.size)); |
| if ((na & FFESYMBOL_attrsRESULT) |
| && ((sfn = ffesymbol_funcresult (s)) != NULL)) |
| { |
| ffesymbol_set_info (sfn, |
| ffeinfo_new (ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| rank, |
| ffesymbol_kind (sfn), |
| ffesymbol_where (sfn), |
| ffestc_local_.decl.size)); |
| ffesymbol_signal_unreported (sfn); |
| } |
| } |
| else if ((ffestc_local_.decl.basic_type != ffesymbol_basictype (s)) |
| || (ffestc_local_.decl.kind_type != ffesymbol_kindtype (s)) |
| || ((ffestc_local_.decl.basic_type |
| == FFEINFO_basictypeCHARACTER) |
| && (ffestc_local_.decl.size != ffesymbol_size (s)))) |
| { /* Explicit type disagrees with established |
| implicit type. */ |
| ffesymbol_error (s, name); |
| } |
| |
| if ((na & FFESYMBOL_attrsADJUSTS) |
| && ((ffestc_local_.decl.basic_type != FFEINFO_basictypeINTEGER) |
| || (ffestc_local_.decl.kind_type != FFEINFO_kindtypeINTEGER1))) |
| ffesymbol_error (s, name); |
| |
| ffesymbol_signal_unreported (s); |
| ffestc_parent_ok_ = TRUE; |
| } |
| } |
| |
| /* ffestc_R501_itemstartvals -- Start list of values |
| |
| ffestc_R501_itemstartvals(); |
| |
| Gonna specify values for the object now. */ |
| |
| void |
| ffestc_R501_itemstartvals () |
| { |
| ffestc_check_item_startvals_ (); |
| |
| if (ffestc_parent_ok_) |
| ffedata_begin (ffestc_local_.decl.initlist); |
| } |
| |
| /* ffestc_R501_itemvalue -- Source value |
| |
| ffestc_R501_itemvalue(repeat,repeat_token,value,value_token); |
| |
| Make sure repeat and value are valid for the object being initialized. */ |
| |
| void |
| ffestc_R501_itemvalue (ffebld repeat, ffelexToken repeat_token, |
| ffebld value, ffelexToken value_token) |
| { |
| ffetargetIntegerDefault rpt; |
| |
| ffestc_check_item_value_ (); |
| |
| if (!ffestc_parent_ok_) |
| return; |
| |
| if (repeat == NULL) |
| rpt = 1; |
| else if (ffebld_op (repeat) == FFEBLD_opCONTER) |
| rpt = ffebld_constant_integerdefault (ffebld_conter (repeat)); |
| else |
| { |
| ffestc_parent_ok_ = FALSE; |
| ffedata_end (TRUE, NULL); |
| return; |
| } |
| |
| if (!(ffestc_parent_ok_ = ffedata_value (rpt, value, |
| (repeat_token == NULL) ? value_token : repeat_token))) |
| ffedata_end (TRUE, NULL); |
| } |
| |
| /* ffestc_R501_itemendvals -- End list of values |
| |
| ffelexToken t; // the SLASH token that ends the list. |
| ffestc_R501_itemendvals(t); |
| |
| No more values, might specify more objects now. */ |
| |
| void |
| ffestc_R501_itemendvals (ffelexToken t) |
| { |
| ffestc_check_item_endvals_ (); |
| |
| if (ffestc_parent_ok_) |
| ffestc_parent_ok_ = ffedata_end (FALSE, t); |
| |
| if (ffestc_parent_ok_) |
| ffesymbol_signal_unreported (ffebld_symter (ffebld_head |
| (ffestc_local_.decl.initlist))); |
| } |
| |
| /* ffestc_R501_finish -- Done |
| |
| ffestc_R501_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R501_finish () |
| { |
| ffestc_check_finish_ (); |
| } |
| |
| /* ffestc_R519_start -- INTENT statement list begin |
| |
| ffestc_R519_start(); |
| |
| Verify that INTENT is valid here, and begin accepting items in the list. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R519_start (ffelexToken intent, ffestrOther intent_kw) |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_spec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R519_start (intent_kw); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R519_item -- INTENT statement for name |
| |
| ffestc_R519_item(name_token); |
| |
| Make sure name_token identifies a valid object to be INTENTed. */ |
| |
| void |
| ffestc_R519_item (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R519_item (name); |
| } |
| |
| /* ffestc_R519_finish -- INTENT statement list complete |
| |
| ffestc_R519_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R519_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R519_finish (); |
| } |
| |
| /* ffestc_R520_start -- OPTIONAL statement list begin |
| |
| ffestc_R520_start(); |
| |
| Verify that OPTIONAL is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R520_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_spec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R520_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R520_item -- OPTIONAL statement for name |
| |
| ffestc_R520_item(name_token); |
| |
| Make sure name_token identifies a valid object to be OPTIONALed. */ |
| |
| void |
| ffestc_R520_item (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R520_item (name); |
| } |
| |
| /* ffestc_R520_finish -- OPTIONAL statement list complete |
| |
| ffestc_R520_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R520_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R520_finish (); |
| } |
| |
| /* ffestc_R521A -- PUBLIC statement |
| |
| ffestc_R521A(); |
| |
| Verify that PUBLIC is valid here. */ |
| |
| void |
| ffestc_R521A () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_access_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestv_access_state_) |
| { |
| case FFESTV_accessstateNONE: |
| ffestv_access_state_ = FFESTV_accessstatePUBLIC; |
| ffestv_access_line_ |
| = ffewhere_line_use (ffelex_token_where_line (ffesta_tokens[0])); |
| ffestv_access_col_ |
| = ffewhere_column_use (ffelex_token_where_column (ffesta_tokens[0])); |
| break; |
| |
| case FFESTV_accessstateANY: |
| break; |
| |
| case FFESTV_accessstatePUBLIC: |
| case FFESTV_accessstatePRIVATE: |
| ffebad_start (FFEBAD_CONFLICTING_ACCESSES); |
| ffebad_here (0, ffestv_access_line_, ffestv_access_col_); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| ffestv_access_state_ = FFESTV_accessstateANY; |
| break; |
| |
| default: |
| assert ("unexpected access state" == NULL); |
| break; |
| } |
| |
| ffestd_R521A (); |
| } |
| |
| /* ffestc_R521Astart -- PUBLIC statement list begin |
| |
| ffestc_R521Astart(); |
| |
| Verify that PUBLIC is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R521Astart () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_access_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R521Astart (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R521Aitem -- PUBLIC statement for name |
| |
| ffestc_R521Aitem(name_token); |
| |
| Make sure name_token identifies a valid object to be PUBLICed. */ |
| |
| void |
| ffestc_R521Aitem (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R521Aitem (name); |
| } |
| |
| /* ffestc_R521Afinish -- PUBLIC statement list complete |
| |
| ffestc_R521Afinish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R521Afinish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R521Afinish (); |
| } |
| |
| /* ffestc_R521B -- PRIVATE statement |
| |
| ffestc_R521B(); |
| |
| Verify that PRIVATE is valid here (outside a derived-type statement). */ |
| |
| void |
| ffestc_R521B () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_access_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestv_access_state_) |
| { |
| case FFESTV_accessstateNONE: |
| ffestv_access_state_ = FFESTV_accessstatePRIVATE; |
| ffestv_access_line_ |
| = ffewhere_line_use (ffelex_token_where_line (ffesta_tokens[0])); |
| ffestv_access_col_ |
| = ffewhere_column_use (ffelex_token_where_column (ffesta_tokens[0])); |
| break; |
| |
| case FFESTV_accessstateANY: |
| break; |
| |
| case FFESTV_accessstatePUBLIC: |
| case FFESTV_accessstatePRIVATE: |
| ffebad_start (FFEBAD_CONFLICTING_ACCESSES); |
| ffebad_here (0, ffestv_access_line_, ffestv_access_col_); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| ffestv_access_state_ = FFESTV_accessstateANY; |
| break; |
| |
| default: |
| assert ("unexpected access state" == NULL); |
| break; |
| } |
| |
| ffestd_R521B (); |
| } |
| |
| /* ffestc_R521Bstart -- PRIVATE statement list begin |
| |
| ffestc_R521Bstart(); |
| |
| Verify that PRIVATE is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R521Bstart () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_access_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R521Bstart (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R521Bitem -- PRIVATE statement for name |
| |
| ffestc_R521Bitem(name_token); |
| |
| Make sure name_token identifies a valid object to be PRIVATEed. */ |
| |
| void |
| ffestc_R521Bitem (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R521Bitem (name); |
| } |
| |
| /* ffestc_R521Bfinish -- PRIVATE statement list complete |
| |
| ffestc_R521Bfinish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R521Bfinish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R521Bfinish (); |
| } |
| |
| #endif |
| /* ffestc_R522 -- SAVE statement with no list |
| |
| ffestc_R522(); |
| |
| Verify that SAVE is valid here, and flag everything as SAVEd. */ |
| |
| void |
| ffestc_R522 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_blockspec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestv_save_state_) |
| { |
| case FFESTV_savestateNONE: |
| ffestv_save_state_ = FFESTV_savestateALL; |
| ffestv_save_line_ |
| = ffewhere_line_use (ffelex_token_where_line (ffesta_tokens[0])); |
| ffestv_save_col_ |
| = ffewhere_column_use (ffelex_token_where_column (ffesta_tokens[0])); |
| break; |
| |
| case FFESTV_savestateANY: |
| break; |
| |
| case FFESTV_savestateSPECIFIC: |
| case FFESTV_savestateALL: |
| if (ffe_is_pedantic ()) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SAVES); |
| ffebad_here (0, ffestv_save_line_, ffestv_save_col_); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| } |
| ffestv_save_state_ = FFESTV_savestateALL; |
| break; |
| |
| default: |
| assert ("unexpected save state" == NULL); |
| break; |
| } |
| |
| ffe_set_is_saveall (TRUE); |
| |
| ffestd_R522 (); |
| } |
| |
| /* ffestc_R522start -- SAVE statement list begin |
| |
| ffestc_R522start(); |
| |
| Verify that SAVE is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R522start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_blockspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestv_save_state_) |
| { |
| case FFESTV_savestateNONE: |
| ffestv_save_state_ = FFESTV_savestateSPECIFIC; |
| ffestv_save_line_ |
| = ffewhere_line_use (ffelex_token_where_line (ffesta_tokens[0])); |
| ffestv_save_col_ |
| = ffewhere_column_use (ffelex_token_where_column (ffesta_tokens[0])); |
| break; |
| |
| case FFESTV_savestateSPECIFIC: |
| case FFESTV_savestateANY: |
| break; |
| |
| case FFESTV_savestateALL: |
| if (ffe_is_pedantic ()) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SAVES); |
| ffebad_here (0, ffestv_save_line_, ffestv_save_col_); |
| ffebad_here (1, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| } |
| ffestv_save_state_ = FFESTV_savestateANY; |
| break; |
| |
| default: |
| assert ("unexpected save state" == NULL); |
| break; |
| } |
| |
| ffestd_R522start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R522item_object -- SAVE statement for object-name |
| |
| ffestc_R522item_object(name_token); |
| |
| Make sure name_token identifies a valid object to be SAVEd. */ |
| |
| void |
| ffestc_R522item_object (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s) |
| && ((ffesymbol_kind (s) != FFEINFO_kindENTITY) |
| || (ffesymbol_where (s) != FFEINFO_whereLOCAL))) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if (!(sa & ~(FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsSAVE; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_update_save (s); |
| ffesymbol_signal_unreported (s); |
| } |
| |
| ffestd_R522item_object (name); |
| } |
| |
| /* ffestc_R522item_cblock -- SAVE statement for common-block-name |
| |
| ffestc_R522item_cblock(name_token); |
| |
| Make sure name_token identifies a valid common block to be SAVEd. */ |
| |
| void |
| ffestc_R522item_cblock (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| s = ffesymbol_declare_cblock (name, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; |
| else if (sa & FFESYMBOL_attrsANY) |
| na = sa; /* Already have an error here, say nothing. */ |
| else if (!(sa & ~(FFESYMBOL_attrsCBLOCK))) |
| na = sa | FFESYMBOL_attrsSAVECBLOCK; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, (name == NULL) ? ffesta_tokens[0] : name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_update_save (s); |
| ffesymbol_signal_unreported (s); |
| } |
| |
| ffestd_R522item_cblock (name); |
| } |
| |
| /* ffestc_R522finish -- SAVE statement list complete |
| |
| ffestc_R522finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R522finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R522finish (); |
| } |
| |
| /* ffestc_R524_start -- DIMENSION statement list begin |
| |
| ffestc_R524_start(bool virtual); |
| |
| Verify that DIMENSION is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R524_start (bool virtual) |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_blockspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R524_start (virtual); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R524_item -- DIMENSION statement for object-name |
| |
| ffestc_R524_item(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be DIMENSIONd. */ |
| |
| void |
| ffestc_R524_item (ffelexToken name, ffesttDimList dims) |
| { |
| ffesymbol s; |
| ffebld array_size; |
| ffebld extents; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffestpDimtype nd; |
| ffeinfoRank rank; |
| bool is_ugly_assumed; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| assert (dims != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* First figure out what kind of object this is based solely on the current |
| object situation (dimension list). */ |
| |
| is_ugly_assumed = (ffe_is_ugly_assumed () |
| && ((sa & FFESYMBOL_attrsDUMMY) |
| || (ffesymbol_where (s) == FFEINFO_whereDUMMY))); |
| |
| nd = ffestt_dimlist_type (dims, is_ugly_assumed); |
| switch (nd) |
| { |
| case FFESTP_dimtypeKNOWN: |
| na = FFESYMBOL_attrsARRAY; |
| break; |
| |
| case FFESTP_dimtypeADJUSTABLE: |
| na = FFESYMBOL_attrsARRAY | FFESYMBOL_attrsADJUSTABLE; |
| break; |
| |
| case FFESTP_dimtypeASSUMED: |
| na = FFESYMBOL_attrsARRAY | FFESYMBOL_attrsANYSIZE; |
| break; |
| |
| case FFESTP_dimtypeADJUSTABLEASSUMED: |
| na = FFESYMBOL_attrsARRAY | FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYSIZE; |
| break; |
| |
| default: |
| assert ("Unexpected dims type" == NULL); |
| na = FFESYMBOL_attrsetNONE; |
| break; |
| } |
| |
| /* Now figure out what kind of object we've got based on previous |
| declarations of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (!ffesta_is_entry_valid |
| && (sa & FFESYMBOL_attrsANYLEN)) |
| na = FFESYMBOL_attrsetNONE; |
| else if ((sa & FFESYMBOL_attrsARRAY) |
| || ((sa & (FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSAVE)) |
| && (na & (FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYSIZE)))) |
| na = FFESYMBOL_attrsetNONE; |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTABLE |
| | FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsANYSIZE |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSAVE |
| | FFESYMBOL_attrsTYPE))) |
| na |= sa; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_dims (s, ffestt_dimlist_as_expr (dims, &rank, |
| &array_size, |
| &extents, |
| is_ugly_assumed)); |
| ffesymbol_set_arraysize (s, array_size); |
| ffesymbol_set_extents (s, extents); |
| if (!(0 && ffe_is_90 ()) |
| && (ffebld_op (array_size) == FFEBLD_opCONTER) |
| && (ffebld_constant_integerdefault (ffebld_conter (array_size)) |
| == 0)) |
| { |
| ffebad_start (FFEBAD_ZERO_ARRAY); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| rank, |
| ffesymbol_kind (s), |
| ffesymbol_where (s), |
| ffesymbol_size (s))); |
| } |
| |
| ffesymbol_signal_unreported (s); |
| |
| ffestd_R524_item (name, dims); |
| } |
| |
| /* ffestc_R524_finish -- DIMENSION statement list complete |
| |
| ffestc_R524_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R524_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R524_finish (); |
| } |
| |
| /* ffestc_R525_start -- ALLOCATABLE statement list begin |
| |
| ffestc_R525_start(); |
| |
| Verify that ALLOCATABLE is valid here, and begin accepting items in the |
| list. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R525_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R525_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R525_item -- ALLOCATABLE statement for object-name |
| |
| ffestc_R525_item(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be ALLOCATABLEd. */ |
| |
| void |
| ffestc_R525_item (ffelexToken name, ffesttDimList dims) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_R525_item (name, dims); |
| } |
| |
| /* ffestc_R525_finish -- ALLOCATABLE statement list complete |
| |
| ffestc_R525_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R525_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R525_finish (); |
| } |
| |
| /* ffestc_R526_start -- POINTER statement list begin |
| |
| ffestc_R526_start(); |
| |
| Verify that POINTER is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R526_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R526_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R526_item -- POINTER statement for object-name |
| |
| ffestc_R526_item(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be POINTERd. */ |
| |
| void |
| ffestc_R526_item (ffelexToken name, ffesttDimList dims) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_R526_item (name, dims); |
| } |
| |
| /* ffestc_R526_finish -- POINTER statement list complete |
| |
| ffestc_R526_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R526_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R526_finish (); |
| } |
| |
| /* ffestc_R527_start -- TARGET statement list begin |
| |
| ffestc_R527_start(); |
| |
| Verify that TARGET is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R527_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R527_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R527_item -- TARGET statement for object-name |
| |
| ffestc_R527_item(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be TARGETd. */ |
| |
| void |
| ffestc_R527_item (ffelexToken name, ffesttDimList dims) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_R527_item (name, dims); |
| } |
| |
| /* ffestc_R527_finish -- TARGET statement list complete |
| |
| ffestc_R527_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R527_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R527_finish (); |
| } |
| |
| #endif |
| /* ffestc_R528_start -- DATA statement list begin |
| |
| ffestc_R528_start(); |
| |
| Verify that DATA is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R528_start () |
| { |
| ffestcOrder_ order; |
| |
| ffestc_check_start_ (); |
| if (ffe_is_pedantic_not_90 ()) |
| order = ffestc_order_data77_ (); |
| else |
| order = ffestc_order_data_ (); |
| if (order != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| #if 1 |
| ffestc_local_.data.objlist = NULL; |
| #else |
| ffestd_R528_start_ (); |
| #endif |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R528_item_object -- DATA statement target object |
| |
| ffestc_R528_item_object(object,object_token); |
| |
| Make sure object is valid to be DATAd. */ |
| |
| void |
| ffestc_R528_item_object (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| #if 1 |
| if (ffestc_local_.data.objlist == NULL) |
| ffebld_init_list (&ffestc_local_.data.objlist, |
| &ffestc_local_.data.list_bottom); |
| |
| ffebld_append_item (&ffestc_local_.data.list_bottom, expr); |
| #else |
| ffestd_R528_item_object_ (expr, expr_token); |
| #endif |
| } |
| |
| /* ffestc_R528_item_startvals -- DATA statement start list of values |
| |
| ffestc_R528_item_startvals(); |
| |
| No more objects, gonna specify values for the list of objects now. */ |
| |
| void |
| ffestc_R528_item_startvals () |
| { |
| ffestc_check_item_startvals_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| #if 1 |
| assert (ffestc_local_.data.objlist != NULL); |
| ffebld_end_list (&ffestc_local_.data.list_bottom); |
| ffedata_begin (ffestc_local_.data.objlist); |
| #else |
| ffestd_R528_item_startvals_ (); |
| #endif |
| } |
| |
| /* ffestc_R528_item_value -- DATA statement source value |
| |
| ffestc_R528_item_value(repeat,repeat_token,value,value_token); |
| |
| Make sure repeat and value are valid for the objects being initialized. */ |
| |
| void |
| ffestc_R528_item_value (ffebld repeat, ffelexToken repeat_token, |
| ffebld value, ffelexToken value_token) |
| { |
| ffetargetIntegerDefault rpt; |
| |
| ffestc_check_item_value_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| #if 1 |
| if (repeat == NULL) |
| rpt = 1; |
| else if (ffebld_op (repeat) == FFEBLD_opCONTER) |
| rpt = ffebld_constant_integerdefault (ffebld_conter (repeat)); |
| else |
| { |
| ffestc_ok_ = FALSE; |
| ffedata_end (TRUE, NULL); |
| return; |
| } |
| |
| if (!(ffestc_ok_ = ffedata_value (rpt, value, |
| (repeat_token == NULL) |
| ? value_token |
| : repeat_token))) |
| ffedata_end (TRUE, NULL); |
| |
| #else |
| ffestd_R528_item_value_ (repeat, value); |
| #endif |
| } |
| |
| /* ffestc_R528_item_endvals -- DATA statement start list of values |
| |
| ffelexToken t; // the SLASH token that ends the list. |
| ffestc_R528_item_endvals(t); |
| |
| No more values, might specify more objects now. */ |
| |
| void |
| ffestc_R528_item_endvals (ffelexToken t) |
| { |
| ffestc_check_item_endvals_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| #if 1 |
| ffedata_end (!ffestc_ok_, t); |
| ffestc_local_.data.objlist = NULL; |
| #else |
| ffestd_R528_item_endvals_ (t); |
| #endif |
| } |
| |
| /* ffestc_R528_finish -- DATA statement list complete |
| |
| ffestc_R528_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R528_finish () |
| { |
| ffestc_check_finish_ (); |
| |
| #if 1 |
| #else |
| ffestd_R528_finish_ (); |
| #endif |
| } |
| |
| /* ffestc_R537_start -- PARAMETER statement list begin |
| |
| ffestc_R537_start(); |
| |
| Verify that PARAMETER is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R537_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_parameter_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_R537_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R537_item -- PARAMETER statement assignment |
| |
| ffestc_R537_item(dest,dest_token,source,source_token); |
| |
| Make sure the source is a valid source for the destination; make the |
| assignment. */ |
| |
| void |
| ffestc_R537_item (ffebld dest, ffelexToken dest_token, ffebld source, |
| ffelexToken source_token) |
| { |
| ffesymbol s; |
| |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if ((ffebld_op (dest) == FFEBLD_opANY) |
| || (ffebld_op (source) == FFEBLD_opANY)) |
| { |
| if (ffebld_op (dest) == FFEBLD_opSYMTER) |
| { |
| s = ffebld_symter (dest); |
| ffesymbol_set_init (s, ffebld_new_any ()); |
| ffebld_set_info (ffesymbol_init (s), ffeinfo_new_any ()); |
| ffesymbol_signal_unreported (s); |
| } |
| ffestd_R537_item (dest, source); |
| return; |
| } |
| |
| assert (ffebld_op (dest) == FFEBLD_opSYMTER); |
| assert (ffebld_op (source) == FFEBLD_opCONTER); |
| |
| s = ffebld_symter (dest); |
| if ((ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER) |
| && (ffesymbol_size (s) == FFETARGET_charactersizeNONE)) |
| { /* Destination has explicit/implicit |
| CHARACTER*(*) type; set length. */ |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| ffesymbol_kind (s), |
| ffesymbol_where (s), |
| ffebld_size (source))); |
| ffebld_set_info (dest, ffeinfo_use (ffesymbol_info (s))); |
| } |
| |
| source = ffeexpr_convert_expr (source, source_token, dest, dest_token, |
| FFEEXPR_contextDATA); |
| |
| ffesymbol_set_init (s, source); |
| |
| ffesymbol_signal_unreported (s); |
| |
| ffestd_R537_item (dest, source); |
| } |
| |
| /* ffestc_R537_finish -- PARAMETER statement list complete |
| |
| ffestc_R537_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R537_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R537_finish (); |
| } |
| |
| /* ffestc_R539 -- IMPLICIT NONE statement |
| |
| ffestc_R539(); |
| |
| Verify that the IMPLICIT NONE statement is ok here and implement. */ |
| |
| void |
| ffestc_R539 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_implicitnone_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffeimplic_none (); |
| |
| ffestd_R539 (); |
| } |
| |
| /* ffestc_R539start -- IMPLICIT statement |
| |
| ffestc_R539start(); |
| |
| Verify that the IMPLICIT statement is ok here and implement. */ |
| |
| void |
| ffestc_R539start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_implicit_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R539start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R539item -- IMPLICIT statement specification (R540) |
| |
| ffestc_R539item(...); |
| |
| Verify that the type and letter list are all ok and implement. */ |
| |
| void |
| ffestc_R539item (ffestpType type, ffebld kind, ffelexToken kindt, |
| ffebld len, ffelexToken lent, ffesttImpList letters) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if ((type == FFESTP_typeCHARACTER) && (len != NULL) |
| && (ffebld_op (len) == FFEBLD_opSTAR)) |
| { /* Complain and pretend they're CHARACTER |
| [*1]. */ |
| ffebad_start (FFEBAD_IMPLICIT_ADJLEN); |
| ffebad_here (0, ffelex_token_where_line (lent), |
| ffelex_token_where_column (lent)); |
| ffebad_finish (); |
| len = NULL; |
| lent = NULL; |
| } |
| ffestc_establish_declstmt_ (type, ffesta_tokens[0], kind, kindt, len, lent); |
| ffestc_establish_declinfo_ (NULL, NULL, NULL, NULL); |
| |
| ffestt_implist_drive (letters, ffestc_establish_impletter_); |
| |
| ffestd_R539item (type, kind, kindt, len, lent, letters); |
| } |
| |
| /* ffestc_R539finish -- IMPLICIT statement |
| |
| ffestc_R539finish(); |
| |
| Finish up any local activities. */ |
| |
| void |
| ffestc_R539finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R539finish (); |
| } |
| |
| /* ffestc_R542_start -- NAMELIST statement list begin |
| |
| ffestc_R542_start(); |
| |
| Verify that NAMELIST is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R542_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| if (ffe_is_f2c_library () |
| && (ffe_case_source () == FFE_caseNONE)) |
| { |
| ffebad_start (FFEBAD_NAMELIST_CASE); |
| ffesta_ffebad_here_current_stmt (0); |
| ffebad_finish (); |
| } |
| |
| ffestd_R542_start (); |
| |
| ffestc_local_.namelist.symbol = NULL; |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R542_item_nlist -- NAMELIST statement for group-name |
| |
| ffestc_R542_item_nlist(groupname_token); |
| |
| Make sure name_token identifies a valid object to be NAMELISTd. */ |
| |
| void |
| ffestc_R542_item_nlist (ffelexToken name) |
| { |
| ffesymbol s; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_local_.namelist.symbol != NULL) |
| ffesymbol_signal_unreported (ffestc_local_.namelist.symbol); |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| |
| if ((ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| || ((ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| && (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))) |
| { |
| ffestc_parent_ok_ = TRUE; |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffebld_init_list (ffesymbol_ptr_to_namelist (s), |
| ffesymbol_ptr_to_listbottom (s)); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindNAMELIST, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| } |
| } |
| else |
| { |
| if (ffesymbol_kind (s) != FFEINFO_kindANY) |
| ffesymbol_error (s, name); |
| ffestc_parent_ok_ = FALSE; |
| } |
| |
| ffestc_local_.namelist.symbol = s; |
| |
| ffestd_R542_item_nlist (name); |
| } |
| |
| /* ffestc_R542_item_nitem -- NAMELIST statement for variable-name |
| |
| ffestc_R542_item_nitem(name_token); |
| |
| Make sure name_token identifies a valid object to be NAMELISTd. */ |
| |
| void |
| ffestc_R542_item_nitem (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffebld e; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s) |
| && ((ffesymbol_kind (s) != FFEINFO_kindENTITY) |
| || ((ffesymbol_where (s) != FFEINFO_whereLOCAL) |
| && (ffesymbol_where (s) != FFEINFO_whereCOMMON)))) |
| na = FFESYMBOL_attrsetNONE; |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsCOMMON |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSAVE |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsNAMELIST; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_namelisted (s, TRUE); |
| ffesymbol_signal_unreported (s); |
| #if 0 /* No need to establish type yet! */ |
| if (!ffeimplic_establish_symbol (s)) |
| ffesymbol_error (s, name); |
| #endif |
| } |
| |
| if (ffestc_parent_ok_) |
| { |
| e = ffebld_new_symter (s, FFEINTRIN_genNONE, FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| ffebld_set_info (e, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, 0, |
| FFEINFO_kindNONE, |
| FFEINFO_whereNONE, |
| FFETARGET_charactersizeNONE)); |
| ffebld_append_item |
| (ffesymbol_ptr_to_listbottom (ffestc_local_.namelist.symbol), e); |
| } |
| |
| ffestd_R542_item_nitem (name); |
| } |
| |
| /* ffestc_R542_finish -- NAMELIST statement list complete |
| |
| ffestc_R542_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R542_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffesymbol_signal_unreported (ffestc_local_.namelist.symbol); |
| |
| ffestd_R542_finish (); |
| } |
| |
| /* ffestc_R544_start -- EQUIVALENCE statement list begin |
| |
| ffestc_R544_start(); |
| |
| Verify that EQUIVALENCE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R544_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_blockspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R544_item -- EQUIVALENCE statement assignment |
| |
| ffestc_R544_item(exprlist); |
| |
| Make sure the equivalence is valid, then implement it. */ |
| |
| void |
| ffestc_R544_item (ffesttExprList exprlist) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| /* First we go through the list and come up with one ffeequiv object that |
| will describe all items in the list. When an ffeequiv object is first |
| found, it is used (else we create one as a "local equiv" for the time |
| being). If subsequent ffeequiv objects are found, they are merged with |
| the first so we end up with one. However, if more than one COMMON |
| variable is involved, then an error condition occurs. */ |
| |
| ffestc_local_.equiv.ok = TRUE; |
| ffestc_local_.equiv.t = NULL; /* No token yet. */ |
| ffestc_local_.equiv.eq = NULL;/* No equiv yet. */ |
| ffestc_local_.equiv.save = FALSE; /* No SAVEd variables yet. */ |
| |
| ffebld_init_list (&ffestc_local_.equiv.list, &ffestc_local_.equiv.bottom); |
| ffestt_exprlist_drive (exprlist, ffestc_R544_equiv_); /* Get one equiv. */ |
| ffebld_end_list (&ffestc_local_.equiv.bottom); |
| |
| if (!ffestc_local_.equiv.ok) |
| return; /* Something went wrong, stop bothering with |
| this stuff. */ |
| |
| if (ffestc_local_.equiv.eq == NULL) |
| ffestc_local_.equiv.eq = ffeequiv_new (); /* Make local equivalence. */ |
| |
| /* Append this list of equivalences to list of such lists for this |
| equivalence. */ |
| |
| ffeequiv_add (ffestc_local_.equiv.eq, ffestc_local_.equiv.list, |
| ffestc_local_.equiv.t); |
| if (ffestc_local_.equiv.save) |
| ffeequiv_update_save (ffestc_local_.equiv.eq); |
| } |
| |
| /* ffestc_R544_equiv_ -- EQUIVALENCE statement handler for item in list |
| |
| ffebld expr; |
| ffelexToken t; |
| ffestc_R544_equiv_(expr,t); |
| |
| Record information, if any, on symbol in expr; if symbol has equivalence |
| object already, merge with outstanding object if present or make it |
| the outstanding object. */ |
| |
| static void |
| ffestc_R544_equiv_ (ffebld expr, ffelexToken t) |
| { |
| ffesymbol s; |
| |
| if (!ffestc_local_.equiv.ok) |
| return; |
| |
| if (ffestc_local_.equiv.t == NULL) |
| ffestc_local_.equiv.t = t; |
| |
| switch (ffebld_op (expr)) |
| { |
| case FFEBLD_opANY: |
| return; /* Don't put this on the list. */ |
| |
| case FFEBLD_opSYMTER: |
| case FFEBLD_opARRAYREF: |
| case FFEBLD_opSUBSTR: |
| break; /* All of these are ok. */ |
| |
| default: |
| assert ("ffestc_R544_equiv_ bad op" == NULL); |
| return; |
| } |
| |
| ffebld_append_item (&ffestc_local_.equiv.bottom, expr); |
| |
| s = ffeequiv_symbol (expr); |
| |
| /* See if symbol has an equivalence object already. */ |
| |
| if (ffesymbol_equiv (s) != NULL) |
| { |
| if (ffestc_local_.equiv.eq == NULL) |
| ffestc_local_.equiv.eq = ffesymbol_equiv (s); /* New equiv obj. */ |
| else if (ffestc_local_.equiv.eq != ffesymbol_equiv (s)) |
| { |
| ffestc_local_.equiv.eq = ffeequiv_merge (ffesymbol_equiv (s), |
| ffestc_local_.equiv.eq, |
| t); |
| if (ffestc_local_.equiv.eq == NULL) |
| ffestc_local_.equiv.ok = FALSE; /* Couldn't merge. */ |
| } |
| } |
| |
| if (ffesymbol_is_save (s)) |
| ffestc_local_.equiv.save = TRUE; |
| } |
| |
| /* ffestc_R544_finish -- EQUIVALENCE statement list complete |
| |
| ffestc_R544_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R544_finish () |
| { |
| ffestc_check_finish_ (); |
| } |
| |
| /* ffestc_R547_start -- COMMON statement list begin |
| |
| ffestc_R547_start(); |
| |
| Verify that COMMON is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R547_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_blockspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_local_.common.symbol = NULL; /* Blank common is the default. */ |
| ffestc_parent_ok_ = TRUE; |
| |
| ffestd_R547_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R547_item_object -- COMMON statement for object-name |
| |
| ffestc_R547_item_object(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be COMMONd. */ |
| |
| void |
| ffestc_R547_item_object (ffelexToken name, ffesttDimList dims) |
| { |
| ffesymbol s; |
| ffebld array_size; |
| ffebld extents; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffestpDimtype nd; |
| ffebld e; |
| ffeinfoRank rank; |
| bool is_ugly_assumed; |
| |
| if (ffestc_parent_ok_ && (ffestc_local_.common.symbol == NULL)) |
| ffestc_R547_item_cblock (NULL); /* As if "COMMON [//] ...". */ |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| if (dims != NULL) |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* First figure out what kind of object this is based solely on the current |
| object situation (dimension list). */ |
| |
| is_ugly_assumed = (ffe_is_ugly_assumed () |
| && ((sa & FFESYMBOL_attrsDUMMY) |
| || (ffesymbol_where (s) == FFEINFO_whereDUMMY))); |
| |
| nd = ffestt_dimlist_type (dims, is_ugly_assumed); |
| switch (nd) |
| { |
| case FFESTP_dimtypeNONE: |
| na = FFESYMBOL_attrsCOMMON; |
| break; |
| |
| case FFESTP_dimtypeKNOWN: |
| na = FFESYMBOL_attrsCOMMON | FFESYMBOL_attrsARRAY; |
| break; |
| |
| default: |
| na = FFESYMBOL_attrsetNONE; |
| break; |
| } |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (na == FFESYMBOL_attrsetNONE) |
| ; |
| else if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if ((sa & (FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsSFARG)) |
| && (na & FFESYMBOL_attrsARRAY)) |
| na = FFESYMBOL_attrsetNONE; |
| else if (!(sa & ~(FFESYMBOL_attrsADJUSTS |
| | FFESYMBOL_attrsARRAY |
| | FFESYMBOL_attrsEQUIV |
| | FFESYMBOL_attrsINIT |
| | FFESYMBOL_attrsNAMELIST |
| | FFESYMBOL_attrsSFARG |
| | FFESYMBOL_attrsTYPE))) |
| na |= sa; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if ((ffesymbol_equiv (s) != NULL) |
| && (ffeequiv_common (ffesymbol_equiv (s)) != NULL) |
| && (ffeequiv_common (ffesymbol_equiv (s)) |
| != ffestc_local_.common.symbol)) |
| { |
| /* Oops, just COMMONed a symbol to a different area (via equiv). */ |
| ffebad_start (FFEBAD_EQUIV_COMMON); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_string (ffesymbol_text (ffestc_local_.common.symbol)); |
| ffebad_string (ffesymbol_text (ffeequiv_common (ffesymbol_equiv (s)))); |
| ffebad_finish (); |
| ffesymbol_set_attr (s, na | FFESYMBOL_attrANY); |
| ffesymbol_set_info (s, ffeinfo_new_any ()); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_signal_unreported (s); |
| } |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_common (s, ffestc_local_.common.symbol); |
| #if FFEGLOBAL_ENABLED |
| if (ffesymbol_is_init (s)) |
| ffeglobal_init_common (ffestc_local_.common.symbol, name); |
| #endif |
| if (ffesymbol_is_save (ffestc_local_.common.symbol)) |
| ffesymbol_update_save (s); |
| if (ffesymbol_equiv (s) != NULL) |
| { /* Is this newly COMMONed symbol involved in |
| an equivalence? */ |
| if (ffeequiv_common (ffesymbol_equiv (s)) == NULL) |
| ffeequiv_set_common (ffesymbol_equiv (s), /* Yes, tell equiv obj. */ |
| ffestc_local_.common.symbol); |
| #if FFEGLOBAL_ENABLED |
| if (ffeequiv_is_init (ffesymbol_equiv (s))) |
| ffeglobal_init_common (ffestc_local_.common.symbol, name); |
| #endif |
| if (ffesymbol_is_save (ffestc_local_.common.symbol)) |
| ffeequiv_update_save (ffesymbol_equiv (s)); |
| } |
| if (dims != NULL) |
| { |
| ffesymbol_set_dims (s, ffestt_dimlist_as_expr (dims, &rank, |
| &array_size, |
| &extents, |
| is_ugly_assumed)); |
| ffesymbol_set_arraysize (s, array_size); |
| ffesymbol_set_extents (s, extents); |
| if (!(0 && ffe_is_90 ()) |
| && (ffebld_op (array_size) == FFEBLD_opCONTER) |
| && (ffebld_constant_integerdefault (ffebld_conter (array_size)) |
| == 0)) |
| { |
| ffebad_start (FFEBAD_ZERO_ARRAY); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| rank, |
| ffesymbol_kind (s), |
| ffesymbol_where (s), |
| ffesymbol_size (s))); |
| } |
| ffesymbol_signal_unreported (s); |
| } |
| |
| if (ffestc_parent_ok_) |
| { |
| e = ffebld_new_symter (s, FFEINTRIN_genNONE, FFEINTRIN_specNONE, |
| FFEINTRIN_impNONE); |
| ffebld_set_info (e, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindNONE, |
| FFEINFO_whereNONE, |
| FFETARGET_charactersizeNONE)); |
| ffebld_append_item |
| (ffesymbol_ptr_to_listbottom (ffestc_local_.common.symbol), e); |
| } |
| |
| ffestd_R547_item_object (name, dims); |
| } |
| |
| /* ffestc_R547_item_cblock -- COMMON statement for common-block-name |
| |
| ffestc_R547_item_cblock(name_token); |
| |
| Make sure name_token identifies a valid common block to be COMMONd. */ |
| |
| void |
| ffestc_R547_item_cblock (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_local_.common.symbol != NULL) |
| ffesymbol_signal_unreported (ffestc_local_.common.symbol); |
| |
| s = ffesymbol_declare_cblock (name, |
| ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; /* Already have an error here, say nothing. */ |
| else if (!(sa & ~(FFESYMBOL_attrsCBLOCK |
| | FFESYMBOL_attrsSAVECBLOCK))) |
| { |
| if (!(sa & FFESYMBOL_attrsCBLOCK)) |
| ffebld_init_list (ffesymbol_ptr_to_commonlist (s), |
| ffesymbol_ptr_to_listbottom (s)); |
| na = sa | FFESYMBOL_attrsCBLOCK; |
| } |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name == NULL ? ffesta_tokens[0] : name); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else if (na & FFESYMBOL_attrsANY) |
| ffestc_parent_ok_ = FALSE; |
| else |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| if (name == NULL) |
| ffesymbol_update_save (s); |
| ffestc_parent_ok_ = TRUE; |
| } |
| |
| ffestc_local_.common.symbol = s; |
| |
| ffestd_R547_item_cblock (name); |
| } |
| |
| /* ffestc_R547_finish -- COMMON statement list complete |
| |
| ffestc_R547_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R547_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_local_.common.symbol != NULL) |
| ffesymbol_signal_unreported (ffestc_local_.common.symbol); |
| |
| ffestd_R547_finish (); |
| } |
| |
| /* ffestc_R620 -- ALLOCATE statement |
| |
| ffestc_R620(exprlist,stat,stat_token); |
| |
| Make sure the expression list is valid, then implement it. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R620 (ffesttExprList exprlist, ffebld stat, ffelexToken stat_token) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R620 (exprlist, stat); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R624 -- NULLIFY statement |
| |
| ffestc_R624(pointer_name_list); |
| |
| Make sure pointer_name_list identifies valid pointers for a NULLIFY. */ |
| |
| void |
| ffestc_R624 (ffesttExprList pointers) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R624 (pointers); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R625 -- DEALLOCATE statement |
| |
| ffestc_R625(exprlist,stat,stat_token); |
| |
| Make sure the equivalence is valid, then implement it. */ |
| |
| void |
| ffestc_R625 (ffesttExprList exprlist, ffebld stat, ffelexToken stat_token) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R625 (exprlist, stat); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| #endif |
| /* ffestc_let -- R1213 or R737 |
| |
| ffestc_let(...); |
| |
| Verify that R1213 defined-assignment or R737 assignment-stmt are |
| valid here, figure out which one, and implement. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_let (ffebld dest, ffebld source, ffelexToken source_token) |
| { |
| ffestc_R737 (dest, source, source_token); |
| } |
| |
| #endif |
| /* ffestc_R737 -- Assignment statement |
| |
| ffestc_R737(dest_expr,source_expr,source_token); |
| |
| Make sure the assignment is valid. */ |
| |
| void |
| ffestc_R737 (ffebld dest, ffebld source, ffelexToken source_token) |
| { |
| ffestc_check_simple_ (); |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| #if FFESTR_F90 |
| case FFESTV_stateWHERE: |
| case FFESTV_stateWHERETHEN: |
| if (ffestc_order_actionwhere_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R737B (dest, source); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| return; |
| #endif |
| |
| default: |
| break; |
| } |
| |
| if (ffestc_order_actionwhere_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| source = ffeexpr_convert_expr (source, source_token, dest, ffesta_tokens[0], |
| FFEEXPR_contextLET); |
| |
| ffestd_R737A (dest, source); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R738 -- Pointer assignment statement |
| |
| ffestc_R738(dest_expr,source_expr,source_token); |
| |
| Make sure the assignment is valid. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R738 (ffebld dest, ffebld source, ffelexToken source_token) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R738 (dest, source); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R740 -- WHERE statement |
| |
| ffestc_R740(expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R740 (ffebld expr, ffelexToken expr_token) |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, ffestw_top_do (ffestw_previous (b))); |
| ffestw_set_state (b, FFESTV_stateWHERE); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_where_lost_); |
| |
| ffestd_R740 (expr); |
| |
| /* Leave label finishing to next statement. */ |
| |
| } |
| |
| /* ffestc_R742 -- WHERE-construct statement |
| |
| ffestc_R742(expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R742 (ffebld expr, ffelexToken expr_token) |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_probably_this_wont_work_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, ffestw_top_do (ffestw_previous (b))); |
| ffestw_set_state (b, FFESTV_stateWHERETHEN); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_wherethen_); |
| ffestw_set_substate (b, 0); /* Haven't seen ELSEWHERE yet. */ |
| |
| ffestd_R742 (expr); |
| } |
| |
| /* ffestc_R744 -- ELSE WHERE statement |
| |
| ffestc_R744(); |
| |
| Make sure ffestc_kind_ identifies a WHERE block. |
| Implement the ELSE of the current WHERE block. */ |
| |
| void |
| ffestc_R744 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_where_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_SECOND_ELSE_WHERE); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Saw ELSEWHERE. */ |
| |
| ffestd_R744 (); |
| } |
| |
| /* ffestc_R745 -- END WHERE statement |
| |
| ffestc_R745(); |
| |
| Make sure ffestc_kind_ identifies a WHERE block. |
| Implement the end of the current WHERE block. */ |
| |
| void |
| ffestc_R745 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_where_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_shriek_wherethen_ (TRUE); |
| } |
| |
| #endif |
| /* ffestc_R803 -- Block IF (IF-THEN) statement |
| |
| ffestc_R803(construct_name,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R803 (ffelexToken construct_name, ffebld expr, |
| ffelexToken expr_token UNUSED) |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, ffestw_top_do (ffestw_previous (b))); |
| ffestw_set_state (b, FFESTV_stateIFTHEN); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_ifthen_); |
| ffestw_set_substate (b, 0); /* Haven't seen ELSE yet. */ |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| s = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, construct_name); |
| } |
| |
| ffestd_R803 (construct_name, expr); |
| } |
| |
| /* ffestc_R804 -- ELSE IF statement |
| |
| ffestc_R804(expr,expr_token,name_token); |
| |
| Make sure ffestc_kind_ identifies an IF block. If not |
| NULL, make sure name_token gives the correct name. Implement the else |
| of the IF block. */ |
| |
| void |
| ffestc_R804 (ffebld expr, ffelexToken expr_token UNUSED, |
| ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_ifthen_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (name != NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, |
| ffestw_name (ffestw_stack_top ())) |
| != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_AFTER_ELSE); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| return; /* Don't upset back end with ELSEIF |
| after ELSE. */ |
| } |
| |
| ffestd_R804 (expr, name); |
| } |
| |
| /* ffestc_R805 -- ELSE statement |
| |
| ffestc_R805(name_token); |
| |
| Make sure ffestc_kind_ identifies an IF block. If not |
| NULL, make sure name_token gives the correct name. Implement the ELSE |
| of the IF block. */ |
| |
| void |
| ffestc_R805 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_ifthen_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (name != NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_AFTER_ELSE); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| return; /* Tell back end about only one ELSE. */ |
| } |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Saw ELSE. */ |
| |
| ffestd_R805 (name); |
| } |
| |
| /* ffestc_R806 -- END IF statement |
| |
| ffestc_R806(name_token); |
| |
| Make sure ffestc_kind_ identifies an IF block. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the IF block. */ |
| |
| void |
| ffestc_R806 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_ifthen_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_endif_ (); |
| |
| if (name == NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestc_shriek_ifthen_ (TRUE); |
| } |
| |
| /* ffestc_R807 -- Logical IF statement |
| |
| ffestc_R807(expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R807 (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_action_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, ffestw_top_do (ffestw_previous (b))); |
| ffestw_set_state (b, FFESTV_stateIF); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_if_lost_); |
| |
| ffestd_R807 (expr); |
| |
| /* Do the label finishing in the next statement. */ |
| |
| } |
| |
| /* ffestc_R809 -- SELECT CASE statement |
| |
| ffestc_R809(construct_name,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R809 (ffelexToken construct_name, ffebld expr, ffelexToken expr_token) |
| { |
| ffestw b; |
| mallocPool pool; |
| ffestwSelect s; |
| ffesymbol sym; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, ffestw_top_do (ffestw_previous (b))); |
| ffestw_set_state (b, FFESTV_stateSELECT0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_select_); |
| ffestw_set_substate (b, 0); /* Haven't seen CASE DEFAULT yet. */ |
| |
| /* Init block to manage CASE list. */ |
| |
| pool = malloc_pool_new ("Select", ffe_pool_any_unit (), 1024); |
| s = (ffestwSelect) malloc_new_kp (pool, "Select", sizeof (*s)); |
| s->first_rel = (ffestwCase) &s->first_rel; |
| s->last_rel = (ffestwCase) &s->first_rel; |
| s->first_stmt = (ffestwCase) &s->first_rel; |
| s->last_stmt = (ffestwCase) &s->first_rel; |
| s->pool = pool; |
| s->cases = 1; |
| s->t = ffelex_token_use (expr_token); |
| s->type = ffeinfo_basictype (ffebld_info (expr)); |
| s->kindtype = ffeinfo_kindtype (ffebld_info (expr)); |
| ffestw_set_select (b, s); |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| sym = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (sym) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (sym, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (sym, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| sym = ffecom_sym_learned (sym); |
| ffesymbol_signal_unreported (sym); |
| } |
| else |
| ffesymbol_error (sym, construct_name); |
| } |
| |
| ffestd_R809 (construct_name, expr); |
| } |
| |
| /* ffestc_R810 -- CASE statement |
| |
| ffestc_R810(case_value_range_list,name); |
| |
| If case_value_range_list is NULL, it's CASE DEFAULT. name is the case- |
| construct-name. Make sure no more than one CASE DEFAULT is present for |
| a given case-construct and that there aren't any overlapping ranges or |
| duplicate case values. */ |
| |
| void |
| ffestc_R810 (ffesttCaseList cases, ffelexToken name) |
| { |
| ffesttCaseList caseobj; |
| ffestwSelect s; |
| ffestwCase c, nc; |
| ffebldConstant expr1c, expr2c; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_selectcase_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| s = ffestw_select (ffestw_stack_top ()); |
| |
| if (ffestw_state (ffestw_stack_top ()) == FFESTV_stateSELECT0) |
| { |
| #if 0 /* Not sure we want to have msgs point here |
| instead of SELECT CASE. */ |
| ffestw_update (NULL); /* Update state line/col info. */ |
| #endif |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateSELECT1); |
| } |
| |
| if (name != NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, |
| ffestw_name (ffestw_stack_top ())) |
| != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| if (cases == NULL) |
| { |
| if (ffestw_substate (ffestw_stack_top ()) != 0) |
| { |
| ffebad_start (FFEBAD_CASE_SECOND_DEFAULT); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Saw ELSE. */ |
| } |
| else |
| { /* For each case, try to fit into sorted list |
| of ranges. */ |
| for (caseobj = cases->next; caseobj != cases; caseobj = caseobj->next) |
| { |
| if ((caseobj->expr1 == NULL) |
| && (!caseobj->range |
| || (caseobj->expr2 == NULL))) |
| { /* "CASE (:)". */ |
| ffebad_start (FFEBAD_CASE_BAD_RANGE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_finish (); |
| continue; |
| } |
| if (((caseobj->expr1 != NULL) |
| && ((ffeinfo_basictype (ffebld_info (caseobj->expr1)) |
| != s->type) |
| || ((ffeinfo_kindtype (ffebld_info (caseobj->expr1)) |
| != s->kindtype) |
| && (ffeinfo_kindtype (ffebld_info (caseobj->expr1)) != FFEINFO_kindtypeINTEGER1 )) |
| || ((caseobj->range) |
| && (caseobj->expr2 != NULL) |
| && ((ffeinfo_basictype (ffebld_info (caseobj->expr2)) |
| != s->type) |
| || ((ffeinfo_kindtype (ffebld_info (caseobj->expr2)) |
| != s->kindtype) |
| && (ffeinfo_kindtype (ffebld_info (caseobj->expr2)) != FFEINFO_kindtypeINTEGER1))))))) |
| { |
| ffebad_start (FFEBAD_CASE_TYPE_DISAGREE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_here (1, ffelex_token_where_line (s->t), |
| ffelex_token_where_column (s->t)); |
| ffebad_finish (); |
| continue; |
| } |
| |
| |
| |
| if ((s->type == FFEINFO_basictypeLOGICAL) && (caseobj->range)) |
| { |
| ffebad_start (FFEBAD_CASE_LOGICAL_RANGE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_finish (); |
| continue; |
| } |
| |
| if (caseobj->expr1 == NULL) |
| expr1c = NULL; |
| else if (ffebld_op (caseobj->expr1) != FFEBLD_opCONTER) |
| continue; /* opANY. */ |
| else |
| expr1c = ffebld_conter (caseobj->expr1); |
| |
| if (!caseobj->range) |
| expr2c = expr1c; /* expr1c and expr2c are NOT NULL in this |
| case. */ |
| else if (caseobj->expr2 == NULL) |
| expr2c = NULL; |
| else if (ffebld_op (caseobj->expr2) != FFEBLD_opCONTER) |
| continue; /* opANY. */ |
| else |
| expr2c = ffebld_conter (caseobj->expr2); |
| |
| if (expr1c == NULL) |
| { /* "CASE (:high)", must be first in list. */ |
| c = s->first_rel; |
| if ((c != (ffestwCase) &s->first_rel) |
| && ((c->low == NULL) |
| || (ffebld_constant_cmp (expr2c, c->low) >= 0))) |
| { /* Other "CASE (:high)" or lowest "CASE |
| (low[:high])" low. */ |
| ffebad_start (FFEBAD_CASE_DUPLICATE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_here (1, ffelex_token_where_line (c->t), |
| ffelex_token_where_column (c->t)); |
| ffebad_finish (); |
| continue; |
| } |
| } |
| else if (expr2c == NULL) |
| { /* "CASE (low:)", must be last in list. */ |
| c = s->last_rel; |
| if ((c != (ffestwCase) &s->first_rel) |
| && ((c->high == NULL) |
| || (ffebld_constant_cmp (expr1c, c->high) <= 0))) |
| { /* Other "CASE (low:)" or lowest "CASE |
| ([low:]high)" high. */ |
| ffebad_start (FFEBAD_CASE_DUPLICATE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_here (1, ffelex_token_where_line (c->t), |
| ffelex_token_where_column (c->t)); |
| ffebad_finish (); |
| continue; |
| } |
| c = c->next_rel; /* Same as c = (ffestwCase) &s->first;. */ |
| } |
| else |
| { /* (expr1c != NULL) && (expr2c != NULL). */ |
| if (ffebld_constant_cmp (expr1c, expr2c) > 0) |
| { /* Such as "CASE (3:1)" or "CASE ('B':'A')". */ |
| ffebad_start (FFEBAD_CASE_RANGE_USELESS); /* Warn/inform only. */ |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_finish (); |
| continue; |
| } |
| for (c = s->first_rel; |
| (c != (ffestwCase) &s->first_rel) |
| && ((c->low == NULL) |
| || (ffebld_constant_cmp (expr1c, c->low) > 0)); |
| c = c->next_rel) |
| ; |
| nc = c; /* Which one to report? */ |
| if (((c != (ffestwCase) &s->first_rel) |
| && (ffebld_constant_cmp (expr2c, c->low) >= 0)) |
| || (((nc = c->previous_rel) != (ffestwCase) &s->first_rel) |
| && (ffebld_constant_cmp (expr1c, nc->high) <= 0))) |
| { /* Interference with range in case nc. */ |
| ffebad_start (FFEBAD_CASE_DUPLICATE); |
| ffebad_here (0, ffelex_token_where_line (caseobj->t), |
| ffelex_token_where_column (caseobj->t)); |
| ffebad_here (1, ffelex_token_where_line (nc->t), |
| ffelex_token_where_column (nc->t)); |
| ffebad_finish (); |
| continue; |
| } |
| } |
| |
| /* If we reach here for this case range/value, it's ok (sorts into |
| the list of ranges/values) so we give it its own case object |
| sorted into the list of case statements. */ |
| |
| nc = malloc_new_kp (s->pool, "Case range", sizeof (*nc)); |
| nc->next_rel = c; |
| nc->previous_rel = c->previous_rel; |
| nc->next_stmt = (ffestwCase) &s->first_rel; |
| nc->previous_stmt = s->last_stmt; |
| nc->low = expr1c; |
| nc->high = expr2c; |
| nc->casenum = s->cases; |
| nc->t = ffelex_token_use (caseobj->t); |
| nc->next_rel->previous_rel = nc; |
| nc->previous_rel->next_rel = nc; |
| nc->next_stmt->previous_stmt = nc; |
| nc->previous_stmt->next_stmt = nc; |
| } |
| } |
| |
| ffestd_R810 ((cases == NULL) ? 0 : s->cases); |
| |
| s->cases++; /* Increment # of cases. */ |
| } |
| |
| /* ffestc_R811 -- END SELECT statement |
| |
| ffestc_R811(name_token); |
| |
| Make sure ffestc_kind_ identifies a SELECT block. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the SELECT block. */ |
| |
| void |
| ffestc_R811 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_selectcase_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if (name == NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, |
| ffestw_name (ffestw_stack_top ())) |
| != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestc_shriek_select_ (TRUE); |
| } |
| |
| /* ffestc_R819A -- Iterative labeled DO statement |
| |
| ffestc_R819A(construct_name,label_token,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R819A (ffelexToken construct_name, ffelexToken label_token, ffebld var, |
| ffelexToken var_token, ffebld start, ffelexToken start_token, ffebld end, |
| ffelexToken end_token, ffebld incr, ffelexToken incr_token) |
| { |
| ffestw b; |
| ffelab label; |
| ffesymbol s; |
| ffesymbol varsym; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if (!ffestc_labelref_is_loopend_ (label_token, &label)) |
| return; |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, b); |
| ffestw_set_state (b, FFESTV_stateDO); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_do_); |
| ffestw_set_label (b, label); |
| switch (ffebld_op (var)) |
| { |
| case FFEBLD_opSYMTER: |
| if ((ffeinfo_basictype (ffebld_info (var)) == FFEINFO_basictypeREAL) |
| && ffe_is_warn_surprising ()) |
| { |
| ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */ |
| ffebad_here (0, ffelex_token_where_line (var_token), |
| ffelex_token_where_column (var_token)); |
| ffebad_string (ffesymbol_text (ffebld_symter (var))); |
| ffebad_finish (); |
| } |
| if (!ffesymbol_is_doiter (varsym = ffebld_symter (var))) |
| { /* Presumably already complained about by |
| ffeexpr_lhs_. */ |
| ffesymbol_set_is_doiter (varsym, TRUE); |
| ffestw_set_do_iter_var (b, varsym); |
| ffestw_set_do_iter_var_t (b, ffelex_token_use (var_token)); |
| break; |
| } |
| /* Fall through. */ |
| case FFEBLD_opANY: |
| ffestw_set_do_iter_var (b, NULL); |
| ffestw_set_do_iter_var_t (b, NULL); |
| break; |
| |
| default: |
| assert ("bad iter var" == NULL); |
| break; |
| } |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| s = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, construct_name); |
| } |
| |
| if (incr == NULL) |
| { |
| incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1)); |
| ffebld_set_info (incr, ffeinfo_new |
| (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| } |
| |
| start = ffeexpr_convert_expr (start, start_token, var, var_token, |
| FFEEXPR_contextLET); |
| end = ffeexpr_convert_expr (end, end_token, var, var_token, |
| FFEEXPR_contextLET); |
| incr = ffeexpr_convert_expr (incr, incr_token, var, var_token, |
| FFEEXPR_contextLET); |
| |
| ffestd_R819A (construct_name, label, var, |
| start, start_token, |
| end, end_token, |
| incr, incr_token); |
| } |
| |
| /* ffestc_R819B -- Labeled DO WHILE statement |
| |
| ffestc_R819B(construct_name,label_token,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R819B (ffelexToken construct_name, ffelexToken label_token, |
| ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestw b; |
| ffelab label; |
| ffesymbol s; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if (!ffestc_labelref_is_loopend_ (label_token, &label)) |
| return; |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, b); |
| ffestw_set_state (b, FFESTV_stateDO); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_do_); |
| ffestw_set_label (b, label); |
| ffestw_set_do_iter_var (b, NULL); |
| ffestw_set_do_iter_var_t (b, NULL); |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| s = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, construct_name); |
| } |
| |
| ffestd_R819B (construct_name, label, expr); |
| } |
| |
| /* ffestc_R820A -- Iterative nonlabeled DO statement |
| |
| ffestc_R820A(construct_name,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R820A (ffelexToken construct_name, ffebld var, ffelexToken var_token, |
| ffebld start, ffelexToken start_token, ffebld end, ffelexToken end_token, |
| ffebld incr, ffelexToken incr_token) |
| { |
| ffestw b; |
| ffesymbol s; |
| ffesymbol varsym; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, b); |
| ffestw_set_state (b, FFESTV_stateDO); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_do_); |
| ffestw_set_label (b, NULL); |
| switch (ffebld_op (var)) |
| { |
| case FFEBLD_opSYMTER: |
| if ((ffeinfo_basictype (ffebld_info (var)) == FFEINFO_basictypeREAL) |
| && ffe_is_warn_surprising ()) |
| { |
| ffebad_start (FFEBAD_DO_REAL); /* See error message!!! */ |
| ffebad_here (0, ffelex_token_where_line (var_token), |
| ffelex_token_where_column (var_token)); |
| ffebad_string (ffesymbol_text (ffebld_symter (var))); |
| ffebad_finish (); |
| } |
| if (!ffesymbol_is_doiter (varsym = ffebld_symter (var))) |
| { /* Presumably already complained about by |
| ffeexpr_lhs_. */ |
| ffesymbol_set_is_doiter (varsym, TRUE); |
| ffestw_set_do_iter_var (b, varsym); |
| ffestw_set_do_iter_var_t (b, ffelex_token_use (var_token)); |
| break; |
| } |
| /* Fall through. */ |
| case FFEBLD_opANY: |
| ffestw_set_do_iter_var (b, NULL); |
| ffestw_set_do_iter_var_t (b, NULL); |
| break; |
| |
| default: |
| assert ("bad iter var" == NULL); |
| break; |
| } |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| s = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, construct_name); |
| } |
| |
| if (incr == NULL) |
| { |
| incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1)); |
| ffebld_set_info (incr, ffeinfo_new |
| (FFEINFO_basictypeINTEGER, |
| FFEINFO_kindtypeINTEGERDEFAULT, |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereCONSTANT, |
| FFETARGET_charactersizeNONE)); |
| } |
| |
| start = ffeexpr_convert_expr (start, start_token, var, var_token, |
| FFEEXPR_contextLET); |
| end = ffeexpr_convert_expr (end, end_token, var, var_token, |
| FFEEXPR_contextLET); |
| incr = ffeexpr_convert_expr (incr, incr_token, var, var_token, |
| FFEEXPR_contextLET); |
| |
| #if 0 |
| if ((ffebld_op (incr) == FFEBLD_opCONTER) |
| && (ffebld_constant_is_zero (ffebld_conter (incr)))) |
| { |
| ffebad_start (FFEBAD_DO_STEP_ZERO); |
| ffebad_here (0, ffelex_token_where_line (incr_token), |
| ffelex_token_where_column (incr_token)); |
| ffebad_string ("Iterative DO loop"); |
| ffebad_finish (); |
| } |
| #endif |
| |
| ffestd_R819A (construct_name, NULL, var, |
| start, start_token, |
| end, end_token, |
| incr, incr_token); |
| } |
| |
| /* ffestc_R820B -- Nonlabeled DO WHILE statement |
| |
| ffestc_R820B(construct_name,expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R820B (ffelexToken construct_name, ffebld expr, |
| ffelexToken expr_token UNUSED) |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_exec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, b); |
| ffestw_set_state (b, FFESTV_stateDO); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_do_); |
| ffestw_set_label (b, NULL); |
| ffestw_set_do_iter_var (b, NULL); |
| ffestw_set_do_iter_var_t (b, NULL); |
| |
| if (construct_name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| { |
| ffestw_set_name (b, ffelex_token_use (construct_name)); |
| |
| s = ffesymbol_declare_local (construct_name, FALSE); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindCONSTRUCT, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| s = ffecom_sym_learned (s); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, construct_name); |
| } |
| |
| ffestd_R819B (construct_name, NULL, expr); |
| } |
| |
| /* ffestc_R825 -- END DO statement |
| |
| ffestc_R825(name_token); |
| |
| Make sure ffestc_kind_ identifies a DO block. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the DO block. */ |
| |
| void |
| ffestc_R825 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_do_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (name == NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) != NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| } |
| else |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, |
| ffestw_name (ffestw_stack_top ())) |
| != 0) |
| { |
| ffebad_start (FFEBAD_CONSTRUCT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| if (ffesta_label_token == NULL) |
| { /* If top of stack has label, its an error! */ |
| if (ffestw_label (ffestw_stack_top ()) != NULL) |
| { |
| ffebad_start (FFEBAD_DO_HAD_LABEL); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_do_ (TRUE); |
| |
| ffestc_try_shriek_do_ (); |
| |
| return; |
| } |
| |
| ffestd_R825 (name); |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R834 -- CYCLE statement |
| |
| ffestc_R834(name_token); |
| |
| Handle a CYCLE within a loop. */ |
| |
| void |
| ffestc_R834 (ffelexToken name) |
| { |
| ffestw block; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actiondo_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| if (name == NULL) |
| block = ffestw_top_do (ffestw_stack_top ()); |
| else |
| { /* Search for name. */ |
| for (block = ffestw_top_do (ffestw_stack_top ()); |
| (block != NULL) && (ffestw_blocknum (block) != 0); |
| block = ffestw_top_do (ffestw_previous (block))) |
| { |
| if ((ffestw_name (block) != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (block)) == 0)) |
| break; |
| } |
| if ((block == NULL) || (ffestw_blocknum (block) == 0)) |
| { |
| block = ffestw_top_do (ffestw_stack_top ()); |
| ffebad_start (FFEBAD_CONSTRUCT_NO_DO_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestd_R834 (block); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) CYCLE". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R835 -- EXIT statement |
| |
| ffestc_R835(name_token); |
| |
| Handle a EXIT within a loop. */ |
| |
| void |
| ffestc_R835 (ffelexToken name) |
| { |
| ffestw block; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actiondo_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| if (name == NULL) |
| block = ffestw_top_do (ffestw_stack_top ()); |
| else |
| { /* Search for name. */ |
| for (block = ffestw_top_do (ffestw_stack_top ()); |
| (block != NULL) && (ffestw_blocknum (block) != 0); |
| block = ffestw_top_do (ffestw_previous (block))) |
| { |
| if ((ffestw_name (block) != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (block)) == 0)) |
| break; |
| } |
| if ((block == NULL) || (ffestw_blocknum (block) == 0)) |
| { |
| block = ffestw_top_do (ffestw_stack_top ()); |
| ffebad_start (FFEBAD_CONSTRUCT_NO_DO_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestd_R835 (block); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) EXIT". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R836 -- GOTO statement |
| |
| ffestc_R836(label_token); |
| |
| Make sure label_token identifies a valid label for a GOTO. Update |
| that label's info to indicate it is the target of a GOTO. */ |
| |
| void |
| ffestc_R836 (ffelexToken label_token) |
| { |
| ffelab label; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| if (ffestc_labelref_is_branch_ (label_token, &label)) |
| ffestd_R836 (label); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) GOTO 100". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R837 -- Computed GOTO statement |
| |
| ffestc_R837(label_list,expr,expr_token); |
| |
| Make sure label_list identifies valid labels for a GOTO. Update |
| each label's info to indicate it is the target of a GOTO. */ |
| |
| void |
| ffestc_R837 (ffesttTokenList label_toks, ffebld expr, |
| ffelexToken expr_token UNUSED) |
| { |
| ffesttTokenItem ti; |
| bool ok = TRUE; |
| int i; |
| ffelab *labels; |
| |
| assert (label_toks != NULL); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| labels = malloc_new_kp (ffesta_output_pool, "FFESTC labels", |
| sizeof (*labels) |
| * ffestt_tokenlist_count (label_toks)); |
| |
| for (ti = label_toks->first, i = 0; |
| ti != (ffesttTokenItem) &label_toks->first; |
| ti = ti->next, ++i) |
| { |
| if (!ffestc_labelref_is_branch_ (ti->t, &labels[i])) |
| { |
| ok = FALSE; |
| break; |
| } |
| } |
| |
| if (ok) |
| ffestd_R837 (labels, ffestt_tokenlist_count (label_toks), expr); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R838 -- ASSIGN statement |
| |
| ffestc_R838(label_token,target_variable,target_token); |
| |
| Make sure label_token identifies a valid label for an assignment. Update |
| that label's info to indicate it is the source of an assignment. Update |
| target_variable's info to indicate it is the target the assignment of that |
| label. */ |
| |
| void |
| ffestc_R838 (ffelexToken label_token, ffebld target, |
| ffelexToken target_token UNUSED) |
| { |
| ffelab label; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| /* Mark target symbol as target of an ASSIGN. */ |
| if (ffebld_op (target) == FFEBLD_opSYMTER) |
| ffesymbol_set_assigned (ffebld_symter (target), TRUE); |
| |
| if (ffestc_labelref_is_assignable_ (label_token, &label)) |
| ffestd_R838 (label, target); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R839 -- Assigned GOTO statement |
| |
| ffestc_R839(target,target_token,label_list); |
| |
| Make sure label_list identifies valid labels for a GOTO. Update |
| each label's info to indicate it is the target of a GOTO. */ |
| |
| void |
| ffestc_R839 (ffebld target, ffelexToken target_token UNUSED, |
| ffesttTokenList label_toks) |
| { |
| ffesttTokenItem ti; |
| bool ok = TRUE; |
| int i; |
| ffelab *labels; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| if (label_toks == NULL) |
| { |
| labels = NULL; |
| i = 0; |
| } |
| else |
| { |
| labels = malloc_new_kp (ffesta_output_pool, "FFESTC labels", |
| sizeof (*labels) * ffestt_tokenlist_count (label_toks)); |
| |
| for (ti = label_toks->first, i = 0; |
| ti != (ffesttTokenItem) &label_toks->first; |
| ti = ti->next, ++i) |
| { |
| if (!ffestc_labelref_is_branch_ (ti->t, &labels[i])) |
| { |
| ok = FALSE; |
| break; |
| } |
| } |
| } |
| |
| if (ok) |
| ffestd_R839 (target, labels, i); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) GOTO I". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R840 -- Arithmetic IF statement |
| |
| ffestc_R840(expr,expr_token,neg,zero,pos); |
| |
| Make sure the labels are valid; implement. */ |
| |
| void |
| ffestc_R840 (ffebld expr, ffelexToken expr_token UNUSED, |
| ffelexToken neg_token, ffelexToken zero_token, |
| ffelexToken pos_token) |
| { |
| ffelab neg; |
| ffelab zero; |
| ffelab pos; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| if (ffestc_labelref_is_branch_ (neg_token, &neg) |
| && ffestc_labelref_is_branch_ (zero_token, &zero) |
| && ffestc_labelref_is_branch_ (pos_token, &pos)) |
| ffestd_R840 (expr, neg, zero, pos); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) GOTO (100,200,300), I". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R841 -- CONTINUE statement |
| |
| ffestc_R841(); */ |
| |
| void |
| ffestc_R841 () |
| { |
| ffestc_check_simple_ (); |
| |
| if (ffestc_order_actionwhere_ () != FFESTC_orderOK_) |
| return; |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| #if FFESTR_F90 |
| case FFESTV_stateWHERE: |
| case FFESTV_stateWHERETHEN: |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R841 (TRUE); |
| |
| /* It's okay that we call ffestc_labeldef_branch_end_ () below, |
| since that will be a no-op after calling _useless_ () above. */ |
| break; |
| #endif |
| |
| default: |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R841 (FALSE); |
| |
| break; |
| } |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R842 -- STOP statement |
| |
| ffestc_R842(expr,expr_token); |
| |
| Make sure statement is valid here; implement. expr and expr_token are |
| both NULL if there was no expression. */ |
| |
| void |
| ffestc_R842 (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| ffestd_R842 (expr); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) STOP". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R843 -- PAUSE statement |
| |
| ffestc_R843(expr,expr_token); |
| |
| Make sure statement is valid here; implement. expr and expr_token are |
| both NULL if there was no expression. */ |
| |
| void |
| ffestc_R843 (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R843 (expr); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R904 -- OPEN statement |
| |
| ffestc_R904(); |
| |
| Make sure an OPEN is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R904 () |
| { |
| int i; |
| int expect_file; |
| static const char *const status_strs[] = |
| { |
| "New", |
| "Old", |
| "Replace", |
| "Scratch", |
| "Unknown" |
| }; |
| static const char *const access_strs[] = |
| { |
| "Append", |
| "Direct", |
| "Keyed", |
| "Sequential" |
| }; |
| static const char *const blank_strs[] = |
| { |
| "Null", |
| "Zero" |
| }; |
| static const char *const carriagecontrol_strs[] = |
| { |
| "Fortran", |
| "List", |
| "None" |
| }; |
| static const char *const dispose_strs[] = |
| { |
| "Delete", |
| "Keep", |
| "Print", |
| "Print/Delete", |
| "Save", |
| "Submit", |
| "Submit/Delete" |
| }; |
| static const char *const form_strs[] = |
| { |
| "Formatted", |
| "Unformatted" |
| }; |
| static const char *const organization_strs[] = |
| { |
| "Indexed", |
| "Relative", |
| "Sequential" |
| }; |
| static const char *const position_strs[] = |
| { |
| "Append", |
| "AsIs", |
| "Rewind" |
| }; |
| static const char *const action_strs[] = |
| { |
| "Read", |
| "ReadWrite", |
| "Write" |
| }; |
| static const char *const delim_strs[] = |
| { |
| "Apostrophe", |
| "None", |
| "Quote" |
| }; |
| static const char *const recordtype_strs[] = |
| { |
| "Fixed", |
| "Segmented", |
| "Stream", |
| "Stream_CR", |
| "Stream_LF", |
| "Variable" |
| }; |
| static const char *const pad_strs[] = |
| { |
| "No", |
| "Yes" |
| }; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.open.open_spec[FFESTP_openixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.open.open_spec[FFESTP_openixUNIT])) |
| { |
| i = ffestc_subr_binsrch_ (status_strs, |
| ARRAY_SIZE (status_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixSTATUS], |
| "NEW, OLD, REPLACE, SCRATCH, or UNKNOWN"); |
| switch (i) |
| { |
| case 0: /* Unknown. */ |
| case 5: /* UNKNOWN. */ |
| expect_file = 2; /* Unknown, don't care about FILE=. */ |
| break; |
| |
| case 1: /* NEW. */ |
| case 2: /* OLD. */ |
| if (ffe_is_pedantic ()) |
| expect_file = 1; /* Yes, need FILE=. */ |
| else |
| expect_file = 2; /* f2clib doesn't care about FILE=. */ |
| break; |
| |
| case 3: /* REPLACE. */ |
| expect_file = 1; /* Yes, need FILE=. */ |
| break; |
| |
| case 4: /* SCRATCH. */ |
| expect_file = 0; /* No, disallow FILE=. */ |
| break; |
| |
| default: |
| assert ("invalid _binsrch_ result" == NULL); |
| expect_file = 0; |
| break; |
| } |
| if ((expect_file == 0) |
| && ffestp_file.open.open_spec[FFESTP_openixFILE].kw_or_val_present) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| assert (ffestp_file.open.open_spec[FFESTP_openixFILE].kw_or_val_present); |
| if (ffestp_file.open.open_spec[FFESTP_openixFILE].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixFILE].kw), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixFILE].kw)); |
| } |
| else |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixFILE].value), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixFILE].value)); |
| } |
| assert (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw_or_val_present); |
| if (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw_present) |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw)); |
| } |
| else |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].value), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].value)); |
| } |
| ffebad_finish (); |
| } |
| else if ((expect_file == 1) |
| && !ffestp_file.open.open_spec[FFESTP_openixFILE].kw_or_val_present) |
| { |
| ffebad_start (FFEBAD_MISSING_SPECIFIER); |
| assert (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw_or_val_present); |
| if (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].kw)); |
| } |
| else |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].value), |
| ffelex_token_where_column |
| (ffestp_file.open.open_spec[FFESTP_openixSTATUS].value)); |
| } |
| ffebad_string ("FILE="); |
| ffebad_finish (); |
| } |
| |
| ffestc_subr_binsrch_ (access_strs, ARRAY_SIZE (access_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixACCESS], |
| "APPEND, DIRECT, KEYED, or SEQUENTIAL"); |
| |
| ffestc_subr_binsrch_ (blank_strs, ARRAY_SIZE (blank_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixBLANK], |
| "NULL or ZERO"); |
| |
| ffestc_subr_binsrch_ (carriagecontrol_strs, |
| ARRAY_SIZE (carriagecontrol_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixCARRIAGECONTROL], |
| "FORTRAN, LIST, or NONE"); |
| |
| ffestc_subr_binsrch_ (dispose_strs, ARRAY_SIZE (dispose_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixDISPOSE], |
| "DELETE, KEEP, PRINT, PRINT/DELETE, SAVE, SUBMIT, or SUBMIT/DELETE"); |
| |
| ffestc_subr_binsrch_ (form_strs, ARRAY_SIZE (form_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixFORM], |
| "FORMATTED or UNFORMATTED"); |
| |
| ffestc_subr_binsrch_ (organization_strs, ARRAY_SIZE (organization_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixORGANIZATION], |
| "INDEXED, RELATIVE, or SEQUENTIAL"); |
| |
| ffestc_subr_binsrch_ (position_strs, ARRAY_SIZE (position_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixPOSITION], |
| "APPEND, ASIS, or REWIND"); |
| |
| ffestc_subr_binsrch_ (action_strs, ARRAY_SIZE (action_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixACTION], |
| "READ, READWRITE, or WRITE"); |
| |
| ffestc_subr_binsrch_ (delim_strs, ARRAY_SIZE (delim_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixDELIM], |
| "APOSTROPHE, NONE, or QUOTE"); |
| |
| ffestc_subr_binsrch_ (recordtype_strs, ARRAY_SIZE (recordtype_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixRECORDTYPE], |
| "FIXED, SEGMENTED, STREAM, STREAM_CR, STREAM_LF, or VARIABLE"); |
| |
| ffestc_subr_binsrch_ (pad_strs, ARRAY_SIZE (pad_strs), |
| &ffestp_file.open.open_spec[FFESTP_openixPAD], |
| "NO or YES"); |
| |
| ffestd_R904 (); |
| } |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R907 -- CLOSE statement |
| |
| ffestc_R907(); |
| |
| Make sure a CLOSE is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R907 () |
| { |
| static const char *const status_strs[] = |
| { |
| "Delete", |
| "Keep", |
| "Print", |
| "Print/Delete", |
| "Save", |
| "Submit", |
| "Submit/Delete" |
| }; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.close.close_spec[FFESTP_closeixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.close.close_spec[FFESTP_closeixUNIT])) |
| { |
| ffestc_subr_binsrch_ (status_strs, ARRAY_SIZE (status_strs), |
| &ffestp_file.close.close_spec[FFESTP_closeixSTATUS], |
| "DELETE, KEEP, PRINT, PRINT/DELETE, SAVE, SUBMIT, or SUBMIT/DELETE"); |
| |
| ffestd_R907 (); |
| } |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R909_start -- READ(...) statement list begin |
| |
| ffestc_R909_start(FALSE); |
| |
| Verify that READ is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R909_start (bool only_format) |
| { |
| ffestvUnit unit; |
| ffestvFormat format; |
| bool rec; |
| bool key; |
| ffestpReadIx keyn; |
| ffestpReadIx spec1; |
| ffestpReadIx spec2; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_format_ |
| (&ffestp_file.read.read_spec[FFESTP_readixFORMAT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.read.read_spec[FFESTP_readixFORMAT]); |
| ffestc_namelist_ = (format == FFESTV_formatNAMELIST); |
| |
| if (only_format) |
| { |
| ffestd_R909_start (TRUE, FFESTV_unitNONE, format, FALSE, FALSE); |
| |
| ffestc_ok_ = TRUE; |
| return; |
| } |
| |
| if (!ffestc_subr_is_branch_ |
| (&ffestp_file.read.read_spec[FFESTP_readixEOR]) |
| || !ffestc_subr_is_branch_ |
| (&ffestp_file.read.read_spec[FFESTP_readixERR]) |
| || !ffestc_subr_is_branch_ |
| (&ffestp_file.read.read_spec[FFESTP_readixEND])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| unit = ffestc_subr_unit_ |
| (&ffestp_file.read.read_spec[FFESTP_readixUNIT]); |
| if (unit == FFESTV_unitNONE) |
| { |
| ffebad_start (FFEBAD_NO_UNIT_SPEC); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| rec = ffestp_file.read.read_spec[FFESTP_readixREC].kw_or_val_present; |
| |
| if (ffestp_file.read.read_spec[FFESTP_readixKEYEQ].kw_or_val_present) |
| { |
| key = TRUE; |
| keyn = spec1 = FFESTP_readixKEYEQ; |
| } |
| else |
| { |
| key = FALSE; |
| keyn = spec1 = FFESTP_readix; |
| } |
| |
| if (ffestp_file.read.read_spec[FFESTP_readixKEYGT].kw_or_val_present) |
| { |
| if (key) |
| { |
| spec2 = FFESTP_readixKEYGT; |
| whine: /* :::::::::::::::::::: */ |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| assert (ffestp_file.read.read_spec[spec1].kw_or_val_present); |
| if (ffestp_file.read.read_spec[spec1].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec1].kw)); |
| } |
| else |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec1].value), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec1].value)); |
| } |
| assert (ffestp_file.read.read_spec[spec2].kw_or_val_present); |
| if (ffestp_file.read.read_spec[spec2].kw_present) |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec2].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec2].kw)); |
| } |
| else |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec2].value), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec2].value)); |
| } |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| key = TRUE; |
| keyn = spec1 = FFESTP_readixKEYGT; |
| } |
| |
| if (ffestp_file.read.read_spec[FFESTP_readixKEYGE].kw_or_val_present) |
| { |
| if (key) |
| { |
| spec2 = FFESTP_readixKEYGT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| key = TRUE; |
| keyn = FFESTP_readixKEYGT; |
| } |
| |
| if (rec) |
| { |
| spec1 = FFESTP_readixREC; |
| if (key) |
| { |
| spec2 = keyn; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (unit == FFESTV_unitCHAREXPR) |
| { |
| spec2 = FFESTP_readixUNIT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if ((format == FFESTV_formatASTERISK) |
| || (format == FFESTV_formatNAMELIST)) |
| { |
| spec2 = FFESTP_readixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixADVANCE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixEND].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixEND; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixNULLS].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixNULLS; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| else if (key) |
| { |
| spec1 = keyn; |
| if (unit == FFESTV_unitCHAREXPR) |
| { |
| spec2 = FFESTP_readixUNIT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if ((format == FFESTV_formatASTERISK) |
| || (format == FFESTV_formatNAMELIST)) |
| { |
| spec2 = FFESTP_readixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixADVANCE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixEND].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixEND; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixEOR].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixEOR; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixNULLS].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixNULLS; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixREC].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixREC; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixSIZE].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixSIZE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| else |
| { /* Sequential/Internal. */ |
| if (unit == FFESTV_unitCHAREXPR) |
| { /* Internal file. */ |
| spec1 = FFESTP_readixUNIT; |
| if (format == FFESTV_formatNAMELIST) |
| { |
| spec2 = FFESTP_readixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw_or_val_present) |
| { |
| spec2 = FFESTP_readixADVANCE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw_or_val_present) |
| { /* ADVANCE= specified. */ |
| spec1 = FFESTP_readixADVANCE; |
| if (format == FFESTV_formatNONE) |
| { |
| ffebad_start (FFEBAD_MISSING_FORMAT_SPEC); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec1].kw)); |
| ffebad_finish (); |
| |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| if (format == FFESTV_formatNAMELIST) |
| { |
| spec2 = FFESTP_readixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixEOR].kw_or_val_present) |
| { /* EOR= specified. */ |
| spec1 = FFESTP_readixEOR; |
| if (ffestc_subr_speccmp_ ("No", |
| &ffestp_file.read.read_spec[FFESTP_readixADVANCE], |
| NULL, NULL) != 0) |
| { |
| goto whine_advance; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixNULLS].kw_or_val_present) |
| { /* NULLS= specified. */ |
| spec1 = FFESTP_readixNULLS; |
| if (format != FFESTV_formatASTERISK) |
| { |
| spec2 = FFESTP_readixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.read.read_spec[FFESTP_readixSIZE].kw_or_val_present) |
| { /* SIZE= specified. */ |
| spec1 = FFESTP_readixSIZE; |
| if (ffestc_subr_speccmp_ ("No", |
| &ffestp_file.read.read_spec[FFESTP_readixADVANCE], |
| NULL, NULL) != 0) |
| { |
| whine_advance: /* :::::::::::::::::::: */ |
| if (ffestp_file.read.read_spec[FFESTP_readixADVANCE] |
| .kw_or_val_present) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec1].kw)); |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[FFESTP_readixADVANCE].kw)); |
| ffebad_finish (); |
| } |
| else |
| { |
| ffebad_start (FFEBAD_MISSING_ADVANCE_SPEC); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.read.read_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.read.read_spec[spec1].kw)); |
| ffebad_finish (); |
| } |
| |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| } |
| } |
| |
| if (unit == FFESTV_unitCHAREXPR) |
| ffestc_iolist_context_ = FFEEXPR_contextIOLISTDF; |
| else |
| ffestc_iolist_context_ = FFEEXPR_contextIOLIST; |
| |
| ffestd_R909_start (FALSE, unit, format, rec, key); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R909_item -- READ statement i/o item |
| |
| ffestc_R909_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_R909_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_namelist_ != 0) |
| { |
| if (ffestc_namelist_ == 1) |
| { |
| ffestc_namelist_ = 2; |
| ffebad_start (FFEBAD_NAMELIST_ITEMS); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| |
| ffestd_R909_item (expr, expr_token); |
| } |
| |
| /* ffestc_R909_finish -- READ statement list complete |
| |
| ffestc_R909_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R909_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R909_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R910_start -- WRITE(...) statement list begin |
| |
| ffestc_R910_start(); |
| |
| Verify that WRITE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R910_start () |
| { |
| ffestvUnit unit; |
| ffestvFormat format; |
| bool rec; |
| ffestpWriteIx spec1; |
| ffestpWriteIx spec2; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_branch_ |
| (&ffestp_file.write.write_spec[FFESTP_writeixEOR]) |
| || !ffestc_subr_is_branch_ |
| (&ffestp_file.write.write_spec[FFESTP_writeixERR]) |
| || !ffestc_subr_is_format_ |
| (&ffestp_file.write.write_spec[FFESTP_writeixFORMAT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.write.write_spec[FFESTP_writeixFORMAT]); |
| ffestc_namelist_ = (format == FFESTV_formatNAMELIST); |
| |
| unit = ffestc_subr_unit_ |
| (&ffestp_file.write.write_spec[FFESTP_writeixUNIT]); |
| if (unit == FFESTV_unitNONE) |
| { |
| ffebad_start (FFEBAD_NO_UNIT_SPEC); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| rec = ffestp_file.write.write_spec[FFESTP_writeixREC].kw_or_val_present; |
| |
| if (rec) |
| { |
| spec1 = FFESTP_writeixREC; |
| if (unit == FFESTV_unitCHAREXPR) |
| { |
| spec2 = FFESTP_writeixUNIT; |
| whine: /* :::::::::::::::::::: */ |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| assert (ffestp_file.write.write_spec[spec1].kw_or_val_present); |
| if (ffestp_file.write.write_spec[spec1].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec1].kw)); |
| } |
| else |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec1].value), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec1].value)); |
| } |
| assert (ffestp_file.write.write_spec[spec2].kw_or_val_present); |
| if (ffestp_file.write.write_spec[spec2].kw_present) |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec2].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec2].kw)); |
| } |
| else |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec2].value), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec2].value)); |
| } |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| if ((format == FFESTV_formatASTERISK) |
| || (format == FFESTV_formatNAMELIST)) |
| { |
| spec2 = FFESTP_writeixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.write.write_spec[FFESTP_writeixADVANCE].kw_or_val_present) |
| { |
| spec2 = FFESTP_writeixADVANCE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| else |
| { /* Sequential/Indexed/Internal. */ |
| if (unit == FFESTV_unitCHAREXPR) |
| { /* Internal file. */ |
| spec1 = FFESTP_writeixUNIT; |
| if (format == FFESTV_formatNAMELIST) |
| { |
| spec2 = FFESTP_writeixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| if (ffestp_file.write.write_spec[FFESTP_writeixADVANCE].kw_or_val_present) |
| { |
| spec2 = FFESTP_writeixADVANCE; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.write.write_spec[FFESTP_writeixADVANCE].kw_or_val_present) |
| { /* ADVANCE= specified. */ |
| spec1 = FFESTP_writeixADVANCE; |
| if (format == FFESTV_formatNONE) |
| { |
| ffebad_start (FFEBAD_MISSING_FORMAT_SPEC); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec1].kw)); |
| ffebad_finish (); |
| |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| if (format == FFESTV_formatNAMELIST) |
| { |
| spec2 = FFESTP_writeixFORMAT; |
| goto whine; /* :::::::::::::::::::: */ |
| } |
| } |
| if (ffestp_file.write.write_spec[FFESTP_writeixEOR].kw_or_val_present) |
| { /* EOR= specified. */ |
| spec1 = FFESTP_writeixEOR; |
| if (ffestc_subr_speccmp_ ("No", |
| &ffestp_file.write.write_spec[FFESTP_writeixADVANCE], |
| NULL, NULL) != 0) |
| { |
| if (ffestp_file.write.write_spec[FFESTP_writeixADVANCE] |
| .kw_or_val_present) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec1].kw)); |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.write.write_spec[FFESTP_writeixADVANCE].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[FFESTP_writeixADVANCE].kw)); |
| ffebad_finish (); |
| } |
| else |
| { |
| ffebad_start (FFEBAD_MISSING_ADVANCE_SPEC); |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.write.write_spec[spec1].kw), |
| ffelex_token_where_column |
| (ffestp_file.write.write_spec[spec1].kw)); |
| ffebad_finish (); |
| } |
| |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| } |
| } |
| |
| if (unit == FFESTV_unitCHAREXPR) |
| ffestc_iolist_context_ = FFEEXPR_contextIOLISTDF; |
| else |
| ffestc_iolist_context_ = FFEEXPR_contextIOLIST; |
| |
| ffestd_R910_start (unit, format, rec); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R910_item -- WRITE statement i/o item |
| |
| ffestc_R910_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_R910_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_namelist_ != 0) |
| { |
| if (ffestc_namelist_ == 1) |
| { |
| ffestc_namelist_ = 2; |
| ffebad_start (FFEBAD_NAMELIST_ITEMS); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| |
| ffestd_R910_item (expr, expr_token); |
| } |
| |
| /* ffestc_R910_finish -- WRITE statement list complete |
| |
| ffestc_R910_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R910_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R910_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R911_start -- PRINT(...) statement list begin |
| |
| ffestc_R911_start(); |
| |
| Verify that PRINT is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R911_start () |
| { |
| ffestvFormat format; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_format_ |
| (&ffestp_file.print.print_spec[FFESTP_printixFORMAT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.print.print_spec[FFESTP_printixFORMAT]); |
| ffestc_namelist_ = (format == FFESTV_formatNAMELIST); |
| |
| ffestd_R911_start (format); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R911_item -- PRINT statement i/o item |
| |
| ffestc_R911_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_R911_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_namelist_ != 0) |
| { |
| if (ffestc_namelist_ == 1) |
| { |
| ffestc_namelist_ = 2; |
| ffebad_start (FFEBAD_NAMELIST_ITEMS); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| |
| ffestd_R911_item (expr, expr_token); |
| } |
| |
| /* ffestc_R911_finish -- PRINT statement list complete |
| |
| ffestc_R911_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R911_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R911_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R919 -- BACKSPACE statement |
| |
| ffestc_R919(); |
| |
| Make sure a BACKSPACE is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R919 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.beru.beru_spec[FFESTP_beruixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.beru.beru_spec[FFESTP_beruixUNIT])) |
| ffestd_R919 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R920 -- ENDFILE statement |
| |
| ffestc_R920(); |
| |
| Make sure a ENDFILE is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R920 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.beru.beru_spec[FFESTP_beruixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.beru.beru_spec[FFESTP_beruixUNIT])) |
| ffestd_R920 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R921 -- REWIND statement |
| |
| ffestc_R921(); |
| |
| Make sure a REWIND is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R921 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.beru.beru_spec[FFESTP_beruixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.beru.beru_spec[FFESTP_beruixUNIT])) |
| ffestd_R921 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R923A -- INQUIRE statement (non-IOLENGTH version) |
| |
| ffestc_R923A(); |
| |
| Make sure an INQUIRE is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_R923A () |
| { |
| bool by_file; |
| bool by_unit; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.inquire.inquire_spec[FFESTP_inquireixERR])) |
| { |
| by_file = ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE] |
| .kw_or_val_present; |
| by_unit = ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT] |
| .kw_or_val_present; |
| if (by_file && by_unit) |
| { |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| assert (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].kw_or_val_present); |
| if (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].kw), |
| ffelex_token_where_column |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].kw)); |
| } |
| else |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].value), |
| ffelex_token_where_column |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixUNIT].value)); |
| } |
| assert (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].kw_or_val_present); |
| if (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].kw_present) |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].kw), |
| ffelex_token_where_column |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].kw)); |
| } |
| else |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].value), |
| ffelex_token_where_column |
| (ffestp_file.inquire.inquire_spec[FFESTP_inquireixFILE].value)); |
| } |
| ffebad_finish (); |
| } |
| else if (!by_file && !by_unit) |
| { |
| ffebad_start (FFEBAD_MISSING_SPECIFIER); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_string ("UNIT= or FILE="); |
| ffebad_finish (); |
| } |
| else |
| ffestd_R923A (by_file); |
| } |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R923B_start -- INQUIRE(IOLENGTH=expr) statement list begin |
| |
| ffestc_R923B_start(); |
| |
| Verify that INQUIRE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_R923B_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R923B_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R923B_item -- INQUIRE statement i/o item |
| |
| ffestc_R923B_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_R923B_item (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R923B_item (expr); |
| } |
| |
| /* ffestc_R923B_finish -- INQUIRE statement list complete |
| |
| ffestc_R923B_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R923B_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R923B_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R1001 -- FORMAT statement |
| |
| ffestc_R1001(format_list); |
| |
| Make sure format_list is valid. Update label's info to indicate it is a |
| FORMAT label, and (perhaps) warn if there is no label! */ |
| |
| void |
| ffestc_R1001 (ffesttFormatList f) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_format_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_format_ (); |
| |
| ffestd_R1001 (f); |
| } |
| |
| /* ffestc_R1102 -- PROGRAM statement |
| |
| ffestc_R1102(name_token); |
| |
| Make sure ffestc_kind_ identifies an empty block. Make sure name_token |
| gives a valid name. Implement the beginning of a main program. */ |
| |
| void |
| ffestc_R1102 (ffelexToken name) |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| assert (name != NULL); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_unit_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_blocknum_ = 0; |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_statePROGRAM0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_end_program_); |
| |
| ffestw_set_name (b, ffelex_token_use (name)); |
| |
| s = ffesymbol_declare_programunit (name, |
| ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindPROGRAM, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, name); |
| |
| ffestd_R1102 (s, name); |
| } |
| |
| /* ffestc_R1103 -- END PROGRAM statement |
| |
| ffestc_R1103(name_token); |
| |
| Make sure ffestc_kind_ identifies the current kind of program unit. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the current program unit. */ |
| |
| void |
| ffestc_R1103 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_program_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if (name != NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_PROGRAM_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0) |
| { |
| ffebad_start (FFEBAD_UNIT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestc_shriek_end_program_ (TRUE); |
| } |
| |
| /* ffestc_R1105 -- MODULE statement |
| |
| ffestc_R1105(name_token); |
| |
| Make sure ffestc_kind_ identifies an empty block. Make sure name_token |
| gives a valid name. Implement the beginning of a module. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R1105 (ffelexToken name) |
| { |
| ffestw b; |
| |
| assert (name != NULL); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_unit_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_blocknum_ = 0; |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateMODULE0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_module_); |
| ffestw_set_name (b, ffelex_token_use (name)); |
| |
| ffestd_R1105 (name); |
| } |
| |
| /* ffestc_R1106 -- END MODULE statement |
| |
| ffestc_R1106(name_token); |
| |
| Make sure ffestc_kind_ identifies the current kind of program unit. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the current program unit. */ |
| |
| void |
| ffestc_R1106 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_module_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if ((name != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0)) |
| { |
| ffebad_start (FFEBAD_UNIT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_module_ (TRUE); |
| } |
| |
| /* ffestc_R1107_start -- USE statement list begin |
| |
| ffestc_R1107_start(); |
| |
| Verify that USE is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R1107_start (ffelexToken name, bool only) |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_use_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R1107_start (name, only); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R1107_item -- USE statement for name |
| |
| ffestc_R1107_item(local_token,use_token); |
| |
| Make sure name_token identifies a valid object to be USEed. local_token |
| may be NULL if _start_ was called with only==TRUE. */ |
| |
| void |
| ffestc_R1107_item (ffelexToken local, ffelexToken use) |
| { |
| ffestc_check_item_ (); |
| assert (use != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1107_item (local, use); |
| } |
| |
| /* ffestc_R1107_finish -- USE statement list complete |
| |
| ffestc_R1107_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R1107_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1107_finish (); |
| } |
| |
| #endif |
| /* ffestc_R1111 -- BLOCK DATA statement |
| |
| ffestc_R1111(name_token); |
| |
| Make sure ffestc_kind_ identifies no current program unit. If not |
| NULL, make sure name_token gives a valid name. Implement the beginning |
| of a block data program unit. */ |
| |
| void |
| ffestc_R1111 (ffelexToken name) |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_unit_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_blocknum_ = 0; |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateBLOCKDATA0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_blockdata_); |
| |
| if (name == NULL) |
| ffestw_set_name (b, NULL); |
| else |
| ffestw_set_name (b, ffelex_token_use (name)); |
| |
| s = ffesymbol_declare_blockdataunit (name, |
| ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindBLOCKDATA, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| ffesymbol_error (s, name); |
| |
| ffestd_R1111 (s, name); |
| } |
| |
| /* ffestc_R1112 -- END BLOCK DATA statement |
| |
| ffestc_R1112(name_token); |
| |
| Make sure ffestc_kind_ identifies the current kind of program unit. If not |
| NULL, make sure name_token gives the correct name. Implement the end |
| of the current program unit. */ |
| |
| void |
| ffestc_R1112 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_blockdata_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (name != NULL) |
| { |
| if (ffestw_name (ffestw_stack_top ()) == NULL) |
| { |
| ffebad_start (FFEBAD_BLOCKDATA_NOT_NAMED); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| else if (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0) |
| { |
| ffebad_start (FFEBAD_UNIT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| } |
| |
| ffestc_shriek_blockdata_ (TRUE); |
| } |
| |
| /* ffestc_R1202 -- INTERFACE statement |
| |
| ffestc_R1202(operator,defined_name); |
| |
| Make sure ffestc_kind_ identifies an INTERFACE block. |
| Implement the end of the current interface. |
| |
| 15-May-90 JCB 1.1 |
| Allow no operator or name to mean INTERFACE by itself; missed this |
| valid form when originally doing syntactic analysis code. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R1202 (ffestpDefinedOperator operator, ffelexToken name) |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_interfacespec_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateINTERFACE0); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_interface_); |
| |
| if ((operator == FFESTP_definedoperatorNone) && (name == NULL)) |
| ffestw_set_substate (b, 0); /* No generic-spec, so disallow MODULE |
| PROCEDURE. */ |
| else |
| ffestw_set_substate (b, 1); /* MODULE PROCEDURE ok. */ |
| |
| ffestd_R1202 (operator, name); |
| |
| ffe_init_4 (); |
| } |
| |
| /* ffestc_R1203 -- END INTERFACE statement |
| |
| ffestc_R1203(); |
| |
| Make sure ffestc_kind_ identifies an INTERFACE block. |
| Implement the end of the current interface. */ |
| |
| void |
| ffestc_R1203 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_interface_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_shriek_interface_ (TRUE); |
| |
| ffe_terminate_4 (); |
| } |
| |
| /* ffestc_R1205_start -- MODULE PROCEDURE statement list begin |
| |
| ffestc_R1205_start(); |
| |
| Verify that MODULE PROCEDURE is valid here, and begin accepting items in |
| the list. */ |
| |
| void |
| ffestc_R1205_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_interface_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) == 0) |
| { |
| ffebad_start (FFEBAD_INVALID_MODULE_PROCEDURE); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| if (ffestw_state (ffestw_stack_top ()) == FFESTV_stateINTERFACE0) |
| { |
| ffestw_update (NULL); /* Update state line/col info. */ |
| ffestw_set_state (ffestw_stack_top (), FFESTV_stateINTERFACE1); |
| } |
| |
| ffestd_R1205_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R1205_item -- MODULE PROCEDURE statement for name |
| |
| ffestc_R1205_item(name_token); |
| |
| Make sure name_token identifies a valid object to be MODULE PROCEDUREed. */ |
| |
| void |
| ffestc_R1205_item (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1205_item (name); |
| } |
| |
| /* ffestc_R1205_finish -- MODULE PROCEDURE statement list complete |
| |
| ffestc_R1205_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R1205_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1205_finish (); |
| } |
| |
| #endif |
| /* ffestc_R1207_start -- EXTERNAL statement list begin |
| |
| ffestc_R1207_start(); |
| |
| Verify that EXTERNAL is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R1207_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R1207_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R1207_item -- EXTERNAL statement for name |
| |
| ffestc_R1207_item(name_token); |
| |
| Make sure name_token identifies a valid object to be EXTERNALd. */ |
| |
| void |
| ffestc_R1207_item (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (!(sa & ~(FFESYMBOL_attrsDUMMY |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsEXTERNAL; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_explicitwhere (s, TRUE); |
| ffesymbol_reference (s, name, FALSE); |
| ffesymbol_signal_unreported (s); |
| } |
| |
| ffestd_R1207_item (name); |
| } |
| |
| /* ffestc_R1207_finish -- EXTERNAL statement list complete |
| |
| ffestc_R1207_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R1207_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1207_finish (); |
| } |
| |
| /* ffestc_R1208_start -- INTRINSIC statement list begin |
| |
| ffestc_R1208_start(); |
| |
| Verify that INTRINSIC is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_R1208_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R1208_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R1208_item -- INTRINSIC statement for name |
| |
| ffestc_R1208_item(name_token); |
| |
| Make sure name_token identifies a valid object to be INTRINSICd. */ |
| |
| void |
| ffestc_R1208_item (ffelexToken name) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffeintrinGen gen; |
| ffeintrinSpec spec; |
| ffeintrinImp imp; |
| |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| s = ffesymbol_declare_local (name, TRUE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = sa; |
| else if (!(sa & ~FFESYMBOL_attrsTYPE)) |
| { |
| if (ffeintrin_is_intrinsic (ffelex_token_text (name), name, TRUE, |
| &gen, &spec, &imp) |
| && ((imp == FFEINTRIN_impNONE) |
| #if 0 /* Don't bother with this for now. */ |
| || ((ffeintrin_basictype (spec) |
| == ffesymbol_basictype (s)) |
| && (ffeintrin_kindtype (spec) |
| == ffesymbol_kindtype (s))) |
| #else |
| || 1 |
| #endif |
| || !(sa & FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsINTRINSIC; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| } |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| else if (!(na & FFESYMBOL_attrsANY)) |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| 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_kindNONE, |
| FFEINFO_whereINTRINSIC, |
| ffesymbol_size (s))); |
| ffesymbol_set_explicitwhere (s, TRUE); |
| ffesymbol_reference (s, name, TRUE); |
| } |
| |
| ffesymbol_signal_unreported (s); |
| |
| ffestd_R1208_item (name); |
| } |
| |
| /* ffestc_R1208_finish -- INTRINSIC statement list complete |
| |
| ffestc_R1208_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_R1208_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_R1208_finish (); |
| } |
| |
| /* ffestc_R1212 -- CALL statement |
| |
| ffestc_R1212(expr,expr_token); |
| |
| Make sure statement is valid here; implement. */ |
| |
| void |
| ffestc_R1212 (ffebld expr, ffelexToken expr_token UNUSED) |
| { |
| ffebld item; /* ITEM. */ |
| ffebld labexpr; /* LABTOK=>LABTER. */ |
| ffelab label; |
| bool ok; /* TRUE if all LABTOKs were ok. */ |
| bool ok1; /* TRUE if a particular LABTOK is ok. */ |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffebld_op (expr) != FFEBLD_opSUBRREF) |
| ffestd_R841 (FALSE); /* CONTINUE. */ |
| else |
| { |
| ok = TRUE; |
| |
| for (item = ffebld_right (expr); |
| item != NULL; |
| item = ffebld_trail (item)) |
| { |
| if (((labexpr = ffebld_head (item)) != NULL) |
| && (ffebld_op (labexpr) == FFEBLD_opLABTOK)) |
| { |
| ok1 = ffestc_labelref_is_branch_ (ffebld_labtok (labexpr), |
| &label); |
| ffelex_token_kill (ffebld_labtok (labexpr)); |
| if (!ok1) |
| { |
| label = NULL; |
| ok = FALSE; |
| } |
| ffebld_set_op (labexpr, FFEBLD_opLABTER); |
| ffebld_set_labter (labexpr, label); |
| } |
| } |
| |
| if (ok) |
| ffestd_R1212 (expr); |
| } |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R1213 -- Defined assignment statement |
| |
| ffestc_R1213(dest_expr,source_expr,source_token); |
| |
| Make sure the assignment is valid. */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R1213 (ffebld dest, ffebld source, ffelexToken source_token) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_R1213 (dest, source); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| #endif |
| /* ffestc_R1219 -- FUNCTION statement |
| |
| ffestc_R1219(funcname,arglist,ending_token,kind,kindt,len,lent, |
| recursive); |
| |
| Make sure statement is valid here, register arguments for the |
| function name, and so on. |
| |
| 06-Apr-90 JCB 2.0 |
| Added the kind, len, and recursive arguments. */ |
| |
| void |
| ffestc_R1219 (ffelexToken funcname, ffesttTokenList args, |
| ffelexToken final UNUSED, ffestpType type, ffebld kind, |
| ffelexToken kindt, ffebld len, ffelexToken lent, |
| ffelexToken recursive, ffelexToken result) |
| { |
| ffestw b; |
| ffesymbol s; |
| ffesymbol fs; /* FUNCTION symbol when dealing with RESULT |
| symbol. */ |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| ffelexToken res; |
| bool separate_result; |
| |
| assert ((funcname != NULL) |
| && (ffelex_token_type (funcname) == FFELEX_typeNAME)); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_iface_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_blocknum_ = 0; |
| ffesta_is_entry_valid = |
| (ffestw_state (ffestw_stack_top ()) == FFESTV_stateNIL); |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateFUNCTION0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_function_); |
| ffestw_set_name (b, ffelex_token_use (funcname)); |
| |
| if (type == FFESTP_typeNone) |
| { |
| ffestc_local_.decl.basic_type = FFEINFO_basictypeNONE; |
| ffestc_local_.decl.kind_type = FFEINFO_kindtypeNONE; |
| ffestc_local_.decl.size = FFETARGET_charactersizeNONE; |
| } |
| else |
| { |
| ffestc_establish_declstmt_ (type, ffesta_tokens[0], |
| kind, kindt, len, lent); |
| ffestc_establish_declinfo_ (NULL, NULL, NULL, NULL); |
| } |
| |
| separate_result = (result != NULL) |
| && (ffelex_token_strcmp (funcname, result) != 0); |
| |
| if (separate_result) |
| fs = ffesymbol_declare_funcnotresunit (funcname); /* Global/local. */ |
| else |
| fs = ffesymbol_declare_funcunit (funcname); /* Global only. */ |
| |
| if (ffesymbol_state (fs) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (fs, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_signal_unreported (fs); |
| |
| /* Note that .basic_type and .kind_type might be NONE here. */ |
| |
| ffesymbol_set_info (fs, |
| ffeinfo_new (ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| 0, |
| FFEINFO_kindFUNCTION, |
| FFEINFO_whereLOCAL, |
| ffestc_local_.decl.size)); |
| |
| /* Check whether the type info fits the filewide expectations; |
| set ok flag accordingly. */ |
| |
| ffesymbol_reference (fs, funcname, FALSE); |
| if (ffesymbol_attrs (fs) & FFESYMBOL_attrsANY) |
| ffestc_parent_ok_ = FALSE; |
| else |
| ffestc_parent_ok_ = TRUE; |
| } |
| else |
| { |
| if (ffesymbol_kind (fs) != FFEINFO_kindANY) |
| ffesymbol_error (fs, funcname); |
| ffestc_parent_ok_ = FALSE; |
| } |
| |
| if (ffestc_parent_ok_) |
| { |
| ffebld_init_list (&fs->dummy_args, &ffestc_local_.dummy.list_bottom); |
| ffestt_tokenlist_drive (args, ffestc_promote_dummy_); |
| ffebld_end_list (&ffestc_local_.dummy.list_bottom); |
| } |
| |
| if (result == NULL) |
| res = funcname; |
| else |
| res = result; |
| |
| s = ffesymbol_declare_funcresult (res); |
| 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_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (ffesymbol_state (s) != FFESYMBOL_stateNONE) |
| na = FFESYMBOL_attrsetNONE; |
| else |
| { |
| na = FFESYMBOL_attrsRESULT; |
| if (ffestc_local_.decl.basic_type != FFEINFO_basictypeNONE) |
| { |
| na |= FFESYMBOL_attrsTYPE; |
| if ((ffestc_local_.decl.basic_type == FFEINFO_basictypeCHARACTER) |
| && (ffestc_local_.decl.size == FFETARGET_charactersizeNONE)) |
| na |= FFESYMBOL_attrsANYLEN; |
| } |
| } |
| |
| /* 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_attrsANY) == FFESYMBOL_attrsetNONE) |
| { |
| if (!(na & FFESYMBOL_attrsANY)) |
| ffesymbol_error (s, res); |
| ffesymbol_set_funcresult (fs, NULL); |
| ffesymbol_set_funcresult (s, NULL); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| ffesymbol_set_funcresult (fs, s); |
| ffesymbol_set_funcresult (s, fs); |
| if (ffestc_local_.decl.basic_type != FFEINFO_basictypeNONE) |
| { |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffestc_local_.decl.basic_type, |
| ffestc_local_.decl.kind_type, |
| 0, |
| FFEINFO_kindNONE, |
| FFEINFO_whereNONE, |
| ffestc_local_.decl.size)); |
| } |
| } |
| |
| ffesymbol_signal_unreported (fs); |
| |
| ffestd_R1219 (fs, funcname, args, type, kind, kindt, len, lent, |
| (recursive != NULL), result, separate_result); |
| } |
| |
| /* ffestc_R1221 -- END FUNCTION statement |
| |
| ffestc_R1221(name_token); |
| |
| Make sure ffestc_kind_ identifies the current kind of program unit. If |
| not NULL, make sure name_token gives the correct name. Implement the end |
| of the current program unit. */ |
| |
| void |
| ffestc_R1221 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_function_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if ((name != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0)) |
| { |
| ffebad_start (FFEBAD_UNIT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_function_ (TRUE); |
| } |
| |
| /* ffestc_R1223 -- SUBROUTINE statement |
| |
| ffestc_R1223(subrname,arglist,ending_token,recursive_token); |
| |
| Make sure statement is valid here, register arguments for the |
| subroutine name, and so on. |
| |
| 06-Apr-90 JCB 2.0 |
| Added the recursive argument. */ |
| |
| void |
| ffestc_R1223 (ffelexToken subrname, ffesttTokenList args, |
| ffelexToken final, ffelexToken recursive) |
| { |
| ffestw b; |
| ffesymbol s; |
| |
| assert ((subrname != NULL) |
| && (ffelex_token_type (subrname) == FFELEX_typeNAME)); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_iface_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestc_blocknum_ = 0; |
| ffesta_is_entry_valid |
| = (ffestw_state (ffestw_stack_top ()) == FFESTV_stateNIL); |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateSUBROUTINE0); |
| ffestw_set_blocknum (b, ffestc_blocknum_++); |
| ffestw_set_shriek (b, ffestc_shriek_subroutine_); |
| ffestw_set_name (b, ffelex_token_use (subrname)); |
| |
| s = ffesymbol_declare_subrunit (subrname); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindSUBROUTINE, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| ffestc_parent_ok_ = TRUE; |
| } |
| else |
| { |
| if (ffesymbol_kind (s) != FFEINFO_kindANY) |
| ffesymbol_error (s, subrname); |
| ffestc_parent_ok_ = FALSE; |
| } |
| |
| if (ffestc_parent_ok_) |
| { |
| ffebld_init_list (&s->dummy_args, &ffestc_local_.dummy.list_bottom); |
| ffestt_tokenlist_drive (args, ffestc_promote_dummy_); |
| ffebld_end_list (&ffestc_local_.dummy.list_bottom); |
| } |
| |
| ffesymbol_signal_unreported (s); |
| |
| ffestd_R1223 (s, subrname, args, final, (recursive != NULL)); |
| } |
| |
| /* ffestc_R1225 -- END SUBROUTINE statement |
| |
| ffestc_R1225(name_token); |
| |
| Make sure ffestc_kind_ identifies the current kind of program unit. If |
| not NULL, make sure name_token gives the correct name. Implement the end |
| of the current program unit. */ |
| |
| void |
| ffestc_R1225 (ffelexToken name) |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_subroutine_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_ (); |
| |
| if ((name != NULL) |
| && (ffelex_token_strcmp (name, ffestw_name (ffestw_stack_top ())) != 0)) |
| { |
| ffebad_start (FFEBAD_UNIT_WRONG_NAME); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_here (1, ffelex_token_where_line (ffestw_name (ffestw_stack_top ())), |
| ffelex_token_where_column (ffestw_name (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_subroutine_ (TRUE); |
| } |
| |
| /* ffestc_R1226 -- ENTRY statement |
| |
| ffestc_R1226(entryname,arglist,ending_token); |
| |
| Make sure we're in a SUBROUTINE or FUNCTION, register arguments for the |
| entry point name, and so on. */ |
| |
| void |
| ffestc_R1226 (ffelexToken entryname, ffesttTokenList args, |
| ffelexToken final UNUSED) |
| { |
| ffesymbol s; |
| ffesymbol fs; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| bool in_spec; /* TRUE if further specification statements |
| may follow, FALSE if executable stmts. */ |
| bool in_func; /* TRUE if ENTRY is a FUNCTION, not |
| SUBROUTINE. */ |
| |
| assert ((entryname != NULL) |
| && (ffelex_token_type (entryname) == FFELEX_typeNAME)); |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_entry_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateFUNCTION1: |
| case FFESTV_stateFUNCTION2: |
| case FFESTV_stateFUNCTION3: |
| in_func = TRUE; |
| in_spec = TRUE; |
| break; |
| |
| case FFESTV_stateFUNCTION4: |
| in_func = TRUE; |
| in_spec = FALSE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE1: |
| case FFESTV_stateSUBROUTINE2: |
| case FFESTV_stateSUBROUTINE3: |
| in_func = FALSE; |
| in_spec = TRUE; |
| break; |
| |
| case FFESTV_stateSUBROUTINE4: |
| in_func = FALSE; |
| in_spec = FALSE; |
| break; |
| |
| default: |
| assert ("ENTRY not in FUNCTION or SUBROUTINE?" == NULL); |
| in_func = FALSE; |
| in_spec = FALSE; |
| break; |
| } |
| |
| if (in_func) |
| fs = ffesymbol_declare_funcunit (entryname); |
| else |
| fs = ffesymbol_declare_subrunit (entryname); |
| |
| if (ffesymbol_state (fs) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (fs, FFESYMBOL_stateUNDERSTOOD); |
| else |
| { |
| if (ffesymbol_kind (fs) != FFEINFO_kindANY) |
| ffesymbol_error (fs, entryname); |
| } |
| |
| ++ffestc_entry_num_; |
| |
| ffebld_init_list (&fs->dummy_args, &ffestc_local_.dummy.list_bottom); |
| if (in_spec) |
| ffestt_tokenlist_drive (args, ffestc_promote_dummy_); |
| else |
| ffestt_tokenlist_drive (args, ffestc_promote_execdummy_); |
| ffebld_end_list (&ffestc_local_.dummy.list_bottom); |
| |
| if (in_func) |
| { |
| s = ffesymbol_declare_funcresult (entryname); |
| ffesymbol_set_funcresult (fs, s); |
| ffesymbol_set_funcresult (s, fs); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous |
| declarations of or references to the object. */ |
| |
| if (ffesymbol_state (s) == FFESYMBOL_stateUNDERSTOOD) |
| na = FFESYMBOL_attrsetNONE; |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (!(sa & ~(FFESYMBOL_attrsANYLEN |
| | FFESYMBOL_attrsTYPE))) |
| na = sa | FFESYMBOL_attrsRESULT; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, entryname); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else if (na & FFESYMBOL_attrsANY) |
| { |
| ffestc_parent_ok_ = FALSE; |
| } |
| else |
| { |
| ffesymbol_set_attrs (s, na); |
| if (ffesymbol_state (s) == FFESYMBOL_stateNONE) |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| else if (ffesymbol_state (s) == FFESYMBOL_stateUNCERTAIN) |
| { |
| ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD); |
| ffesymbol_set_info (s, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| FFEINFO_kindENTITY, |
| FFEINFO_whereRESULT, |
| ffesymbol_size (s))); |
| ffesymbol_resolve_intrin (s); |
| ffestorag_exec_layout (s); |
| } |
| } |
| |
| /* Since ENTRY might appear after executable stmts, do what would have |
| been done if it hadn't -- give symbol implicit type and |
| exec-transition it. */ |
| |
| if (!in_spec && ffesymbol_is_specable (s)) |
| { |
| if (!ffeimplic_establish_symbol (s)) /* Do implicit typing. */ |
| ffesymbol_error (s, entryname); |
| s = ffecom_sym_exec_transition (s); |
| } |
| |
| /* Use whatever type info is available for ENTRY to set up type for its |
| global-name-space function symbol relative. */ |
| |
| ffesymbol_set_info (fs, |
| ffeinfo_new (ffesymbol_basictype (s), |
| ffesymbol_kindtype (s), |
| 0, |
| FFEINFO_kindFUNCTION, |
| FFEINFO_whereLOCAL, |
| ffesymbol_size (s))); |
| |
| |
| /* Check whether the type info fits the filewide expectations; |
| set ok flag accordingly. */ |
| |
| ffesymbol_reference (fs, entryname, FALSE); |
| |
| /* ~~Question??: |
| When ENTRY FOO() RESULT(IBAR) is supported, what will the typing be |
| if FOO and IBAR would normally end up with different types? I think |
| the answer is that FOO is always given whatever type would be chosen |
| for IBAR, rather than the other way around, and I think it ends up |
| working that way for FUNCTION FOO() RESULT(IBAR), but this should be |
| checked out in all its different combos. Related question is, is |
| there any way that FOO in either case ends up without type info |
| filled in? Does anyone care? */ |
| |
| ffesymbol_signal_unreported (s); |
| } |
| else |
| { |
| ffesymbol_set_info (fs, |
| ffeinfo_new (FFEINFO_basictypeNONE, |
| FFEINFO_kindtypeNONE, |
| 0, |
| FFEINFO_kindSUBROUTINE, |
| FFEINFO_whereLOCAL, |
| FFETARGET_charactersizeNONE)); |
| } |
| |
| if (!in_spec) |
| fs = ffecom_sym_exec_transition (fs); |
| |
| ffesymbol_signal_unreported (fs); |
| |
| ffestd_R1226 (fs); |
| } |
| |
| /* ffestc_R1227 -- RETURN statement |
| |
| ffestc_R1227(expr,expr_token); |
| |
| Make sure statement is valid here; implement. expr and expr_token are |
| both NULL if there was no expression. */ |
| |
| void |
| ffestc_R1227 (ffebld expr, ffelexToken expr_token) |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_notloop_begin_ (); |
| |
| for (b = ffestw_stack_top (); ; b = ffestw_previous (b)) |
| { |
| switch (ffestw_state (b)) |
| { |
| case FFESTV_statePROGRAM4: |
| case FFESTV_stateSUBROUTINE4: |
| case FFESTV_stateFUNCTION4: |
| goto base; /* :::::::::::::::::::: */ |
| |
| case FFESTV_stateNIL: |
| assert ("bad state" == NULL); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| base: |
| switch (ffestw_state (b)) |
| { |
| case FFESTV_statePROGRAM4: |
| if (ffe_is_pedantic ()) |
| { |
| ffebad_start (FFEBAD_RETURN_IN_MAIN); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| } |
| if (expr != NULL) |
| { |
| ffebad_start (FFEBAD_ALTRETURN_IN_PROGRAM); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| expr = NULL; |
| } |
| break; |
| |
| case FFESTV_stateSUBROUTINE4: |
| break; |
| |
| case FFESTV_stateFUNCTION4: |
| if (expr != NULL) |
| { |
| ffebad_start (FFEBAD_ALTRETURN_IN_FUNCTION); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| expr = NULL; |
| } |
| break; |
| |
| default: |
| assert ("bad state #2" == NULL); |
| break; |
| } |
| |
| ffestd_R1227 (expr); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| |
| /* notloop's that are actionif's can be the target of a loop-end |
| statement if they're in the "then" part of a logical IF, as |
| in "DO 10", "10 IF (...) RETURN". */ |
| |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_R1228 -- CONTAINS statement |
| |
| ffestc_R1228(); */ |
| |
| #if FFESTR_F90 |
| void |
| ffestc_R1228 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_contains_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_R1228 (); |
| |
| ffe_terminate_3 (); |
| ffe_init_3 (); |
| } |
| |
| #endif |
| /* ffestc_R1229_start -- STMTFUNCTION statement begin |
| |
| ffestc_R1229_start(func_name,func_arg_list,close_paren); |
| |
| Verify that STMTFUNCTION is valid here, establish func_arg_list in a new |
| "live" scope within the current scope, and expect the actual expression |
| (or NULL) in ffestc_R1229_finish. The reason there are two ffestc |
| functions to handle this is so the scope can be established, allowing |
| ffeexpr to assign proper characteristics to references to the dummy |
| arguments. */ |
| |
| void |
| ffestc_R1229_start (ffelexToken name, ffesttTokenList args, |
| ffelexToken final UNUSED) |
| { |
| ffesymbol s; |
| ffesymbolAttrs sa; |
| ffesymbolAttrs na; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_sfunc_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| assert (name != NULL); |
| assert (args != NULL); |
| |
| s = ffesymbol_declare_local (name, FALSE); |
| sa = ffesymbol_attrs (s); |
| |
| /* Figure out what kind of object we've got based on previous declarations |
| of or references to the object. */ |
| |
| if (!ffesymbol_is_specable (s)) |
| na = FFESYMBOL_attrsetNONE; /* Can't dcl sym ref'd in sfuncdef. */ |
| else if (sa & FFESYMBOL_attrsANY) |
| na = FFESYMBOL_attrsANY; |
| else if (!(sa & ~FFESYMBOL_attrsTYPE)) |
| na = sa | FFESYMBOL_attrsSFUNC; |
| else |
| na = FFESYMBOL_attrsetNONE; |
| |
| /* 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, name); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else if (na & FFESYMBOL_attrsANY) |
| ffestc_parent_ok_ = FALSE; |
| else |
| { |
| ffesymbol_set_attrs (s, na); |
| ffesymbol_set_state (s, FFESYMBOL_stateSEEN); |
| if (!ffeimplic_establish_symbol (s) |
| || ((ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER) |
| && (ffesymbol_size (s) == FFETARGET_charactersizeNONE))) |
| { |
| ffesymbol_error (s, ffesta_tokens[0]); |
| ffestc_parent_ok_ = FALSE; |
| } |
| else |
| { |
| /* Tell ffeexpr that sfunc def is in progress. */ |
| ffesymbol_set_sfexpr (s, ffebld_new_any ()); |
| ffebld_set_info (ffesymbol_sfexpr (s), ffeinfo_new_any ()); |
| ffestc_parent_ok_ = TRUE; |
| } |
| } |
| |
| ffe_init_4 (); |
| |
| if (ffestc_parent_ok_) |
| { |
| ffebld_init_list (&s->dummy_args, &ffestc_local_.dummy.list_bottom); |
| ffestc_sfdummy_argno_ = 0; |
| ffestt_tokenlist_drive (args, ffestc_promote_sfdummy_); |
| ffebld_end_list (&ffestc_local_.dummy.list_bottom); |
| } |
| |
| ffestc_local_.sfunc.symbol = s; |
| |
| ffestd_R1229_start (name, args); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_R1229_finish -- STMTFUNCTION statement list complete |
| |
| ffestc_R1229_finish(expr,expr_token); |
| |
| If expr is NULL, an error occurred parsing the expansion expression, so |
| just cancel the effects of ffestc_R1229_start and pretend nothing |
| happened. Otherwise, install the expression as the expansion for the |
| statement function named in _start_, then clean up. */ |
| |
| void |
| ffestc_R1229_finish (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_parent_ok_ && (expr != NULL)) |
| ffesymbol_set_sfexpr (ffestc_local_.sfunc.symbol, |
| ffeexpr_convert_to_sym (expr, |
| expr_token, |
| ffestc_local_.sfunc.symbol, |
| ffesta_tokens[0])); |
| |
| ffestd_R1229_finish (ffestc_local_.sfunc.symbol); |
| |
| ffesymbol_signal_unreported (ffestc_local_.sfunc.symbol); |
| |
| ffe_terminate_4 (); |
| } |
| |
| /* ffestc_S3P4 -- INCLUDE line |
| |
| ffestc_S3P4(filename,filename_token); |
| |
| Make sure INCLUDE not preceded by any semicolons or a label def; implement. */ |
| |
| void |
| ffestc_S3P4 (ffebld filename, ffelexToken filename_token UNUSED) |
| { |
| ffestc_check_simple_ (); |
| ffestc_labeldef_invalid_ (); |
| |
| ffestd_S3P4 (filename); |
| } |
| |
| /* ffestc_V003_start -- STRUCTURE statement list begin |
| |
| ffestc_V003_start(structure_name); |
| |
| Verify that STRUCTURE is valid here, and begin accepting items in the list. */ |
| |
| #if FFESTR_VXT |
| void |
| ffestc_V003_start (ffelexToken structure_name) |
| { |
| ffestw b; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_vxtstructure_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| ffestc_local_.V003.list_state = 2; /* Require at least one field |
| name. */ |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen at least one |
| member. */ |
| break; |
| |
| default: |
| ffestc_local_.V003.list_state = 0; /* No field names required. */ |
| if (structure_name == NULL) |
| { |
| ffebad_start (FFEBAD_STRUCT_MISSING_NAME); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_finish (); |
| } |
| break; |
| } |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateSTRUCTURE); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_structure_); |
| ffestw_set_substate (b, 0); /* No field-declarations seen yet. */ |
| |
| ffestd_V003_start (structure_name); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V003_item -- STRUCTURE statement for object-name |
| |
| ffestc_V003_item(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be STRUCTUREd. */ |
| |
| void |
| ffestc_V003_item (ffelexToken name, ffesttDimList dims) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_local_.V003.list_state < 2) |
| { |
| if (ffestc_local_.V003.list_state == 0) |
| { |
| ffestc_local_.V003.list_state = 1; |
| ffebad_start (FFEBAD_STRUCT_IGNORING_FIELD); |
| ffebad_here (0, ffelex_token_where_line (name), |
| ffelex_token_where_column (name)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| ffestc_local_.V003.list_state = 3; /* Have at least one field name. */ |
| |
| if (dims != NULL) |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_V003_item (name, dims); |
| } |
| |
| /* ffestc_V003_finish -- STRUCTURE statement list complete |
| |
| ffestc_V003_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V003_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_local_.V003.list_state == 2) |
| { |
| ffebad_start (FFEBAD_STRUCT_MISSING_FIELD); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_previous (ffestw_stack_top ())), |
| ffestw_col (ffestw_previous (ffestw_stack_top ()))); |
| ffebad_finish (); |
| } |
| |
| ffestd_V003_finish (); |
| } |
| |
| /* ffestc_V004 -- END STRUCTURE statement |
| |
| ffestc_V004(); |
| |
| Make sure ffestc_kind_ identifies a STRUCTURE block. |
| Implement the end of the current STRUCTURE block. */ |
| |
| void |
| ffestc_V004 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_structure_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 1) |
| { |
| ffebad_start (FFEBAD_STRUCT_NO_COMPONENTS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_structure_ (TRUE); |
| } |
| |
| /* ffestc_V009 -- UNION statement |
| |
| ffestc_V009(); */ |
| |
| void |
| ffestc_V009 () |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_structure_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen at least one member. */ |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateUNION); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_union_); |
| ffestw_set_substate (b, 0); /* No map decls seen yet. */ |
| |
| ffestd_V009 (); |
| } |
| |
| /* ffestc_V010 -- END UNION statement |
| |
| ffestc_V010(); |
| |
| Make sure ffestc_kind_ identifies a UNION block. |
| Implement the end of the current UNION block. */ |
| |
| void |
| ffestc_V010 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_union_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 2) |
| { |
| ffebad_start (FFEBAD_UNION_NO_TWO_MAPS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_union_ (TRUE); |
| } |
| |
| /* ffestc_V012 -- MAP statement |
| |
| ffestc_V012(); */ |
| |
| void |
| ffestc_V012 () |
| { |
| ffestw b; |
| |
| ffestc_check_simple_ (); |
| if (ffestc_order_union_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 2) |
| ffestw_substate (ffestw_stack_top ())++; /* 0=>1, 1=>2. */ |
| |
| b = ffestw_update (ffestw_push (NULL)); |
| ffestw_set_top_do (b, NULL); |
| ffestw_set_state (b, FFESTV_stateMAP); |
| ffestw_set_blocknum (b, 0); |
| ffestw_set_shriek (b, ffestc_shriek_map_); |
| ffestw_set_substate (b, 0); /* No field-declarations seen yet. */ |
| |
| ffestd_V012 (); |
| } |
| |
| /* ffestc_V013 -- END MAP statement |
| |
| ffestc_V013(); |
| |
| Make sure ffestc_kind_ identifies a MAP block. |
| Implement the end of the current MAP block. */ |
| |
| void |
| ffestc_V013 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_map_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_useless_ (); |
| |
| if (ffestw_substate (ffestw_stack_top ()) != 1) |
| { |
| ffebad_start (FFEBAD_MAP_NO_COMPONENTS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| ffebad_here (1, ffestw_line (ffestw_stack_top ()), ffestw_col (ffestw_stack_top ())); |
| ffebad_finish (); |
| } |
| |
| ffestc_shriek_map_ (TRUE); |
| } |
| |
| #endif |
| /* ffestc_V014_start -- VOLATILE statement list begin |
| |
| ffestc_V014_start(); |
| |
| Verify that VOLATILE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V014_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_progspec_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_V014_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V014_item_object -- VOLATILE statement for object-name |
| |
| ffestc_V014_item_object(name_token); |
| |
| Make sure name_token identifies a valid object to be VOLATILEd. */ |
| |
| void |
| ffestc_V014_item_object (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V014_item_object (name); |
| } |
| |
| /* ffestc_V014_item_cblock -- VOLATILE statement for common-block-name |
| |
| ffestc_V014_item_cblock(name_token); |
| |
| Make sure name_token identifies a valid common block to be VOLATILEd. */ |
| |
| void |
| ffestc_V014_item_cblock (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V014_item_cblock (name); |
| } |
| |
| /* ffestc_V014_finish -- VOLATILE statement list complete |
| |
| ffestc_V014_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V014_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V014_finish (); |
| } |
| |
| /* ffestc_V016_start -- RECORD statement list begin |
| |
| ffestc_V016_start(); |
| |
| Verify that RECORD is valid here, and begin accepting items in the list. */ |
| |
| #if FFESTR_VXT |
| void |
| ffestc_V016_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_record_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| switch (ffestw_state (ffestw_stack_top ())) |
| { |
| case FFESTV_stateSTRUCTURE: |
| case FFESTV_stateMAP: |
| ffestw_set_substate (ffestw_stack_top (), 1); /* Seen at least one |
| member. */ |
| break; |
| |
| default: |
| break; |
| } |
| |
| ffestd_V016_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V016_item_structure -- RECORD statement for common-block-name |
| |
| ffestc_V016_item_structure(name_token); |
| |
| Make sure name_token identifies a valid structure to be RECORDed. */ |
| |
| void |
| ffestc_V016_item_structure (ffelexToken name) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V016_item_structure (name); |
| } |
| |
| /* ffestc_V016_item_object -- RECORD statement for object-name |
| |
| ffestc_V016_item_object(name_token,dim_list); |
| |
| Make sure name_token identifies a valid object to be RECORDd. */ |
| |
| void |
| ffestc_V016_item_object (ffelexToken name, ffesttDimList dims) |
| { |
| ffestc_check_item_ (); |
| assert (name != NULL); |
| if (!ffestc_ok_) |
| return; |
| |
| if (dims != NULL) |
| ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE); |
| |
| ffestd_V016_item_object (name, dims); |
| } |
| |
| /* ffestc_V016_finish -- RECORD statement list complete |
| |
| ffestc_V016_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V016_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V016_finish (); |
| } |
| |
| /* ffestc_V018_start -- REWRITE(...) statement list begin |
| |
| ffestc_V018_start(); |
| |
| Verify that REWRITE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V018_start () |
| { |
| ffestvFormat format; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_branch_ |
| (&ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixERR]) |
| || !ffestc_subr_is_format_ |
| (&ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT]) |
| || !ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixUNIT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT]); |
| switch (format) |
| { |
| case FFESTV_formatNAMELIST: |
| case FFESTV_formatASTERISK: |
| ffebad_start (FFEBAD_CONFLICTING_SPECS); |
| ffebad_here (0, ffelex_token_where_line (ffesta_tokens[0]), |
| ffelex_token_where_column (ffesta_tokens[0])); |
| assert (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].kw_or_val_present); |
| if (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].kw_present) |
| { |
| ffebad_here (0, ffelex_token_where_line |
| (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].kw), |
| ffelex_token_where_column |
| (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].kw)); |
| } |
| else |
| { |
| ffebad_here (1, ffelex_token_where_line |
| (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].value), |
| ffelex_token_where_column |
| (ffestp_file.rewrite.rewrite_spec[FFESTP_rewriteixFMT].value)); |
| } |
| ffebad_finish (); |
| ffestc_ok_ = FALSE; |
| return; |
| |
| default: |
| break; |
| } |
| |
| ffestd_V018_start (format); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V018_item -- REWRITE statement i/o item |
| |
| ffestc_V018_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_V018_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V018_item (expr); |
| } |
| |
| /* ffestc_V018_finish -- REWRITE statement list complete |
| |
| ffestc_V018_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V018_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V018_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V019_start -- ACCEPT statement list begin |
| |
| ffestc_V019_start(); |
| |
| Verify that ACCEPT is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V019_start () |
| { |
| ffestvFormat format; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_format_ |
| (&ffestp_file.accept.accept_spec[FFESTP_acceptixFORMAT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.accept.accept_spec[FFESTP_acceptixFORMAT]); |
| ffestc_namelist_ = (format == FFESTV_formatNAMELIST); |
| |
| ffestd_V019_start (format); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V019_item -- ACCEPT statement i/o item |
| |
| ffestc_V019_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_V019_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_namelist_ != 0) |
| { |
| if (ffestc_namelist_ == 1) |
| { |
| ffestc_namelist_ = 2; |
| ffebad_start (FFEBAD_NAMELIST_ITEMS); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| |
| ffestd_V019_item (expr); |
| } |
| |
| /* ffestc_V019_finish -- ACCEPT statement list complete |
| |
| ffestc_V019_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V019_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V019_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| #endif |
| /* ffestc_V020_start -- TYPE statement list begin |
| |
| ffestc_V020_start(); |
| |
| Verify that TYPE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V020_start () |
| { |
| ffestvFormat format; |
| |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_format_ |
| (&ffestp_file.type.type_spec[FFESTP_typeixFORMAT])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| format = ffestc_subr_format_ |
| (&ffestp_file.type.type_spec[FFESTP_typeixFORMAT]); |
| ffestc_namelist_ = (format == FFESTV_formatNAMELIST); |
| |
| ffestd_V020_start (format); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V020_item -- TYPE statement i/o item |
| |
| ffestc_V020_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_V020_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| if (ffestc_namelist_ != 0) |
| { |
| if (ffestc_namelist_ == 1) |
| { |
| ffestc_namelist_ = 2; |
| ffebad_start (FFEBAD_NAMELIST_ITEMS); |
| ffebad_here (0, ffelex_token_where_line (expr_token), |
| ffelex_token_where_column (expr_token)); |
| ffebad_finish (); |
| } |
| return; |
| } |
| |
| ffestd_V020_item (expr); |
| } |
| |
| /* ffestc_V020_finish -- TYPE statement list complete |
| |
| ffestc_V020_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V020_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V020_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V021 -- DELETE statement |
| |
| ffestc_V021(); |
| |
| Make sure a DELETE is valid in the current context, and implement it. */ |
| |
| #if FFESTR_VXT |
| void |
| ffestc_V021 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.delete.delete_spec[FFESTP_deleteixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.delete.delete_spec[FFESTP_deleteixUNIT])) |
| ffestd_V021 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V022 -- UNLOCK statement |
| |
| ffestc_V022(); |
| |
| Make sure a UNLOCK is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_V022 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.beru.beru_spec[FFESTP_beruixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.beru.beru_spec[FFESTP_beruixUNIT])) |
| ffestd_V022 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V023_start -- ENCODE(...) statement list begin |
| |
| ffestc_V023_start(); |
| |
| Verify that ENCODE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V023_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_branch_ |
| (&ffestp_file.vxtcode.vxtcode_spec[FFESTP_vxtcodeixERR])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| ffestd_V023_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V023_item -- ENCODE statement i/o item |
| |
| ffestc_V023_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_V023_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V023_item (expr); |
| } |
| |
| /* ffestc_V023_finish -- ENCODE statement list complete |
| |
| ffestc_V023_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V023_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V023_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V024_start -- DECODE(...) statement list begin |
| |
| ffestc_V024_start(); |
| |
| Verify that DECODE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V024_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (!ffestc_subr_is_branch_ |
| (&ffestp_file.vxtcode.vxtcode_spec[FFESTP_vxtcodeixERR])) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| |
| ffestd_V024_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V024_item -- DECODE statement i/o item |
| |
| ffestc_V024_item(expr,expr_token); |
| |
| Implement output-list expression. */ |
| |
| void |
| ffestc_V024_item (ffebld expr, ffelexToken expr_token) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V024_item (expr); |
| } |
| |
| /* ffestc_V024_finish -- DECODE statement list complete |
| |
| ffestc_V024_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V024_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V024_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V025_start -- DEFINEFILE statement list begin |
| |
| ffestc_V025_start(); |
| |
| Verify that DEFINEFILE is valid here, and begin accepting items in the |
| list. */ |
| |
| void |
| ffestc_V025_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_branch_begin_ (); |
| |
| ffestd_V025_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V025_item -- DEFINE FILE statement item |
| |
| ffestc_V025_item(u,ut,m,mt,n,nt,asv,asvt); |
| |
| Implement item. */ |
| |
| void |
| ffestc_V025_item (ffebld u, ffelexToken ut, ffebld m, ffelexToken mt, |
| ffebld n, ffelexToken nt, ffebld asv, ffelexToken asvt) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V025_item (u, m, n, asv); |
| } |
| |
| /* ffestc_V025_finish -- DEFINE FILE statement list complete |
| |
| ffestc_V025_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V025_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V025_finish (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| /* ffestc_V026 -- FIND statement |
| |
| ffestc_V026(); |
| |
| Make sure a FIND is valid in the current context, and implement it. */ |
| |
| void |
| ffestc_V026 () |
| { |
| ffestc_check_simple_ (); |
| if (ffestc_order_actionif_ () != FFESTC_orderOK_) |
| return; |
| ffestc_labeldef_branch_begin_ (); |
| |
| if (ffestc_subr_is_branch_ |
| (&ffestp_file.find.find_spec[FFESTP_findixERR]) |
| && ffestc_subr_is_present_ ("UNIT", |
| &ffestp_file.find.find_spec[FFESTP_findixUNIT]) |
| && ffestc_subr_is_present_ ("REC", |
| &ffestp_file.find.find_spec[FFESTP_findixREC])) |
| ffestd_V026 (); |
| |
| if (ffestc_shriek_after1_ != NULL) |
| (*ffestc_shriek_after1_) (TRUE); |
| ffestc_labeldef_branch_end_ (); |
| } |
| |
| #endif |
| /* ffestc_V027_start -- VXT PARAMETER statement list begin |
| |
| ffestc_V027_start(); |
| |
| Verify that PARAMETER is valid here, and begin accepting items in the list. */ |
| |
| void |
| ffestc_V027_start () |
| { |
| ffestc_check_start_ (); |
| if (ffestc_order_parameter_ () != FFESTC_orderOK_) |
| { |
| ffestc_ok_ = FALSE; |
| return; |
| } |
| ffestc_labeldef_useless_ (); |
| |
| ffestd_V027_start (); |
| |
| ffestc_ok_ = TRUE; |
| } |
| |
| /* ffestc_V027_item -- VXT PARAMETER statement assignment |
| |
| ffestc_V027_item(dest,dest_token,source,source_token); |
| |
| Make sure the source is a valid source for the destination; make the |
| assignment. */ |
| |
| void |
| ffestc_V027_item (ffelexToken dest_token, ffebld source, |
| ffelexToken source_token UNUSED) |
| { |
| ffestc_check_item_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V027_item (dest_token, source); |
| } |
| |
| /* ffestc_V027_finish -- VXT PARAMETER statement list complete |
| |
| ffestc_V027_finish(); |
| |
| Just wrap up any local activities. */ |
| |
| void |
| ffestc_V027_finish () |
| { |
| ffestc_check_finish_ (); |
| if (!ffestc_ok_) |
| return; |
| |
| ffestd_V027_finish (); |
| } |
| |
| /* Any executable statement. Mainly make sure that one-shot things |
| like the statement for a logical IF are reset. */ |
| |
| void |
| ffestc_any () |
| { |
| ffestc_check_simple_ (); |
| |
| ffestc_order_any_ (); |
| |
| ffestc_labeldef_any_ (); |
| |
| if (ffestc_shriek_after1_ == NULL) |
| return; |
| |
| ffestd_any (); |
| |
| (*ffestc_shriek_after1_) (TRUE); |
| } |