diff options
Diffstat (limited to 'gcc/cobol')
33 files changed, 4268 insertions, 2365 deletions
diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog index 4b05399..918371d 100644 --- a/gcc/cobol/ChangeLog +++ b/gcc/cobol/ChangeLog @@ -1,3 +1,476 @@ +2025-08-01 Robert Dubner <rdubner@symas.com> + + PR cobol/119324 + * cbldiag.h (location_dump): Inline suppression of knownConditionTrueFalse. + * genapi.cc (parser_statement_begin): Combine two if() statements. + * genutil.cc (get_binary_value): File-level suppression of duplicateBreak. + * symbols.cc (symbol_elem_cmp): File-level suppression of duplicateBreak. + +2025-07-31 Robert Dubner <rdubner@symas.com> + + PR cobol/120244 + * genapi.cc (get_level_88_domain): Increase array size for final byte. + (psa_FldLiteralA): Use correct length in build_string_literal call. + * scan.l: Use a loop instead of std:transform to avoid EOF overrun. + * scan_ante.h (binary_integer_usage): Use a variable-length buffer. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * util.cc: Update for diagnostic_t becoming + enum class diagnostics::kind. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * util.cc: Update for renaming of diagnostic_option_id to + diagnostics::option_id. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * util.cc: Remove redundant #includes + +2025-07-24 Robert Dubner <rdubner@symas.com> + + PR cobol/119231 + * gcobolspec.cc: (lang_specific_driver): Pass OPT_static through. + Handle -static and -static-libgcobol properly. + +2025-07-23 Robert Dubner <rdubner@symas.com> + + * genapi.cc (leave_procedure): Adjust location_t for PERFORM. + (parser_perform_times): Likewise. + (internal_perform_through_times): Likewise. + (perform_outofline_before_until): Likewise. + (perform_outofline_after_until): Likewise. + (perform_outofline_testafter_varying): Likewise. + (perform_outofline_before_varying): Likewise. + +2025-07-21 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + PR cobol/120402 + * Make-lang.in: Elminate commented-out scripting. + * cbldiag.h (_CBLDIAG_H): Change #if 0 to #if GCOBOL_GETENV + (warn_msg): Add printf attributes. + (location_dump): Add debugging message. + * cdf.y: Improved linemap tracking. + * genapi.cc (treeplet_fill_source): const attribute for formal parameter. + (insert_nop): Created to consolidate var_decl_nop writes. + (build_main_that_calls_something): Move generation to the end of executable. + (level_88_helper): Formatting. + (parser_call_targets_dump): Formatting. + (function_pointer_from_name): const attribute for formal parameter. + (parser_initialize_programs): const attribute for formal parameter. + (parser_statement_begin): Improved linemap handling. + (section_label): Improved linemap handling. + (paragraph_label): Improved linemap handling. + (pseudo_return_pop): Improved linemap handling. + (leave_procedure): Formatting. + (parser_enter_section): Improved linemap handling. + (parser_enter_paragraph): Improved linemap handling. + (parser_perform): Formatting. + (parser_leave_file): Move creation of main() to this routine. + (parser_enter_program): Move creation of main from here to leave_file. + (parser_accept): Formatting. const attribute for formal parameter. + (parser_accept_command_line): const attribute for formal parameter. + (parser_accept_command_line_count): const attribute for formal parameter. + (parser_accept_envar): Likewise. + (parser_set_envar): Likewise. + (parser_display): Likewise. + (get_exhibit_name): Implement EXHIBIT verb. + (parser_exhibit): Likewise. + (parser_sleep): const attribute for formal parameter. + (parser_division): Improved linemap handling. + (parser_classify): const attribute for formal parameter. + (create_iline_address_pairs): Improved linemap handling. + (parser_perform_start): Likewise. + (perform_inline_until): Likewise. + (perform_inline_testbefore_varying): Likewise. + (parser_perform_until): Likewise. + (parser_perform_inline_times): Likewise. + (parser_intrinsic_subst): const attribute for formal parameter. + (parser_file_merge): Formatting. + (create_and_call): Improved linemap handling. + (mh_identical): const attribute for formal parameter. + (mh_numeric_display): const attribute for formal parameter. + (mh_little_endian): Likewise. + (mh_source_is_group): Likewise. + (psa_FldLiteralA): Formatting. + * genapi.h (parser_accept): const attribute for formal parameter. + (parser_accept_envar): Likewise. + (parser_set_envar): Likewise. + (parser_accept_command_line): Likewise. + (parser_accept_command_line_count): Likewise. + (parser_add): Likewise. + (parser_classify): Likewise. + (parser_sleep): Likewise. + (parser_exhibit): Likewise. + (parser_display): Likewise. + (parser_initialize_programs): Likewise. + (parser_intrinsic_subst): Likewise. + * gengen.cc (gg_assign): Improved linemap handling. + (gg_add_field_to_structure): Likewise. + (gg_define_from_declaration): Likewise. + (gg_build_relational_expression): Likewise. + (gg_goto_label_decl): Likewise. + (gg_goto): Likewise. + (gg_printf): Likewise. + (gg_fprintf): Likewise. + (gg_memset): Likewise. + (gg_memchr): Likewise. + (gg_memcpy): Likewise. + (gg_memmove): Likewise. + (gg_strcpy): Likewise. + (gg_strcmp): Likewise. + (gg_strncmp): Likewise. + (gg_return): Likewise. + (chain_parameter_to_function): Likewise. + (gg_define_function): Likewise. + (gg_get_function_decl): Likewise. + (gg_call_expr): Likewise. + (gg_call): Likewise. + (gg_call_expr_list): Likewise. + (gg_exit): Likewise. + (gg_abort): Likewise. + (gg_strlen): Likewise. + (gg_strdup): Likewise. + (gg_malloc): Likewise. + (gg_realloc): Likewise. + (gg_free): Likewise. + (gg_set_current_line_number): Likewise. + (gg_get_current_line_number): Likewise. + (gg_insert_into_assembler): Likewise. + (token_location_override): Likewise. + (gg_token_location): Likewise. + * gengen.h (location_from_lineno): Likewise. + (gg_set_current_line_number): Likewise. + (gg_get_current_line_number): Likewise. + (gg_token_location): Likewise. + (current_token_location): Likewise. + (current_location_minus_one): Likewise. + (current_location_minus_one_clear): Likewise. + (token_location_override): Likewise. + * genmath.cc (fast_divide): const attribute for formal parameter. + * genutil.cc (get_and_check_refstart_and_reflen): Likewise. + (get_data_offset): Likewise. + (refer_refmod_length): Likewise. + (refer_offset): Likewise. + (refer_size): Likewise. + (refer_size_dest): Likewise. + (refer_size_source): Likewise. + (qualified_data_location): Likewise. + * genutil.h (refer_offset): Likewise. + (refer_size_source): Likewise. + (refer_size_dest): Likewise. + (qualified_data_location): Likewise. + * parse.y: EVALUATE token; Implement EXHIBIT verb; + Improved linemap handling. + * parse_ante.h (input_file_status_notify): Improved linemap handling. + (location_set): Likewise. + * scan.l: PICTURE string validation. + * scan_ante.h (class picture_t): PICTURE string validation. + (validate_picture): Likewise. + * symbols.cc (symbol_currency): Revised default currency handling. + * symbols.h (symbol_currency): Likewise. + * util.cc (location_from_lineno): Improved linemap handling. + (current_token_location): Improved linemap handling. + (current_location_minus_one): Improved linemap handling. + (current_location_minus_one_clear): Improved linemap handling. + (gcc_location_set_impl): Improved linemap handling. + (warn_msg): Improved linemap handling. + * util.h (cobol_lineno): Improved linemap handling. + +2025-07-15 Jakub Jelinek <jakub@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c/44677 + * gcobolspec.cc (lang_specific_driver): Remove unused but set variable + n_cobol_files. + +2025-07-14 Robert Dubner <rdubner@symas.com> + + * cobol1.cc (cobol_langhook_handle_option): Eliminate cppcheck warnings. + * dts.h: Likewise. + * except.cc (cbl_enabled_exceptions_t::dump): Likewise. + * gcobolspec.cc (lang_specific_driver): Likewise. + * genapi.cc (parser_file_merge): Likewise. + * gengen.cc (gg_unique_in_function): Likewise. + (gg_declare_variable): Likewise. + (gg_peek_fn_decl): Likewise. + (gg_define_function): Likewise. + * genmath.cc (set_up_on_exception_label): Likewise. + (set_up_compute_error_label): Likewise. + (arithmetic_operation): Likewise. + (fast_divide): Likewise. + * genutil.cc (get_and_check_refstart_and_reflen): Likewise. + (get_depending_on_value_from_odo): Likewise. + (get_data_offset): Likewise. + (get_binary_value): Likewise. + (process_this_exception): Likewise. + (copy_little_endian_into_place): Likewise. + (refer_is_clean): Likewise. + (refer_fill_depends): Likewise. + * genutil.h (process_this_exception): Likewise. + (copy_little_endian_into_place): Likewise. + (refer_is_clean): Likewise. + * lexio.cc (check_push_pop_directive): Likewise. + (check_source_format_directive): Likewise. + (location_in): Likewise. + (lexer_input): Likewise. + (cdftext::lex_open): Likewise. + (lexio_dialect_mf): Likewise. + (valid_sequence_area): Likewise. + (cdftext::free_form_reference_format): Likewise. + (cdftext::segment_line): Likewise. + * lexio.h (struct span_t): Likewise. + * scan_ante.h (trim_location): Likewise. + * symbols.cc (symbol_elem_cmp): Likewise. + (symbol_alphabet): Likewise. + (end_of_group): Likewise. + (cbl_field_t::attr_str): Likewise. + (symbols_update): Likewise. + (symbol_typedef_add): Likewise. + (symbol_field_add): Likewise. + (new_temporary_impl): Likewise. + (symbol_label_section_exists): Likewise. + (symbol_program_callables): Likewise. + (file_status_status_of): Likewise. + * symfind.cc (is_data_field): Likewise. + (finalize_symbol_map2): Likewise. + (class in_scope): Likewise. + (symbol_match2): Likewise. + * util.cc (get_current_dir_name): Likewise. + (gb4): Likewise. + (class cdf_directives_t): Likewise. + (cbl_field_t::report_invalid_initial_value): Likewise. + (literal_subscript_oob): Likewise. + (cbl_refer_t::str): Likewise. + (date_time_fmt): Likewise. + (class unique_stack): Likewise. + (cobol_set_pp_option): Likewise. + (cobol_filename): Likewise. + (cobol_filename_restore): Likewise. + (gcc_location_set_impl): Likewise. + (ydferror): Likewise. + (error_msg_direct): Likewise. + (yyerror): Likewise. + (cbl_unimplemented_at): Likewise. + +2025-07-13 Robert Dubner <rdubner@symas.com> + + * Make-lang.in: Eliminate the .cc.o override. + * genapi.cc (level_88_helper): Eliminate cppcheck warning. + (get_level_88_domain): Likewise. + (get_class_condition_string): Likewise. + (parser_call_targets_dump): Likewise. + (parser_compile_ecs): Likewise. + (initialize_variable_internal): Likewise. + (move_tree): Likewise. + (combined_name): Likewise. + (assembler_label): Likewise. + (find_procedure): Likewise. + (parser_perform): Likewise. + (parser_perform_times): Likewise. + (internal_perform_through): Likewise. + (internal_perform_through_times): Likewise. + (psa_FldLiteralN): Likewise. + (psa_FldBlob): Likewise. + (parser_accept): Likewise. + (parser_accept_exception): Likewise. + (parser_accept_exception_end): Likewise. + (parser_accept_command_line): Likewise. + (parser_accept_envar): Likewise. + (parser_display_internal): Likewise. + (parser_display): Likewise. + (parser_assign): Likewise. + (parser_initialize_table): Likewise. + (parser_arith_error): Likewise. + (parser_arith_error_end): Likewise. + (parser_division): Likewise. + (label_fetch): Likewise. + (parser_label_label): Likewise. + (parser_label_goto): Likewise. + (parser_perform_start): Likewise. + (parser_perform_conditional): Likewise. + (parser_perform_conditional_end): Likewise. + (parser_perform_until): Likewise. + (parser_file_delete): Likewise. + (parser_intrinsic_subst): Likewise. + (create_lsearch_address_pairs): Likewise. + (parser_bsearch_start): Likewise. + (is_ascending_key): Likewise. + (parser_sort): Likewise. + (parser_file_sort): Likewise. + (parser_return_start): Likewise. + (parser_file_merge): Likewise. + (parser_string_overflow): Likewise. + (parser_unstring): Likewise. + (parser_string): Likewise. + (parser_call_exception): Likewise. + (create_and_call): Likewise. + (mh_identical): Likewise. + (move_helper): Likewise. + (binary_initial_from_float128): Likewise. + (initial_from_initial): Likewise. + (psa_FldLiteralA): Likewise. + (parser_local_add): Likewise. + (parser_symbol_add): Likewise. + * genapi.h (parser_display): Likewise. + * gengen.cc (gg_call_expr): Explict check for NULL_TREE. + (gg_call): Likewise. + * show_parse.h (SHOW_PARSE_LABEL_OK): Likewise. + (TRACE1_FIELD_VALUE): Likewise. + (CHECK_FIELD): Likewise. + (CHECK_FIELD2): Likewise. + (CHECK_LABEL): Likewise. + * util.cc (cbl_internal_error): Apply [[noreturn]] attribute. + * util.h (cbl_internal_error): Likewise. + +2025-07-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR cobol/120621 + * lexio.cc (parse_replace_pairs): Cast mfile.lineno() to fmt_size_t. + * parse.y (intrinsic): Print ptrdiff_t using %ld, cast arg to long. + * scan_ante.h (numstr_of): Print nx using %ld, cast arg to long. + * util.cc (cbl_field_t::report_invalid_initial_value): Print + ptrdiff_t using %ld, cast arg to long. + +2025-07-10 James K. Lowden <jklowden@cobolworx.com> + + PR cobol/120765 + * cdf.y: Extend grammar for new CDF syntax, relocate dictionary. + * cdfval.h (cdf_dictionary): Use new CDF dictionary. + * dts.h: Remove useless assignment, note incorrect behavior. + * except.cc: Remove obsolete EC state. + * gcobol.1: Document CDF in its own section. + * genapi.cc (parser_statement_begin): Use new EC state function. + (parser_file_merge): Same. + (parser_check_fatal_exception): Same. + * genutil.cc (get_and_check_refstart_and_reflen): Same. + (get_depending_on_value_from_odo): Same. + (get_data_offset): Same. + (process_this_exception): Same. + * lexio.cc (check_push_pop_directive): New function. + (check_source_format_directive): Restrict regex search to 1 line. + (cdftext::free_form_reference_format): Use new function. + * parse.y: Define new CDF tokens, use new CDF state. + * parse_ante.h (cdf_tokens): Use new CDF state. + (redefined_token): Same. + (class prog_descr_t): Remove obsolete CDF state. + (class program_stack_t): Same. + (current_call_convention): Same. + * scan.l: Recognize new CDF tokens. + * scan_post.h (is_cdf_token): Same. + * symbols.h (cdf_current_tokens): Change current_call_convention to return void. + * token_names.h: Regenerate. + * udf/stored-char-length.cbl: Use new PUSH/POP CDF functionality. + * util.cc (class cdf_directives_t): Define cdf_directives_t. + (current_call_convention): Same. + (cdf_current_tokens): Same. + (cdf_dictionary): Same. + (cdf_enabled_exceptions): Same. + (cdf_push): Same. + (cdf_push_call_convention): Same. + (cdf_push_current_tokens): Same. + (cdf_push_dictionary): Same. + (cdf_push_enabled_exceptions): Same. + (cdf_push_source_format): Same. + (cdf_pop): Same. + (cdf_pop_call_convention): Same. + (cdf_pop_current_tokens): Same. + (cdf_pop_dictionary): Same. + (cdf_pop_enabled_exceptions): Same. + (cdf_pop_source_format): Same. + * util.h (cdf_push): Declare cdf_directives_t. + (cdf_push_call_convention): Same. + (cdf_push_current_tokens): Same. + (cdf_push_dictionary): Same. + (cdf_push_enabled_exceptions): Same. + (cdf_push_source_format): Same. + (cdf_pop): Same. + (cdf_pop_call_convention): Same. + (cdf_pop_current_tokens): Same. + (cdf_pop_dictionary): Same. + (cdf_pop_source_format): Same. + (cdf_pop_enabled_exceptions): Same. + +2025-07-09 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + PR cobol/120765 + PR cobol/119337 + PR cobol/120794 + * Make-lang.in: Take control of the .cc.o rule. + * cbldiag.h (error_msg_direct): New declaration. + (gcc_location_dump): Forward declaration. + (location_dump): Use gcc_location_dump. + * cdf.y: Change some tokens. + * gcobc: Change dialect handling. + * genapi.cc (parser_call_targets_dump): Temporarily remove from service. + (parser_compile_dcls): Combine temporary arrays. + (get_binary_value_from_float): Apply const to one parameter. + (depending_on_value): Localize a boolean variable. + (normal_normal_compare): Likewise. + (cobol_compare): Eliminate cppcheck warning. + (combined_name): Apply const to an input parameter. + (parser_perform): Apply const to a variable. + (parser_accept): Improve handling of special_name_t parameter and + the exception conditions. + (parser_display): Improve handling of speciat_name_t parameter; use the + os_filename[] string when appropriate. + (program_end_stuff): Rename shadowing variable. + (parser_division): Consolidate temporary char[] arrays. + (parser_file_start): Apply const to a parameter. + (inspect_replacing): Likewise. + (parser_program_hierarchy): Rename shadowing variable. + (mh_identical): Apply const to parameters. + (float_type_of): Likewise. + (picky_memcpy): Likewise. + (mh_numeric_display): Likewise. + (mh_little_endian): Likewise. + (mh_source_is_group): Apply static to a variable it. + (move_helper): Quiet a cppcheck warning. + * genapi.h (parser_accept): Add exceptions to declaration. + (parser_accept_under_discussion): Add declaration. + (parser_display): Change to std::vector; add exceptions to declaration. + * lexio.cc (cdf_source_format): Improve source code location handling. + (source_format_t::infer): Likewise. + (is_fixed_format): Likewise. + (is_reference_format): Likewise. + (left_margin): Likewise. + (right_margin): Likewise. + (cobol_set_indicator_column): Likewise. + (include_debug): Likewise. + (continues_at): Likewise. + (indicated): Likewise. + (check_source_format_directive): Likewise. + (cdftext::free_form_reference_format): Likewise. + * parse.y: Tokens; program and function names; DISPLAY and ACCEPT + handling. + * parse_ante.h (class tokenset_t): Removed. + (class current_tokens_t): Removed. + (field_of): Removed. + * scan.l: Token handling. + * scan_ante.h (level_found): Comment. + * scan_post.h (start_condition_str): Remove cast author_state:. + * symbols.cc (symbols_update): Change error message. + (symbol_table_init): Correct and reorder entries. + (symbol_unresolved_file_key): New function definition. + (cbl_file_key_t::deforward): Change error message. + * symbols.h (symbol_unresolved_file_key): New declaration. + (keyword_tok): New function. + (redefined_token): New function. + (class current_tokens_t): New class. + * symfind.cc (symbol_match): Revise error message. + * token_names.h: Reorder and change numbers in comments. + * util.cc (class cdf_directives_t): New class. + (cobol_set_indicator_column): New function. + (cdf_source_format): New function. + (gcc_location_set_impl): Improve column handling in token_location. + (gcc_location_dump): New function. + (class temp_loc_t): Modify constructor. + (error_msg_direct): New function. + * util.h (class source_format_t): New class. + 2025-07-01 James K. Lowden <jklowden@cobolworx.com> * Make-lang.in: Use && instead of semicolon between commands. diff --git a/gcc/cobol/Make-lang.in b/gcc/cobol/Make-lang.in index e884212..0e2a773 100644 --- a/gcc/cobol/Make-lang.in +++ b/gcc/cobol/Make-lang.in @@ -384,3 +384,4 @@ cobol.stagefeedback: stagefeedback-start selftest-cobol: lang_checks += check-cobol + diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h index 548b0f2..dd16190 100644 --- a/gcc/cobol/cbldiag.h +++ b/gcc/cobol/cbldiag.h @@ -33,7 +33,7 @@ #else #define _CBLDIAG_H -#if 0 +#if GCOBOL_GETENV #define gcobol_getenv(x) getenv(x) #else #define gcobol_getenv(x) ((char *)nullptr) @@ -78,10 +78,19 @@ struct YDFLTYPE #endif +// Diagnostic format specifiers are documented in gcc/pretty-print.cc // an error at a location, called from the parser for semantic errors void error_msg( const YYLTYPE& loc, const char gmsgid[], ... ) ATTRIBUTE_GCOBOL_DIAG(2, 3); +bool +warn_msg( const YYLTYPE& loc, const char gmsgid[], ... ) + ATTRIBUTE_GCOBOL_DIAG(2, 3); + +// an error that uses token_location, not yylloc +void error_msg_direct( const char gmsgid[], ... ) + ATTRIBUTE_GCOBOL_DIAG(1, 2); + void dialect_error( const YYLTYPE& loc, const char term[], const char dialect[] ); @@ -104,16 +113,23 @@ void dbgmsg( const char fmt[], ... ) ATTRIBUTE_PRINTF_1; void gcc_location_set( const YYLTYPE& loc ); +void gcc_location_dump(); + // tree.h defines yy_flex_debug as a macro because options.h #if ! defined(yy_flex_debug) template <typename LOC> static void location_dump( const char func[], int line, const char tag[], const LOC& loc) { extern int yy_flex_debug; // cppcheck-suppress shadowVariable - if( yy_flex_debug && gcobol_getenv("update_location") ) - fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", - func, line, tag, - loc.first_line, loc.first_column, loc.last_line, loc.last_column); + if( yy_flex_debug ) { + const char *detail = gcobol_getenv("update_location"); // cppcheck-suppress knownConditionTrueFalse + if( detail ) { + fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", + func, line, tag, + loc.first_line, loc.first_column, loc.last_line, loc.last_column); + if( *detail == '2' ) gcc_location_dump(); + } + } } #endif // defined(yy_flex_debug) diff --git a/gcc/cobol/cdf.y b/gcc/cobol/cdf.y index 3344271..53fea5d 100644 --- a/gcc/cobol/cdf.y +++ b/gcc/cobol/cdf.y @@ -95,7 +95,7 @@ void input_file_status_notify(); } \ location_dump("cdf.c", __LINE__, "current", (Current)); \ input_file_status_notify(); \ - gcc_location_set( location_set(Current) ); \ + location_set(Current); \ } while (0) %} @@ -105,14 +105,14 @@ void input_file_status_notify(); using std::map; - static map<std::string, cdfval_t> dictionary; - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" static bool cdfval_add( const char name[], const cdfval_t& value, bool override = false ) { + cdf_values_t& dictionary( cdf_dictionary() ); + if( scanner_parsing() ) { if( ! override ) { if( dictionary.find(name) != dictionary.end() ) return false; @@ -123,6 +123,8 @@ void input_file_status_notify(); } static void cdfval_off( const char name[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); + if( scanner_parsing() ) { auto p = dictionary.find(name); if( p == dictionary.end() ) { @@ -159,6 +161,8 @@ exception_turn_t exception_turn; bool apply_cdf_turn( const exception_turn_t& turn ) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); + for( auto elem : turn.exception_files() ) { std::set<size_t> files(elem.second.begin(), elem.second.end()); enabled_exceptions.turn_on_off(turn.enabled, @@ -204,15 +208,17 @@ apply_cdf_turn( const exception_turn_t& turn ) { %type <file> filename %type <files> filenames -%token BY 478 +%type <number> cdf_stackable + +%token BY 486 %token COPY 362 %token CDF_DISPLAY 384 ">>DISPLAY" -%token IN 597 +%token IN 605 %token NAME 286 %token NUMSTR 305 "numeric literal" -%token OF 678 -%token PSEUDOTEXT 713 -%token REPLACING 735 +%token OF 686 +%token PSEUDOTEXT 721 +%token REPLACING 743 %token LITERAL 298 %token SUPPRESS 376 @@ -227,25 +233,32 @@ apply_cdf_turn( const exception_turn_t& turn ) { %token CDF_WHEN 389 ">>WHEN" %token CDF_END_EVALUATE 390 ">>END-EVALUATE" -%token AS 460 CONSTANT 361 DEFINED 363 +%token ALL 450 +%token CALL_CONVENTION 391 ">>CALL-CONVENTION" +%token COBOL_WORDS 380 ">>COBOL-WORDS" +%token CDF_PUSH 394 ">>PUSH" +%token CDF_POP 395 ">>POP" +%token SOURCE_FORMAT 396 ">>SOURCE FORMAT" + +%token AS 468 CONSTANT 361 DEFINED 363 %type <boolean> DEFINED -%token OTHER 690 PARAMETER_kw 368 "PARAMETER" -%token OFF 679 OVERRIDE 369 -%token THRU 931 -%token TRUE_kw 805 "True" +%token OTHER 698 PARAMETER_kw 368 "PARAMETER" +%token OFF 687 OVERRIDE 369 +%token THRU 939 +%token TRUE_kw 813 "True" -%token CALL_COBOL 391 "CALL" -%token CALL_VERBATIM 392 "CALL (as C)" +%token CALL_COBOL 392 "CALL" +%token CALL_VERBATIM 393 "CALL (as C)" -%token TURN 807 CHECKING 488 LOCATION 641 ON 681 WITH 833 +%token TURN 815 CHECKING 496 LOCATION 649 ON 689 WITH 841 -%left OR 932 -%left AND 933 -%right NOT 934 -%left '<' '>' '=' NE 935 LE 936 GE 937 +%left OR 940 +%left AND 941 +%right NOT 942 +%left '<' '>' '=' NE 943 LE 944 GE 945 %left '-' '+' %left '*' '/' -%right NEG 939 +%right NEG 947 %define api.prefix {ydf} %define api.token.prefix{YDF_} @@ -277,6 +290,8 @@ complete: cdf_define | cdf_display | cdf_turn | cdf_call_convention + | cdf_push + | cdf_pop ; /* @@ -328,6 +343,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override } if( !cdfval_add( $NAME, cdfval_t($value), $override) ) { error_msg(@NAME, "name already in dictionary: %s", $NAME); + cdf_values_t& dictionary( cdf_dictionary() ); const cdfval_t& entry = dictionary[$NAME]; if( entry.filename ) { error_msg(@NAME, "%s previously defined in %s:%d", @@ -357,7 +373,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override * available regardless. */ { - if( 0 == dictionary.count($NAME) ) { + if( 0 == cdf_dictionary().count($NAME) ) { yywarn("CDF: '%s' is defined AS PARAMETER " "but was not defined", $NAME); } @@ -400,6 +416,35 @@ cdf_call_convention: } ; +cdf_push: CDF_PUSH cdf_stackable { + switch( $cdf_stackable ) { + case YDF_ALL: cdf_push(); break; + case YDF_CALL_CONVENTION: cdf_push_call_convention(); break; + case YDF_CDF_DEFINE: cdf_push_dictionary(); break; + case YDF_COBOL_WORDS: cdf_push_current_tokens(); break; + case YDF_SOURCE_FORMAT: cdf_push_source_format(); break; + default: gcc_unreachable(); + } + } + ; +cdf_pop: CDF_POP cdf_stackable { + switch( $cdf_stackable ) { + case YDF_ALL: cdf_pop(); break; + case YDF_CALL_CONVENTION: cdf_pop_call_convention(); break; + case YDF_CDF_DEFINE: cdf_pop_dictionary(); break; + case YDF_COBOL_WORDS: cdf_pop_current_tokens(); break; + case YDF_SOURCE_FORMAT: cdf_pop_source_format(); break; + default: gcc_unreachable(); + } + } + ; + +cdf_stackable: ALL { $$ = YDF_ALL; } + | CALL_CONVENTION { $$ = YDF_CALL_CONVENTION; } + | COBOL_WORDS { $$ = YDF_COBOL_WORDS; } + | CDF_DEFINE { $$ = YDF_CDF_DEFINE; } + | SOURCE_FORMAT { $$ = YDF_SOURCE_FORMAT; } + ; except_names: except_name | except_names except_name @@ -471,6 +516,7 @@ cdf_eval_obj: cdf_cond_expr cdf_cond_expr: BOOL | NAME DEFINED { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find($1); bool found = p != dictionary.end(); if( !$DEFINED ) found = ! found; @@ -552,6 +598,7 @@ cdf_expr: cdf_expr '+' cdf_expr { $$ = $1(@1) + $3(@3); } ; cdf_factor: NAME { + cdf_values_t& dictionary( cdf_dictionary() ); auto that = dictionary.find($1); if( that != dictionary.end() ) { $$ = that->second; @@ -651,6 +698,7 @@ name_any: namelit name_one: NAME { + cdf_values_t& dictionary( cdf_dictionary() ); cdf_arg_t arg = { YDF_NAME, $1 }; auto p = dictionary.find($1); @@ -665,6 +713,7 @@ name_one: NAME namelit: name { + cdf_values_t& dictionary( cdf_dictionary() ); cdf_arg_t arg = { YDF_NAME, $1 }; auto p = dictionary.find($1); @@ -745,6 +794,7 @@ location_set( const YYLTYPE& loc ) { bool // used by cobol1.cc defined_cmd( const char arg[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); cdfval_t value(1); char *name = xstrdup(arg); @@ -868,6 +918,7 @@ static int ydflex(void) { bool cdf_value( const char name[], const cdfval_t& value ) { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find(name); if( p != dictionary.end() ) return false; @@ -878,6 +929,7 @@ cdf_value( const char name[], const cdfval_t& value ) { const cdfval_t * cdf_value( const char name[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find(name); if( p == dictionary.end() ) return NULL; diff --git a/gcc/cobol/cdfval.h b/gcc/cobol/cdfval.h index 465bdbb..cc474a2 100644 --- a/gcc/cobol/cdfval.h +++ b/gcc/cobol/cdfval.h @@ -126,4 +126,8 @@ cdf_value( const char name[] ); bool cdf_value( const char name[], const cdfval_t& value ); +typedef std::map<std::string, cdfval_t> cdf_values_t; + +cdf_values_t& cdf_dictionary(); + #endif diff --git a/gcc/cobol/cobol1.cc b/gcc/cobol/cobol1.cc index 4bd79f1..3146da5 100644 --- a/gcc/cobol/cobol1.cc +++ b/gcc/cobol/cobol1.cc @@ -357,7 +357,7 @@ cobol_langhook_handle_option (size_t scode, return true; case OPT_M: - cobol_set_pp_option('M'); + cobol_set_pp_option('M'); return true; case OPT_fstatic_call: @@ -368,16 +368,18 @@ cobol_langhook_handle_option (size_t scode, wsclear(cobol_default_byte); return true; - case OPT_fflex_debug: + case OPT_fflex_debug: // cppcheck-suppress syntaxError // The need for this is a mystery yy_flex_debug = 1; cobol_set_debugging( true, yy_debug == 1, cobol_trace_debug == 1 ); return true; + case OPT_fyacc_debug: yy_debug = 1; cobol_set_debugging(yy_flex_debug == 1, true, cobol_trace_debug == 1 ); return true; + case OPT_ftrace_debug: cobol_set_debugging( yy_flex_debug == 1, yy_debug == 1, true ); return true; @@ -406,11 +408,13 @@ cobol_langhook_handle_option (size_t scode, case OPT_fsyntax_only: mode_syntax_only(identification_div_e); break; + case OPT_preprocess: if( ! preprocess_filter_add(arg) ) { cbl_errx( "could not execute preprocessor %s", arg); } return true; + case OPT_include: if( ! include_file_add(arg) ) { cbl_errx( "could not include %s", arg); diff --git a/gcc/cobol/dts.h b/gcc/cobol/dts.h index aa3fa58..c900c45 100644 --- a/gcc/cobol/dts.h +++ b/gcc/cobol/dts.h @@ -86,24 +86,30 @@ namespace dts { #if __cpp_exceptions static const char msg[] = "input not NUL-terminated"; throw std::domain_error( msg ); -#else - // eoinput terminates input - eoinput = strchr(input, '\0'); // cppcheck-suppress uselessAssignmentPtrArg #endif } auto ncm = re.size(); cm.resize(ncm); std::vector <regmatch_t> cms(ncm); - int erc = regexec( &re, input, ncm, cms.data(), 0 ); if( erc != 0 ) return false; +#if __cpp_exceptions + // This is not correct at all, but current use depends on current behavior. + // The following line is excluded from the GCC build, which is compiled + // without __cpp_exceptions. parse_copy_directive (for one) depends on + // regex_search returning true even if the match is beyond eoinput. + if( eoinput < cm[0].second ) return false; + // Correct behavior would return match only between input and eoinput. + // Because regex(3) uses a NUL terminator, it may match text between + // eoinput and the NUL. +#endif std::transform( cms.begin(), cms.end(), cm.begin(), [input]( const regmatch_t& m ) { return csub_match( input, m ); } ); return true; } -}; +} diff --git a/gcc/cobol/except.cc b/gcc/cobol/except.cc index 60b8416..df1c7df 100644 --- a/gcc/cobol/except.cc +++ b/gcc/cobol/except.cc @@ -84,8 +84,6 @@ cbl_enabled_exception_t::dump( int i ) const { file ); } -cbl_enabled_exceptions_t enabled_exceptions; - void cbl_enabled_exceptions_t::dump() const { extern int yydebug; @@ -98,7 +96,7 @@ cbl_enabled_exceptions_t::dump() const { return; } int i = 1; - for( auto& elem : *this ) { + for( auto& elem : *this ) { // cppcheck-suppress constVariableReference dbgmsg("cbl_enabled_exceptions_t: %2d {%s, %s, %lu}", i++, elem.location? "with location" : " no location", diff --git a/gcc/cobol/gcobc b/gcc/cobol/gcobc index 01c75dd..fa9f609 100755 --- a/gcc/cobol/gcobc +++ b/gcc/cobol/gcobc @@ -125,25 +125,24 @@ $0 recognizes the following GnuCOBOL cobc compilation options: -std=mvs -std=mvs-strict -std=mf -std=mf-strict -std=cobol85 -std=cobol2002 -std=cobol2014 - Options that are the same in gcobol and cobc are passed through verbatim. - Options that have no analog in gcobol produce a warning message. - To produce this message, use -HELP. +Options that are the same in gcobol and cobc are passed through verbatim. +Options that have no analog in gcobol produce a warning message. +To produce this message, use -HELP. To see the constructed cobc command-line, use -echo. To override the default cobc, set the "cobc" environment variable. By default, gcobc invokes the gcobol the same directory the gcobc resides. To override, set the gcobol environment variable. - EOF - } +EOF +} -dialect="gnu" +dialect="mf gnu" out_set="" first="" - # - # Simply iterate over the command-line tokens. We can't use getopts - # here because it's not designed for single-dash words (e.g. -shared). # - +# Iterate over the command-line tokens. We can't use getopts here +# because it's not designed for single-dash words (e.g. -shared). +# for opt in "$@" do if [ "$skip_arg" ] @@ -441,11 +440,13 @@ do -std=mvs | -std=mvs-strict | -std=ibm | -std=ibm-strict) dialect=ibm ;; -std=mf | -std=mf-strict) dialect=mf - ;; - -std=default) dialect=gnu # that's GnuCOBOL's default and GCC's dialect for GnuCOBOL - ;; - -std=cobol*) dialect="" # GCC COBOL targets COBOL2024 "mostly backward to COBOL85" - ;; + ;; + # GnuCOBOL's default and GCC's dialect for GnuCOBOL + -std=default) dialect=gnu + ;; + # GCC COBOL targets COBOL2024 "mostly backward to COBOL85" + -std=cobol*) dialect="" + ;; -std=*) dialect="" warn "$opt (unkown dialect)" @@ -480,7 +481,8 @@ do opts="$opts /dev/stdin" ;; - *) if [ -z "$output_name" ] # first non-option argument is source file name + # First file name argument is default output filename. + *) if [ -z "$output_name" -a -e "$opt" ] then output_name=$(basename "${opt%.*}") case $mode in @@ -512,6 +514,11 @@ fi # To override the default gcobol, set the "gcobol" environment variable. gcobol="${gcobol:-${0%/*}/gcobol}" +if [ "$dialect" ] +then + dialect=$(echo $dialect | sed -E 's/[[:alnum:]]+/-dialect &/g') +fi + if [ "$echo" ] then echo $gcobol $mode $opts @@ -523,4 +530,4 @@ then set -x fi -exec $gcobol $mode $opts +exec $gcobol $mode $dialect $opts diff --git a/gcc/cobol/gcobol.1 b/gcc/cobol/gcobol.1 index 6db5400..ebb833c 100644 --- a/gcc/cobol/gcobol.1 +++ b/gcc/cobol/gcobol.1 @@ -587,6 +587,21 @@ statement, regardless of compile-time constants. .. . .Ss Implemented Exception Conditions +By default, per ISO, no EC is enabled. Implemented ECs may be enabled +on the command line or via the +.Sy TURN +directive. Any attempt to enable an EC that is not implemented is +treated as an error. +.Pp +An enabled EC not handled by a +.Sy DECLARATIVE +is written to the system log and to standard error. (The authors +intend to make that an option.) A fatal EC not handled with +.Sy RESUME +ends with a call to +.Xr abort 3 +and process termination. +.Pp Not all Exception Conditions are implemented. Any attempt to enable an EC that that is not implemented produces a warning message. The following are implemented: @@ -913,11 +928,90 @@ or has no effect; the two are interchangeable. .. . -.Ss Compiler-Directing Facility (CDF) +.Sh COMPILER-DIRECTING FACILITY The CDF should be used with caution because no comprehensive test -suite has been identified. +suite has been identified. . -.Ss Conditional Compilation +.Ss CDF Text Manipulation +.Bl -tag -width >>DEFINE +.It Sy COPY Ar copybook Li Oo OF|BY Ar library Oc Oo Sy REPLACING ... Oc +If +.Ar copybook +is a literal, it treated a literal filename, which either does or does not exist. If +.Ar copybook +is a \*[lang] word, +.Nm +looks first for an environment variable named +.Va copybook +and, if found, uses the contents of that variable as the name of the +copybook file. If that file does not exist, it continues looking for +a file named one of: +.sp +.Bl -bullet -compact -offset 5n +.It +.Pa copybook +(literally) +.It +.Pa copybook.cpy +.It +.Pa copybook.CPY +.It +.Pa copybook.cbl +.It +.Pa copybook.CBL +.It +.Pa copybook.cob +.It +.Pa copybook.COB +.El +.sp +in that order. It looks first in the same directory as the source +code file, and then in any +.Ar copybook-path +named with the +.Fl I +option. +. +.\" FIXME: need escape mechanism for directories with ':' in the name. +.Ar copybook-path +may (like the shell's +.Ev PATH +variable) be a colon-separated list. +The +.Fl I +option may occur multiple times on the command line. Each successive +.Ar copybook-path +is concatenated to previous ones. +Relative paths (having no leading +.Ql / Ns +\&) +are searched relative to the compiler's current working directory. +.Pp +For example, +.D1 \& +.D1 Fl I Li /usr/local/include:include +.D1 \& +searches first the directory where the \*[lang] program is found, next in +.Pa /usr/local/include , +and finally in an +.Pa include +subdirectory of the directory from which +.Nm +was invoked. +.Pp +For the +.Sy REPLACING +phrase, both the modern pseudo-text and the \*[lang]/85 forms are +recognized. (The older forms are used in the NIST CCVS/85 test suite.) +.It Sy REPLACE ... +.Nm +supports the full ISO +.Sy REPLACE +syntax. +.El +. +.Ss CDF Directives +.\"Bl -tag -width >>PROPAGATE .Bl -tag -width >>DEFINE .It >> Ns Sy DEFINE Ar name Sy AS Bro Ar expression Li | Sy PARAMETER Brc Op Sy OVERRIDE Define @@ -959,10 +1053,6 @@ is supported. Boolean literals are not supported. . .It >> Ns Sy EVALUATE Not implemented. -.El -. -.Ss Other CDF Directives -.Bl -tag -width >>PROPAGATE .It >> Ns Sy CALL-CONVENTION Ar convention .Ar convention may be one of: @@ -1036,6 +1126,24 @@ Not implemented. Not implemented. .It >> Ns Sy PROPAGATE Not implemented. +.It >> Ns Sy PUSH Ar directive +.It >> Ns Sy POP Ar directive +With +.Sy PUSH , +push CDF state onto a stack. +With +.Sy POP , +return to the prior pushed state. +.Ar directive +may be one of +.Bl -tag -compact +.It Sy CALL-CONVENTION +.It Sy COBOL-WORDS +.It Sy DEFINE +.It Sy SOURCE FORMAT +.It Sy TURN +.El +. .It >> Ns Sy TURN Oo .Ar ec Oo Ar file Li ... Oc ... .Oc Sy CHECKING Bro Oo Sy ON Oc Oo Oo Sy WITH Oc Sy LOCATION Oc | Sy OFF Brc @@ -1087,76 +1195,6 @@ the directive must appear before To test a feature-set variable, use .Dl >>IF Ar feature Li DEFINED . -.Ss Copybooks -.Nm -supports the CDF -.Sy COPY -statement, with or without its -.Sy REPLACING -component. For any statement -.sp -.D1 COPY Ar copybook -.sp -.Nm -looks first for an environment variable named -.Va copybook -and, if found, uses the contents of that variable as the name of the -copybook file. If that file does not exist, it continues looking for -a file named one of: -.sp -.Bl -bullet -compact -offset 5n -.It -.Pa copybook -(literally) -.It -.Pa copybook.cpy -.It -.Pa copybook.CPY -.It -.Pa copybook.cbl -.It -.Pa copybook.CBL -.It -.Pa copybook.cob -.It -.Pa copybook.COB -.El -.sp -in that order. It looks first in the same directory as the source -code file, and then in any -.Ar copybook-path -named with the -.Fl I -option. -. -.\" FIXME: need escape mechanism for directories with ':' in the name. -.Ar copybook-path -may (like the shell's -.Ev PATH -variable) be a colon-separated list. -. -The -.Fl I -option may occur multiple times on the command line. Each successive -.Ar copybook-path -is concatenated to previous ones. -Relative paths (having no leading -.Ql / Ns -\&) -are searched relative to the compiler's current working directory. -.Pp -For example, -.D1 \& -.D1 Fl I Li /usr/local/include:include -.D1 \& -searches first the directory where the \*[lang] program is found, next in -.Pa /usr/local/include , -and finally in an -.Pa include -subdirectory of the directory from which -.Nm -was invoked. -. .Ss Intrinsic functions .Nm implements all intrinsic functions defined by \*[isostd], plus a few diff --git a/gcc/cobol/gcobolspec.cc b/gcc/cobol/gcobolspec.cc index 70784d7..1f1b463 100644 --- a/gcc/cobol/gcobolspec.cc +++ b/gcc/cobol/gcobolspec.cc @@ -142,9 +142,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, int n_infiles = 0; int n_outfiles = 0; - // The number of input files when the language is "none" or "cobol" - int n_cobol_files = 0; - // saw_OPT_no_main means "don't expect -main" bool saw_OPT_no_main = false; @@ -234,11 +231,6 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, case OPT_SPECIAL_input_file: no_files_error = false; n_infiles += 1; - if( strcmp(language, "none") == 0 - || strcmp(language, "cobol") == 0 ) - { - n_cobol_files += 1; - } if( strstr(decoded_options[i].orig_option_with_args_text, "libgcobol.a") ) { // We have been given an explicit libgcobol.a. We need to note that. @@ -478,7 +470,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, //// break; ////#endif case OPT_static: +#if defined (HAVE_LD_STATIC_DYNAMIC) + append_arg(decoded_options[i]); static_in_general = true; +#endif break; default: @@ -506,17 +501,23 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, need_libgcobol = false; } + if( static_in_general ) + { + // These two options interfere with each other. + static_libgcobol = false; + } + if( need_libgcobol ) { add_arg_lib(COBOL_LIBRARY, static_libgcobol); } if( need_libdl ) { - add_arg_lib(DL_LIBRARY, static_in_general); + add_arg_lib(DL_LIBRARY, false); } if( need_libstdc ) { - add_arg_lib(STDCPP_LIBRARY, static_in_general); + add_arg_lib(STDCPP_LIBRARY, false); } if( prior_main ) @@ -529,7 +530,8 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, // cl_decoded_option size_t new_option_count = new_opt.size(); - struct cl_decoded_option *new_options = XNEWVEC (struct cl_decoded_option, new_option_count); + struct cl_decoded_option *new_options = XNEWVEC (struct cl_decoded_option, + new_option_count); for(size_t i=0; i<new_option_count; i++) { @@ -539,7 +541,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, #ifdef NOISY verbose = true; #endif - if( verbose && new_options != original_options ) + if( verbose && new_options != original_options ) // cppcheck-suppress knownConditionTrueFalse { fprintf(stderr, _("Driving: (" HOST_SIZE_T_PRINT_DEC ")\n"), (fmt_size_t)new_option_count); diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc index 8017788..c9d2da4 100644 --- a/gcc/cobol/genapi.cc +++ b/gcc/cobol/genapi.cc @@ -27,6 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "cobol-system.h" #include "coretypes.h" @@ -117,7 +118,7 @@ typedef struct TREEPLET static void -treeplet_fill_source(TREEPLET &treeplet, cbl_refer_t &refer) +treeplet_fill_source(TREEPLET &treeplet, const cbl_refer_t &refer) { treeplet.pfield = gg_get_address_of(refer.field->var_decl_node); treeplet.offset = refer_offset(refer); @@ -190,6 +191,9 @@ const char *gv_trace_switch = NULL; char const *bTRACE1 = NULL; tree trace_handle; tree trace_indent; + +// This variable is set to true when the output cursor is known to be at the +// start-of-line. bool cursor_at_sol = true; static void @@ -229,6 +233,13 @@ trace1_init() } } +static +void +insert_nop(int n) + { + gg_assign(var_decl_nop, build_int_cst_type(INT, n)); + } + static void create_cblc_string_variable(const char *var_name, const char *var_contents) { @@ -266,8 +277,6 @@ build_main_that_calls_something(const char *something) SHOW_PARSE_END } - gg_set_current_line_number(DEFAULT_LINE_NUMBER); - tree function_decl = gg_define_function( INT, "main", "main", @@ -321,7 +330,6 @@ build_main_that_calls_something(const char *something) argc, argv, NULL_TREE))); - strncpy(ach_cobol_entry_point, psz, sizeof(ach_cobol_entry_point)-1); free(psz); gg_finalize_function(); } @@ -361,8 +369,11 @@ level_88_helper(size_t parent_capacity, size_t &returned_size) { // We return a MALLOCed return value, which the caller must free. - char *retval = (char *)xmalloc(parent_capacity + 64); - char *builder = (char *)xmalloc(parent_capacity + 64); + char *retval = static_cast<char *>(xmalloc(parent_capacity + 64)); + gcc_assert(retval); + char *builder = static_cast<char *>(xmalloc(parent_capacity + 64)); + gcc_assert(builder); + size_t nbuild = 0; cbl_figconst_t figconst = cbl_figconst_of( elem.name()); @@ -403,7 +414,8 @@ level_88_helper(size_t parent_capacity, // Pick up the string size_t first_name_length = elem.size(); - char *first_name = (char *)xmalloc(first_name_length + 1); + char *first_name = static_cast<char *>(xmalloc(first_name_length + 1)); + gcc_assert(first_name); memcpy(first_name, elem.name(), first_name_length); first_name[first_name_length] = '\0'; @@ -480,7 +492,7 @@ get_level_88_domain(size_t parent_capacity, cbl_field_t *var, size_t &returned_s // Numerics are converted to strings, and handled as above size_t retval_capacity = 64; - char *retval = (char *)xmalloc(retval_capacity); + char *retval = static_cast<char *>(xmalloc(retval_capacity)); size_t output_index = 0; // Loop through the provided domains: @@ -497,8 +509,9 @@ get_level_88_domain(size_t parent_capacity, cbl_field_t *var, size_t &returned_s if( output_index + stream_len > retval_capacity ) { retval_capacity *= 2; - retval = (char *)xrealloc(retval, retval_capacity); + retval = static_cast<char *>(xrealloc(retval, retval_capacity)); } + gcc_assert(retval); memcpy(retval + output_index, stream, stream_len); output_index += stream_len; returned_size += stream_len; @@ -509,14 +522,23 @@ get_level_88_domain(size_t parent_capacity, cbl_field_t *var, size_t &returned_s if( output_index + stream_len > retval_capacity ) { retval_capacity *= 2; - retval = (char *)xrealloc(retval, retval_capacity); + retval = static_cast<char *>(xrealloc(retval, retval_capacity)); } + gcc_assert(retval); memcpy(retval + output_index, stream, stream_len); output_index += stream_len; returned_size += stream_len; free(stream); domain += 1; } + + if( returned_size >= retval_capacity) + { + retval_capacity *= 2; + retval = static_cast<char *>(xrealloc(retval, retval_capacity)); + } + + gcc_assert(returned_size < retval_capacity); retval[returned_size++] = '\0'; return retval; } @@ -608,13 +630,8 @@ get_class_condition_string(cbl_field_t *var) // Since the first.name is a single character, we can do this as // a single-character pair. - // Keep in mind that the single character might be a two-byte UTF-8 - // codepoint - uint8_t ch1 = domain->first.name()[0]; - uint8_t ch2 = domain->last.name()[0]; - - gcc_assert(first_name_length <= 2); - gcc_assert(last_name_length <= 2); + uint8_t ch1; + uint8_t ch2; char *p2; size_t one; @@ -766,8 +783,10 @@ parser_call_target_convention( tree func ) void parser_call_targets_dump() { - dbgmsg( "call targets for #" HOST_SIZE_T_PRINT_UNSIGNED, + dbgmsg( "call targets for #" HOST_SIZE_T_PRINT_UNSIGNED " NOT dumping", (fmt_size_t)current_program_index() ); +#if 0 // A change to call_targets rendered this routine useless. Until we get + // around to repairing it, this code is left for reference. for( const auto& elem : call_targets ) { const auto& k = elem.first; const auto& v = elem.second; @@ -781,6 +800,7 @@ parser_call_targets_dump() } fprintf(stderr, " ]\n"); } +#endif } size_t @@ -808,8 +828,8 @@ parser_call_target_update( size_t caller, } static tree -function_pointer_from_name(cbl_refer_t &name, - tree function_return_type) +function_pointer_from_name(const cbl_refer_t &name, + tree function_return_type) { Analyze(); @@ -885,7 +905,8 @@ function_pointer_from_name(cbl_refer_t &name, } void -parser_initialize_programs(size_t nprogs, struct cbl_refer_t *progs) +parser_initialize_programs( size_t nprogs, + const struct cbl_refer_t *progs) { Analyze(); SHOW_PARSE @@ -985,14 +1006,13 @@ parser_compile_ecs( const std::vector<uint64_t>& ecs ) return NULL_TREE; } - char ach[32]; + char ach[64]; static int counter = 1; sprintf(ach, "_ecs_table_%d", counter++); tree retval = array_of_long_long(ach, ecs); SHOW_IF_PARSE(nullptr) { SHOW_PARSE_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(ecs.size()), as_voidp(retval)); SHOW_PARSE_TEXT(ach) @@ -1001,7 +1021,6 @@ parser_compile_ecs( const std::vector<uint64_t>& ecs ) TRACE1 { TRACE1_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(ecs.size()), as_voidp(retval)); TRACE1_TEXT_ABC("", ach, ""); @@ -1034,14 +1053,13 @@ parser_compile_dcls( const std::vector<uint64_t>& dcls ) return NULL_TREE; } - char ach[32]; + char ach[64]; static int counter = 1; sprintf(ach, "_dcls_table_%d", counter++); tree retval = array_of_long_long(ach, dcls); SHOW_IF_PARSE(nullptr) { SHOW_PARSE_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(dcls.size()), as_voidp(retval)); SHOW_PARSE_TEXT(ach); @@ -1050,7 +1068,6 @@ parser_compile_dcls( const std::vector<uint64_t>& dcls ) TRACE1 { TRACE1_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(dcls.size()), as_voidp(retval)); TRACE1_TEXT_ABC("", ach, ""); @@ -1167,21 +1184,13 @@ parser_statement_begin( const cbl_name_t statement_name, // the execution time of a program doing two-billion simple adds in an inner // loop dropped from 3.8 seconds to 0.175 seconds. - bool exception_processing = enabled_exceptions.size() ; + bool exception_processing = cdf_enabled_exceptions().size() ; if( !exception_processing ) { exception_processing = file_ops.find(statement_name) != file_ops.end(); } - if( gg_get_current_line_number() == DEFAULT_LINE_NUMBER ) - { - // This code is intended to prevert GDB anomalies when the first line of a - // program is a PERFORM <proc> ... TEST AFTER ... UNTIL ... - gg_set_current_line_number(CURRENT_LINE_NUMBER-1); - gg_assign(var_decl_nop, build_int_cst_type(INT, 106)); - } - // At this point, if any exception is enabled, we store the location stuff. // Each file I-O routine calls store_location_stuff explicitly, because // those exceptions can't be defeated. @@ -1189,14 +1198,9 @@ parser_statement_begin( const cbl_name_t statement_name, if( exception_processing ) { store_location_stuff(statement_name); - } - - gg_set_current_line_number(CURRENT_LINE_NUMBER); - - if( exception_processing ) - { set_exception_environment(ecs, dcls); } + sv_is_i_o = false; } @@ -1210,10 +1214,9 @@ initialize_variable_internal( cbl_refer_t refer, // gg_string_literal(refer.field->name), // NULL_TREE); cbl_field_t *parsed_var = refer.field; - - if( parsed_var->type == FldLiteralA ) + if( !parsed_var ) { - return; + cbl_internal_error("%s should not be null", "parsed_var"); } if( parsed_var->is_key_name() ) @@ -1229,7 +1232,7 @@ initialize_variable_internal( cbl_refer_t refer, return; } - if( parsed_var && parsed_var->type == FldBlob ) + if( parsed_var->type == FldBlob ) { return; } @@ -1347,8 +1350,6 @@ initialize_variable_internal( cbl_refer_t refer, SHOW_PARSE_END } - CHECK_FIELD(parsed_var); - // When initializing a variable, we have to ignore any DEPENDING ON clause // that might otherwise apply suppress_dest_depends = true; @@ -1588,7 +1589,7 @@ parser_initialize(const cbl_refer_t& refer, bool like_parser_symbol_add) static void get_binary_value_from_float(tree value, - cbl_refer_t &dest, + const cbl_refer_t &dest, cbl_field_t *source, tree source_offset ) @@ -1682,6 +1683,7 @@ depending_on_value(tree depending_on, cbl_field_t *current_sizer) // gg_assign(occurs_lower, build_int_cst_type(LONG, current_sizer->occurs.bounds.lower)); // gg_assign(occurs_upper, build_int_cst_type(LONG, current_sizer->occurs.bounds.upper)); + gcc_assert(current_sizer); if( current_sizer->occurs.depending_on ) { get_depending_on_value_from_odo(depending_on, current_sizer); @@ -1825,16 +1827,12 @@ normal_normal_compare(bool debugging, NULL_TREE); } - bool needs_adjusting; if( !left_intermediate && !right_intermediate ) { // Yay! Both sides have fixed rdigit values. - // Flag needs_adjusting as false, because we are going to do it here: - needs_adjusting = false; int adjust = get_scaled_rdigits(left_side_ref->field) - get_scaled_rdigits(right_side_ref->field); - if( adjust > 0 ) { // We need to make right_side bigger to match the scale of left_side @@ -1849,6 +1847,7 @@ normal_normal_compare(bool debugging, else { // At least one side is right_intermediate + bool needs_adjusting; tree adjust; if( !left_intermediate && right_intermediate ) @@ -2357,7 +2356,7 @@ cobol_compare( tree return_int, build_int_cst_type(INT, rightflags), integer_zero_node, NULL_TREE)); - compared = true; + // compared = true; // Commented out to quiet cppcheck } // gg_printf(" result is %d\n", return_int, NULL_TREE); @@ -2377,6 +2376,8 @@ move_tree( cbl_field_t *dest, SHOW_PARSE_END } + CHECK_FIELD(dest); + bool moved = true; tree source_length = gg_define_size_t(); @@ -2460,7 +2461,7 @@ move_tree( cbl_field_t *dest, psz_source, min_length, member(dest->var_decl_node, "picture"), - NULL); + NULL_TREE); break; } @@ -2563,7 +2564,7 @@ get_string_from(cbl_field_t *field) } static char * -combined_name(cbl_label_t *label) +combined_name(const cbl_label_t *label) { // This routine returns a pointer to a static, so make sure you use the result // before calling the routine again @@ -2578,7 +2579,7 @@ combined_name(cbl_label_t *label) if( label->parent ) { // It's possible for implicit - cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); + const cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); sect_name = section_label->name; } } @@ -2588,7 +2589,7 @@ combined_name(cbl_label_t *label) } static size_t retval_size = 256; - static char *retval= (char *)xmalloc(retval_size); + static char *retval= static_cast<char *>(xmalloc(retval_size)); char *paragraph = cobol_name_mangler(para_name); char *section = cobol_name_mangler(sect_name); @@ -2600,8 +2601,9 @@ combined_name(cbl_label_t *label) + 24 ) { retval_size *= 2; - retval = (char *)xrealloc(retval, retval_size); + retval = static_cast<char *>(xrealloc(retval, retval_size)); } + gcc_assert(retval); *retval = '\0'; char ach[24]; @@ -2648,8 +2650,9 @@ assembler_label(const char *label) { length = strlen(label) + strlen(local_text) + 1; free(build); - build = (char *)xmalloc(length); + build = static_cast<char *>(xmalloc(length)); } + gcc_assert(build); strcpy(build, label); strcat(build, local_text); @@ -2663,8 +2666,6 @@ section_label(struct cbl_proc_t *procedure) // With nested programs, you can have multiple program/section pairs with the // the same names; we use a deconflictor to avoid collisions - gg_set_current_line_number(CURRENT_LINE_NUMBER); - size_t deconflictor = symbol_label_id(procedure->label); cbl_label_t *label = procedure->label; @@ -2689,7 +2690,7 @@ section_label(struct cbl_proc_t *procedure) } assembler_label(psz2); free(psz2); - gg_assign(var_decl_nop, build_int_cst_type(INT, 108)); + insert_nop(108); } static void @@ -2704,8 +2705,6 @@ paragraph_label(struct cbl_proc_t *procedure) // are not referenced by the program. We provide a deconflictor to // separate such labels. - gg_set_current_line_number(CURRENT_LINE_NUMBER); - cbl_label_t *paragraph = procedure->label; cbl_label_t *section = nullptr; @@ -2727,6 +2726,9 @@ paragraph_label(struct cbl_proc_t *procedure) section_name ? section_name: "(null)" , current_function->our_unmangled_name ? current_function->our_unmangled_name: "" , (fmt_size_t)deconflictor ); + + // (0) is wrong, so back up one + gg_insert_into_assembler(psz1); SHOW_PARSE @@ -2743,7 +2745,25 @@ paragraph_label(struct cbl_proc_t *procedure) combined_name(procedure->label)); assembler_label(psz2); free(psz2); - gg_assign(var_decl_nop, build_int_cst_type(INT, 109)); + + // We are inserting a NOP after having created a label for the procedure. + // This means that when using GDC_COBOL to step into a procedure, the + // execution will stop there and show "123 para-name." at the stopped point. + // + // Note that because there is no user-specified executable code at that point + // the user can't set a working breakpoint with "break 123". But because + // GDB will pick up the psz2 text and set a breakpoint there (which is the + // location of the NOP) "break para-name" will actually stop and show line + // 123. + // + // This really only makes sense when you look at the assembly language. Keep + // in mind as you read it that issuing a "break 123" causes GDB to set a + // breakpoint at the first executable machine language code following the + // first ".loc 123" directive. + // + // Yes, trying to understand this causes headaches for many people who read + // this. Take an aspirin. + insert_nop(109); } static void @@ -2787,6 +2807,7 @@ pseudo_return_pop(cbl_proc_t *procedure) NULL_TREE); } + token_location_override(current_location_minus_one()); IF( var_decl_exit_address, eq_op, procedure->exit.addr ) { TRACE1 @@ -2796,11 +2817,13 @@ pseudo_return_pop(cbl_proc_t *procedure) // The top of the stack is us! // Pick up the return address from the pseudo_return stack: + token_location_override(current_location_minus_one()); gg_assign(current_function->void_star_temp, gg_call_expr( VOID_P, "__gg__pseudo_return_pop", NULL_TREE)); // And do the return: + token_location_override(current_location_minus_one()); gg_goto(current_function->void_star_temp); } ELSE @@ -2834,11 +2857,13 @@ leave_procedure(struct cbl_proc_t *procedure, bool /*section*/) // procedure->bottom.label); // Procedure can be null, for example at the beginning of a // new program, or after somebody else has cleared it out. + gg_append_statement(procedure->exit.label); char *psz; psz = xasprintf("_procret." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)symbol_label_id(procedure->label)); + token_location_override(current_location_minus_one()); gg_insert_into_assembler(psz); free(psz); pseudo_return_pop(procedure); @@ -2951,7 +2976,9 @@ find_procedure(cbl_label_t *label) static int counter=1; // This is a new section or paragraph; we need to create its values: - retval = (struct cbl_proc_t *)xmalloc(sizeof(struct cbl_proc_t)); + retval = static_cast<struct cbl_proc_t *> + (xmalloc(sizeof(struct cbl_proc_t))); + gcc_assert(retval); retval->label = label; gg_create_goto_pair(&retval->top.go_to, @@ -3007,6 +3034,8 @@ parser_enter_section(cbl_label_t *label) { SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", label) + SHOW_PARSE_INDENT + linemap_dump_location( line_table, current_token_location(), stderr ); SHOW_PARSE_END } @@ -3014,8 +3043,7 @@ parser_enter_section(cbl_label_t *label) // This NOP is needed to give GDB a line number for the entry point of // paragraphs - gg_set_current_line_number(CURRENT_LINE_NUMBER); - gg_assign(var_decl_nop, build_int_cst_type(INT, 101)); + insert_nop(101); struct cbl_proc_t *procedure = find_procedure(label); gg_append_statement(procedure->top.label); @@ -3042,6 +3070,8 @@ parser_enter_paragraph(cbl_label_t *label) { SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", label) + SHOW_PARSE_INDENT + linemap_dump_location( line_table, current_token_location(), stderr ); SHOW_PARSE_END } @@ -3257,16 +3287,20 @@ parser_goto( cbl_refer_t value_ref, size_t narg, cbl_label_t * const labels[] ) void parser_perform(cbl_label_t *label, bool suppress_nexting) { - label->used = yylineno; Analyze(); SHOW_PARSE { SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", label) char ach[32]; - sprintf(ach, " label is at %p", (void*)label); + sprintf(ach, " label is at %p", static_cast<void*>(label)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " label->proc is %p", (void*)label->structs.proc); + if( label ) + { + sprintf(ach, + " label->proc is %p", + static_cast<void*>(label->structs.proc)); + } SHOW_PARSE_TEXT(ach) SHOW_PARSE_END } @@ -3279,6 +3313,7 @@ parser_perform(cbl_label_t *label, bool suppress_nexting) } CHECK_LABEL(label); + label->used = yylineno; struct cbl_proc_t *procedure = find_procedure(label); @@ -3315,9 +3350,9 @@ parser_perform(cbl_label_t *label, bool suppress_nexting) char ach[256]; if( label->type == LblParagraph ) { - cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); + const cbl_label_t *sec_label = cbl_label_of(symbol_at(label->parent)); para_name = label->name; - sect_name = section_label->name; + sect_name = sec_label->name; sprintf(ach, "%s PERFORM %s of %s of %s (" HOST_SIZE_T_PRINT_DEC ")", ASM_COMMENT_START, @@ -3377,9 +3412,9 @@ parser_perform_times( cbl_label_t *proc_1, cbl_refer_t count ) SHOW_PARSE_REF(" ", count) SHOW_PARSE_TEXT(" TIMES") char ach[32]; - sprintf(ach, " proc_1 is at %p", (void*)proc_1); + sprintf(ach, " proc_1 is at %p", static_cast<void*>(proc_1)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " proc_1->proc is %p", (void*)proc_1->structs.proc); + sprintf(ach, " proc_1->proc is %p", static_cast<void*>(proc_1->structs.proc)); SHOW_PARSE_TEXT(ach) SHOW_PARSE_END } @@ -3416,6 +3451,7 @@ parser_perform_times( cbl_label_t *proc_1, cbl_refer_t count ) sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler(ach); } @@ -3430,17 +3466,22 @@ internal_perform_through( cbl_label_t *proc_1, SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", proc_1); char ach[32]; - sprintf(ach, " proc_1 is at %p", (void*)proc_1); + sprintf(ach, " proc_1 is at %p", static_cast<void*>(proc_1)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " proc_1->proc is %p", (void*)proc_1->structs.proc); + if( proc_1 ) + { + sprintf(ach, + " proc_1->proc is %p", + static_cast<void*>(proc_1->structs.proc)); + } SHOW_PARSE_TEXT(ach) if( proc_2 ) { SHOW_PARSE_INDENT - SHOW_PARSE_LABEL("", proc_2); - sprintf(ach, " proc_2 is at %p", (void*)proc_2); + SHOW_PARSE_LABEL_OK("", proc_2); + sprintf(ach, " proc_2 is at %p", static_cast<void*>(proc_2)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " proc_2->proc is %p", (void*)proc_2->structs.proc); + sprintf(ach, " proc_2->proc is %p", static_cast<void*>(proc_2->structs.proc)); SHOW_PARSE_TEXT(ach) } SHOW_PARSE_END @@ -3453,14 +3494,12 @@ internal_perform_through( cbl_label_t *proc_1, CHECK_LABEL(proc_1); - if(!proc_2) + if( !proc_2 ) { parser_perform(proc_1, suppress_nexting); return; } - CHECK_LABEL(proc_2); - struct cbl_proc_t *proc1 = find_procedure(proc_1); struct cbl_proc_t *proc2 = find_procedure(proc_2); @@ -3515,17 +3554,22 @@ internal_perform_through_times( cbl_label_t *proc_1, SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", proc_1); char ach[32]; - sprintf(ach, " proc_1 is at %p", (void*)proc_1); + sprintf(ach, " proc_1 is at %p", static_cast<void*>(proc_1)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " proc_1->proc is %p", (void*)proc_1->structs.proc); + if( proc_1 ) + { + sprintf(ach, + " proc_1->proc is %p", + static_cast<void*>(proc_1->structs.proc)); + } SHOW_PARSE_TEXT(ach) if( proc_2 ) { SHOW_PARSE_INDENT - SHOW_PARSE_LABEL("", proc_2); - sprintf(ach, " proc_2 is at %p", (void*)proc_2); + SHOW_PARSE_LABEL_OK("", proc_2); + sprintf(ach, " proc_2 is at %p", static_cast<void*>(proc_2)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " proc_2->proc is %p", (void*)proc_2->structs.proc); + sprintf(ach, " proc_2->proc is %p", static_cast<void*>(proc_2->structs.proc)); SHOW_PARSE_TEXT(ach) } SHOW_PARSE_REF(" ", count); @@ -3561,6 +3605,7 @@ internal_perform_through_times( cbl_label_t *proc_1, sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler( ach ); } @@ -3752,6 +3797,22 @@ parser_leave_file() { // We are leaving the top-level file, which means this compilation is // done, done, done. + + // There is, however, one thing left to do. If the command line says + // that this module needs a main entry point, then this is where + // we create a main() function. We build it at the end, so that all of + // the .loc directives associated with it appear at the end of the + // source code. We used to create the main() entry point at the beginning, + // but that created confusion for GDB when trying to debug the generated + // executable. + if( main_entry_point ) + { + next_program_is_main = false; + build_main_that_calls_something(main_entry_point); + free(main_entry_point); + main_entry_point = NULL; + } + gg_leaving_the_source_code_file(); } } @@ -3861,17 +3922,8 @@ parser_enter_program( const char *funcname_, // The first thing we have to do is mangle this name. This is safe even // though the end result will be mangled again, because the mangler doesn't // change a mangled name. - - char *mangled_name; - - if( current_call_convention() == cbl_call_cobol_e ) - { - mangled_name = cobol_name_mangler(funcname_); - } - else - { - mangled_name = xstrdup(funcname_); - } + + char *mangled_name = cobol_name_mangler(funcname_); size_t parent_index = current_program_index(); char *funcname; @@ -3899,28 +3951,25 @@ parser_enter_program( const char *funcname_, if( !is_function && !parent_index ) { - // This is a top_level program, and not a function + // This is a top_level program-id, and not a function if( next_program_is_main ) { + // This is the first top-level program-id. next_program_is_main = false; - if(main_entry_point) + if( !main_entry_point ) { - build_main_that_calls_something(main_entry_point); - free(main_entry_point); - main_entry_point = NULL; - } - else - { - build_main_that_calls_something(funcname); + // Because no explicit main_entry_point was specified, this program-id, + // the first in the file, becomes the target of the main() function + // that will be created at parser_leave_file time. + main_entry_point = xstrdup(funcname); + + char *psz = cobol_name_mangler(main_entry_point); + strncpy(ach_cobol_entry_point, psz, sizeof(ach_cobol_entry_point)-1); + free(psz); } } } - // Call this after build_main_that_calls_something, because it manipulates - // the current line number to DEFAULT_LINE_NUMBER. We have to manipulate it - // back afterward. - gg_set_current_line_number(CURRENT_LINE_NUMBER); - if( strcmp(funcname_, "main") == 0 && this_module_has_main ) { // setting 'retval' to 1 let's the caller know that we are being told @@ -4110,6 +4159,8 @@ psa_FldLiteralN(struct cbl_field_t *field ) // We are constructing a completely static constant structure, based on the // text string in .initial + CHECK_FIELD(field); + FIXED_WIDE_INT(128) value = 0; do @@ -4302,6 +4353,8 @@ psa_FldBlob(struct cbl_field_t *var ) SHOW_PARSE_END } + CHECK_FIELD(var); + // We are constructing a completely static constant structure. We know the // capacity. We'll create it from the data.initial. The var_decl_node will // be a pointer to the data @@ -4339,67 +4392,182 @@ psa_FldBlob(struct cbl_field_t *var ) } void -parser_accept( struct cbl_refer_t refer, - enum special_name_t special_e ) +parser_accept(const struct cbl_refer_t &tgt, + special_name_t special_e, + cbl_label_t *error, + cbl_label_t *not_error ) { - Analyze(); SHOW_PARSE { SHOW_PARSE_HEADER - SHOW_PARSE_REF(" ", refer); + if( error ) + { + SHOW_PARSE_LABEL(" error ", error) + } + if( not_error ) + { + SHOW_PARSE_LABEL(" not_error ", not_error) + } SHOW_PARSE_END } - TRACE1 - { - TRACE1_HEADER - TRACE1_END - } - - /* - enum special_name_t - { - SYSIN_e, - SYSIPT_e, - SYSOUT_e, - SYSLIST_e, - SYSLST_e, - SYSPUNCH_e, - SYSPCH_e, - CONSOLE_e, - C01_e, C02_e, C03_e, C04_e, C05_e, C06_e, - C07_e, C08_e, C09_e, C10_e, C11_e, C12_e, - CSP_e, - S01_e, S02_e, S03_e, S04_e, S05_e, - AFP_5A_e, - }; - */ // The ISO spec describes the valid special names for ACCEPT as implementation // dependent. We are following IBM's lead. tree environment = build_int_cst_type(INT, special_e); - switch( special_e ) + const char *function_to_call = NULL; + + switch(special_e) { + case STDIN_e: case CONSOLE_e: case SYSIPT_e: case SYSIN_e: - break; - default: - dbgmsg("%s(): We don't know what to do with special_name_t %d,", __func__, special_e); - dbgmsg("%s(): so we are ignoring it.", __func__); - yywarn("unrecognized SPECIAL NAME ignored"); + // This is ordinary input from from the stdin: + gg_call(VOID, + "__gg__accept", + environment, + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_dest(tgt), + NULL_TREE); return; break; - } - gg_call(VOID, - "__gg__accept", - environment, - gg_get_address_of(refer.field->var_decl_node), - refer_offset(refer), - refer_size_dest(refer), - NULL_TREE); + case C01_e: + case C02_e: + case C03_e: + case C04_e: + case C05_e: + case C06_e: + case C07_e: + case C08_e: + case C09_e: + case C10_e: + case C11_e: + case C12_e: + case CSP_e: + case S01_e: + case S02_e: + case S03_e: + case S04_e: + case S05_e: + case AFP_5A_e: + case STDOUT_e: + case SYSOUT_e: + case SYSLIST_e: + case SYSLST_e: + case STDERR_e: + case SYSPUNCH_e: + case SYSPCH_e: + case SYSERR_e: + cbl_internal_error("Not valid for ACCEPT statement."); + break; + + case ARG_NUM_e: + // This ACCEPT statement wants the number of argv values: + gg_call(VOID, + "__gg__get_argc", + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_source(tgt), + NULL_TREE); + return; + break; + + case ENV_NAME_e: + // This fetches the environment name set by DISPLAY... UPON ENV_NAME_e + gg_call(VOID, + "__gg__get_env_name", + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_source(tgt), + NULL_TREE); + return; + break; + + case ENV_VALUE_e: + // This fetches the environment value associated with the previously + // esablished name + function_to_call = "__gg__get_env_value"; + break; + + case ARG_VALUE_e: + // We are fetching the variable whose index was established by a prior + // DISPLAY UPON ARGUMENT-NUMBER. After the fetch, the value will be + // incremented by one. + function_to_call = "__gg__accept_arg_value"; + break; + } + if( function_to_call ) + { + tree erf = gg_define_int(); + gg_assign(erf, + gg_call_expr( INT, + function_to_call, + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_dest(tgt), + NULL_TREE)); + if( error ) + { + // There is an ON EXCEPTION phrase: + IF( erf, ne_op, integer_zero_node ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down GOTO error->INTO for_argv") + SHOW_PARSE_LABEL_OK(" ", error) + } + gg_append_statement( error->structs.arith_error->into.go_to ); + } + ELSE + { + } + ENDIF + } + if( not_error ) + { + // There is an NOT ON EXCEPTION phrase: + IF( erf, eq_op, integer_zero_node ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down GOTO not_error->INTO for_argv") + SHOW_PARSE_LABEL_OK(" ", not_error) + } + gg_append_statement( not_error->structs.arith_error->into.go_to ); + } + ELSE + { + } + ENDIF + } + if( error ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down LABEL error->bottom") + SHOW_PARSE_LABEL_OK(" ", error) + } + gg_append_statement( error->structs.arith_error->bottom.label ); + } + if( not_error ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down LABEL not_error->bottom") + SHOW_PARSE_LABEL_OK(" ", not_error) + SHOW_PARSE_END + } + gg_append_statement( not_error->structs.arith_error->bottom.label ); + } + } } // TODO: update documentation. @@ -4411,7 +4579,6 @@ parser_accept_exception( cbl_label_t *accept_label ) // We are entering either SIZE ERROR or NOT SIZE ERROR code RETURN_IF_PARSE_ONLY; - set_up_on_exception_label(accept_label); SHOW_PARSE { @@ -4424,6 +4591,9 @@ parser_accept_exception( cbl_label_t *accept_label ) SHOW_PARSE_END } + CHECK_LABEL(accept_label); + set_up_on_exception_label(accept_label); + // Jump over the [NOT] ON EXCEPTION code that is about to be laid down gg_append_statement( accept_label->structs.arith_error->over.go_to ); // Create the label that allows the following code to be executed at @@ -4450,6 +4620,8 @@ parser_accept_exception_end( cbl_label_t *accept_label ) SHOW_PARSE_END } + CHECK_LABEL(accept_label); + // Jump to the end of the arithmetic code: gg_append_statement( accept_label->structs.arith_error->bottom.go_to ); // Lay down the label that allows the ERROR/NOT ERROR instructions @@ -4459,8 +4631,8 @@ parser_accept_exception_end( cbl_label_t *accept_label ) } void -parser_accept_command_line( cbl_refer_t tgt, - cbl_refer_t source, +parser_accept_command_line( const cbl_refer_t &tgt, + const cbl_refer_t &source, cbl_label_t *error, cbl_label_t *not_error ) { @@ -4500,7 +4672,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down GOTO error->INTO for_command_line") - SHOW_PARSE_LABEL(" ", error) + SHOW_PARSE_LABEL_OK(" ", error) } gg_append_statement( error->structs.arith_error->into.go_to ); } @@ -4518,7 +4690,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down GOTO not_error->INTO for command_line") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) } gg_append_statement( not_error->structs.arith_error->into.go_to ); } @@ -4550,7 +4722,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down GOTO error->INTO for_argv") - SHOW_PARSE_LABEL(" ", error) + SHOW_PARSE_LABEL_OK(" ", error) } gg_append_statement( error->structs.arith_error->into.go_to ); } @@ -4568,7 +4740,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down GOTO not_error->INTO for_argv") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) } gg_append_statement( not_error->structs.arith_error->into.go_to ); } @@ -4584,7 +4756,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down LABEL error->bottom") - SHOW_PARSE_LABEL(" ", error) + SHOW_PARSE_LABEL_OK(" ", error) } gg_append_statement( error->structs.arith_error->bottom.label ); } @@ -4594,7 +4766,7 @@ parser_accept_command_line( cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down LABEL not_error->bottom") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) SHOW_PARSE_END } gg_append_statement( not_error->structs.arith_error->bottom.label ); @@ -4602,7 +4774,7 @@ parser_accept_command_line( cbl_refer_t tgt, } void -parser_accept_command_line_count( cbl_refer_t tgt ) +parser_accept_command_line_count( const cbl_refer_t &tgt ) { Analyze(); SHOW_PARSE @@ -4624,10 +4796,10 @@ parser_accept_command_line_count( cbl_refer_t tgt ) } void -parser_accept_envar(struct cbl_refer_t tgt, - struct cbl_refer_t envar, - cbl_label_t *error, - cbl_label_t *not_error ) +parser_accept_envar(const struct cbl_refer_t &tgt, + const struct cbl_refer_t &envar, + cbl_label_t *error, + cbl_label_t *not_error ) { Analyze(); @@ -4692,7 +4864,7 @@ parser_accept_envar(struct cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down LABEL error->bottom") - SHOW_PARSE_LABEL(" ", error) + SHOW_PARSE_LABEL_OK(" ", error) } gg_append_statement( error->structs.arith_error->bottom.label ); } @@ -4702,7 +4874,7 @@ parser_accept_envar(struct cbl_refer_t tgt, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT("Laying down LABEL not_error->bottom") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) SHOW_PARSE_END } gg_append_statement( not_error->structs.arith_error->bottom.label ); @@ -4710,7 +4882,8 @@ parser_accept_envar(struct cbl_refer_t tgt, } void -parser_set_envar( struct cbl_refer_t name, struct cbl_refer_t value ) +parser_set_envar( const struct cbl_refer_t &name, + const struct cbl_refer_t &value ) { Analyze(); SHOW_PARSE @@ -5112,7 +5285,6 @@ parser_display_internal(tree file_descriptor, build_int_cst_type(SIZE_T, refer.field->data.capacity), advance ? integer_one_node : integer_zero_node, NULL_TREE ); - cursor_at_sol = advance; } else if( refer.field->type == FldLiteralN ) { @@ -5150,50 +5322,50 @@ parser_display_internal(tree file_descriptor, *p = 'E'; if( exp < 0 && exp >= -9 ) { - p[1] = '-'; - p[2] = '0'; - p[3] = '0' - exp; - p[4] = '\0'; + p[1] = '-'; + p[2] = '0'; + p[3] = '0' - exp; + p[4] = '\0'; } else if( exp >= 0 && exp <= 9 ) { - p[1] = '+'; - p[2] = '0'; - p[3] = '0' + exp; - p[4] = '\0'; + p[1] = '+'; + p[2] = '0'; + p[3] = '0' + exp; + p[4] = '\0'; } } else if (exp == 0) { - p[-1] = '\0'; + p[-1] = '\0'; } else if (exp < 0) { - p[-1] = '\0'; - char *q = strchr (ach, '.'); - char dig = q[-1]; - q[-1] = '\0'; - char tem[132]; - snprintf (tem, 132, "%s0.%0*u%c%s", ach, -exp - 1, 0, dig, q + 1); - strcpy (ach, tem); + p[-1] = '\0'; + char *q = strchr (ach, '.'); + char dig = q[-1]; + q[-1] = '\0'; + char tem[132]; + snprintf (tem, 132, "%s0.%0*d%c%s", ach, -exp - 1, 0, dig, q + 1); + strcpy (ach, tem); } - else if (exp > 0) + else // if (exp > 0) { - p[-1] = '\0'; - char *q = strchr (ach, '.'); - for (int i = 0; i != exp; ++i) - q[i] = q[i + 1]; - q[exp] = '.'; + p[-1] = '\0'; + char *q = strchr (ach, '.'); + for (int i = 0; i != exp; ++i) + q[i] = q[i + 1]; + q[exp] = '.'; } __gg__remove_trailing_zeroes(ach); } if( symbol_decimal_point() == ',' ) { - char *p = strchr(ach, '.' ); - if( p ) + char *pdot = strchr(ach, '.' ); + if( pdot ) { - *p = symbol_decimal_point(); + *pdot = symbol_decimal_point(); } } @@ -5250,22 +5422,29 @@ parser_display_field(cbl_field_t *field) DISPLAY_NO_ADVANCE); } -/* - * The first parameter to parser_display is the "device" upon which to display - * the data. Besides normal devices, these may include elements that define the - * Unix command line and environment: - * 1. ARG_NUM_e, the ARGUMENT-NUMBER - * 2. ARG_VALUE_e, the ARGUMENT-VALUE - * 3. ENV_NAME_e, the ENVIRONMENT-NAME - * 4. ENV_VALUE_e, the ENVIRONMENT-VALUE - * that need special care and feeding. - */ void parser_display( const struct cbl_special_name_t *upon, - struct cbl_refer_t refs[], - size_t n, - bool advance ) + const std::vector<cbl_refer_t> &refs, + bool advance, + const cbl_label_t *not_error, + const cbl_label_t *error ) { + const size_t n = refs.size(); + /* + * The first parameter to parser_display is the "device" upon which to display + * the data. Besides normal devices, these may include elements that define the + * Unix command line and environment: + * 1. ARG_NUM_e, the ARGUMENT-NUMBER + * 2. ARG_VALUE_e, the ARGUMENT-VALUE + * 3. ENV_NAME_e, the ENVIRONMENT-NAME + * 4. ENV_VALUE_e, the ENVIRONMENT-VALUE + * that need special care and feeding. + */ + + // At the present time, I am not sure what not_error and error are for + gcc_assert(!not_error); + gcc_assert(!error); + Analyze(); SHOW_PARSE { @@ -5274,7 +5453,7 @@ parser_display( const struct cbl_special_name_t *upon, for(size_t i=0; i<n; i++) { SHOW_PARSE_INDENT - SHOW_PARSE_REF("", refs[i]); + SHOW_PARSE_REF("", refs.at(i)); } if( advance ) { @@ -5306,23 +5485,81 @@ parser_display( const struct cbl_special_name_t *upon, { switch(upon->id) { + // See table 5 in the IBM Cobol For Linux x86 1.2 document. + + case STDIN_e: + case SYSIN_e: + case SYSIPT_e: + cbl_internal_error("Attempting to send to an input device."); + break; + + case C01_e: + case C02_e: + case C03_e: + case C04_e: + case C05_e: + case C06_e: + case C07_e: + case C08_e: + case C09_e: + case C10_e: + case C11_e: + case C12_e: + case CSP_e: + case S01_e: + case S02_e: + case S03_e: + case S04_e: + case S05_e: + case AFP_5A_e: + case ARG_VALUE_e: + cbl_internal_error("Not valid for DISPLAY statement."); + break; + case STDOUT_e: - case SYSOUT_e: - case SYSLIST_e: - case SYSLST_e: case CONSOLE_e: + // These are inarguably stdout gg_assign(file_descriptor, integer_one_node); break; case STDERR_e: + case SYSERR_e: + // These are inarguably stderr + gg_assign(file_descriptor, integer_two_node); + break; + + case SYSOUT_e: + case SYSLIST_e: + case SYSLST_e: case SYSPUNCH_e: case SYSPCH_e: - gg_assign(file_descriptor, integer_two_node); + // In the 21st century, when there are no longer valid assumptions to + // be made about the existence of line printers, and where things + // formerly-ubiquitous card punches no longer exist, there is a need + // for the possibility of assigning these "devices" to externally- + // determined Unix gadgetry in /dev: + gg_assign(file_descriptor, + gg_call_expr( INT, + "__gg__get_file_descriptor", + gg_string_literal(upon->os_filename), + NULL_TREE)); + needs_closing = true; break; + case ARG_NUM_e: + // Set the index number for a subsequent ACCEPT FROM ARG_VALUE_e + gg_call(VOID, + "__gg__set_arg_num", + gg_get_address_of(refs[0].field->var_decl_node), + refer_offset(refs[0]), + refer_size_source(refs[0]), + NULL_TREE); + return; + break; + case ENV_NAME_e: - // This Part I of the slightly absurd method of using DISPLAY...UPON - // to fetch, or set, environment variables. + // Establish the name of an environment variable for later use with + // in either DISPLAY UPON or ACCEPT FROM gg_call(VOID, "__gg__set_env_name", gg_get_address_of(refs[0].field->var_decl_node), @@ -5332,19 +5569,16 @@ parser_display( const struct cbl_special_name_t *upon, return; break; - default: - if( upon->os_filename[0] ) - { - tree topen = gg_open( gg_string_literal(upon->os_filename), - build_int_cst_type(INT, O_APPEND|O_WRONLY)); - gg_assign(file_descriptor, topen); - needs_closing = true; - } - else - { - fprintf(stderr, "We don't know what to do in parser_display\n"); - gcc_unreachable(); - } + case ENV_VALUE_e: + // Set the contents of the environment variable named with ENV_NAME_e + gg_call(VOID, + "__gg__set_env_value", + gg_get_address_of(refs[0].field->var_decl_node), + refer_offset(refs[0]), + refer_size_source(refs[0]), + NULL_TREE); + return; + break; } } else @@ -5359,17 +5593,114 @@ parser_display( const struct cbl_special_name_t *upon, } CHECK_FIELD(refs[n-1].field); parser_display_internal(file_descriptor, refs[n-1], advance ? DISPLAY_ADVANCE : DISPLAY_NO_ADVANCE); - if( needs_closing ) { - tree tclose = gg_close(file_descriptor); - // We are ignoring the close() return value - gg_append_statement(tclose); + gg_close(file_descriptor); } cursor_at_sol = advance; } +static +bool // Returns false for literals; true for named variables +get_exhibit_name(tree file_descriptor, const cbl_refer_t &arg) + { + bool retval; + if( is_literal(arg.field) ) + { + // If something is a literal, we just display the literal value + parser_display_internal(file_descriptor, + arg, + DISPLAY_NO_ADVANCE); + retval = false; + } + else + { + // It's not a literal, so we show its name, and the names or literal + // values) of any qualifier subscripts or refmods + gg_write( file_descriptor, + gg_string_literal(arg.field->name), + build_int_cst_type(SIZE_T, strlen(arg.field->name)) ); + + if( arg.subscripts.size() ) + { + // This refer has subscripts: + gg_write( file_descriptor, + gg_string_literal("("), + integer_one_node ); + for(size_t i=0; i<arg.subscripts.size(); i++) + { + if( i > 0 ) + { + gg_write( file_descriptor, + gg_string_literal(","), + integer_one_node ); + } + get_exhibit_name(file_descriptor, arg.subscripts[i]); + } + gg_write( file_descriptor, + gg_string_literal(")"), + integer_one_node ); + } + if( arg.refmod.from || arg.refmod.len ) + { + gg_write( file_descriptor, + gg_string_literal("("), + integer_one_node ); + if( arg.refmod.from ) + { + get_exhibit_name(file_descriptor, *(arg.refmod.from)); + } + gg_write( file_descriptor, + gg_string_literal(":"), + integer_one_node ); + if( arg.refmod.len ) + { + get_exhibit_name(file_descriptor, *(arg.refmod.len)); + } + gg_write( file_descriptor, + gg_string_literal(")"), + integer_one_node ); + } + retval = true; + } + return retval; + } + +void +parser_exhibit( bool /*changed*/, bool /*named*/, + const std::vector<cbl_refer_t> &args ) + { + tree file_descriptor = gg_define_int(); + gg_assign(file_descriptor, integer_one_node); // stdout is file descriptor 1. + + for(size_t i=0; i<args.size(); i++) + { + CHECK_FIELD(args[i].field); + if(i > 0) + { + // When there more than one argument, the second through Nth get a space + // in front of them. + gg_write( file_descriptor, + gg_string_literal(" "), + integer_one_node); + } + if( get_exhibit_name(file_descriptor, args[i]) ) + { + gg_write( file_descriptor, + gg_string_literal("="), + integer_one_node); + parser_display_internal(file_descriptor, + args[i], + DISPLAY_NO_ADVANCE); + } + } + gg_write( file_descriptor, + gg_string_literal("\n"), + integer_one_node); + cursor_at_sol = true; + } + static tree get_literalN_value(cbl_field_t *var) { @@ -5642,12 +5973,12 @@ parser_assign( size_t nC, cbl_num_result_t *C, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT(" Laying down on_error GOTO into") - SHOW_PARSE_LABEL(" ", on_error) + SHOW_PARSE_LABEL_OK(" ", on_error) } IF( gg_bitwise_or(error_flag, compute_error->structs.compute_error->compute_error_code), - ne_op, - integer_zero_node ) + ne_op, + integer_zero_node ) { gg_append_statement( on_error->structs.arith_error->into.go_to ); } @@ -5673,7 +6004,7 @@ parser_assign( size_t nC, cbl_num_result_t *C, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT(" Laying down not_error GOTO into") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) } IF( compute_error->structs.compute_error->compute_error_code, eq_op, integer_zero_node ) { @@ -5689,7 +6020,7 @@ parser_assign( size_t nC, cbl_num_result_t *C, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT(" Laying down on_error LABEL BOTTOM:") - SHOW_PARSE_LABEL(" ", on_error) + SHOW_PARSE_LABEL_OK(" ", on_error) } gg_append_statement( on_error->structs.arith_error->bottom.label ); } @@ -5700,7 +6031,7 @@ parser_assign( size_t nC, cbl_num_result_t *C, { SHOW_PARSE_INDENT SHOW_PARSE_TEXT(" Laying down not_error LABEL BOTTOM:") - SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_LABEL_OK(" ", not_error) } gg_append_statement( not_error->structs.arith_error->bottom.label ); } @@ -5975,10 +6306,18 @@ parser_initialize_table(size_t nelem, } typedef size_t span_t[2]; static_assert(sizeof(spans[0]) == sizeof(span_t), "pair size wrong"); - static tree tspans = gg_define_variable(SIZE_T_P, "..pit_v1", vs_file_static); - static tree ttbls = gg_define_variable(SIZE_T_P, "..pit_v2", vs_file_static); - gg_assign(tspans, build_array_of_size_t(2*nspan, (const size_t *)spans)); - gg_assign(ttbls, build_array_of_size_t(2*ntbl, (const size_t *)tbls)); + static tree tspans = gg_define_variable(SIZE_T_P, + "..pit_v1", + vs_file_static); + static tree ttbls = gg_define_variable(SIZE_T_P, + "..pit_v2", +vs_file_static); + gg_assign(tspans, + build_array_of_size_t(2*nspan, + reinterpret_cast<const size_t *>(spans))); + gg_assign(ttbls, + build_array_of_size_t(2*ntbl, + reinterpret_cast<const size_t *>(tbls))); gg_call(VOID, "__gg__mirror_range", @@ -6137,7 +6476,7 @@ is_valuable( cbl_field_type_t type ) { return false; } -void parser_sleep(cbl_refer_t seconds) +void parser_sleep(const cbl_refer_t &seconds) { if( seconds.field ) { @@ -6157,7 +6496,7 @@ void parser_sleep(cbl_refer_t seconds) // This is a naked place-holding CONTINUE. Generate some do-nothing // code that will stick some .LOC information into the assembly language, // so that GDB-COBOL can display the CONTINUE statement. - gg_assign(var_decl_nop, build_int_cst_type(INT, 103)); + insert_nop(103); } } @@ -6240,12 +6579,12 @@ program_end_stuff(cbl_refer_t refer, ec_type_t ec) tree array_type = build_array_type_nelts(UCHAR, returner->data.capacity); - tree retval = gg_define_variable(array_type, vs_static); - gg_memcpy(gg_get_address_of(retval), + tree array = gg_define_variable(array_type, vs_static); + gg_memcpy(gg_get_address_of(array), member(returner->var_decl_node, "data"), member(returner->var_decl_node, "capacity")); - tree actual = gg_cast(COBOL_FUNCTION_RETURN_TYPE, gg_get_address_of(retval)); + tree actual = gg_cast(COBOL_FUNCTION_RETURN_TYPE, gg_get_address_of(array)); restore_local_variables(); gg_return(actual); @@ -6501,7 +6840,6 @@ parser_arith_error(cbl_label_t *arithmetic_label) // We are entering either SIZE ERROR or NOT SIZE ERROR code RETURN_IF_PARSE_ONLY; - set_up_on_exception_label(arithmetic_label); SHOW_PARSE { @@ -6514,6 +6852,10 @@ parser_arith_error(cbl_label_t *arithmetic_label) SHOW_PARSE_END } + CHECK_LABEL(arithmetic_label); + + set_up_on_exception_label(arithmetic_label); + // Jump over the [NOT] ON EXCEPTION code that is about to be laid down gg_append_statement( arithmetic_label->structs.arith_error->over.go_to ); // Create the label that allows the following code to be executed at @@ -6540,6 +6882,8 @@ parser_arith_error_end(cbl_label_t *arithmetic_label) SHOW_PARSE_END } + CHECK_LABEL(arithmetic_label); + // Jump to the end of the arithmetic code: gg_append_statement( arithmetic_label->structs.arith_error->bottom.go_to ); // Lay down the label that allows the ERROR/NOT ERROR instructions @@ -6723,8 +7067,6 @@ parser_division(cbl_division_t division, SHOW_PARSE_END } - gg_set_current_line_number(CURRENT_LINE_NUMBER); - if( division == data_div_e ) { Analyze(); @@ -6876,7 +7218,6 @@ parser_division(cbl_division_t division, // expected formal parameter and tacks it onto the end of the // function's arguments chain. - char ach[2*sizeof(cbl_name_t)]; sprintf(ach, "_p_%s", args[i].refer.field->name); size_t nbytes = 0; @@ -6896,14 +7237,13 @@ parser_division(cbl_division_t division, chain_parameter_to_function(current_function->function_decl, par_type, ach); } - bool check_for_parameter_count = false; - if( nusing ) { // During the call, we saved the parameter_count and an array of variable // lengths. We need to look at those values if, and only if, one or more // of our USING arguments has an OPTIONAL flag or if one of our targets is // marked as VARYING. + bool check_for_parameter_count = false; for(size_t i=0; i<nusing; i++) { if( args[i].optional ) @@ -7099,7 +7439,6 @@ parser_division(cbl_division_t division, // If so, we have to give var2::data_pointer the same value as // var1::data_pointer // - cbl_field_t *next_var; size_t our_index = symbol_index(symbol_elem_of(new_var)); size_t next_index = our_index + 1; // Look ahead in the symbol table for the next LEVEL01/77 @@ -7110,7 +7449,7 @@ parser_division(cbl_division_t division, { break; } - next_var = cbl_field_of(e); + cbl_field_t *next_var = cbl_field_of(e); if( !next_var ) { break; @@ -7185,6 +7524,11 @@ parser_division(cbl_division_t division, ENDIF } ENDIF + // The first token_location that the parser establishes is caused by the + // parser scanning all of the lines in the source code. This messes up the + // logic for backing up one line, which is needed to correctly step through + // COBOL code with GDB-COBOL. So, we clear it here. + current_location_minus_one_clear(); } } @@ -7629,7 +7973,9 @@ label_fetch(struct cbl_label_t *label) if( !label->structs.goto_trees ) { label->structs.goto_trees - = (cbl_label_addresses_t *)xmalloc(sizeof(struct cbl_label_addresses_t) ); + = static_cast<cbl_label_addresses_t *> + (xmalloc(sizeof(struct cbl_label_addresses_t))); + gcc_assert(label->structs.goto_trees); gg_create_goto_pair(&label->structs.goto_trees->go_to, &label->structs.goto_trees->label); @@ -7647,15 +7993,18 @@ parser_label_label(struct cbl_label_t *label) SHOW_PARSE_HEADER SHOW_PARSE_LABEL("", label) char ach[32]; - sprintf(ach, " label is at %p", (void*)label); + sprintf(ach, " label is at %p", static_cast<void*>(label)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " label->proc is %p", (void*)label->structs.proc); + if( label ) + { + sprintf(ach, + " label->proc is %p", + static_cast<void*>(label->structs.proc)); + } SHOW_PARSE_TEXT(ach) SHOW_PARSE_END } - CHECK_LABEL(label); - TRACE1 { TRACE1_HEADER @@ -7663,6 +8012,8 @@ parser_label_label(struct cbl_label_t *label) TRACE1_END } + CHECK_LABEL(label); + if(strcmp(label->name, "_end_declaratives") == 0 ) { suppress_cobol_entry_point = false; @@ -7674,21 +8025,25 @@ void parser_label_goto(struct cbl_label_t *label) { label->used = yylineno; + Analyze(); SHOW_PARSE { SHOW_PARSE_HEADER SHOW_PARSE_LABEL(" ", label) char ach[32]; - sprintf(ach, " label is at %p", (void*)label); + sprintf(ach, " label is at %p", static_cast<void*>(label)); SHOW_PARSE_TEXT(ach) - sprintf(ach, " label->proc is %p", (void*)label->structs.proc); + if( label ) + { + sprintf(ach, + " label->proc is %p", + static_cast<void*>(label->structs.proc)); + } SHOW_PARSE_TEXT(ach) SHOW_PARSE_END } - CHECK_LABEL(label); - TRACE1 { TRACE1_HEADER @@ -7696,7 +8051,9 @@ parser_label_goto(struct cbl_label_t *label) TRACE1_END } - if(strcmp(label->name, "_end_declaratives") == 0 ) + CHECK_LABEL(label); + + if( strcmp(label->name, "_end_declaratives") == 0 ) { suppress_cobol_entry_point = true; } @@ -7780,7 +8137,7 @@ parser_setop( struct cbl_field_t *tgt, void parser_classify( cbl_field_t *tgt, - cbl_refer_t candidate, + const cbl_refer_t &candidate, enum classify_t type ) { Analyze(); @@ -7877,14 +8234,6 @@ create_iline_address_pairs(struct cbl_perform_tgt_t *tgt) gg_create_goto_pair(&tgt->addresses.setup.go_to, &tgt->addresses.setup.label); - - // Even in -O0 compilations, the compiler does some elementary optimizations - // around JMP instructions. We have the SETUP code for in-line performats - // in an island at the end of the loop code. With this intervention, NEXTing - // through the code shows you the final statement of the loop before the - // loop actually starts. - - tgt->addresses.line_number_of_setup_code = gg_get_current_line_number(); } void @@ -7898,7 +8247,7 @@ parser_perform_start( struct cbl_perform_tgt_t *tgt ) { SHOW_PARSE_TEXT(" cbl_perform_tgt_t is at") char ach[32]; - sprintf(ach, " %p", (void*)tgt); + sprintf(ach, " %p", static_cast<void*>(tgt)); SHOW_PARSE_TEXT(ach); SHOW_PARSE_LABEL(" ", tgt->from()) if( tgt->to() ) @@ -7947,7 +8296,7 @@ parser_perform_start( struct cbl_perform_tgt_t *tgt ) // Give GDB-COBOL something to chew on when NEXTing. This instruction will // get the line number of the PERFORM N TIMES code. gg_append_statement(tgt->addresses.top.label); - gg_assign(var_decl_nop, build_int_cst_type(INT, 104)); + insert_nop(104); } void @@ -7959,7 +8308,7 @@ parser_perform_conditional( struct cbl_perform_tgt_t *tgt ) SHOW_PARSE_HEADER SHOW_PARSE_TEXT(" cbl_perform_tgt_t is at") char ach[32]; - sprintf(ach, " %p", (void*)tgt); + sprintf(ach, " %p", static_cast<void*>(tgt)); SHOW_PARSE_TEXT(ach); SHOW_PARSE_END } @@ -8009,7 +8358,7 @@ parser_perform_conditional_end( struct cbl_perform_tgt_t *tgt ) SHOW_PARSE_HEADER SHOW_PARSE_TEXT(" cbl_perform_tgt_t is at") char ach[32]; - sprintf(ach, " %p", (void*)tgt); + sprintf(ach, " %p", static_cast<void*>(tgt)); SHOW_PARSE_TEXT(ach); SHOW_PARSE_END } @@ -8099,6 +8448,7 @@ perform_outofline_before_until(struct cbl_perform_tgt_t *tgt, sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler( ach ); } @@ -8162,6 +8512,7 @@ perform_outofline_after_until(struct cbl_perform_tgt_t *tgt, sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler( ach ); } @@ -8282,6 +8633,7 @@ perform_outofline_testafter_varying(struct cbl_perform_tgt_t *tgt, sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler( ach ); } @@ -8425,6 +8777,7 @@ perform_outofline_before_varying( struct cbl_perform_tgt_t *tgt, sprintf(ach, "_procretb." HOST_SIZE_T_PRINT_DEC ":", (fmt_size_t)our_pseudo_label); + token_location_override(current_location_minus_one()); gg_insert_into_assembler( ach ); } @@ -8504,8 +8857,6 @@ perform_inline_until( struct cbl_perform_tgt_t *tgt, GOTO TOP EXIT: */ - gg_set_current_line_number(cobol_location().last_line); - gg_append_statement(tgt->addresses.test.label); // Go to where the conditional is recalculated.... @@ -8620,8 +8971,6 @@ perform_inline_testbefore_varying( struct cbl_perform_tgt_t *tgt, parser_move(varys[i].varying, varys[i].from); } - gg_set_current_line_number(cobol_location().last_line); - // Lay down the testing cycle: for(size_t i=0; i<N; i++) { @@ -8933,7 +9282,7 @@ parser_perform_until( struct cbl_perform_tgt_t *tgt, SHOW_PARSE_HEADER SHOW_PARSE_TEXT(" cbl_perform_tgt_t is at") char ach[32]; - sprintf(ach, " %p", (void*)tgt); + sprintf(ach, " %p", static_cast<void*>(tgt)); SHOW_PARSE_TEXT(ach); SHOW_PARSE_LABEL(" ", tgt->from()) if( tgt->to() ) @@ -8943,9 +9292,6 @@ parser_perform_until( struct cbl_perform_tgt_t *tgt, SHOW_PARSE_END } - gg_set_current_line_number(cobol_location().last_line); - gg_assign(var_decl_nop, build_int_cst_type(INT, 105)); - if( tgt->from()->type != LblLoop ) { perform_outofline( tgt, test_before, N, varys); @@ -9012,10 +9358,6 @@ parser_perform_inline_times(struct cbl_perform_tgt_t *tgt, gg_append_statement( tgt->addresses.testA.label ); gg_append_statement( tgt->addresses.test.label ); - // AT this point, we want to set the line_number to the location of the - // END-PERFORM statement. - gg_set_current_line_number(cobol_location().last_line); - gg_decrement(counter); // Do the test: IF( counter, gt_op, gg_cast(LONG, integer_zero_node) ) @@ -9046,8 +9388,6 @@ parser_perform_inline_times(struct cbl_perform_tgt_t *tgt, SHOW_PARSE_END } - int stash = gg_get_current_line_number(); - gg_set_current_line_number(tgt->addresses.line_number_of_setup_code); gg_append_statement( tgt->addresses.setup.label ); // Get the count: @@ -9078,8 +9418,6 @@ parser_perform_inline_times(struct cbl_perform_tgt_t *tgt, gg_append_statement( tgt->addresses.exit.go_to ); ENDIF - gg_set_current_line_number(stash); - SHOW_PARSE { SHOW_PARSE_INDENT @@ -9768,13 +10106,19 @@ void parser_file_delete( struct cbl_file_t *file, bool /*sequentially*/ ) { Analyze(); + + if( !file ) + { + cbl_internal_error("The file pointer should not be null"); + abort(); // Because cppcheck doesn't recognize [[noerror]] + } + bool sequentially = file->access == file_access_seq_e || file->org == file_sequential_e || file->org == file_line_sequential_e; SHOW_PARSE { SHOW_PARSE_HEADER - if(file) { SHOW_PARSE_TEXT(" "); SHOW_PARSE_TEXT(file->name); @@ -9787,10 +10131,6 @@ parser_file_delete( struct cbl_file_t *file, bool /*sequentially*/ ) SHOW_PARSE_TEXT(" sequentially") } } - else - { - SHOW_PARSE_TEXT(" *file is NULL") - } SHOW_PARSE_END } @@ -9947,8 +10287,8 @@ parser_file_start(struct cbl_file_t *file, // A key has a number of fields for(size_t ifield=0; ifield<file->keys[key_number].nfield; ifield++) { - size_t field_index = file->keys[key_number].fields[ifield]; - cbl_field_t *field = cbl_field_of(symbol_at(field_index)); + size_t nfield = file->keys[key_number].fields[ifield]; + cbl_field_t *field = cbl_field_of(symbol_at(nfield)); combined_length += field->data.capacity; } gg_assign(length, build_int_cst_type(SIZE_T, combined_length)); @@ -9975,7 +10315,7 @@ parser_file_start(struct cbl_file_t *file, static void inspect_tally(bool backward, - cbl_refer_t identifier_1, + const cbl_refer_t &identifier_1, cbl_inspect_opers_t& identifier_2) { Analyze(); @@ -10175,8 +10515,8 @@ inspect_tally(bool backward, static void inspect_replacing(int backward, - cbl_refer_t identifier_1, - cbl_inspect_opers_t& operations) + const cbl_refer_t &identifier_1, + cbl_inspect_opers_t &operations) { Analyze(); // This is an INSPECT FORMAT 2 @@ -10516,7 +10856,7 @@ parser_intrinsic_numval_c( cbl_field_t *f, void parser_intrinsic_subst( cbl_field_t *f, - cbl_refer_t& ref1, + const cbl_refer_t& ref1, size_t argc, cbl_substitute_t * argv ) { @@ -10541,7 +10881,9 @@ parser_intrinsic_subst( cbl_field_t *f, sv_is_i_o = true; store_location_stuff("SUBSTITUTE"); - unsigned char *control_bytes = (unsigned char *)xmalloc(argc * sizeof(unsigned char)); + unsigned char *control_bytes = + static_cast<unsigned char *>(xmalloc(argc * sizeof(unsigned char))); + gcc_assert(control_bytes); std::vector<cbl_refer_t> arg1(argc); std::vector<cbl_refer_t> arg2(argc); @@ -10978,7 +11320,9 @@ static void create_lsearch_address_pairs(struct cbl_label_t *name) { // Create the lsearch structure - name->structs.lsearch = (cbl_lsearch_t *)xmalloc(sizeof(cbl_lsearch_t)); + name->structs.lsearch = + static_cast<cbl_lsearch_t *>(xmalloc(sizeof(cbl_lsearch_t))); + gcc_assert(name->structs.lsearch); cbl_lsearch_t *lsearch = name->structs.lsearch; gg_create_goto_pair(&lsearch->addresses.at_exit.go_to, @@ -11228,7 +11572,9 @@ parser_bsearch_start( cbl_label_t* name, } // We need a cbl_bsearch_t structure: - name->structs.bsearch = (cbl_bsearch_t *)xmalloc(sizeof(cbl_bsearch_t)); + name->structs.bsearch = + static_cast<cbl_bsearch_t *>(xmalloc(sizeof(cbl_bsearch_t))); + gcc_assert(name->structs.bsearch); cbl_bsearch_t *bsearch = name->structs.bsearch; // Create the address/label pairs we need @@ -11261,6 +11607,8 @@ parser_bsearch_start( cbl_label_t* name, current = parent_of(current); } + CHECK_FIELD(current); + // There are a number of things we learn from the field "current" // We get the index: @@ -11373,7 +11721,6 @@ is_ascending_key(const cbl_refer_t& key) bool retval = true; cbl_field_t *family_tree = key.field; - gcc_assert(family_tree); while( family_tree ) { if( family_tree->occurs.nkey ) @@ -11382,7 +11729,10 @@ is_ascending_key(const cbl_refer_t& key) } family_tree = parent_of(family_tree); } + + CHECK_FIELD(family_tree); gcc_assert(family_tree->occurs.nkey); + for(size_t i=0; i<family_tree->occurs.nkey; i++) { for(size_t j=0; j<family_tree->occurs.keys[i].field_list.nfield; j++) @@ -11542,8 +11892,12 @@ parser_sort(cbl_refer_t tableref, return n + key.fields.size(); } ); typedef const cbl_field_t * const_field_t; - const_field_t *flattened_fields = (const_field_t *)xmalloc(total_keys * sizeof(cbl_field_t *)); - size_t *flattened_ascending = (size_t *)xmalloc(total_keys * sizeof(size_t)); + const_field_t *flattened_fields = + static_cast<const_field_t *>(xmalloc(total_keys * sizeof(cbl_field_t *))); + gcc_assert(flattened_fields); + size_t *flattened_ascending = + static_cast<size_t *>(xmalloc(total_keys * sizeof(size_t))); + gcc_assert(flattened_ascending); size_t key_index = 0; for( size_t i=0; i<keys.size(); i++ ) @@ -11679,8 +12033,12 @@ parser_file_sort( cbl_file_t *workfile, return n + key.fields.size(); } ); typedef const cbl_field_t * const_field_t; - auto flattened_fields = (const_field_t *)xmalloc(total_keys * sizeof(cbl_field_t *)); - size_t *flattened_ascending = (size_t *) xmalloc(total_keys * sizeof(size_t)); + auto flattened_fields + = static_cast<const_field_t *>(xmalloc(total_keys * sizeof(cbl_field_t *))); + gcc_assert(flattened_fields); + size_t *flattened_ascending = + static_cast<size_t *>(xmalloc(total_keys * sizeof(size_t))); + gcc_assert(flattened_ascending); size_t key_index = 0; for( size_t i=0; i<keys.size(); i++ ) @@ -11839,7 +12197,9 @@ parser_return_start( cbl_file_t *workfile, cbl_refer_t into ) // We assume that workfile is open. - workfile->addresses = (cbl_sortreturn_t *)xmalloc(sizeof(cbl_sortreturn_t)); + workfile->addresses = static_cast<cbl_sortreturn_t *> + (xmalloc(sizeof(cbl_sortreturn_t))); + gcc_assert(workfile->addresses); gg_create_goto_pair(&workfile->addresses->at_end.go_to, &workfile->addresses->at_end.label); gg_create_goto_pair(&workfile->addresses->not_at_end.go_to, @@ -12025,9 +12385,13 @@ parser_file_merge( cbl_file_t *workfile, return i + key.fields.size(); } ); typedef const cbl_field_t * const_field_t; - const_field_t *flattened_fields = (const_field_t *)xmalloc(total_keys * sizeof(cbl_field_t *)); + const_field_t *flattened_fields + = static_cast<const_field_t *> + (xmalloc(total_keys * sizeof(cbl_field_t *))); + gcc_assert(flattened_fields); size_t *flattened_ascending - = (size_t *)xmalloc(total_keys * sizeof(size_t)); + = static_cast<size_t *>(xmalloc(total_keys * sizeof(size_t))); + gcc_assert(flattened_ascending); size_t key_index = 0; for( size_t i=0; i<keys.size(); i++ ) @@ -12041,8 +12405,9 @@ parser_file_merge( cbl_file_t *workfile, } // Create the array of cbl_field_t pointers for the keys - tree all_keys = gg_array_of_field_pointers(total_keys, - const_cast<cbl_field_t**>(flattened_fields)); + tree all_keys = gg_array_of_field_pointers( + total_keys, + const_cast<cbl_field_t**>(flattened_fields)); // Create the array of integers that are the flags for ASCENDING: tree ascending = gg_array_of_size_t(total_keys, flattened_ascending); @@ -12066,6 +12431,9 @@ parser_file_merge( cbl_file_t *workfile, ELSE ENDIF + const cbl_enabled_exceptions_t& + enabled_exceptions( cdf_enabled_exceptions() ); + for(size_t i=0; i<ninputs; i++) { if( process_this_exception(ec_sort_merge_file_open_e) ) @@ -12223,7 +12591,8 @@ parser_string_overflow( cbl_label_t *name ) */ name->structs.unstring - = (cbl_unstring_t *)xmalloc(sizeof(struct cbl_unstring_t) ); + = static_cast<cbl_unstring_t *>(xmalloc(sizeof(struct cbl_unstring_t))); + gcc_assert(name->structs.unstring); // Set up the address pairs for this clause gg_create_goto_pair(&name->structs.unstring->over.go_to, @@ -12282,8 +12651,8 @@ parser_unstring(cbl_refer_t src, } std::vector<cbl_refer_t> delims(ndelimited); - char *alls = (char *)xmalloc(ndelimited+1); - + char *alls = static_cast<char *>(xmalloc(ndelimited+1)); + gcc_assert(alls); for(size_t i=0; i<ndelimited; i++) { delims[i] = delimiteds[i]; @@ -12374,7 +12743,8 @@ parser_string(const cbl_refer_t& tgt, } // We need an array of nsource+1 integers: - size_t *integers = (size_t *)xmalloc((nsource+1)*sizeof(size_t)); + size_t *integers = static_cast<size_t *>(xmalloc((nsource+1)*sizeof(size_t))); + gcc_assert(integers); // Count up how many treeplets we are going to need: size_t cblc_count = 2; // tgt and pointer @@ -12465,8 +12835,9 @@ parser_call_exception( cbl_label_t *name ) } name->structs.call_exception - = (cbl_call_exception_t *)xmalloc(sizeof(struct cbl_call_exception_t) ); - + = static_cast<cbl_call_exception_t *> + (xmalloc(sizeof(struct cbl_call_exception_t))); + gcc_assert(name->structs.call_exception); // Set up the address pairs for this clause gg_create_goto_pair(&name->structs.call_exception->over.go_to, &name->structs.call_exception->over.label); @@ -12526,8 +12897,10 @@ create_and_call(size_t narg, if(narg) { - arguments = (tree *)xmalloc(2*narg * sizeof(tree)); - allocated = (int * )xmalloc(narg * sizeof(int)); + arguments = static_cast<tree *>(xmalloc(2*narg * sizeof(tree))); + gcc_assert(arguments); + allocated = static_cast<int *>(xmalloc(narg * sizeof(int))); + gcc_assert(allocated); } // Put the arguments onto the "stack" of calling parameters: @@ -12759,7 +13132,7 @@ create_and_call(size_t narg, // Fetch the FUNCTION_DECL for that FUNCTION_TYPE tree function_decl = gg_build_fn_decl(funcname, fndecl_type); set_call_convention(function_decl, current_call_convention()); - + // Take the address of the function decl: tree address_of_function = gg_get_address_of(function_decl); @@ -12771,7 +13144,7 @@ create_and_call(size_t narg, parser_call_target( funcname, assigment ); // Create the call_expr from that address - call_expr = build_call_array_loc( location_from_lineno(), + call_expr = build_call_array_loc( gg_token_location(), returned_value_type, address_of_function, narg, @@ -13510,9 +13883,9 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) // are also accessible by us. Go find them. std::vector<const hier_node *>uncles; find_uncles(nodes[i], uncles); - for( size_t i=0; i<uncles.size(); i++ ) + for( size_t j=0; j<uncles.size(); j++ ) { - const hier_node *uncle = uncles[i]; + const hier_node *uncle = uncles[j]; if( map_of_sets[caller].find(uncle->name) == map_of_sets[caller].end() ) { // We have a COMMON uncle or sibling we haven't seen before. @@ -13550,7 +13923,6 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) if( callers.find(caller) == callers.end() ) { // We haven't seen this caller before - callers.insert(caller); char ach[3*sizeof(cbl_name_t)]; tree names_table_type = build_array_type_nelts(CHAR_P, mol->second.size()+1); @@ -13617,6 +13989,8 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) (fmt_size_t)caller); tree accessible_programs_decl = gg_trans_unit_var_decl(ach); gg_assign( accessible_programs_decl, gg_get_address_of(the_constructed_table) ); + + callers.insert(caller); } } } @@ -13734,7 +14108,7 @@ parser_check_fatal_exception() // in its innermost loop had an execution time of 19.5 seconds. By putting in // the if() statement, that was reduced to 3.8 seconds. - if( enabled_exceptions.size() || sv_is_i_o ) + if( cdf_enabled_exceptions().size() || sv_is_i_o ) { gg_call(VOID, "__gg__check_fatal_exception", @@ -13882,9 +14256,9 @@ conditional_abs(tree source, const cbl_field_t *field) } static bool -mh_identical(cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource) +mh_identical(const cbl_refer_t &destref, + const cbl_refer_t &sourceref, + const TREEPLET &tsource) { // Check to see if the two variables are identical types, thus allowing // for a simple byte-for-byte copy of the data areas: @@ -13906,7 +14280,7 @@ mh_identical(cbl_refer_t &destref, ) { // The source and destination are identical in type - if( (sourceref.field->attr & intermediate_e) || !symbol_find_odo(sourceref.field) ) + if( !symbol_find_odo(sourceref.field) ) { Analyze(); // Source doesn't have a depending_on clause @@ -14224,7 +14598,7 @@ float_type_of(const cbl_field_t *field) } static tree -float_type_of(cbl_refer_t *refer) +float_type_of(const cbl_refer_t *refer) { return float_type_of(refer->field); } @@ -14456,7 +14830,7 @@ picky_memset(tree &dest_p, unsigned char value, size_t length) } static void -picky_memcpy(tree &dest_p, tree &source_p, size_t length) +picky_memcpy(tree &dest_p, const tree &source_p, size_t length) { if( length ) { @@ -14475,10 +14849,10 @@ picky_memcpy(tree &dest_p, tree &source_p, size_t length) } static bool -mh_numeric_display( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource, - tree size_error) +mh_numeric_display( const cbl_refer_t &destref, + const cbl_refer_t &sourceref, + const TREEPLET &tsource, + tree size_error) { bool moved = false; @@ -14964,11 +15338,11 @@ mh_numeric_display( cbl_refer_t &destref, } static bool -mh_little_endian( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource, - bool check_for_error, - tree size_error) +mh_little_endian( const cbl_refer_t &destref, + const cbl_refer_t &sourceref, + const TREEPLET &tsource, + bool check_for_error, + tree size_error) { bool moved = false; @@ -15036,9 +15410,9 @@ mh_little_endian( cbl_refer_t &destref, } static bool -mh_source_is_group( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsrc) +mh_source_is_group( const cbl_refer_t &destref, + const cbl_refer_t &sourceref, + const TREEPLET &tsrc) { bool retval = false; if( sourceref.field->type == FldGroup && !(destref.field->attr & rjust_e) ) @@ -15103,7 +15477,7 @@ move_helper(tree size_error, // This is an INT { // We are creating a copy of the original destination in case we clobber it // and have to restore it because of a computational error. - bool first_time = true; + static bool first_time = true; static size_t stash_size = 1024; if( first_time ) { @@ -15128,7 +15502,7 @@ move_helper(tree size_error, // This is an INT //goto dont_be_clever; this will go through to the default. } - if( !moved ) + // if( !moved ) // commented out to quiet cppcheck { moved = mh_source_is_group(destref, sourceref, tsource); } @@ -15197,8 +15571,9 @@ move_helper(tree size_error, // This is an INT if( buffer_size < source_length ) { buffer_size = source_length; - buffer = (char *)xrealloc(buffer, buffer_size); + buffer = static_cast<char *>(xrealloc(buffer, buffer_size)); } + gcc_assert(buffer); if( figconst ) { @@ -15341,7 +15716,7 @@ move_helper(tree size_error, // This is an INT gg_attribute_bit_clear(destref.field, refmod_e); } - moved = true; + // moved = true; // commented out to quiet cppcheck } if( restore_on_error ) @@ -15472,7 +15847,8 @@ binary_initial_from_float128(cbl_field_t *field, int rdigits, FIXED_WIDE_INT(128) i = FIXED_WIDE_INT(128)::from (real_to_integer (&value, &fail, 128), SIGNED); - retval = (char *)xmalloc(field->data.capacity); + retval = static_cast<char *>(xmalloc(field->data.capacity)); + gcc_assert(retval); switch(field->data.capacity) { tree type; @@ -15483,7 +15859,7 @@ binary_initial_from_float128(cbl_field_t *field, int rdigits, case 16: type = build_nonstandard_integer_type ( field->data.capacity * BITS_PER_UNIT, 0); - native_encode_wide_int (type, i, (unsigned char *)retval, + native_encode_wide_int (type, i, PTRCAST(unsigned char, retval), field->data.capacity); break; default: @@ -15613,7 +15989,8 @@ initial_from_initial(cbl_field_t *field) } if( set_return ) { - retval = (char *)xmalloc(field->data.capacity+1); + retval = static_cast<char *>(xmalloc(field->data.capacity+1)); + gcc_assert(retval); memset(retval, const_char, field->data.capacity); retval[field->data.capacity] = '\0'; return retval; @@ -15683,7 +16060,8 @@ initial_from_initial(cbl_field_t *field) case FldNumericDisplay: { - retval = (char *)xmalloc(field->data.capacity); + retval = static_cast<char *>(xmalloc(field->data.capacity)); + gcc_assert(retval); char *pretval = retval; char ach[128]; @@ -15763,7 +16141,8 @@ initial_from_initial(cbl_field_t *field) case FldPacked: { - retval = (char *)xmalloc(field->data.capacity); + retval = static_cast<char *>(xmalloc(field->data.capacity)); + gcc_assert(retval); char *pretval = retval; char ach[128]; @@ -15830,7 +16209,8 @@ initial_from_initial(cbl_field_t *field) { if( field->data.initial ) { - retval = (char *)xmalloc(field->data.capacity+1); + retval = static_cast<char *>(xmalloc(field->data.capacity+1)); + gcc_assert(retval); if( field->attr & hex_encoded_e) { memcpy(retval, field->data.initial, field->data.capacity); @@ -15838,7 +16218,7 @@ initial_from_initial(cbl_field_t *field) else { size_t buffer_size = 0; - size_t length = (size_t)field->data.capacity; + size_t length = field->data.capacity; memset(retval, internal_space, length); raw_to_internal(&retval, &buffer_size, field->data.initial, length); if( strlen(field->data.initial) < length ) @@ -15854,7 +16234,8 @@ initial_from_initial(cbl_field_t *field) case FldNumericEdited: { - retval = (char *)xmalloc(field->data.capacity+1); + retval = static_cast<char *>(xmalloc(field->data.capacity+1)); + gcc_assert(retval); if( field->data.initial && field->attr & quoted_e ) { // What the programmer says the value is, the value becomes, no @@ -15889,7 +16270,6 @@ initial_from_initial(cbl_field_t *field) char ach[128]; memset(ach, 0, sizeof(ach)); memset(retval, 0, field->data.capacity); - size_t ndigits = field->data.capacity; if( (field->attr & blank_zero_e) && real_iszero (&value) ) { @@ -15897,6 +16277,7 @@ initial_from_initial(cbl_field_t *field) } else { + size_t ndigits = field->data.capacity; digits_from_float128(ach, field, ndigits, rdigits, value); /* ??? This resides in libgcobol valconv.cc. */ __gg__string_to_numeric_edited( retval, @@ -15911,23 +16292,24 @@ initial_from_initial(cbl_field_t *field) case FldFloat: { - retval = (char *)xmalloc(field->data.capacity); + retval = static_cast<char *>(xmalloc(field->data.capacity)); + gcc_assert(retval); switch( field->data.capacity ) { case 4: value = real_value_truncate (TYPE_MODE (FLOAT), value); native_encode_real (SCALAR_FLOAT_TYPE_MODE (FLOAT), &value, - (unsigned char *)retval, 4, 0); + PTRCAST(unsigned char, retval), 4, 0); break; case 8: value = real_value_truncate (TYPE_MODE (DOUBLE), value); native_encode_real (SCALAR_FLOAT_TYPE_MODE (DOUBLE), &value, - (unsigned char *)retval, 8, 0); + PTRCAST(unsigned char, retval), 8, 0); break; case 16: value = real_value_truncate (TYPE_MODE (FLOAT128), value); native_encode_real (SCALAR_FLOAT_TYPE_MODE (FLOAT128), &value, - (unsigned char *)retval, 16, 0); + PTRCAST(unsigned char, retval), 16, 0); break; } break; @@ -16313,12 +16695,13 @@ psa_FldLiteralA(struct cbl_field_t *field ) // First make room static size_t buffer_size = 1024; - static char *buffer = (char *)xmalloc(buffer_size); + static char *buffer = static_cast<char *>(xmalloc(buffer_size)); if( buffer_size < field->data.capacity+1 ) { buffer_size = field->data.capacity+1; - buffer = (char *)xrealloc(buffer, buffer_size); + buffer = static_cast<char *>(xrealloc(buffer, buffer_size)); } + gcc_assert(buffer); cbl_figconst_t figconst = cbl_figconst_of( field->data.initial ); gcc_assert(figconst == normal_value_e); @@ -16373,7 +16756,7 @@ psa_FldLiteralA(struct cbl_field_t *field ) vs_file_static); } else -#endif +#endif { // We have not seen that string before static int nvar = 0; @@ -16387,9 +16770,9 @@ psa_FldLiteralA(struct cbl_field_t *field ) vs_file_static); actually_create_the_static_field( field, - build_string_literal(field->data.capacity+1, + build_string_literal(field->data.capacity, buffer), - field->data.capacity+1, + field->data.capacity, field->data.initial, NULL_TREE, field->var_decl_node); @@ -16417,6 +16800,8 @@ parser_local_add(struct cbl_field_t *new_var ) SHOW_PARSE_END } + CHECK_FIELD(new_var); + IF( member(new_var->var_decl_node, "data"), ne_op, gg_cast(UCHAR_P, null_pointer_node) ) @@ -16473,8 +16858,8 @@ parser_symbol_add(struct cbl_field_t *new_var ) } while(0); - fprintf(stderr, " %2.2d %s<%s> off:" HOST_SIZE_T_PRINT_DEC " " - "msiz:%d cap:%d dig:%d rdig:%d attr:0x" HOST_SIZE_T_PRINT_HEX_PURE " loc:%p", + fprintf(stderr, " %2.2u %s<%s> off:" HOST_SIZE_T_PRINT_UNSIGNED " " + "msiz:%u cap:%u dig:%u rdig:%d attr:0x" HOST_SIZE_T_PRINT_HEX_PURE " loc:%p", new_var->level, new_var->name, cbl_field_type_str(new_var->type), @@ -16484,7 +16869,7 @@ parser_symbol_add(struct cbl_field_t *new_var ) new_var->data.digits, new_var->data.rdigits, (fmt_size_t)new_var->attr, - (void*)new_var); + static_cast<void*>(new_var)); if( is_table(new_var) ) { @@ -16524,7 +16909,7 @@ parser_symbol_add(struct cbl_field_t *new_var ) { fprintf(stderr, " redefines:(%p)%s", - (void*)symbol_redefines(new_var), + static_cast<void*>(symbol_redefines(new_var)), symbol_redefines(new_var)->name); } @@ -16624,10 +17009,12 @@ parser_symbol_add(struct cbl_field_t *new_var ) TRACE1_TEXT_ABC(" (", cbl_field_type_str(new_var->type) ,")") if( new_var->type == FldLiteralN) { + const void *p1 = (new_var->data.initial); + const long *pldata = static_cast<const long *>(p1); + long ldata = *pldata; gg_fprintf( trace_handle, 1, " [%ld]", - build_int_cst_type(LONG, - *(const long *)new_var->data.initial)); + build_int_cst_type(LONG, ldata)); } TRACE1_END } diff --git a/gcc/cobol/genapi.h b/gcc/cobol/genapi.h index 36d947b..b41b906 100644 --- a/gcc/cobol/genapi.h +++ b/gcc/cobol/genapi.h @@ -52,17 +52,26 @@ void parser_division( cbl_division_t division, void parser_enter_program(const char *funcname, bool is_function, int *retval); void parser_leave_program(); -void parser_accept( cbl_refer_t refer, special_name_t special_e); +void parser_accept( const cbl_refer_t &refer, + special_name_t special_e, + cbl_label_t *error, + cbl_label_t *not_error ); void parser_accept_exception( cbl_label_t *name ); void parser_accept_exception_end( cbl_label_t *name ); -void parser_accept_envar( cbl_refer_t refer, cbl_refer_t envar, - cbl_label_t *error, cbl_label_t *not_error ); -void parser_set_envar( cbl_refer_t envar, cbl_refer_t refer ); +void parser_accept_under_discussion(struct cbl_refer_t tgt, special_name_t special, + cbl_label_t *error, cbl_label_t *not_error ); +void parser_accept_envar( const cbl_refer_t &refer, + const cbl_refer_t &envar, + cbl_label_t *error, + cbl_label_t *not_error ); +void parser_set_envar( const cbl_refer_t &envar, const cbl_refer_t &refer ); -void parser_accept_command_line( cbl_refer_t tgt, cbl_refer_t src, - cbl_label_t *error, cbl_label_t *not_error ); -void parser_accept_command_line_count( cbl_refer_t tgt ); +void parser_accept_command_line(const cbl_refer_t &tgt, + const cbl_refer_t &src, + cbl_label_t *error, + cbl_label_t *not_error ); +void parser_accept_command_line_count( const cbl_refer_t &tgt ); void parser_accept_date_yymmdd( cbl_field_t *tgt ); void parser_accept_date_yyyymmdd( cbl_field_t *tgt ); @@ -86,8 +95,7 @@ parser_add( size_t nC, cbl_num_result_t *C, size_t nA, cbl_refer_t *A, cbl_arith_format_t format, cbl_label_t *error, - cbl_label_t *not_error, - void *compute_error = NULL); // This has to be cast to a tree pointer to int + cbl_label_t *not_error, void *compute_error = NULL); // This has to be cast to a tree pointer to int void parser_arith_error( cbl_label_t *name ); void parser_arith_error_end( cbl_label_t *name ); @@ -174,7 +182,8 @@ parser_bitwise_op(struct cbl_field_t *tgt, void parser_classify( struct cbl_field_t *tgt, - struct cbl_refer_t srca, enum classify_t type ); + const struct cbl_refer_t &srca, + enum classify_t type ); void parser_op( struct cbl_refer_t cref, @@ -253,7 +262,7 @@ parser_program_hierarchy( const struct cbl_prog_hier_t& hier ); void parser_end_program(const char *name=NULL); -void parser_sleep(cbl_refer_t seconds); +void parser_sleep(const cbl_refer_t &seconds); void parser_exit( const cbl_refer_t& refer, ec_type_t = ec_none_e ); void parser_exit_section(void); @@ -262,9 +271,14 @@ void parser_exit_perform( struct cbl_perform_tgt_t *tgt, bool cycle ); void parser_exit_program(void); // exits back to COBOL only, else continue void +parser_exhibit( bool changed, bool named, + const std::vector<cbl_refer_t> &args ); +void parser_display( const struct cbl_special_name_t *upon, - struct cbl_refer_t args[], size_t n, - bool advance = DISPLAY_ADVANCE ); + const std::vector<cbl_refer_t> &args, + bool advance = DISPLAY_ADVANCE, + const cbl_label_t *not_error = nullptr, + const cbl_label_t *compute_error = nullptr ); void parser_display_field(cbl_field_t *fld); @@ -300,7 +314,7 @@ void parser_initialize(const cbl_refer_t& refer, bool like_parser_symbol_add=false); void -parser_initialize_programs(size_t nprog, struct cbl_refer_t *progs); +parser_initialize_programs(size_t nprog, const struct cbl_refer_t *progs); void parser_label_label( struct cbl_label_t *label ); @@ -447,7 +461,7 @@ parser_intrinsic_numval_c( cbl_field_t *f, void parser_intrinsic_subst( cbl_field_t *f, - cbl_refer_t& ref1, + const cbl_refer_t& ref1, size_t argc, cbl_substitute_t * argv ); diff --git a/gcc/cobol/gengen.cc b/gcc/cobol/gengen.cc index e42747b..3ad3344 100644 --- a/gcc/cobol/gengen.cc +++ b/gcc/cobol/gengen.cc @@ -107,8 +107,6 @@ // Don't like it? Cry me a river. static const int ARG_LIMIT = 512; -static int sv_current_line_number; - // These are globally useful constants tree char_nodes[256]; @@ -140,7 +138,7 @@ struct cbl_translation_unit_t gg_trans_unit; // the compiler when a source code module makes that mistake. static std::unordered_set<std::string> names_we_have_seen; -// This vector is used to process the function_decls at the point we leave +// This vector is used to process the function_decls at the point we leave // the file. static std::vector<tree> finalized_function_decls; @@ -452,7 +450,7 @@ gg_assign(tree dest, const tree source) if( okay ) { - stmt = build2_loc(location_from_lineno(), + stmt = build2_loc(gg_token_location(), MODIFY_EXPR, TREE_TYPE(dest), dest, @@ -616,7 +614,7 @@ gg_add_field_to_structure(const tree type_of_field, const char *name_of_field, t tree id_of_field = get_identifier (name_of_field); // Create the new field: - tree new_field_decl = build_decl( location_from_lineno(), + tree new_field_decl = build_decl( gg_token_location(), FIELD_DECL, id_of_field, type_of_field); @@ -893,7 +891,7 @@ gg_create_assembler_name(const char *cobol_name) static char * gg_unique_in_function(const char *var_name, gg_variable_scope_t vs_scope) { - char *retval = (char *)xmalloc(strlen(var_name)+32); + char *retval = static_cast<char *>(xmalloc(strlen(var_name)+32)); if( (vs_scope == vs_stack || vs_scope == vs_static) ) { sprintf(retval, "%s." HOST_SIZE_T_PRINT_DEC, var_name, @@ -1028,10 +1026,7 @@ gg_declare_variable(tree type_decl, break; } DECL_INITIAL(var_decl) = initial_value; - if( unique_name ) - { - free(unique_name); - } + free(unique_name); return var_decl; } @@ -1046,7 +1041,7 @@ gg_define_from_declaration(tree var_decl) { // Having made sure the chain of variable declarations is nicely started, // it's time to actually define the storage with a decl_expression: - tree stmt = build1_loc (location_from_lineno(), + tree stmt = build1_loc (gg_token_location(), DECL_EXPR, TREE_TYPE(var_decl), var_decl); @@ -1777,7 +1772,7 @@ gg_build_relational_expression(tree operand_a, compare = LE_EXPR; break; } - tree relational_expression = build2_loc(location_from_lineno(), + tree relational_expression = build2_loc(gg_token_location(), compare, boolean_type_node, operand_a, @@ -1894,7 +1889,7 @@ gg_create_goto_pair(tree *goto_expr, void gg_goto_label_decl(tree label_decl) { - tree goto_expr = build1_loc( location_from_lineno(), + tree goto_expr = build1_loc( gg_token_location(), GOTO_EXPR, void_type_node, label_decl); @@ -1941,7 +1936,7 @@ gg_create_goto_pair(tree *goto_expr, tree *label_expr, const char *name) void gg_goto(tree var_decl_pointer) { - tree go_to = build1_loc(location_from_lineno(), + tree go_to = build1_loc(gg_token_location(), GOTO_EXPR, void_type_node, var_decl_pointer); @@ -2189,7 +2184,7 @@ gg_printf(const char *format_string, ...) function = gg_get_function_address(INT, "__gg__fprintf_stderr"); } - tree stmt = build_call_array_loc (location_from_lineno(), + tree stmt = build_call_array_loc (gg_token_location(), INT, function, nargs, @@ -2236,7 +2231,7 @@ gg_fprintf(tree fd, int nargs, const char *format_string, ...) function = gg_get_function_address(INT, "sprintf"); } - tree stmt = build_call_array_loc (location_from_lineno(), + tree stmt = build_call_array_loc (gg_token_location(), INT, function, argc, @@ -2283,7 +2278,7 @@ void gg_memset(tree dest, const tree value, tree size) { tree the_call = - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_MEMSET), 3, dest, @@ -2297,7 +2292,7 @@ gg_memchr(tree buf, tree ch, tree length) { tree the_call = fold_convert( pvoid_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_MEMCHR), 3, buf, @@ -2312,7 +2307,7 @@ void gg_memcpy(tree dest, const tree src, tree size) { tree the_call = build_call_expr_loc( - location_from_lineno(), + gg_token_location(), builtin_decl_explicit (BUILT_IN_MEMCPY), 3, dest, @@ -2327,7 +2322,7 @@ void gg_memmove(tree dest, const tree src, tree size) { tree the_call = build_call_expr_loc( - location_from_lineno(), + gg_token_location(), builtin_decl_explicit (BUILT_IN_MEMMOVE), 3, dest, @@ -2360,7 +2355,7 @@ void gg_strcpy(tree dest, tree src) { tree the_call = - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_STRCPY), 2, dest, @@ -2373,7 +2368,7 @@ gg_strcmp(tree A, tree B) { tree the_call = fold_convert( integer_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_STRCMP), 2, A, @@ -2405,7 +2400,7 @@ gg_strncmp(tree char_star_A, tree char_star_B, tree size_t_N) { tree the_call = fold_convert( integer_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_STRNCMP), 3, char_star_A, @@ -2436,7 +2431,7 @@ gg_return(tree operand) { // When there is no operand, or if the function result is void, then // we just generate a return_expr. - stmt = build1_loc(location_from_lineno(), RETURN_EXPR, void_type_node, NULL_TREE); + stmt = build1_loc(gg_token_location(), RETURN_EXPR, void_type_node, NULL_TREE); } else { @@ -2446,7 +2441,7 @@ gg_return(tree operand) function_type, DECL_RESULT(current_function->function_decl), gg_cast(function_type, operand)); - stmt = build1_loc(location_from_lineno(), RETURN_EXPR, void_type_node, modify); + stmt = build1_loc(gg_token_location(), RETURN_EXPR, void_type_node, modify); } gg_append_statement(stmt); } @@ -2454,7 +2449,7 @@ gg_return(tree operand) void chain_parameter_to_function(tree function_decl, const tree param_type, const char *name) { - tree parm = build_decl (location_from_lineno(), + tree parm = build_decl (gg_token_location(), PARM_DECL, get_identifier (name), param_type); @@ -2521,12 +2516,12 @@ gg_peek_fn_decl(const char *funcname, tree fndecl_type) } return retval; } - + tree gg_build_fn_decl(const char *funcname, tree fndecl_type) { tree function_decl; - + std::string key = function_decl_key(funcname, fndecl_type); std::unordered_map<std::string, tree>::const_iterator it = map_of_function_decls.find(key); @@ -2617,13 +2612,13 @@ gg_define_function( tree return_type, } va_end(params); + char ach[32]; std::unordered_set<std::string>::const_iterator it = names_we_have_seen.find(funcname); if( it != names_we_have_seen.end() ) { static int bum_counter = 1; // We have seen this name before. Replace it with something unique: - char ach[32]; sprintf(ach, "..no_dupes.%d", bum_counter++); funcname = ach; } @@ -2689,7 +2684,7 @@ gg_define_function( tree return_type, } // Establish the RESULT_DECL for the function: - tree resdecl = build_decl (location_from_lineno(), RESULT_DECL, NULL_TREE, return_type); + tree resdecl = build_decl (gg_token_location(), RESULT_DECL, NULL_TREE, return_type); DECL_CONTEXT (resdecl) = function_decl; DECL_RESULT (function_decl) = resdecl; @@ -2821,7 +2816,7 @@ gg_get_function_decl(tree return_type, const char *funcname, ...) } // Establish the RESULT_DECL for the function: - tree resdecl = build_decl (location_from_lineno(), RESULT_DECL, NULL_TREE, return_type); + tree resdecl = build_decl (gg_token_location(), RESULT_DECL, NULL_TREE, return_type); DECL_CONTEXT (resdecl) = function_decl; DECL_RESULT (function_decl) = resdecl; @@ -3058,7 +3053,7 @@ gg_call_expr(tree return_type, const char *function_name, ...) tree arg = va_arg(ap, tree); - if( !arg ) + if( arg == NULL_TREE ) { break; } @@ -3079,7 +3074,7 @@ gg_call_expr(tree return_type, const char *function_name, ...) tree the_func_addr = build1(ADDR_EXPR, build_pointer_type (TREE_TYPE(function_decl)), function_decl); - tree the_call = build_call_array_loc(location_from_lineno(), + tree the_call = build_call_array_loc(gg_token_location(), return_type, the_func_addr, nargs, @@ -3114,7 +3109,7 @@ gg_call(tree return_type, const char *function_name, ...) tree arg = va_arg(ap, tree); - if( !arg ) + if( arg == NULL_TREE ) { break; } @@ -3135,7 +3130,7 @@ gg_call(tree return_type, const char *function_name, ...) tree the_func_addr = build1(ADDR_EXPR, build_pointer_type (TREE_TYPE(function_decl)), function_decl); - tree the_call = build_call_array_loc(location_from_lineno(), + tree the_call = build_call_array_loc(gg_token_location(), return_type, the_func_addr, nargs, @@ -3160,7 +3155,7 @@ gg_call_expr_list(tree return_type, tree function_pointer, int param_count, tree // Avoid that with something like // gg_assign( dest, gg_call_expr_list(...) ); - tree the_call = build_call_array_loc(location_from_lineno(), + tree the_call = build_call_array_loc(gg_token_location(), return_type, function_pointer, param_count, @@ -3195,7 +3190,7 @@ void gg_exit(tree exit_code) { tree the_call = - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_EXIT), 1, exit_code); @@ -3206,7 +3201,7 @@ void gg_abort() { tree the_call = - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_ABORT), 0); gg_append_statement(the_call); @@ -3217,7 +3212,7 @@ gg_strlen(tree psz) { tree the_call = fold_convert( size_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_STRLEN), 1, psz)); @@ -3229,7 +3224,7 @@ gg_strdup(tree psz) { tree the_call = fold_convert( build_pointer_type(char_type_node), - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_STRDUP), 1, psz)); @@ -3243,7 +3238,7 @@ gg_malloc(tree size) { tree the_call = fold_convert( pvoid_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_MALLOC), 1, size)); @@ -3255,7 +3250,7 @@ gg_realloc(tree base, tree size) { tree the_call = fold_convert( pvoid_type_node, - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_REALLOC), 2, base, @@ -3279,7 +3274,7 @@ void gg_free(tree pointer) { tree the_call = - build_call_expr_loc(location_from_lineno(), + build_call_expr_loc(gg_token_location(), builtin_decl_explicit (BUILT_IN_FREE), 1, pointer); @@ -3380,18 +3375,6 @@ gg_string_literal(const char *string) return build_string_literal(strlen(string)+1, string); } -void -gg_set_current_line_number(int line_number) - { - sv_current_line_number = line_number; - } - -int -gg_get_current_line_number() - { - return sv_current_line_number; - } - tree gg_trans_unit_var_decl(const char *var_name) { @@ -3413,7 +3396,7 @@ gg_insert_into_assembler(const char ach[]) if( !optimize ) { // Create the required generic tag - tree asm_expr = build5_loc( location_from_lineno(), + tree asm_expr = build5_loc( gg_token_location(), ASM_EXPR, VOID, build_string(strlen(ach), ach), @@ -3450,5 +3433,28 @@ gg_insert_into_assemblerf(const char *format, ...) gg_insert_into_assembler(ach); } } +#pragma GCC diagnostic pop + +static location_t sv_token_location_override = 0; -#pragma GCC diagnostic pop
\ No newline at end of file +void +token_location_override(location_t loc) + { + sv_token_location_override = loc; + } + +location_t +gg_token_location() + { + location_t retval; + if( sv_token_location_override ) + { + retval = sv_token_location_override; + sv_token_location_override = 0; + } + else + { + retval = current_token_location(); + } + return retval; + } diff --git a/gcc/cobol/gengen.h b/gcc/cobol/gengen.h index 06b28e06..96e69dd 100644 --- a/gcc/cobol/gengen.h +++ b/gcc/cobol/gengen.h @@ -525,11 +525,11 @@ extern tree gg_indirect(tree pointer, tree byte_offset = NULL_TREE); extern tree gg_string_literal(const char *string); #define CURRENT_LINE_NUMBER (cobol_location().first_line) -extern location_t location_from_lineno(); - -// When set to true, use UNKNOWN_LOCATION instead of CURRENT_LINE_NUMBER -extern void gg_set_current_line_number(int line_number); -extern int gg_get_current_line_number(); +extern location_t gg_token_location(); +extern location_t current_token_location(); +extern location_t current_location_minus_one(); +extern void current_location_minus_one_clear(); +extern void token_location_override(location_t loc); extern tree gg_trans_unit_var_decl(const char *var_name); diff --git a/gcc/cobol/genmath.cc b/gcc/cobol/genmath.cc index 0a1c12d..e7eb971 100644 --- a/gcc/cobol/genmath.cc +++ b/gcc/cobol/genmath.cc @@ -52,7 +52,8 @@ set_up_on_exception_label(cbl_label_t *arithmetic_label) if( !arithmetic_label->structs.arith_error ) { arithmetic_label->structs.arith_error - = (cbl_arith_error_t *)xmalloc(sizeof(struct cbl_arith_error_t) ); + = static_cast<cbl_arith_error_t *> + (xmalloc(sizeof(struct cbl_arith_error_t))); // Set up the address pairs for this clause gg_create_goto_pair(&arithmetic_label->structs.arith_error->over.go_to, &arithmetic_label->structs.arith_error->over.label); @@ -72,8 +73,8 @@ set_up_compute_error_label(cbl_label_t *compute_label) if( !compute_label->structs.compute_error ) { compute_label->structs.compute_error - = (cbl_compute_error_t *) - xmalloc(sizeof(struct cbl_compute_error_t) ); + = static_cast<cbl_compute_error_t *> + (xmalloc(sizeof(struct cbl_compute_error_t))); compute_label->structs.compute_error->compute_error_code = gg_define_int(0); } @@ -112,7 +113,6 @@ arithmetic_operation(size_t nC, cbl_num_result_t *C, { TRACE1_HEADER TRACE1_TEXT_ABC("calling ", operation, "") - TRACE1_END for(size_t ii=0; ii<nA; ii++) { TRACE1_INDENT @@ -129,7 +129,6 @@ arithmetic_operation(size_t nC, cbl_num_result_t *C, build_int_cst_type(SIZE_T, ii)); TRACE1_REFER("", B[ii], ""); } - TRACE1_END } // We need to split up cbl_num_result_t into two arrays, one for the refer_t @@ -223,7 +222,6 @@ arithmetic_operation(size_t nC, cbl_num_result_t *C, { for(size_t ii=0; ii<nC; ii++) { - break; // Breaks on ADD 1 SUB2 GIVING SUB4 both PIC S9(3) COMP TRACE1_INDENT gg_fprintf( trace_handle, 1, "result: C[%ld]: ", @@ -612,7 +610,7 @@ static bool fast_divide(size_t nC, cbl_num_result_t *C, size_t nA, cbl_refer_t *A, size_t nB, cbl_refer_t *B, - cbl_refer_t remainder) + const cbl_refer_t &remainder) { bool retval = false; if( all_results_binary(nC, C) ) @@ -663,8 +661,10 @@ fast_divide(size_t nC, cbl_num_result_t *C, // We now either divide into C[n] or assign dividend/divisor to C[n]: for(size_t i=0; i<nC; i++ ) { - tree dest_type = tree_type_from_size(C[i].refer.field->data.capacity, 0); - tree dest_addr = gg_add(member(C[i].refer.field->var_decl_node, "data"), + tree dest_type = + tree_type_from_size(C[i].refer.field->data.capacity, 0); + tree dest_addr = gg_add(member( C[i].refer.field->var_decl_node, + "data"), refer_offset(C[i].refer)); tree ptr = gg_cast(build_pointer_type(dest_type), dest_addr); if( nB ) @@ -680,16 +680,15 @@ fast_divide(size_t nC, cbl_num_result_t *C, } // This is where we handle any remainder, keeping in mind that for - // nB != 0, the actual dividend is in the value we have named "divisor". - // - // And, yes, I hate comments like that, too. + // nB != 0, the actual dividend is in the value we have named + // "divisor". // We calculate the remainder by calculating // dividend minus quotient * divisor if( remainder.field ) { - tree dest_addr = gg_add(member(remainder.field->var_decl_node, "data"), - refer_offset(remainder)); + dest_addr = gg_add( member(remainder.field->var_decl_node, "data"), + refer_offset(remainder)); dest_type = tree_type_from_size(remainder.field->data.capacity, 0); ptr = gg_cast(build_pointer_type(dest_type), dest_addr); diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc index 1d921a3..a5f69a0 100644 --- a/gcc/cobol/genutil.cc +++ b/gcc/cobol/genutil.cc @@ -27,6 +27,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// cppcheck-suppress-file duplicateBreak + #include "cobol-system.h" #include "coretypes.h" #include "tree.h" @@ -305,8 +308,11 @@ static void get_and_check_refstart_and_reflen( tree refstart,// LONG returned value tree reflen, // LONG returned value - cbl_refer_t &refer) + const cbl_refer_t &refer) { + const cbl_enabled_exceptions_t& + enabled_exceptions( cdf_enabled_exceptions() ); + if( !enabled_exceptions.match(ec_bound_ref_mod_e) ) { // This is normal operation -- no exception checking. Thus, we won't @@ -458,6 +464,8 @@ get_depending_on_value_from_odo(tree retval, cbl_field_t *odo) declarative with a RESUME NEXT STATEMENT, or before the default_condition processing can do a controlled exit. */ + const cbl_enabled_exceptions_t& + enabled_exceptions( cdf_enabled_exceptions() ); cbl_field_t *depending_on; depending_on = cbl_field_of(symbol_at(odo->occurs.depending_on)); @@ -471,8 +479,8 @@ get_depending_on_value_from_odo(tree retval, cbl_field_t *odo) return; } - // Bounds checking is enabled, so we test the DEPENDING ON value to be between - // the lower and upper OCCURS limits: + // Bounds checking is enabled, so we test the DEPENDING ON value to be + // between the lower and upper OCCURS limits: get_integer_value(retval, depending_on, NULL, @@ -482,23 +490,28 @@ get_depending_on_value_from_odo(tree retval, cbl_field_t *odo) { // This needs to evaluate to an integer set_exception_code(ec_bound_odo_e); - gg_assign(retval, build_int_cst_type(TREE_TYPE(retval), odo->occurs.bounds.lower)); + gg_assign(retval, build_int_cst_type( TREE_TYPE(retval), + odo->occurs.bounds.lower)); gg_assign(var_decl_rdigits, integer_zero_node); } ELSE ENDIF - IF( retval, gt_op, build_int_cst_type(TREE_TYPE(retval), odo->occurs.bounds.upper) ) + IF( retval, gt_op, build_int_cst_type(TREE_TYPE(retval), + odo->occurs.bounds.upper) ) { set_exception_code(ec_bound_odo_e); - gg_assign(retval, build_int_cst_type(TREE_TYPE(retval), odo->occurs.bounds.lower)); + gg_assign(retval, build_int_cst_type( TREE_TYPE(retval), + odo->occurs.bounds.lower)); } ELSE { - IF( retval, lt_op, build_int_cst_type(TREE_TYPE(retval), odo->occurs.bounds.lower) ) + IF( retval, lt_op, build_int_cst_type(TREE_TYPE(retval), + odo->occurs.bounds.lower) ) { set_exception_code(ec_bound_odo_e); - gg_assign(retval, build_int_cst_type(TREE_TYPE(retval), odo->occurs.bounds.lower)); + gg_assign(retval, build_int_cst_type( TREE_TYPE(retval), + odo->occurs.bounds.lower)); } ELSE ENDIF @@ -532,8 +545,8 @@ get_depending_on_value(tree retval, const cbl_refer_t &refer) static tree -get_data_offset(cbl_refer_t &refer, - int *pflags = NULL) +get_data_offset(const cbl_refer_t &refer, + int *pflags = NULL) { Analyze(); // This routine returns a tree which is the size_t offset to the data in the @@ -548,7 +561,6 @@ get_data_offset(cbl_refer_t &refer, // We have a refer. // At the very least, we have an constant offset int all_flags = 0; - int all_flag_bit = 1; if( refer.nsubscript() ) { @@ -568,6 +580,7 @@ get_data_offset(cbl_refer_t &refer, // Establish the field_t pointer for walking up through our ancestors: cbl_field_t *parent = refer.field; + int all_flag_bit = 1; // Note the backwards test, because refer->nsubscript is an unsigned value for(size_t i=refer.nsubscript()-1; i<refer.nsubscript(); i-- ) { @@ -601,6 +614,8 @@ get_data_offset(cbl_refer_t &refer, } else { + const cbl_enabled_exceptions_t& + enabled_exceptions( cdf_enabled_exceptions() ); if( !enabled_exceptions.match(ec_bound_subscript_e) ) { // With no exception testing, just pick up the value @@ -625,21 +640,25 @@ get_data_offset(cbl_refer_t &refer, } ELSE { - IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), integer_one_node) ) + IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), + integer_one_node) ) { // The subscript is too small set_exception_code(ec_bound_subscript_e); - gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 1)); + gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), + 1)); } ELSE { IF( subscript, ge_op, - build_int_cst_type(TREE_TYPE(subscript), parent->occurs.ntimes()) ) + build_int_cst_type( TREE_TYPE(subscript), + parent->occurs.ntimes()) ) { // The subscript is too large set_exception_code(ec_bound_subscript_e); - gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 1)); + gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), + 1)); } ELSE { @@ -654,14 +673,19 @@ get_data_offset(cbl_refer_t &refer, all_flag_bit <<= 1; - // Although we strictly don't need to look at the ODO value at this point, - // we do want it checked for the purposes of ec-bound-odo + // Although we strictly don't need to look at the ODO value at this + // point, we do want it checked for the purposes of ec-bound-odo + + const cbl_enabled_exceptions_t& + enabled_exceptions( cdf_enabled_exceptions() ); if( enabled_exceptions.match(ec_bound_odo_e) ) { if( parent->occurs.depending_on ) { - static tree value64 = gg_define_variable(LONG, ".._gdos_value64", vs_file_static); + static tree value64 = gg_define_variable( LONG, + ".._gdos_value64", + vs_file_static); cbl_field_t *odo = symbol_find_odo(parent); get_depending_on_value_from_odo(value64, odo); } @@ -1238,18 +1262,13 @@ get_binary_value( tree value, break; } - case FldAlphanumeric: - { - - } - - default: { - fprintf(stderr, "%s(): We know not how to" - " get a binary value from %s\n", - __func__, - cbl_field_type_str(field->type) ); + char *err = xasprintf("%s(): We know not how to" + " get a binary value from %s\n", + __func__, + cbl_field_type_str(field->type) ); + cbl_internal_error("%s", err); abort(); break; } @@ -1667,8 +1686,9 @@ set_exception_code_func(ec_type_t ec, int /*line*/, int from_raise_statement) } bool -process_this_exception(ec_type_t ec) +process_this_exception(const ec_type_t ec) { + const cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); bool retval; if( enabled_exceptions.match(ec) || !skip_exception_processing ) { @@ -1700,7 +1720,7 @@ copy_little_endian_into_place(cbl_field_t *dest, tree value, int rhs_rdigits, bool check_for_error, - tree &size_error) + const tree &size_error) { if( check_for_error ) { @@ -1926,7 +1946,7 @@ get_literal_string(cbl_field_t *field) } bool -refer_is_clean(cbl_refer_t &refer) +refer_is_clean(const cbl_refer_t &refer) { if( !refer.field || refer.field->type == FldLiteralN ) { @@ -1957,7 +1977,7 @@ refer_is_clean(cbl_refer_t &refer) */ static tree // size_t -refer_refmod_length(cbl_refer_t &refer) +refer_refmod_length(const cbl_refer_t &refer) { Analyze(); REFER("refstart and reflen"); @@ -1973,7 +1993,7 @@ refer_refmod_length(cbl_refer_t &refer) static tree // size_t -refer_fill_depends(cbl_refer_t &refer) +refer_fill_depends(const cbl_refer_t &refer) { REFER(""); // This returns a positive number which is the amount a depends-limited @@ -2000,8 +2020,8 @@ refer_fill_depends(cbl_refer_t &refer) } tree // size_t -refer_offset(cbl_refer_t &refer, - int *pflags) +refer_offset(const cbl_refer_t &refer, + int *pflags) { // This routine calculates the effect of a refer offset on the // refer.field->data location. When there are subscripts, the data location @@ -2028,7 +2048,7 @@ refer_offset(cbl_refer_t &refer, static tree // size_t -refer_size(cbl_refer_t &refer, refer_type_t refer_type) +refer_size(const cbl_refer_t &refer, refer_type_t refer_type) { Analyze(); static tree retval = gg_define_variable(SIZE_T, "..rs_retval", vs_file_static); @@ -2069,13 +2089,13 @@ refer_size(cbl_refer_t &refer, refer_type_t refer_type) } tree // size_t -refer_size_dest(cbl_refer_t &refer) +refer_size_dest(const cbl_refer_t &refer) { return refer_size(refer, refer_dest); } tree // size_t -refer_size_source(cbl_refer_t &refer) +refer_size_source(const cbl_refer_t &refer) { /* There are oddities involved with refer_size_source and refer_size_dest. See the comments in refer_has_depends for some explanation. There are @@ -2112,7 +2132,7 @@ refer_size_source(cbl_refer_t &refer) } tree -qualified_data_location(cbl_refer_t &refer) +qualified_data_location(const cbl_refer_t &refer) { return gg_add(member(refer.field->var_decl_node, "data"), refer_offset(refer)); diff --git a/gcc/cobol/genutil.h b/gcc/cobol/genutil.h index 0d9028e..f12124e 100644 --- a/gcc/cobol/genutil.h +++ b/gcc/cobol/genutil.h @@ -118,7 +118,7 @@ void set_exception_code_func(ec_type_t ec, int line, int from_raise_statement=0); #define set_exception_code(ec) set_exception_code_func(ec, __LINE__) -bool process_this_exception(ec_type_t ec); +bool process_this_exception(const ec_type_t ec); #define CHECK_FOR_FRACTIONAL_DIGITS true void get_integer_value(tree value, // This is always a LONG cbl_field_t *field, @@ -130,7 +130,7 @@ void copy_little_endian_into_place(cbl_field_t *dest, tree value, int rhs_rdigits, bool check_for_error, - tree &size_error); + const tree &size_error); tree build_array_of_size_t( size_t N, const size_t *values); void parser_display_internal_field(tree file_descriptor, @@ -138,14 +138,14 @@ void parser_display_internal_field(tree file_descriptor, bool advance=DISPLAY_NO_ADVANCE); char *get_literal_string(cbl_field_t *field); -bool refer_is_clean(cbl_refer_t &refer); +bool refer_is_clean(const cbl_refer_t &refer); -tree refer_offset(cbl_refer_t &refer, +tree refer_offset(const cbl_refer_t &refer, int *pflags=NULL); -tree refer_size_source(cbl_refer_t &refer); -tree refer_size_dest(cbl_refer_t &refer); +tree refer_size_source(const cbl_refer_t &refer); +tree refer_size_dest(const cbl_refer_t &refer); -tree qualified_data_location(cbl_refer_t &refer); +tree qualified_data_location(const cbl_refer_t &refer); void build_array_of_treeplets( int ngroup, size_t N, diff --git a/gcc/cobol/lexio.cc b/gcc/cobol/lexio.cc index 2d9fb72..52d1aff 100644 --- a/gcc/cobol/lexio.cc +++ b/gcc/cobol/lexio.cc @@ -38,29 +38,24 @@ extern int yy_flex_debug; -static struct { - bool first_file, explicitly; - int column, right_margin; - bool inference_pending() { - bool tf = first_file && !explicitly; - first_file = false; - return tf; - } - inline bool is_fixed() const { return column == 7; } - inline bool is_reffmt() const { return is_fixed() && right_margin == 73; } - inline bool is_free() const { return ! is_fixed(); } - - const char * description() const { - if( is_reffmt() ) return "REFERENCE"; - if( is_fixed() ) return "FIXED"; - if( is_free() ) return "FREE"; - gcc_unreachable(); - } -} indicator = { true, false, 0, 0 }; +source_format_t& cdf_source_format(); + +void +source_format_t::infer( const char *bol, bool want_reference_format ) { + if( bol ) { + left = 7; + if( want_reference_format ) { + right = 73; + } + } + dbgmsg("%s:%d: %s format detected", __func__, __LINE__, + description()); +} + // public source format test functions -bool is_fixed_format() { return indicator.is_fixed(); } -bool is_reference_format() { return indicator.is_reffmt(); } +bool is_fixed_format() { return cdf_source_format().is_fixed(); } +bool is_reference_format() { return cdf_source_format().is_reffmt(); } static bool debug_mode = false; @@ -76,11 +71,10 @@ static bool debug_mode = false; */ static inline int left_margin() { - return indicator.column == 0? indicator.column : indicator.column - 1; + return cdf_source_format().left_margin(); } static inline int right_margin() { - return indicator.right_margin == 0? - indicator.right_margin : indicator.right_margin - 1; + return cdf_source_format().right_margin(); } /* @@ -89,18 +83,9 @@ static inline int right_margin() { * When setting back to 0 (free), the right margin is also reset to 0. */ void -cobol_set_indicator_column( int column ) -{ - indicator.explicitly = true; - if( column == 0 ) indicator.right_margin = 0; - if( column < 0 ) { - column = -column; - indicator.right_margin = 73; - } - indicator.column = column; -} +cobol_set_indicator_column( int column ); -bool include_debug() { return indicator.column == 7 && debug_mode; } +bool include_debug() { return is_fixed_format() && debug_mode; } bool set_debug( bool tf ) { return debug_mode = tf && is_fixed_format(); } static bool nonblank( const char ch ) { return !isblank(ch); } @@ -114,7 +99,7 @@ start_of_line( char *bol, char *eol ) { static inline char * continues_at( char *bol, char *eol ) { - if( indicator.column == 0 ) return NULL; // cannot continue in free format + if( cdf_source_format().is_free() ) return NULL; // cannot continue in free format bol += left_margin(); if( *bol != '-' ) return NULL; // not a continuation line return start_of_line(++bol, eol); @@ -124,7 +109,7 @@ continues_at( char *bol, char *eol ) { // NULL means no indicator column or tested value not present. static inline char * indicated( char *bol, const char *eol, char ch = '\0' ) { - if( indicator.column == 0 && *bol != '*' ) { + if( cdf_source_format().left_margin() == 0 && *bol != '*' ) { return NULL; // no indicator column in free format, except for comments } gcc_assert(bol != NULL); @@ -336,7 +321,69 @@ recognize_replacements( filespan_t mfile, std::list<replace_t>& pending_replacem } static void +check_push_pop_directive( filespan_t& mfile ) { + char eol = '\0'; + const char *p = std::find(mfile.cur, mfile.eol, '>'); + if( ! (p < mfile.eol && p[1] == *p ) ) return; + + const char pattern[] = + ">>[[:blank:]]*(push|pop)[[:blank:]]+" + "(" + "all|" + "call-convention|" + "cobol-words|" + "define|" + "source[[:blank:]]+format|" + "turn" + ")"; + static regex re(pattern, extended_icase); + + // show contents of marked subexpressions within each match + cmatch cm; + + std::swap(*mfile.eol, eol); // see implementation for excuses + bool ok = regex_search(p, const_cast<const char *>(mfile.eol), cm, re); + std::swap(*mfile.eol, eol); + + if( ok ) { + gcc_assert(cm.size() > 1); + bool push = TOUPPER(cm[1].first[1]) == 'U'; + switch( TOUPPER(cm[2].first[0]) ) { + case 'A': // ALL + push? cdf_push() : cdf_pop(); + break; + case 'C': + switch( TOUPPER(cm[2].first[1]) ) { + case 'A': // CALL-CONVENTION + push? cdf_push_call_convention() : cdf_pop_call_convention(); + break; + case 'O': // COBOL-WORDS + push? cdf_push_current_tokens() : cdf_pop_current_tokens(); + break; + default: + gcc_unreachable(); + } + break; + case 'D': // DEFINE + push? cdf_push_dictionary() : cdf_pop_dictionary(); + break; + case 'S': // SOURCE FORMAT + push? cdf_push_source_format() : cdf_pop_source_format(); + break; + case 'T': // TURN + push? cdf_push_enabled_exceptions() : cdf_pop_enabled_exceptions(); + break; + default: + gcc_unreachable(); + } + erase_line(const_cast<char*>(cm[0].first), + const_cast<char*>(cm[0].second)); + } +} + +static void check_source_format_directive( filespan_t& mfile ) { + char eol = '\0'; const char *p = std::find(mfile.cur, mfile.eol, '>'); if( ! (p < mfile.eol && p[1] == *p ) ) return; @@ -349,7 +396,12 @@ check_source_format_directive( filespan_t& mfile ) { // show contents of marked subexpressions within each match cmatch cm; - if( regex_search(p, const_cast<const char *>(mfile.eol), cm, re) ) { + + std::swap(*mfile.eol, eol); // see implementation for excuses + bool ok = regex_search(p, const_cast<const char *>(mfile.eol), cm, re); + std::swap(*mfile.eol, eol); + + if( ok ) { gcc_assert(cm.size() > 1); switch( cm[3].length() ) { case 4: @@ -365,11 +417,11 @@ check_source_format_directive( filespan_t& mfile ) { dbgmsg( "%s:%d: %s format set, on line " HOST_SIZE_T_PRINT_UNSIGNED, __func__, __LINE__, - indicator.column == 7? "FIXED" : "FREE", + cdf_source_format().description(), (fmt_size_t)mfile.lineno() ); - char *bol = indicator.is_fixed()? mfile.cur : const_cast<char*>(cm[0].first); + char *bol = cdf_source_format().is_fixed()? mfile.cur : const_cast<char*>(cm[0].first); + gcc_assert(cm[0].second <= mfile.eol); erase_line(bol, const_cast<char*>(cm[0].second)); - mfile.cur = const_cast<char*>(cm[0].second); } } @@ -889,7 +941,7 @@ location_in( const filespan_t& mfile, const csub_match& cm ) { gcc_assert(mfile.cur <= cm.first && cm.second <= mfile.eodata); auto nline = std::count(cm.first, cm.second, '\n'); if( nline ) { - gcc_assert(loc.first_line < nline); + gcc_assert(nline < loc.first_line); loc.first_line -= nline; auto p = static_cast<const char*>(memrchr(cm.first, '\n', cm.length())); loc.last_column = (cm.second) - p; @@ -1327,13 +1379,13 @@ lexer_input( char buf[], int max_size, FILE *input ) { for( auto p = mfile.cur; p < next; *output.pos++ = *p++ ) { static bool at_bol = false; if( at_bol ) { - auto nonblank = std::find_if( p, next, + auto nonblank_l = std::find_if( p, next, []( char ch ) { return !isblank(ch); } ); - if( nonblank + 1 < next ) { - if( *nonblank == '\r' ) nonblank++; // Windows - if( *nonblank == '\n' ) { - p = nonblank; + if( nonblank_l + 1 < next ) { + if( *nonblank_l == '\r' ) nonblank_l++; // Windows + if( *nonblank_l == '\n' ) { + p = nonblank_l; continue; } } @@ -1461,7 +1513,6 @@ cdftext::lex_open( const char filename[] ) { // Process any files supplied by the -include command-line option. for( auto name : included_files ) { - int input; if( -1 == (input = open(name, O_RDONLY)) ) { yyerrorvl(1, "", "cannot open -include file %s", name); continue; @@ -1634,7 +1685,7 @@ bool lexio_dialect_mf(); */ static const char * valid_sequence_area( const char *data, const char *eodata ) { - + for( const char *p = data; (p = std::find_if(p, eodata, is_p)) != eodata; p++ ) @@ -1657,7 +1708,7 @@ valid_sequence_area( const char *data, const char *eodata ) { } } } - return nullptr; + return nullptr; } /* @@ -1693,22 +1744,17 @@ cdftext::free_form_reference_format( int input ) { } current( mfile.data ); /* - * Infer source code format. + * Infer source code format. */ - if( indicator.inference_pending() ) { + if( cdf_source_format().inference_pending() ) { const char *bol = valid_sequence_area(mfile.data, mfile.eodata); if( bol ) { - indicator.column = 7; - if( infer_reference_format(bol, mfile.eodata) ) { - indicator.right_margin = 73; - } + cdf_source_format().infer( bol, infer_reference_format(bol, mfile.eodata) ); } - - dbgmsg("%s:%d: %s format detected", __func__, __LINE__, - indicator.description()); } while( mfile.next_line() ) { + check_push_pop_directive(mfile); check_source_format_directive(mfile); remove_inline_comment(mfile.cur, mfile.eol); @@ -1857,7 +1903,7 @@ cdftext::process_file( filespan_t mfile, int output, bool second_pass ) { []( char ch ) { return ch == '\n'; } ); struct { int in, out; filespan_t mfile; } copy; dbgmsg("%s:%d: line " HOST_SIZE_T_PRINT_UNSIGNED ", opening %s on fd %d", - __func__, __LINE__,mfile.lineno(), + __func__, __LINE__, (fmt_size_t)mfile.lineno(), copybook.source(), copybook.current()->fd); copy.in = copybook.current()->fd; copy.mfile = free_form_reference_format( copy.in ); @@ -1936,15 +1982,15 @@ cdftext::segment_line( filespan_t& mfile ) { struct { unsigned long ante, post; } lineno = { gb4(mfile.lineno()), gb4(mfile.lineno() + segment.after.nlines()) }; - char *directive = lineno.ante == lineno.post? + const char *directive = lineno.ante == lineno.post? nullptr : xasprintf("\n#line %lu \"%s\"\n", lineno.ante, cobol_filename()); - if( directive ) + if( directive ) output.push_back( span_t(strlen(directive), directive) ); output.push_back( span_t(mfile.cur, segment.before.p) ); output.push_back( span_t(segment.after.p, segment.after.pend ) ); - if( directive ) + if( directive ) output.push_back( span_t(strlen(directive), directive) ); mfile.cur = const_cast<char*>(segment.before.pend); diff --git a/gcc/cobol/lexio.h b/gcc/cobol/lexio.h index eb41068..ba4ef0a 100644 --- a/gcc/cobol/lexio.h +++ b/gcc/cobol/lexio.h @@ -244,8 +244,8 @@ struct span_t { return span_t(output, eout); } const char * has_nul() const { - auto p = std::find(this->p, pend, '\0'); - return p != pend? p : NULL; + auto p_l = std::find(this->p, pend, '\0'); + return p_l != pend? p_l : NULL; } bool at_eol() const { diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 74637c9..fae96ed 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -45,6 +45,7 @@ }; enum accept_func_t { + accept_e, accept_done_e, accept_command_line_e, accept_envar_e, @@ -349,7 +350,7 @@ %token <string> SECTION %token <number> STANDARD_ALPHABET "STANDARD ALPHABET" %token <string> SWITCH -%token <string> UPSI +%token <string> UPSI %token <number> ZERO /* environment names */ @@ -385,7 +386,10 @@ CDF_EVALUATE ">>EVALUATE" CDF_WHEN ">>WHEN" CDF_END_EVALUATE ">>END-EVALUATE" + CALL_CONVENTION ">>CALL-CONVENTION" CALL_COBOL "CALL" CALL_VERBATIM "CALL (as C)" + CDF_PUSH ">>PUSH" CDF_POP ">>POP" + SOURCE_FORMAT ">>SOURCE FORMAT" IF THEN ELSE SENTENCE @@ -399,7 +403,10 @@ STRING_kw "STRING" STOP SUBTRACT START UNSTRING WRITE WHEN - ABS ACCESS ACOS ACTUAL ADVANCING AFTER ALL + ARGUMENT_NUMBER ARGUMENT_VALUE + ENVIRONMENT_NAME ENVIRONMENT_VALUE + + ABS ACCESS ACOS ACTUAL ADVANCING AFTER ALL ALLOCATE ALPHABET ALPHABETIC ALPHABETIC_LOWER "ALPHABETIC-LOWER" ALPHABETIC_UPPER "ALPHABETIC-UPPER" @@ -793,6 +800,8 @@ %type <error_clauses> io_invalids read_eofs write_eops %type <boolean> io_invalid read_eof write_eop global is_global anycase backward + end_display + exh_changed exh_named %type <number> mistake globally first_last %type <io_mode> io_mode @@ -848,7 +857,7 @@ declarative_list_t* dcl_list_t; isym_list_t* isym_list; struct { radix_t radix; char *string; } numstr; - struct { int token; literal_t name; } prog_end; + struct { YYLTYPE loc; int token; literal_t name; } prog_end; struct { int token; special_name_t id; } special_type; struct { cbl_field_type_t type; uint32_t capacity; bool signable; } computational; @@ -902,7 +911,7 @@ struct refer_pair_t { cbl_refer_t *first, *second; } refer2; struct { refer_collection_t *inputs; refer_pair_t into; } str_body; - struct { accept_func_t func; cbl_refer_t *into, *from; } accept_func; + struct { accept_func_t func; cbl_refer_t *into, *from; special_name_t special;} accept_func; struct unstring_into_t *uns_into; struct unstring_tgt_list_t *uns_tgts; struct unstring_tgt_t *uns_tgt; @@ -1004,7 +1013,9 @@ %right IF THEN ELSE SENTENCE ACCEPT ADD ALTER CALL CANCEL CLOSE COMPUTE CONTINUE - DELETE DISPLAY DIVIDE EVALUATE END EOP EXIT FILLER_kw + DELETE DISPLAY DIVIDE + EVALUATE END EOP EXIT + FILLER_kw GOBACK GOTO INITIALIZE INSPECT MERGE MOVE MULTIPLY OPEN OVERFLOW_kw PARAGRAPH PERFORM @@ -1464,16 +1475,16 @@ cobol_words: cobol_words1 | cobol_words cobol_words1 ; cobol_words1: COBOL_WORDS EQUATE NAME[keyword] WITH NAME[name] { - if( ! tokens.equate(@keyword, $keyword, $name) ) { YYERROR; } + if( ! cdf_tokens.equate(@keyword, $keyword, $name) ) { YYERROR; } } | COBOL_WORDS UNDEFINE NAME[keyword] { - if( ! tokens.undefine(@keyword, $keyword) ) { YYERROR; } + if( ! cdf_tokens.undefine(@keyword, $keyword) ) { YYERROR; } } | COBOL_WORDS SUBSTITUTE NAME[keyword] BY NAME[name] { - if( ! tokens.substitute(@keyword, $keyword, $name) ) { YYERROR; } + if( ! cdf_tokens.substitute(@keyword, $keyword, $name) ) { YYERROR; } } | COBOL_WORDS RESERVE NAME[name] { - if( ! tokens.reserve(@name, $name) ) { YYERROR; } + if( ! cdf_tokens.reserve(@name, $name) ) { YYERROR; } } ; @@ -1513,7 +1524,7 @@ program_as: %empty { static const literal_t empty {}; $$ = empty; } | AS LITERAL { $$ = $2; } ; -function_id: FUNCTION '.' NAME program_as program_attrs[attr] '.' +function_id: FUNCTION NAME program_as program_attrs[attr] '.' { internal_ebcdic_lock(); current_division = identification_div_e; @@ -1547,7 +1558,7 @@ function_id: FUNCTION '.' NAME program_as program_attrs[attr] '.' current.udf_add(current_program_index()); if( nparse_error > 0 ) YYABORT; } - | FUNCTION '.' NAME program_as is PROTOTYPE '.' + | FUNCTION NAME program_as is PROTOTYPE '.' { cbl_unimplemented("FUNCTION PROTOTYPE"); } @@ -1838,7 +1849,7 @@ select: SELECT optional NAME[name] select_clauses[clauses] '.' cbl_file_t *file = $clauses.file; file->optional = $optional; - file->line = yylineno; + file->line = @name.first_line; if( !namcpy(@clauses, file->name, $name) ) YYERROR; if( ! ($clauses.clauses & assign_clause_e) ) { @@ -1911,7 +1922,7 @@ select: SELECT optional NAME[name] select_clauses[clauses] '.' cbl_file_t file = protofile; file.optional = $optional; - file.line = yylineno; + file.line = @name.first_line; if( !namcpy(@name, file.name, $name) ) YYERROR; if( file_add(@name, &file) == NULL ) YYERROR; @@ -2473,7 +2484,7 @@ special_name: dev_mnemonic | CLASS NAME is domains { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 0, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 0, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -2604,6 +2615,10 @@ device_name: SYSIN { $$.token = SYSIN; $$.id = SYSIN_e; } | STDIN { $$.token = STDIN; $$.id = STDIN_e; } | STDOUT { $$.token = STDOUT; $$.id = STDOUT_e; } | STDERR { $$.token = STDERR; $$.id = STDERR_e; } + /* These cannot be both ctx_name and here. * + /* ARGUMENT_NUMBER { $$.token=0; $$.id = ARG_NUM_e; } */ + /* ENVIRONMENT_NAME { $$.token=0; $$.id = ENV_NAME_e; } */ + /* ENVIRONMENT_VALUE { $$.token=0; $$.id = ENV_VALUE_e; } */ ; alphabet_name: STANDARD_ALPHABET { $$ = alphabet_add(@1, ASCII_e); } @@ -3164,7 +3179,7 @@ depending: %empty assert(e->type == SymField); odo = symbol_index(e); } else { - e = symbol_field_forward_add(PROGRAM, 0, $NAME, yylineno); + e = symbol_field_forward_add(PROGRAM, 0, $NAME, @NAME.first_line); if( !e ) YYERROR; symbol_field_location( symbol_index(e), @NAME ); odo = field_index(cbl_field_of(e)); @@ -3364,7 +3379,7 @@ level_name: LEVEL ctx_name } struct cbl_field_t field = { 0, FldInvalid, FldInvalid, 0, 0, 0, capacity_cast($1), - nonarray, yylineno, "", + nonarray, @ctx_name.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@ctx_name, field.name, $2) ) YYERROR; @@ -3389,7 +3404,7 @@ level_name: LEVEL ctx_name } struct cbl_field_t field = { 0, FldInvalid, FldInvalid, 0, 0, 0, capacity_cast($1), - nonarray, yylineno, "", + nonarray, @LEVEL.first_line, "", 0, {}, {}, NULL }; $$ = field_add(@1, &field); @@ -3527,7 +3542,7 @@ data_descr1: level_name } struct cbl_field_t field = { 0, FldLiteralA, FldInvalid, constant_e, 0, 0, 78, nonarray, - yylineno, "", 0, {}, *$data, NULL }; + @name.first_line, "", 0, {}, *$data, NULL }; if( !namcpy(@name, field.name, $name) ) YYERROR; if( field.data.initial ) { field.attr |= quoted_e; @@ -3550,7 +3565,7 @@ data_descr1: level_name | LEVEL88 NAME /* VALUE */ NULLPTR { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 88, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 88, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -3576,7 +3591,7 @@ data_descr1: level_name | LEVEL88 NAME VALUE domains { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 88, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 88, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -4606,7 +4621,7 @@ justified_clause: is JUSTIFIED redefines_clause: REDEFINES NAME[orig] { - struct symbol_elem_t *e = field_of($orig); + struct symbol_elem_t *e = symbol_field(PROGRAM, 0, $orig); if( !e ) { error_msg(@2, "REDEFINES target not defined"); YYERROR; @@ -4906,6 +4921,7 @@ by_value_arg: scalar declaratives: %empty | DECLARATIVES '.' <label>{ + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); current.enabled_exception_cache = enabled_exceptions; enabled_exceptions.clear(); current.doing_declaratives(true); @@ -4924,6 +4940,7 @@ declaratives: %empty * forward reference, because we haven't yet begun to parse * nondeclarative procedures. */ + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); parser_label_label($label); enabled_exceptions = current.enabled_exception_cache; current.enabled_exception_cache.clear(); @@ -5038,6 +5055,7 @@ statement: error { | divide { $$ = DIVIDE; } | entry { $$ = ENTRY; } | evaluate { $$ = EVALUATE; } + | exhibit_stmt { $$ = EXHIBIT; } | exit { $$ = EXIT; } | free { $$ = FREE; } | go_to { $$ = GOTO; } @@ -5068,9 +5086,8 @@ statement: error { /* * ISO defines ON EXCEPTION only for Format 3 (screen). We - * implement extensions defined by MF and Fujitsu (and us) to - * use ACCEPT to interact with the command line and the - * environment. + * implement extensions defined by MF and Fujitsu to use ACCEPT + * to interact with the command line and the environment. * * ISO ACCEPT and some others are implemented in accept_body, * before the parser sees any ON EXCEPTION. In those cases @@ -5085,6 +5102,9 @@ accept: accept_body end_accept { switch( $accept_body.func ) { case accept_done_e: break; + case accept_e: + parser_accept(*$1.into, $1.special, nullptr, nullptr); + break; case accept_command_line_e: if( $1.from->field == NULL ) { // take next command-line arg parser_accept_command_line(*$1.into, argi, NULL, NULL); @@ -5108,6 +5128,9 @@ accept: accept_body end_accept { error_msg(@ec, "ON EXCEPTION valid only " "with ENVIRONMENT or COMMAND-LINE(n)"); break; + case accept_e: + parser_accept(*$1.into, $1.special, $ec.on_error, $ec.not_error); + break; case accept_command_line_e: if( $1.from->field == NULL ) { // take next command-line arg parser_accept_command_line(*$1.into, argi, @@ -5139,7 +5162,7 @@ end_accept: %empty %prec ACCEPT accept_body: accept_refer { $$.func = accept_done_e; - parser_accept(*$1, CONSOLE_e); + parser_accept(*$1, CONSOLE_e, nullptr, nullptr); } | accept_refer FROM DATE { @@ -5198,29 +5221,15 @@ accept_body: accept_refer } | accept_refer FROM acceptable { - cbl_field_t *argc = register_find("_ARGI"); - switch( $acceptable->id ) { - case ARG_NUM_e: - $$.func = accept_command_line_e; - $$.into = $1; - $$.from = new_reference(argc); - break; - case ARG_VALUE_e: - $$.func = accept_command_line_e; - $$.into = $1; - $$.from = cbl_refer_t::empty(); - break; - default: - $$.func = accept_done_e; - parser_accept( *$1, $acceptable->id ); - } + $$.func = accept_e; + $$.into = $1; + $$.special = $acceptable->id; } | accept_refer FROM ENVIRONMENT envar { $$.func = accept_envar_e; $$.into = $1; $$.from = $envar; - //// parser_accept_envar( *$1, *$envar ); } | accept_refer FROM COMMAND_LINE { @@ -5232,7 +5241,6 @@ accept_body: accept_refer $$.func = accept_command_line_e; $$.into = $1; $$.from = $expr; - //// parser_accept_command_line(*$1, $expr->field ); } | accept_refer FROM COMMAND_LINE_COUNT { $$.func = accept_done_e; @@ -5285,7 +5293,7 @@ accept_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("accept"), yylineno); + uniq_label("accept"), @1.first_line); if( !$$.on_error ) YYERROR; parser_accept_exception( $$.on_error ); @@ -5320,15 +5328,54 @@ acceptable: device_name error_msg(@NAME, "no such special name '%s'", $NAME); YYERROR; } + if( ENV_NAME_e == *special_type ) { + error_msg(@NAME, "cannot ACCEPT FROM %qs", $NAME); + YYERROR; + } // Add the name now, as a convenience. - cbl_special_name_t special = { 0, *special_type }; + int token = 0; + switch(*special_type) { + case ARG_NUM_e: token = ARGUMENT_NUMBER; break; + case ARG_VALUE_e: token = ARGUMENT_VALUE; break; + case ENV_VALUE_e: token = ENVIRONMENT_VALUE; break; + + case ENV_NAME_e: + default: + error_msg(@NAME, "cannot ACCEPT FROM %qs", $NAME); + YYERROR; + break; + } + cbl_special_name_t special = { token, *special_type }; namcpy(@NAME, special.name, $NAME); symbol_elem_t *e = symbol_special_add(PROGRAM, &special); $$ = cbl_special_name_of(e); + cbl_special_name_t& unused(*$$); + assert(unused.id); } assert($$); } + | ENVIRONMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_VALUE, ENV_VALUE_e, "ENVIRONMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ARGUMENT_NUMBER { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_NUMBER, ARG_NUM_e, "ARGUMENT-NUMBER" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ARGUMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_VALUE, ARG_VALUE_e, "ARGUMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } ; add: add_impl end_add { ast_add($1); } @@ -5558,46 +5605,18 @@ compute_expr: '=' { } ; -display: disp_body end_display - { - std::vector <cbl_refer_t> args($1.vargs->args.size()); - std::copy( $1.vargs->args.begin(), $1.vargs->args.end(), args.begin() ); - if( $1.special && $1.special->id == ARG_NUM_e ) { - if( $1.vargs->args.size() != 1 ) { - error_msg(@1, "ARGUMENT-NUMBER can be set to only one value"); - } - const cbl_refer_t& src( $1.vargs->args.front() ); - cbl_field_t *dst = register_find("_ARGI"); - parser_move( dst, src ); - } else { - parser_display($1.special, - args.empty()? NULL : args.data(), args.size(), - DISPLAY_ADVANCE); - } - current.declaratives_evaluate(); - } - | disp_body NO ADVANCING end_display +display: disp_body end_display[advance] { - std::vector <cbl_refer_t> args($1.vargs->args.size()); - std::copy( $1.vargs->args.begin(), $1.vargs->args.end(), args.begin() ); - - if( $1.special && $1.special->id == ARG_NUM_e ) { - if( $1.vargs->args.size() != 1 ) { - error_msg(@1, "ARGUMENT-NUMBER can be set to only one value"); - } - const cbl_refer_t& src( $1.vargs->args.front() ); - cbl_field_t *dst = register_find("_ARGI"); - parser_move( dst, src ); - } else { - parser_display($1.special, - args.empty()? NULL : args.data(), args.size(), - DISPLAY_NO_ADVANCE); - } + std::vector <cbl_refer_t> args($1.vargs->args.begin(), + $1.vargs->args.end()); + parser_display($1.special, args, $advance); current.declaratives_evaluate(); } ; -end_display: %empty - | END_DISPLAY +end_display: %empty { $$ = DISPLAY_ADVANCE; } + | END_DISPLAY { $$ = DISPLAY_ADVANCE; } + | NO ADVANCING { $$ = DISPLAY_NO_ADVANCE; } + | NO ADVANCING END_DISPLAY { $$ = DISPLAY_NO_ADVANCE; } ; disp_body: disp_vargs[vargs] { @@ -5628,14 +5647,62 @@ disp_upon: device_name { error_msg(@NAME, "no such special name '%s'", $NAME); YYERROR; } - // Add the name now, as a convenience. - cbl_special_name_t special = { 0, *special_type }; + // Add the name now, as a convenience. + // These may come through as a NAME, depending on how scanned. + int token = 0; + switch(*special_type) { + case ARG_NUM_e: token = ARGUMENT_NUMBER; break; + case ENV_NAME_e: token = ENVIRONMENT_NAME; break; + case ENV_VALUE_e: token = ENVIRONMENT_VALUE; break; + + case ARG_VALUE_e: + default: + error_msg(@NAME, "cannot DISPLAY UPON %qs", $NAME); + YYERROR; + break; + } + cbl_special_name_t special = { token, *special_type }; namcpy(@NAME, special.name, $NAME); e = symbol_special_add(PROGRAM, &special); } $$ = cbl_special_name_of(e); } + | ARGUMENT_NUMBER { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_NUMBER, ARG_NUM_e, "ARGUMENT-NUMBER" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ENVIRONMENT_NAME { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_NAME, ENV_NAME_e, "ENVIRONMENT-NAME" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ENVIRONMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_VALUE, ENV_VALUE_e, "ENVIRONMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + ; + +exhibit_stmt: EXHIBIT exh_changed exh_named vargs { + statement_begin(@1, EXHIBIT); + std::vector<cbl_refer_t> args( $vargs->args.begin(), + $vargs->args.end() ); + parser_exhibit( $exh_changed, $exh_named, args ); + } + ; +exh_changed: %empty { $$ = false; } + | CHANGED { $$ = true; } + ; +exh_named: %empty { $$ = false; } + | NAMED { $$ = true; } ; divide: divide_impl end_divide { ast_divide($1); } @@ -5733,14 +5800,14 @@ end_program: end_program1[end] '.' gcc_unreachable(); } if( !matches ) { - error_msg(@end, "END %s %s does not match " + error_msg($end.loc, "END %s %s does not match " "%<IDENTIFICATION DIVISION %s%>", token_name, name, prog->name); YYERROR; } if( 0 != strcasecmp(prog->name, name) ) { - error_msg(@end, "END PROGRAM '%s' does not match PROGRAM-ID '%s'", + error_msg($end.loc, "END PROGRAM '%s' does not match PROGRAM-ID '%s'", name, prog->name); YYERROR; } @@ -5773,20 +5840,24 @@ end_program: end_program1[end] '.' ; end_program1: END_PROGRAM namestr[name] { + $$.loc = @name; $$.token = END_PROGRAM; $$.name = $name; } | END_FUNCTION namestr[name] { + $$.loc = @name; $$.token = END_FUNCTION; $$.name = $name; } | END_PROGRAM '.' // error { + $$.loc = @1; $$.token = END_PROGRAM; } | END_FUNCTION '.' // error { + $$.loc = @1; $$.token = END_FUNCTION; } ; @@ -6622,7 +6693,7 @@ name: qname auto name = names.front(); names.pop_front(); auto e = symbol_field_forward_add(PROGRAM, parent, - name, yylineno); + name, @1.first_line); if( !e ) YYERROR; symbol_field_location( symbol_index(e), @qname ); parent = symbol_index(e); @@ -6652,6 +6723,10 @@ ctx_name: NAME context_word: APPLY { static char s[] ="APPLY"; $$ = s; } // screen description entry + | ARGUMENT_NUMBER { static char s[] ="ARGUMENT-NUMBER"; + $$ = s; } // Display Upon / Accept From + | ARGUMENT_VALUE { static char s[] ="ARGUMENT-VALUE"; + $$ = s; } // Accept From | ARITHMETIC { static char s[] ="ARITHMETIC"; $$ = s; } // OPTIONS paragraph | ATTRIBUTE { static char s[] ="ATTRIBUTE"; @@ -6688,6 +6763,10 @@ context_word: APPLY { static char s[] ="APPLY"; $$ = s; } // ERASE clause in a screen description entry | ENTRY_CONVENTION { static char s[] ="ENTRY-CONVENTION"; $$ = s; } // OPTIONS paragraph + | ENVIRONMENT_NAME { static char s[] ="ENVIRONMENT-NAME"; + $$ = s; } // Display Upon + | ENVIRONMENT_VALUE { static char s[] ="ENVIRONMENT-VALUE"; + $$ = s; } // Display Upon / Accept From | ERASE { static char s[] ="ERASE"; $$ = s; } // screen description entry | EXPANDS { static char s[] ="EXPANDS"; @@ -7036,9 +7115,9 @@ arith_err: SIZE_ERROR *ptgt = $1 == NOT? current.compute_not_error() : current.compute_on_error(); } else { - *ptgt = label_add(LblArith, uniq_label("arith"), yylineno); + *ptgt = label_add(LblArith, uniq_label("arith"), @1.first_line); } - (*ptgt)->lain = yylineno; + (*ptgt)->lain = @1.first_line; parser_arith_error( *ptgt ); } ; @@ -7575,6 +7654,7 @@ perform_cond: UNTIL { parser_perform_conditional( &perform_current()->tgt); } perform_inline: perform_start statements END_PERFORM { location_set(@END_PERFORM); + parser_sleep(*cbl_refer_t::empty()); $$ = perform_current(); if( $perform_start == LOCATION ) { error_msg(@1, "LOCATION not valid with PERFORM Format 2"); @@ -7583,6 +7663,7 @@ perform_inline: perform_start statements END_PERFORM | perform_start END_PERFORM { location_set(@END_PERFORM); + parser_sleep(*cbl_refer_t::empty()); $$ = perform_current(); if( $perform_start == LOCATION ) { error_msg(@1, "LOCATION not valid with PERFORM Format 2"); @@ -8754,12 +8835,12 @@ search_1_body: name[table] search_varying[varying] cbl_name_t label_name; auto len = snprintf(label_name, sizeof(label_name), - "linear_search_%d", yylineno); + "linear_search_%d", @1.first_line); if( ! (0 < len && len < int(sizeof(label_name))) ) { gcc_unreachable(); } cbl_label_t *name = label_add( LblSearch, - label_name, yylineno ); + label_name, @1.first_line ); auto varying($varying); if( index == varying ) varying = NULL; parser_lsearch_start( name, $table, index, varying ); @@ -8812,9 +8893,9 @@ search_binary: SEARCH ALL search_2_body search_2_cases search_2_body: name[table] { statement_begin(@$, SEARCH); - char *label_name = xasprintf("binary_search_%d", yylineno); + char *label_name = xasprintf("binary_search_%d", @1.first_line); cbl_label_t *name = label_add( LblSearch, - label_name, yylineno ); + label_name, @1.first_line ); parser_bsearch_start( name, $table ); search_alloc(name); } @@ -9759,7 +9840,7 @@ call_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("call"), yylineno); + uniq_label("call"), @1.first_line); if( !$$.on_error ) YYERROR; parser_call_exception( $$.on_error ); @@ -9772,7 +9853,7 @@ call_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("call"), yylineno); + uniq_label("call"), @1.first_line); if( !$$.on_error ) YYERROR; parser_call_exception( $$.on_error ); @@ -9828,7 +9909,7 @@ go_to: GOTO labels[args] } for( auto& label : $args->elems ) { - label->used = yylineno; + label->used = @2.first_line; } cbl_label_t *arg = $args->elems.front(); parser_goto( cbl_refer_t(), 1, &arg ); @@ -9840,7 +9921,7 @@ go_to: GOTO labels[args] std::vector <cbl_label_t *> args($args->elems.size()); std::copy($args->elems.begin(), $args->elems.end(), args.begin()); for( auto& label : $args->elems ) { - label->used = yylineno; + label->used = @2.first_line; } parser_goto( *$value, args.size(), args.data() ); } @@ -9860,7 +9941,7 @@ resume: RESUME NEXT STATEMENT { statement_begin(@1, RESUME); parser_clear_exception(); - $tgt->used = yylineno; + $tgt->used = @1.first_line; parser_goto( cbl_refer_t(), 1, &$tgt ); } ; @@ -10035,7 +10116,7 @@ on_overflow: OVERFLOW_kw { $$.not_error = NULL; $$.on_error = label_add(LblString, - uniq_label("string"), yylineno); + uniq_label("string"), @1.first_line); if( !$$.on_error ) YYERROR; parser_string_overflow( $$.on_error ); @@ -10255,7 +10336,7 @@ intrinsic: function_udf if( p != NULL ) { auto loc = symbol_field_location(field_index(p->field)); error_msg(loc, "FUNCTION %qs has " - "inconsistent parameter type %zu (%qs)", + "inconsistent parameter type %td (%qs)", keyword_str($1), p - args.data(), name_of(p->field) ); YYERROR; } @@ -11377,6 +11458,7 @@ void ast_call( const YYLTYPE& loc, cbl_refer_t name, const cbl_refer_t& returnin */ static bool possible_ec() { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); bool format_1 = current.declaratives.has_format_1(); bool enabled = 0xFF < (current.declaratives.status() @@ -11399,6 +11481,7 @@ possible_ec() { */ static void statement_epilog( int token ) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); if( possible_ec() && token != CONTINUE ) { if( enabled_exceptions.size() ) { current.declaratives_evaluate(); @@ -11461,9 +11544,11 @@ keyword_str( int token ) { return ascii; } - return tokens.name_of(token); + return cdf_tokens.name_of(token); } +bool iso_cobol_word( const std::string& name, bool include_context ); + /* * Return the token for the Cobol name, unless it is a function name. The * lexer uses keyword_tok to determine if what appears to be a NAME is in fact @@ -11474,15 +11559,14 @@ keyword_str( int token ) { */ // tokens.h is generated as needed from parse.h with tokens.h.gen -tokenset_t::tokenset_t() { +current_tokens_t::tokenset_t::tokenset_t() { #include "token_names.h" } -bool iso_cobol_word( const std::string& name, bool include_context ); // Look up the lowercase form of a keyword, excluding some CDF names. int -tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { +current_tokens_t::tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { static const cbl_name_t non_names[] = { // including CDF NAMES, and "SWITCH" "CHECKING", "LIST", "LOCATION", "MAP", "SWITCH", }, * const eonames = non_names + COUNT_OF(non_names); @@ -11532,7 +11616,7 @@ tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { int keyword_tok( const char * text, bool include_intrinsics ) { - return tokens.find(text, include_intrinsics); + return cdf_tokens.find(text, include_intrinsics); } static inline size_t @@ -11724,7 +11808,7 @@ label_add( const YYLTYPE& loc, name, cbl_label_of(p)->name, cbl_label_of(p)->line); } } - struct cbl_label_t label = { type, parent, loc.last_line }; + struct cbl_label_t label = { type, parent, loc.first_line }; if( !namcpy(loc, label.name, name) ) return NULL; auto p = symbol_label_add(PROGRAM, &label); @@ -13074,7 +13158,7 @@ cobol_dialect_set( cbl_dialect_t dialect ) { break; case dialect_gnu_e: if( 0 == (cbl_dialects & dialect) ) { // first time - tokens.equate(YYLTYPE(), "BINARY-DOUBLE", "BINARY-C-LONG"); + cdf_tokens.equate(YYLTYPE(), "BINARY-DOUBLE", "BINARY-C-LONG"); } break; } diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 105afe9..03cb0a0 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -103,7 +103,7 @@ void input_file_status_notify(); } \ location_dump("parse.c", __LINE__, "current", (Current)); \ input_file_status_notify(); \ - gcc_location_set( location_set(Current) ); \ + location_set(Current); \ } while (0) int yylex(void); @@ -935,165 +935,11 @@ teed_up_names() { return name_queue_t::namelist_of( name_queue.peek() ); } -class tokenset_t { - // token_names is initialized from a generated header file. - std::vector<const char *>token_names; // position indicates token value - std::map <std::string, int> tokens; // aliases - std::set<std::string> cobol_words; // Anything in COBOL-WORDS may appear only once. - public: - static std::string - lowercase( const cbl_name_t name ) { - cbl_name_t lname; - std::transform(name, name + strlen(name) + 1, lname, ftolower); - return lname; - } - static std::string - uppercase( const cbl_name_t name ) { - cbl_name_t uname; - std::transform(name, name + strlen(name) + 1, uname, ftoupper); - return uname; - } - - public: - tokenset_t(); - int find( const cbl_name_t name, bool include_intrinsics ); - - bool equate( const YYLTYPE& loc, int token, - const cbl_name_t name, const cbl_name_t verb = "EQUATE") { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); - return false; - } - auto p = tokens.find(lowercase(name)); - bool fOK = p == tokens.end(); - if( fOK ) { // name not already in use - tokens[lname] = token; - dbgmsg("%s:%d: %d has alias %s", __func__, __LINE__, token, name); - } else { - error_msg(loc, "%s: %s already defined as a token", verb, name); - } - return fOK; - } - bool undefine( const YYLTYPE& loc, - const cbl_name_t name, const cbl_name_t verb = "UNDEFINE" ) { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); - return false; - } - - // Do not erase generic, multi-type tokens COMPUTATIONAL and BINARY_INTEGER. - if( binary_integer_usage_of(name) ) { - dbgmsg("%s:%d: generic %s remains valid as a token", __func__, __LINE__, name); - return true; - } - - auto p = tokens.find(lname); - bool fOK = p != tokens.end(); - if( fOK ) { // name in use - tokens.erase(p); - } else { - error_msg(loc, "%s: %s not defined as a token", verb, name); - } - dbgmsg("%s:%d: %s removed as a valid token name", __func__, __LINE__, name); - return fOK; - } - - bool substitute( const YYLTYPE& loc, - const cbl_name_t extant, int token, const cbl_name_t name ) { - return - equate( loc, token, name, "SUBSTITUTE" ) - && - undefine( loc, extant, "SUBSTITUTE" ); - } - bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS RESERVE: %s may appear but once", name); - return false; - } - tokens[lname] = -42; - return true; - } - int redefined_as( const cbl_name_t name ) { - auto lname( lowercase(name) ); - if( cobol_words.find(lname) != cobol_words.end() ) { - auto p = tokens.find(lname); - if( p != tokens.end() ) { - return p->second; - } - } - return 0; - } - const char * name_of( int tok ) const { - tok -= (255 + 3); - gcc_assert(0 <= tok && size_t(tok) < token_names.size()); - return tok < 0? "???" : token_names[tok]; - } -}; - -class current_tokens_t { - tokenset_t tokens; - public: - current_tokens_t() {} - int find( const cbl_name_t name, bool include_intrinsics ) { - return tokens.find(name, include_intrinsics); - } - bool equate( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { - int token; - if( 0 == (token = binary_integer_usage_of(keyword)) ) { - if( 0 == (token = keyword_tok(keyword)) ) { - error_msg(loc, "EQUATE %s: not a valid token", keyword); - return false; - } - } - auto name = keyword_alias_add(tokens.uppercase(keyword), - tokens.uppercase(alias)); - if( name != keyword ) { - error_msg(loc, "EQUATE: %s is already an alias for %s", alias, name.c_str()); - return false; - } - return tokens.equate(loc, token, alias); - } - bool undefine( const YYLTYPE& loc, cbl_name_t keyword ) { - return tokens.undefine(loc, keyword); - } - bool substitute( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { - int token; - if( 0 == (token = binary_integer_usage_of(keyword)) ) { - if( 0 == (token = keyword_tok(keyword)) ) { - error_msg(loc, "SUBSTITUTE %s: not a valid token", keyword); - return false; - } - } - auto name = keyword_alias_add(tokens.uppercase(keyword), - tokens.uppercase(alias)); - if( name != keyword ) { - error_msg(loc, "SUBSTITUTE: %s is already an alias for %s", alias, name.c_str()); - return false; - } - - dbgmsg("%s:%d: %s (%d) will have alias %s", __func__, __LINE__, keyword, token, alias); - return tokens.substitute(loc, keyword, token, alias); - } - bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { - return tokens.reserve(loc, name); - } - int redefined_as( const cbl_name_t name ) { - return tokens.redefined_as(name); - } - const char * name_of( int tok ) const { - return tokens.name_of(tok); - } -} tokens; +#define cdf_tokens cdf_current_tokens() int redefined_token( const cbl_name_t name ) { - return tokens.redefined_as(name); + return cdf_tokens.redefined_as(name); } struct file_list_t { @@ -1475,7 +1321,6 @@ class prog_descr_t { } } } locale; - cbl_call_convention_t call_convention; cbl_options_t options; explicit prog_descr_t( size_t isymbol ) @@ -1484,9 +1329,7 @@ class prog_descr_t { , paragraph(NULL) , section(NULL) , collating_sequence(NULL) - { - call_convention = current_call_convention(); - } + {} std::set<std::string> external_targets() { std::set<std::string> externals; @@ -1575,24 +1418,13 @@ static cbl_label_t * implicit_section(); class program_stack_t : protected std::stack<prog_descr_t> { struct pending_t { - cbl_call_convention_t call_convention; bool initial; - pending_t() - : call_convention(cbl_call_convention_t(0)) - , initial(false) - {} + pending_t() : initial(false) {} } pending; public: - cbl_call_convention_t - pending_call_convention( cbl_call_convention_t convention ) { - return pending.call_convention = convention; - } bool pending_initial() { return pending.initial = true; } void push( prog_descr_t descr ) { - cbl_call_convention_t call_convention = cbl_call_cobol_e; - if( !empty() ) call_convention = top().call_convention; - descr.call_convention = call_convention; std::stack<prog_descr_t>& me(*this); me.push(descr); } @@ -1618,9 +1450,6 @@ class program_stack_t : protected std::stack<prog_descr_t> { } void apply_pending() { - if( size() == 1 && 0 != pending.call_convention ) { - top().call_convention = pending.call_convention; - } if( pending.initial ) { auto e = symbol_at(top().program_index); auto prog(cbl_label_of(e)); @@ -2027,19 +1856,6 @@ static class current_t { return programs.top().options.default_round = mode; } - cbl_call_convention_t - call_convention() { - return programs.empty()? cbl_call_cobol_e : programs.top().call_convention; - } - cbl_call_convention_t - call_convention( cbl_call_convention_t convention) { - if( programs.empty() ) { - return programs.pending_call_convention(convention); - } - auto& prog( programs.top() ); - return prog.call_convention = convention; - } - const char * locale() { return programs.empty()? NULL : programs.top().locale.os_name; @@ -2137,6 +1953,7 @@ static class current_t { * ISO, in new_program. */ std::set<std::string> end_program() { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); if( enabled_exceptions.size() ) { declaratives_evaluate(); } @@ -2427,15 +2244,6 @@ current_rounded_mode( cbl_round_t rounded) { #endif static cbl_round_t current_rounded_mode( int token ); -cbl_call_convention_t -current_call_convention() { - return current.call_convention(); -} -cbl_call_convention_t -current_call_convention( cbl_call_convention_t convention) { - return current.call_convention(convention); -} - size_t program_level() { return current.program_level(); } static size_t constant_index( int token ); @@ -2909,17 +2717,6 @@ group_attr( const cbl_field_t * field ) { return p->attr; } -static struct symbol_elem_t * -field_of( const char F[], int L, const char name[] ) { - struct symbol_elem_t *e = symbol_field(PROGRAM, 0, name); - if( !e ) { - cbl_internal_error("%s:%d: no symbol '%s' found", F, L, name); - } - assert( procedure_div_e != current_division ); - return e; -} -#define field_of( F ) field_of(__func__, __LINE__, (F)) - static struct cbl_field_t * field_add( const YYLTYPE& loc, cbl_field_t *field ) { switch(current_data_section) { @@ -3696,18 +3493,18 @@ goodnight_gracie() { // false after USE statement, to enter Declarative with EC intact. static bool statement_cleanup = true; +static YYLTYPE current_location; static void statement_epilog( int token ); const char * keyword_str( int token ); -static YYLTYPE current_location; - const YYLTYPE& cobol_location() { return current_location; } -static inline YYLTYPE +static inline void location_set( const YYLTYPE& loc ) { - return current_location = loc; + current_location = loc; + gcc_location_set(loc); } static void statement_begin( const YYLTYPE& loc, int token ); diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l index 2fc4aea..ba4c044 100644 --- a/gcc/cobol/scan.l +++ b/gcc/cobol/scan.l @@ -83,10 +83,13 @@ NONWORD [^[:alnum:]$_-]+ SPC [[:space:]]+ OSPC [[:space:]]* +BLANK [[:blank:]]+ +OBLANK [[:blank:]]* EOL \r?\n BLANK_EOL [[:blank:]]*{EOL} BLANK_OEOL [[:blank:]]*{EOL}? +PICTURE [^[:space:]]+ DOTSEP [.]+[[:space:]] DOTEOL [[:blank:]]*[.]{BLANK_EOL} @@ -160,7 +163,7 @@ COMMA [,;][[:blank:]]* ISNT (IS{SPC})?NOT -COMMENTARY DATE-COMPILED|DATE-WRITTEN|INSTALLATION|SECURITY +COMMENTARY AUTHOR|DATE-COMPILED|DATE-WRITTEN|INSTALLATION|SECURITY SORT_MERGE SORT(-MERGE)? @@ -174,7 +177,7 @@ SIZE_ERROR (ON[[[:space:]]+)?SIZE[[:space:]]+ERROR VARTYPE NUMERIC|ALPHABETIC|ALPHABETIC_LOWER|ALPHABETIC_UPPER|DBCS|KANJI NAMTYP {NAME}|{VARTYPE} -NL [[:blank:]]*\r?\n[[:blank:]]* +NL [[:blank:]]*{EOL}[[:blank:]]* PUSH_FILE \f?[#]FILE{SPC}PUSH{SPC}[^\f]+\f POP_FILE \f?[#]FILE{SPC}POP\f @@ -182,7 +185,7 @@ LINE_DIRECTIVE ^[#]line{SPC}[[:alnum:]]+{SPC}[""''].+\n %x procedure_div ident_state addr_of function classify %x program_id_state comment_entries -%x author_state date_state field_level field_state dot_state +%x date_state field_level field_state dot_state %x numeric_state name_state %x quoted1 quoted2 quoteq %x picture picture_count integer_count @@ -238,30 +241,23 @@ WORKING-STORAGE{SPC}SECTION { yy_push_state(field_state); return WORKING_STORAGE_SECT; } LOCAL-STORAGE{SPC}SECTION { - yy_push_state(field_state); - return LOCAL_STORAGE_SECT; } -WORKING-STORAGE { - return WORKING_STORAGE; } -LOCAL-STORAGE { - return LOCAL_STORAGE; } -SCREEN { - return SCREEN; } + yy_push_state(field_state); + return LOCAL_STORAGE_SECT; } +WORKING-STORAGE { return WORKING_STORAGE; } +LOCAL-STORAGE { return LOCAL_STORAGE; } +SCREEN { return SCREEN; } LINKAGE{SPC}SECTION { yy_push_state(field_state); return LINKAGE_SECT; } -FUNCTION-ID { yy_push_state(ident_state); - yy_push_state(program_id_state); - yy_push_state(name_state); return FUNCTION; } - -PROGRAM-ID { yy_push_state(ident_state); - yy_push_state(program_id_state); - yy_push_state(name_state); return PROGRAM_ID; } +FUNCTION-ID{OSPC}{DOTSEP}? { yy_push_state(ident_state); + yy_push_state(program_id_state); + yy_push_state(name_state); return FUNCTION; } -PROGRAM-ID/{DOTEOL} { yy_push_state(ident_state); - yy_push_state(name_state); - yy_push_state(dot_state); return PROGRAM_ID; } +PROGRAM-ID{OSPC}{DOTSEP}? { yy_push_state(ident_state); + yy_push_state(program_id_state); + yy_push_state(name_state); return PROGRAM_ID; } PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); return PROCEDURE_DIV; } @@ -272,30 +268,18 @@ PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); } <ident_state>{ + {BLANK_OEOL} ID(ENTIFICATION)?{SPC}DIVISION { myless(0); yy_pop_state(); } + (ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION { + myless(0); yy_pop_state(); } + OPTIONS { myless(0); yy_pop_state(); } + AS{SPC}[""] { yy_push_state(quoted2); return AS; } AS{SPC}[''] { yy_push_state(quoted1); return AS; } IS { pop_return IS; } - OPTIONS { yy_pop_state(); myless(0); } - [[:blank:]]*(ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION/[[:space:].] { - yy_pop_state(); myless(0); } - [[:blank:]]*AUTHOR[[:blank:].]+{EOL}? { - // Might not have an EOL, but stop on one. - yy_push_state(author_state); } - - {DOTEOL} - {COMMENTARY} { BEGIN(comment_entries); } } -<author_state>{ - [[:blank:]]+ - ^{BLANK_EOL} - [^\r\n]+ { yy_pop_state(); - yylval.string = xstrdup(yytext); - } -} - <INITIAL>{ COBOL { return COBOL; } @@ -307,6 +291,15 @@ PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); yy_push_state(field_state); yy_set_bol(1); myless(0); } + + END{SPC}PROGRAM { yy_push_state(name_state); + return program_level() > 1? + END_SUBPROGRAM : END_PROGRAM; } + + END{SPC}FUNCTION { yy_push_state(name_state); + return program_level() > 1? + END_SUBPROGRAM /*invalid*/ : + END_FUNCTION; } } <INITIAL,procedure_div,cdf_state>{ @@ -444,6 +437,11 @@ STDOUT { return STDOUT; } STDERR { return STDERR; } SYSERR { return STDERR; } +ARGUMENT-NUMBER { return ARGUMENT_NUMBER; } +ARGUMENT-VALUE { return ARGUMENT_VALUE; } +ENVIRONMENT-NAME { return ENVIRONMENT_NAME; } +ENVIRONMENT-VALUE { return ENVIRONMENT_VALUE; } + CANCEL { return CANCEL; } COMMIT { return COMMIT; } COMMON { return COMMON; } @@ -541,7 +539,7 @@ SECTION{SPC}[+-]?{INTEGERZ}/{OSPC}{DOTSEP} { auto eotext = yytext + yyleng; auto p = std::find_if(yytext, eotext, fisspace); p = std::find_if(p, eotext, nonspace); - yylval.string = p; + yylval.string = xstrdup(p); return SECTION; } @@ -968,7 +966,9 @@ USE({SPC}FOR)? { return USE; } return NUMSTR; } - PIC(TURE)?({SPC}IS)?[[:space:]]{BLANK_OEOL} { + PIC(TURE)?({SPC}IS)?{SPC}{PICTURE} { + auto pos = validate_picture(); + myless(pos); yy_push_state(picture); return PIC; } ANY { return ANY; } @@ -1150,7 +1150,7 @@ USE({SPC}FOR)? { return USE; } yy_push_state(hex_state); } N?X{nonseq} { dbgmsg("invalid hexadecimal value: %s", yytext); return NO_CONDITION; } - [[:blank:]]*\r?\n {} + [[:blank:]]*{EOL} {} WORKING-STORAGE{SPC}SECTION { return WORKING_STORAGE_SECT; } LOCAL-STORAGE{SPC}SECTION { return LOCAL_STORAGE_SECT; } @@ -1220,7 +1220,7 @@ USE({SPC}FOR)? { return USE; } {NP}V?/[,.]? { yylval.number = ndigit(yyleng); return picset(PIC_P); } {N9}*V/{N9}* { yylval.number = ndigit(yyleng - 1); return picset(NINEV); } {N9}/{N9}*[,.]? { yylval.number = ndigit(yyleng); return picset(NINES); } - P+/[,.]?\r?\n { yylval.number = yyleng; return picset(PIC_P); } + P+/[,.]?{EOL} { yylval.number = yyleng; return picset(PIC_P); } 1{1,31}/({COUNT}|[(]{NAME}[)]) { yy_push_state(picture_count); @@ -1319,7 +1319,7 @@ USE({SPC}FOR)? { return USE; } [""]{SPC}[&]{SPC}[""''] { if( yytext[yyleng - 1] == '\'' ) BEGIN(quoted1); } - [""]-{OSPC}(\r?\n{OSPC})+[""] /* continue ... */ + [""]-{OSPC}({EOL}{OSPC})+[""] /* continue ... */ [""] { char *s = xstrdup(tmpstring? tmpstring : "\0"); yylval.literal.set_data(strlen(s), s); @@ -1336,7 +1336,7 @@ USE({SPC}FOR)? { return USE; } ['']{SPC}[&]{SPC}[""''] { if( yytext[yyleng - 1] == '"' ) BEGIN(quoted2); } - ['']-{OSPC}(\r?\n{OSPC})+[''] /* continue ... */ + ['']-{OSPC}({EOL}{OSPC})+[''] /* continue ... */ [''] { char *s = xstrdup(tmpstring? tmpstring : "\0"); yylval.literal.set_data(strlen(s), s); @@ -1384,45 +1384,36 @@ USE({SPC}FOR)? { return USE; } } <program_id_state>{ - ^[[:blank:]]+ - ^{BLANK_EOL} + {BLANK_OEOL} (IS)?[[:space:]] + AS/{SPC} { myless(0); yy_pop_state(); } /* => ident_state */ - COMMON/[.]|{SPC}[[:alnum:].] { return COMMON; } - INITIAL/[.]|{SPC}[[:alnum:].] { return INITIAL_kw; } - RECURSIVE { return RECURSIVE; } - PROGRAM/[.]|{SPC}[[:alnum:].] { return PROGRAM_kw; } - - INITIAL { pop_return INITIAL_kw; } - COMMON { pop_return COMMON; } - PROGRAM { pop_return PROGRAM; } + INITIAL { return INITIAL_kw; } + COMMON { return COMMON; } + RECURSIVE { return RECURSIVE; } + PROGRAM { return PROGRAM_kw; } - AS/{SPC} { myless(0); yy_pop_state(); } /* => ident_state */ - [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} { pop_return '.'; } - {DOTEOL} { pop_return '.'; } + {DOTSEP} { pop_return '.'; } } -<name_state>{ - ^[[:blank:]]+ - ^{BLANK_EOL} - {NAME} | - {NAME}/{OSPC}[.] { yy_pop_state(); - yylval.string = xstrdup(yytext); return NAME; } +<name_state>{ /* Either pop from here, or let the quoted state pop */ + {BLANK_OEOL} + {NAME} { yy_pop_state(); + yylval.string = xstrdup(yytext); + return NAME; + } Z?[''] { yylval.literal.set_prefix(yytext, yyleng-1); - yy_push_state(quoted1); } + BEGIN(quoted1); } Z?[""] { yylval.literal.set_prefix(yytext, yyleng-1); - yy_push_state(quoted2); } - - [.]/[[:blank:]]+. { return *yytext; } + BEGIN(quoted2); } - [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} { - yy_pop_state(); myless(0); } - {DOTEOL} { yy_pop_state(); myless(0); } + . { myless(0); yy_pop_state(); + /* Should not happen for valid inputs. */ } } <dot_state>{ [[:blank:]]*[.][[:blank:].]+{EOL} { pop_return '.'; } - [[:blank:]]*[.] { pop_return '.'; } + [[:blank:]]*[.]+ { pop_return '.'; } } <date_state>{ @@ -1645,9 +1636,9 @@ B-SHIFT-RC FUNCTION { yy_push_state(function); return FUNCTION; } - SECTION{OSPC}[.]{SPC}/USE[[:space:]] { yylval.string = NULL; return SECTION; } + SECTION{OSPC}[.]+{SPC}/USE[[:space:]] { yylval.string = NULL; return SECTION; } - [.]({SPC}(EJECT|SKIP[123]))*{SPC}EXIT{OSPC}/{DOTSEP} { + [.]+({SPC}(EJECT|SKIP[123]))*{SPC}EXIT{OSPC}/{DOTSEP} { // EXIT format-1 is a "continue" statement } {NAME}/{OSPC}{DOTSEP} { @@ -1682,16 +1673,17 @@ B-SHIFT-RC p += 2; while( ISSPACE(*p) ) p++; cbl_name_t name2; - std::transform( p, p + sizeof(name2), name2, - []( char ch ) { - switch(ch) { - case '-': - case '_': return ch; - default: - if( ISALNUM(ch) ) return ch; - } - return '\0'; - } ); + const char *pend = p + sizeof(name2); + char *pout = name2; + while( p < pend ) { + char ch = *p++; + if( ISALNUM(ch) || ch == '-' || ch == '_' ) { + *pout++ = ch; + } else { + *pout++ = '\0'; + break; + } + } symbol_elem_t *e = symbol_file(PROGRAM, name2); /* * For NAME IN FILENAME, we want the parser to handle it. @@ -2052,7 +2044,7 @@ BASIS { yy_push_state(basis); return BASIS; } return symbol_file(PROGRAM, yytext)? FILENAME : NAME; } [[:blank:]]+ - \r?\n { yy_pop_state(); } + {EOL} { yy_pop_state(); } } <raising>{ @@ -2073,49 +2065,62 @@ BASIS { yy_push_state(basis); return BASIS; } if( include_debug() ) myless(7); } } - ^[ ]*>>{OSPC}IF { yy_push_state(cdf_state); return CDF_IF; } - ^[ ]*>>{OSPC}ELSE { return CDF_ELSE; } - ^[ ]*>>{OSPC}END-IF { return CDF_END_IF; } + ^[ ]*>>{OBLANK}IF { yy_push_state(cdf_state); return CDF_IF; } + ^[ ]*>>{OBLANK}ELSE { return CDF_ELSE; } + ^[ ]*>>{OBLANK}END-IF { return CDF_END_IF; } - ^[ ]*[$]{OSPC}IF { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}IF { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } yy_push_state(cdf_state); return CDF_IF; } - ^[ ]*[$]{OSPC}ELSE { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}ELSE { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } return CDF_ELSE; } - ^[ ]*[$]{OSPC}END { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}END { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } return CDF_END_IF; } - ^[ ]*[$]{OSPC}SET({SPC}CONSTANT)? { + ^[ ]*[$]{OBLANK}SET({SPC}CONSTANT)? { if( ! dialect_mf() ) dialect_error(yylloc, yytext, "mf"); yy_push_state(cdf_state); return CDF_DEFINE; } - ^[ ]*>>{OSPC}EVALUATE { return CDF_EVALUATE; } - ^[ ]*>>{OSPC}WHEN { return CDF_WHEN; } - ^[ ]*>>{OSPC}END-EVALUATE { return CDF_END_EVALUATE; } + ^[ ]*>>{OBLANK}EVALUATE { return CDF_EVALUATE; } + ^[ ]*>>{OBLANK}WHEN { return CDF_WHEN; } + ^[ ]*>>{OBLANK}END-EVALUATE { return CDF_END_EVALUATE; } + + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}C { return CALL_VERBATIM; } + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}COBOL { return CALL_COBOL; } + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}VERBATIM { return CALL_VERBATIM; } + + ^[ ]*>>{OBLANK}DEFINE { yy_push_state(cdf_state); return CDF_DEFINE; } + ^[ ]*>>{OBLANK}DISPLAY { return CDF_DISPLAY; } + ^[ ]*>>{OBLANK}TURN { yy_push_state(exception); return TURN; } + ^[ ]*>>{OBLANK}COBOL-WORDS { yy_push_state(cobol_words); return COBOL_WORDS; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}C { return CALL_VERBATIM; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}COBOL { return CALL_COBOL; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}VERBATIM { return CALL_VERBATIM; } + ^[ ]*>>{OBLANK}SOURCE{BLANK}FORMAT { return SOURCE_FORMAT; } - ^[ ]*>>{OSPC}DEFINE { yy_push_state(cdf_state); return CDF_DEFINE; } - ^[ ]*>>{OSPC}DISPLAY { return CDF_DISPLAY; } - ^[ ]*>>{OSPC}TURN { yy_push_state(exception); return TURN; } - ^[ ]*>>{OSPC}COBOL-WORDS { yy_push_state(cobol_words); return COBOL_WORDS; } + ^[ ]*>>{OBLANK}PUSH { return CDF_PUSH; } + ^[ ]*>>{OBLANK}POP { return CDF_POP; } - ^[ ]*>>{OSPC}{NAME} { + ^[ ]*>>{OBLANK}{NAME} { error_msg(yylloc, "unknown CDF token: %s", yytext); } + OTHER { return OTHER; } OVERRIDE { return OVERRIDE; } PARAMETER { return PARAMETER_kw; } THRU { return THRU; } TRUE { return TRUE_kw; } + + ALL { return ALL; } + CALL-CONVENTION { return CALL_CONVENTION; } + COBOL-WORDS { return COBOL_WORDS; } + DEFINE { return CDF_DEFINE; } + SOURCE{BLANK}FORMAT { return SOURCE_FORMAT; } + } <cobol_words>{ @@ -2165,10 +2170,10 @@ BASIS { yy_push_state(basis); return BASIS; } <*>OR { return OR; } <*>AND { return AND; } -<*>{DOTSEP}[[:blank:].]+$ { return '.'; } +<*>{DOTSEP} { return '.'; } <*>[().=*/+&-] { return *yytext; } <*>[[:blank:]]+ -<*>\r?\n +<*>{EOL} <*>{ {COMMA} @@ -2369,7 +2374,7 @@ BASIS { yy_push_state(basis); return BASIS; } POINTER { return POINTER; } POSITIVE { return POSITIVE; } PROCEDURE { return PROCEDURE; } - PROGRAM { return PROGRAM; } + PROGRAM { return PROGRAM_kw; } PROGRAM-ID { return PROGRAM_ID; } PROPERTY { return PROPERTY; } PROTOTYPE { return PROTOTYPE; } @@ -2411,7 +2416,7 @@ BASIS { yy_push_state(basis); return BASIS; } SCREEN { return SCREEN; } SD { return SD; } SEARCH { return SEARCH; } - SECTION { return SECTION; } + SECTION { yylval.string = NULL; return SECTION; } SELECT { return SELECT; } SENTENCE { return SENTENCE; } SEPARATE { return SEPARATE; } diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h index ea304ba..31093a6 100644 --- a/gcc/cobol/scan_ante.h +++ b/gcc/cobol/scan_ante.h @@ -149,7 +149,7 @@ numstr_of( const char string[], radix_t radix = decimal_e ) { } auto nx = std::count_if(input, p, fisdigit); if( 36 < nx ) { - error_msg(yylloc, "significand of %s has more than 36 digits (%zu)", input, nx); + error_msg(yylloc, "significand of %s has more than 36 digits (%td)", input, nx); return NO_CONDITION; } @@ -356,6 +356,10 @@ static void level_found() { if( scanner_normal() ) parsing.need_level(false); } +/* + * Trim the scanned location by the amount about to re-scanned. + * Must be a macro because it expands yyless. + */ #define myless(N) \ do { \ auto n(N); \ @@ -486,7 +490,8 @@ trim_location( int nkeep) { (fmt_size_t)nline, (fmt_size_t)rescan.size()); if( nline ) { gcc_assert( yylloc.first_line + nline <= yylloc.last_line ); - yylloc.last_line =- int(nline); + yylloc.last_line -= int(nline); + gcc_assert( yylloc.first_line <= yylloc.last_line ); char *p = static_cast<char*>(memrchr(rescan.p, '\n', rescan.size())); yylloc.last_column = rescan.pend - ++p; return; @@ -604,7 +609,9 @@ static const std::map <std::string, bint_t > binary_integers { static int binary_integer_usage( const char name[]) { - cbl_name_t uname = {}; + // uname can't be cbl_name_t, because at this point name[] might have more + // than sizeof(cbl_name_t) characters. The length check comes later. + char *uname = xstrdup(name); std::transform(name, name + strlen(name), uname, ftoupper); dbgmsg("%s:%d: checking %s in %zu keyword_aliases", @@ -623,6 +630,7 @@ binary_integer_usage( const char name[]) { yylval.computational.signable = p->second.signable; dbgmsg("%s:%d: %s has type %d", __func__, __LINE__, uname, p->second.type ); + free(uname); return p->second.token; } @@ -689,6 +697,387 @@ picset( int token ) { return token; } +/** +## Script and data to produce picture_t::followers. +## Based on ISO Table 10. +#! /usr/bin/awk -f + +BEGIN { + str = "B0/ , . + +- +- CR/DB cs cs Z* Z* + + cs cs 9 AX S V P P 1 N E" + split(str, cols) +} + +$1 ~ /CR|DB|cs/ { next } + +0 && !nlines++ { + for( i=0; i < length(cols); i++ ) { + print i, cols[i], "'" $i "'" + } +} + +$field == "x" { + if( ! nout++ ) { + printf "%2d: %5s: \"", field, cols[field - 1] + } + + gsub(/^ +| +$/, "", $1) + printf "%s", $1 +} + +END { + if( ! nout++ ) { + printf "%2d: %5s: \"", field, cols[field - 1] + } + print "\"" +} + +B x x x - x - - x - x x x x x x x x - x - x - x +0 x x x - x - - x - x x x x x x x x - x - x - x +/ x x x - x - - x - x x x x x x x x - x - x - x +, x x x - x - - x - x x x x x x x - - x - x +. x x - - x - - x - x - x - x - x ++ - - - - - - - - - - - - - - - - - - - - - - - x ++ +– ++ x x x - - - - x x x x - - x x x - - x x x +CR x x x - - - - x x x x - - x x x - - x x x +DB x x x - - - - x x x x - - x x x - - x x x +cs - - - - x +cs x x x - x - - - - x x - - - - x - - x x x + +Z x x - - x - - x - x +* x x - - x - - x - x +Z x x x - x - - x - x x - - - - - - - x - x +* x x x - x - - x - x x - - - - - - - x - x ++ x x - - - - - x - - - x +– x x - - - - - x - - - x ++ x x x - - - - x - - - x x - - - - - x +– x x x - - - - x - - - x x - - - - - x +cs x x - - x - - - - - - - - x +cs x x x - x - - - - - - - - x x - - - x + +9 x x x x x - - x - x - x - x - x x x x - x - - x +A x - - - - - - - - - - - - - - x x +X x - - - - - - - - - - - - - - x x +S +V x x - - x - - x - x - x - x - x - x - x +P x x - - x - - x - x - x - x - x - x - x +P - - - - x - - x - - - - - - - - - x x - x +1 - - - - - - - - - - - - - - - - - - - - - x +N x - - - - - - - - - - - - - - - - - - - - - x +E x x x - x - - - - - - - - - - x +**/ + +class picture_t { + static const char dot = '.', comma = ','; + + typedef std::vector<std::string> followings_t; + static const std::map <char, followings_t> followers; + + const char * const begin; + const char *p, *pend; + size_t pos; + struct exclusions_t { // Nonzero if set, > 1 is false. + // crdb means CR/DB or +/-. + // pluses means 2 or more consecutive '+'. + // minuses means 2 or more consecutive '-'. + // "21) The symbol 'Z' and the symbol '*' are mutually exclusive " + // stars means '*' or Z. + unsigned short int crdb, currency, dot, pluses, minuses, stars, zzz; + exclusions_t() + : crdb(0), currency(0), dot(0), pluses(0), minuses(0), stars(0) + {} + } exclusions; + YYLTYPE loc; + + bool is_crdb() const { // input must be uppercase for CR/DB + if( p[0] == 'C' || p[0] == 'D' ) { + char input[3] = { p[0], p[1] }; + return ( 0 == strcmp(input, "CR") || 0 == strcmp(input, "DB") ); + } + return false; + } + + const char * match_paren( const char *paren ) const { + gcc_assert(paren[0] == '('); // start with opening paren + paren = std::find_if( paren, pend, + []( char ch ) { + return ch == '(' || ch == ')'; + } ); + if( *paren == '(' ) return nullptr; // no nesting + if( paren == pend ) return nullptr; + return ++paren; + } + + const char * next_not( char ch ) const { + return std::find_if( p, pend, + [ch = TOUPPER(ch)]( char next ) { + return ch != next; + } ); + } + + const char * valid_next( const char *p, const std::string& valid ) const { + if( p == pend || p + 1 == pend ) return pend; + if( p[1] == '(' ) { + return match_paren(++p); + } + auto pv = std::find(valid.begin(), valid.end(), TOUPPER(p[1])); + return pv != valid.end()? ++p : nullptr; + } + const char * valid_next( const char *p, + bool first = true, char ch = '\0' ) const { + if( p == pend || p + 1 == pend ) return pend; + if( p[0] == '(' ) { + if( (p = match_paren(p)) == nullptr ) return nullptr; + } + if( p[0] == '(' ) return nullptr; // consecutive parentheses + + int index = first? 0 : 1; + if( !ch ) ch = *p; // use current character unless overridden + auto valid = followers.find(TOUPPER(ch)); + if( valid == followers.end() ) { + YYLTYPE loc(yylloc); + loc.first_column += int(p - begin); + error_msg( loc, "PICTURE: strange character %qc, giving up", ch ); + return nullptr; + } + return valid_next(p, valid->second[index]); + } + + const char * start() { // start modifies exclusions, but not p + auto pnext = p; + + switch(TOUPPER(p[0])) { + case comma: case dot: + // use decimal_is_comma() + // 4: .: "B0/,+Z*+-9E" + exclusions.dot++; + pnext = valid_next(p, "B0/,+Z*+-9E"); + break; + case '+': case '-': + // 6: +-: "B0/,.Z*Z*9VPPE" + exclusions.crdb++; + pnext = next_not(p[0]); + if( p + 1 < pnext ) { + exclusions.pluses++; + } + pnext = valid_next(--pnext, "B0/,.Z*Z*9VPPE"); + break; + case 'Z': case '*': + exclusions.stars++; + pnext = next_not(p[0]); + break; + case 'S': + // 19: S: "9VP" + pnext = valid_next(p, "9VP"); + break; + } + + /* + * "For fixed editing sign control, the currency symbol, when used, shall + * be either the leftmost symbol in character-string-1, optionally preceded + * by one of the symbols '+' or '-' " + */ + if( pnext ) { + if( p == pnext || p[0] == '+' || p[0] == '-' ) { + if( symbol_currency(*pnext) ) { + exclusions.currency++; + pnext = next_not(*pnext); + pnext = valid_next(--pnext, true, '$'); + } + } + } + + return pnext; + } + + const char * next() { // modify state; do not modify position + auto pnext = p; + auto loc(picture_t::loc); + loc.first_column += int(p - begin); + + if( is_crdb() ) { + if( exclusions.crdb++ ) { + error_msg( loc, "PICTURE: CR/DB and %c/%c may appear only once", '+', '-' ); + return nullptr; + } + if( p + 2 != pend ) { + error_msg( loc, "PICTURE: CR/DB must appear at the end" ); + return nullptr; + } + return pend; + } + + if( symbol_currency(p[0]) ) { + if( false && exclusions.currency++ ) { // not enforced + error_msg( loc, "PICTURE: CURRENCY SYMBOL sequence may appear at most once" ); + return nullptr; + } + return valid_next(p, ! exclusions.dot, '$'); + } + + switch(TOUPPER(p[0])) { + case '(': + return match_paren(p); + break; + case 'B': case '0': case '/': + pnext = valid_next(p); + break; + case comma: + if( decimal_is_comma() ) { + if( exclusions.dot++ ) { + error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] ); + return nullptr; + } + pnext = valid_next(p, true, dot); + } else { + pnext = valid_next(p); + } + break; + case dot: + if( p + 1 == pend ) { + pnext = pend; + } else { + if( decimal_is_comma() ) { + pnext = valid_next(p, true, comma ); + } else { + if( exclusions.dot++ ) { + error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] ); + return nullptr; + } + pnext = valid_next(p); + } + } + break; + + case '+': case '-': + // 7 is trailing sign; 13 & 14 are numeric. Leading sign handled by start(). + if( p + 1 == pend ) { + if( exclusions.crdb++ ) { + error_msg( loc, "PICTURE: %c/%c may appear at most once as a sign", '+', '-' ); + return nullptr; + } + pnext = pend; + } else { + pnext = next_not(p[0]); + if( p + 1 < pnext ) { + if( false && exclusions.pluses++ ) { // not enforced + error_msg( loc, "PICTURE: %qc: sequence may appear at most once", p[0] ); + return nullptr; + } + } + pnext = valid_next(pnext, ! exclusions.dot); + } + break; + + case 'Z': case '*': + if( false && exclusions.stars++ ) { // not enforced + error_msg( loc, "PICTURE: %qc: sequence may appear at most once", p[0] ); + return nullptr; + } + if( (pnext = next_not(p[0])) == nullptr ) return pnext; + pnext = valid_next(pnext, ! exclusions.dot); + break; + case 'P': + pnext = valid_next(pnext, ! exclusions.dot); + break; + case '9': + case 'A': case 'X': + case 'V': + case '1': + case 'N': + pnext = valid_next(p); + break; + case 'E': + pnext = valid_next(p, "+9"); + if( pnext && *pnext == '+' ) { + pnext = valid_next(p, "9"); + } + break; + default: + error_msg( loc, "PICTURE: %qc: invalid character", p[0] ); + return nullptr; + } + return pnext; + } + + public: + picture_t( const char *p, int len ) + : begin(p) + , p(p), pend(p + len) + , loc(yylloc) + { + assert(TOUPPER(*p) == 'P'); // as in PICTURE (or PICTURE IS) + // move p to start of picture string + while( (p = std::find_if(p, pend, fisspace)) != pend ) { + this->p = p = std::find_if(p, pend, + []( char ch ) { return ! fisspace(ch); } ); + } + assert(this->p != pend); + pos = this->p - begin; + } + + bool is_valid() { + if( !p ) return false; + if( (p = start()) == nullptr ) { + return false; + } + + while( p && p < pend) { + p = next(); + } + return p == pend; + } + + int starts_at() const { return pos; } +}; + +/* + * The Followers map gives 1 or 2 lists of valid characters following a + * character, the one in the key. If there are two lists, the correct one is + * determined by the caller based on the state of the picture string, i.e., + * what has been seen before. + */ +const std::map <char, picture_t::followings_t> picture_t::followers { + /* B0/ */ { 'B', {"B0/,.Z*+-9AXVPNE" } }, + /* B0/ */ { '0', {"B0/,.Z*+-9AXVPNE" } }, + /* B0/ */ { '/', {"B0/,.Z*+-9AXVPNE" } }, + /* , */ { ',', {"B0/,.Z*+-9VPE"} }, + /* . */ { '.', {"B0/,Z*+-9E"} }, + /* + { '+', "9" }, */ + /* +- */ { '+', {"B0/,.Z*9VPE", "" } }, + /* +- */ { '-', {"B0/,.Z*9VPE", "" } }, + /* CR/DB { 'C', "" }, */ + /* cs { 'c', "B0/,.Z*+-9VP" }, */ + /* cs { 'c', "+" }, */ + /* Z* */ { 'Z', {"B0/,.+Z*9VP", "B0/,+Z*"} }, + /* Z* */ { '*', {"B0/,.+Z*9VP", "B0/,+Z*"} }, + /* + */ { '+', {"B0/,.+-9VP", "B0/,+-"} }, + /* cs */ { '$', {"B0/,.+9VP", "B0/,+"} }, + /* 9 */ { '9', {"B0/,.+9AXVPE"} }, + /* AX */ { 'A', {"B0/9AX"} }, + /* AX */ { 'X', {"B0/9AX"} }, + /* S */ { 'S', {"9VP"} }, + /* V */ { 'V', {"B0/,+Z*+-9P"} }, + /* P */ { 'P', {"+VP", "B0/,+Z*9P"} }, + /* 1 */ { '1', {"1"} }, + /* N */ { 'N', {"B0/N"} }, + /* E */ { 'E', {"+9"} }, +}; + +/* + * Although picture_t::is_valid return a bool, it's not used. The validation + * routines emit messages where the error is detected. The entire string is + * subsequently parsed by the parser, which might otherwise accept an invalid + * string, but will usually emit a message of its own. + */ +static int +validate_picture() { + picture_t picture(yytext, yyleng); + picture.is_valid(); + return picture.starts_at(); +} + static inline bool is_integer_token( int *pvalue = NULL ) { int v, n = 0; diff --git a/gcc/cobol/scan_post.h b/gcc/cobol/scan_post.h index a273da9..7cf2b98 100644 --- a/gcc/cobol/scan_post.h +++ b/gcc/cobol/scan_post.h @@ -34,7 +34,6 @@ start_condition_str( int sc ) { switch(sc) { case INITIAL: state = "INITIAL"; break; case addr_of: state = "addr_of"; break; - case author_state: state = "author_state"; break; case basis: state = "basis"; break; case bool_state: state = "bool_state"; break; case cdf_state: state = "cdf_state"; break; @@ -159,6 +158,8 @@ is_cdf_token( int token ) { case CDF_DISPLAY: case CDF_IF: case CDF_ELSE: case CDF_END_IF: case CDF_EVALUATE: case CDF_WHEN: case CDF_END_EVALUATE: + case CDF_PUSH: + case CDF_POP: return true; case CALL_COBOL: case CALL_VERBATIM: diff --git a/gcc/cobol/show_parse.h b/gcc/cobol/show_parse.h index db24807..bd0e16f 100644 --- a/gcc/cobol/show_parse.h +++ b/gcc/cobol/show_parse.h @@ -176,11 +176,21 @@ extern bool cursor_at_sol; } \ else \ { \ - fprintf(stderr, " %p:%s (%s)", (void*)b, b->name, b->type_str()); \ + fprintf(stderr, " %p:%s (%s)", static_cast<void*>(b), b->name, b->type_str()); \ } \ show_parse_sol = false; \ } while(0); +// Use this version when b is known to be valid. This is necessary to quiet +// cppcheck nullPointerRedundantCheck warnings +#define SHOW_PARSE_LABEL_OK(a, b) \ + do \ + { \ + fprintf(stderr, "%s", a); \ + fprintf(stderr, " %p:%s (%s)", static_cast<void*>(b), b->name, b->type_str()); \ + show_parse_sol = false; \ + } while(0); + #define TRACE1 if(bTRACE1) #define TRACE1_HEADER do \ { \ @@ -211,6 +221,7 @@ extern bool cursor_at_sol; #define TRACE1_FIELD_VALUE(a, field, b) \ do \ { \ + gcc_assert(field); \ cursor_at_sol=false; \ if ( field->type == FldConditional ) \ { \ @@ -423,13 +434,39 @@ extern bool cursor_at_sol; } while(0); // Use CHECK_FIELD when a should be non-null, and a->var_decl_node also should -// by non-null: +// by non-null. (The useless calls to abort() are because cppcheck doesn't +// understand that gcc_unreachable doesn't return); + +// Use this after doing any SHOW_PARSE stuff, to avoid cppcheck complaints +// about nullPointerRedundantCheck #define CHECK_FIELD(a) \ - do { \ + do { \ if(!a) \ { \ - yywarn("%s: parameter %<" #a "%> is NULL", __func__); \ + yywarn("%s: parameter %<" #a "%> is NULL", __func__); \ gcc_unreachable(); \ + abort(); \ + } \ + if( !a->var_decl_node ) \ + { \ + yywarn("%s: parameter %<" #a "%> is variable " \ + "%s<%s> with NULL %<var_decl_node%>", \ + __func__, \ + a->name, \ + cbl_field_type_str(a->type) ); \ + gcc_unreachable(); \ + abort(); \ + } \ + } while(0); + +// This version is a bit more lax, for special cases +#define CHECK_FIELD2(a) \ + do { \ + if(!a) \ + { \ + yywarn("%s: parameter %<" #a "%> is NULL", __func__); \ + gcc_unreachable(); \ + abort(); \ } \ if( !a->var_decl_node && a->type != FldConditional && a->type != FldLiteralA) \ { \ @@ -439,15 +476,18 @@ extern bool cursor_at_sol; a->name, \ cbl_field_type_str(a->type) ); \ gcc_unreachable(); \ + abort(); \ } \ } while(0); + #define CHECK_LABEL(a) \ do{ \ if(!a) \ { \ yywarn("%s: parameter %<" #a "%> is NULL", __func__); \ gcc_unreachable(); \ + abort(); \ } \ }while(0); @@ -504,6 +544,7 @@ class ANALYZE } }; #else +// cppcheck-suppress ctuOneDefinitionRuleViolation class ANALYZE { public: diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index 089c9c1..f2cd1b5 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -28,6 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// cppcheck-suppress-file duplicateBreak + #include "config.h" #include <fstream> // Before cobol-system because it uses poisoned functions #include "cobol-system.h" @@ -672,7 +674,7 @@ symbol_special( size_t program, const char name[] ) struct symbol_elem_t * symbol_alphabet( size_t program, const char name[] ) { - cbl_alphabet_t alphabet(YYLTYPE(), custom_encoding_e); + cbl_alphabet_t alphabet(YYLTYPE(), custom_encoding_e); // cppcheck-suppress syntaxError assert(strlen(name) < sizeof alphabet.name); strcpy(alphabet.name, name); @@ -931,7 +933,7 @@ end_of_group( size_t igroup ) { if( e->program != group->program ) return isym; if( e->type == SymLabel ) return isym; // end of data division if( e->type == SymField ) { - const auto f = cbl_field_of(e); + const cbl_field_t * f = cbl_field_of(e); if( f->level == LEVEL77 || f->level == 66 ) return isym; if( f->level == 1 && f->parent != igroup ) { return isym; @@ -1174,7 +1176,7 @@ static struct symbol_elem_t * // If an 01 record exists for the FD/SD, use its capacity as the // default_record capacity. if( p != symbols_end() ) { - const auto record = cbl_field_of(p); + const cbl_field_t * record = cbl_field_of(p); assert(record->level == 1); e = calculate_capacity(p); auto record_size = std::max(record->data.memsize, @@ -1262,7 +1264,7 @@ static struct symbol_elem_t * // If group has a parent that is a record area, expand it, too. if( 0 < group->parent ) { - auto redefined = symbol_redefines(group); + redefined = symbol_redefines(group); if( redefined && is_record_area(redefined) ) { if( redefined->data.capacity < group->data.memsize ) { redefined->data.capacity = group->data.memsize; @@ -1434,11 +1436,11 @@ cbl_field_t::attr_str( const std::vector<cbl_field_attr_t>& attrs ) const const char *sep = ""; char *out = NULL; - for( auto attr : attrs ) { + for( auto attr_l : attrs ) { char *part = out; - if( has_attr(attr) ) { + if( has_attr(attr_l) ) { int erc = asprintf(&out, "%s%s%s", - part? part : "", sep, cbl_field_attr_str(attr)); + part? part : "", sep, cbl_field_attr_str(attr_l)); if( -1 == erc ) return part; free(part); sep = ", "; @@ -1745,7 +1747,7 @@ symbols_update( size_t first, bool parsed_ok ) { bool size_invalid = field->data.memsize > 0 && symbol_redefines(field); if( size_invalid ) { // redefine of record area is ok - const auto redefined = symbol_redefines(field); + const cbl_field_t * redefined = symbol_redefines(field); size_invalid = ! is_record_area(redefined); } if( !field->is_valid() || size_invalid ) @@ -1768,8 +1770,8 @@ symbols_update( size_t first, bool parsed_ok ) { if( e == symbols_end() ) { // no field redefines the file's default record auto file = cbl_file_of(symbol_at(field->parent)); - ERROR_FIELD(field, "line %d: %s lacks a file description", - file->line, file->name); + ERROR_FIELD(field, "%s lacks a file description", + file->name); return 0; } } @@ -1828,7 +1830,7 @@ symbols_update( size_t first, bool parsed_ok ) { } // Verify REDEFINing field has no ODO components - const auto parent = symbol_redefines(field); + const cbl_field_t * parent = symbol_redefines(field); if( parent && !is_record_area(parent) && is_variable_length(field) ) { ERROR_FIELD(field, "line %d: REDEFINES field %s cannot be variable length", field->line, field->name); @@ -2180,14 +2182,22 @@ symbol_table_init(void) { } static symbol_elem_t environs[] = { + { symbol_elem_t{ 0, cbl_special_name_t{0, CONSOLE_e, "CONSOLE", 0, "/dev/stdout"}} }, // stdout in DISPLAY; stdin in ACCEPT + + { symbol_elem_t{ 0, cbl_special_name_t{0, STDIN_e, "STDIN", 0, "/dev/stdin"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIN_e, "SYSIN", 0, "/dev/stdin"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIPT_e, "SYSIPT", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIPT_e, "SYSIPT", 0, "/dev/stdin"}} }, + + { symbol_elem_t{ 0, cbl_special_name_t{0, STDOUT_e, "STDOUT", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSOUT_e, "SYSOUT", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSLIST_e, "SYSLIST", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSLST_e, "SYSLST", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSPUNCH_e, "SYSPUNCH", 0, "/dev/stderr"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSPCH_e, "SYSPCH", 0, "/dev/stderr"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, CONSOLE_e, "CONSOLE", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, STDERR_e, "STDERR", 0, "/dev/stderr"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSERR_e, "SYSERR", 0, "/dev/stderr"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, C01_e, "C01", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, C02_e, "C02", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, C03_e, "C03", 0, "/dev/null"}} }, @@ -2207,10 +2217,6 @@ symbol_table_init(void) { { symbol_elem_t{ 0, cbl_special_name_t{0, S04_e, "S04", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, S05_e, "S05", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, AFP_5A_e, "AFP-5A", 0, "/dev/null"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDIN_e, "STDIN", 0, "/dev/stdin"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDOUT_e, "STDOUT", 0, "/dev/stdout"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDERR_e, "STDERR", 0, "/dev/stderr"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, SYSERR_e, "SYSERR", 0, "/dev/stderr"}} }, }; struct symbol_elem_t *p = table.elems + table.nelem; @@ -2466,7 +2472,7 @@ symbol_typedef_add( size_t program, struct cbl_field_t *field ) { auto e = symbols_end() - 1; assert( symbols_begin() < e ); if( e->type == SymField ) { - const auto f = cbl_field_of(e); + const cbl_field_t * f = cbl_field_of(e); if( f == field ) return e; } @@ -2516,7 +2522,8 @@ symbol_field_add( size_t program, struct cbl_field_t *field ) if( is_numeric(parent->usage) && parent->data.capacity > 0 ) { field->type = parent->usage; field->data = parent->data; - field->data = 0; + field->data = 0; // cppcheck-suppress redundantAssignment + // // cppcheck doesn't understand multiple overloaded operator= field->data.initial = NULL; } } @@ -3140,7 +3147,6 @@ static cbl_field_t * new_temporary_impl( enum cbl_field_type_t type, const cbl_name_t name = nullptr ) { extern int yylineno; - static int nstack, nliteral; static const struct cbl_field_t empty_alpha = { 0, FldAlphanumeric, FldInvalid, intermediate_e, 0, 0, 0, nonarray, 0, "", @@ -3209,8 +3215,10 @@ new_temporary_impl( enum cbl_field_type_t type, const cbl_name_t name = nullptr f->line = yylineno; if( is_literal(type) ) { + static int nliteral = 0; snprintf(f->name, sizeof(f->name), "_literal%d",++nliteral); } else { + static int nstack = 0; snprintf(f->name, sizeof(f->name), "_stack%d",++nstack); } @@ -3724,6 +3732,12 @@ symbol_label_add( size_t program, cbl_label_t *input ) bool symbol_label_section_exists( size_t eval_label_index ) { auto eval = symbols_begin(eval_label_index); + /* cppcheck warns that the following statement depends on the order of + evaluation of side effects. Since this isn't my code, and since I don't + think the warning can be eliminated without rewriting it, I am just + supprressing it. + -- Bob Dubner, 2025-07-14 */ + // cppcheck-suppress unknownEvaluationOrder bool has_section = std::any_of( ++eval, symbols_end(), [program = eval->program]( const auto& sym ) { if( program == sym.program && sym.type == SymLabel ) { @@ -4183,7 +4197,7 @@ symbol_program_callables( size_t program ) { if( e->type != SymLabel ) continue; if( e->elem.label.type != LblProgram ) continue; - const auto prog = cbl_label_of(e); + const cbl_label_t * prog = cbl_label_of(e); if( program == symbol_index(e) && !prog->recursive ) continue; if( (self->parent == prog->parent && prog->common) || @@ -4237,6 +4251,11 @@ symbol_currency( char sign ) { if( currencies.size() == 0 ) { currencies['$'] = "$"; } + if( sign == '\0' ) { // default + auto result = currencies.begin(); + gcc_assert(result != currencies.end()); + return result->second; + } auto result = currencies.find(sign); return result == currencies.end()? NULL : result->second; } @@ -4345,6 +4364,26 @@ cbl_occurs_t::subscript_ok( const cbl_field_t *subscript ) const { return bounds.lower <= (size_t)sub && (size_t)sub <= bounds.upper; } +const cbl_field_t * +symbol_unresolved_file_key( const cbl_file_t * file, + const cbl_name_t key_field_name ) { + const symbol_elem_t *file_sym = symbol_elem_of(file); + size_t program = file_sym->program; + for( const symbol_elem_t *e = file_sym - 1; e->program == program; e-- ) { + if( e->type == SymFile ) break; + if( e->type == SymField ) { + auto f = cbl_field_of(e); + if( f->type == FldLiteralA ) break; + if( f->type == FldForward ) { + if( 0 == strcmp(key_field_name, f->name) ) { + return f; + } + } + } + } + return nullptr; +} + cbl_file_key_t:: cbl_file_key_t( cbl_name_t name, const std::list<cbl_field_t *>& fields, @@ -4486,7 +4525,7 @@ cbl_file_key_t::deforward( size_t ifile ) { if( ifield == fwd ) { ERROR_FIELD(field, "line %d: %s of %s " "is not defined", - file->line, field->name, file->name); + field->line, field->name, file->name); return ifield; } @@ -4515,9 +4554,13 @@ cbl_file_key_t::deforward( size_t ifile ) { // looked-up field must have same file as parent if( ! (parent != NULL && symbol_index(symbol_elem_of(parent)) == ifile) ) { - ERROR_FIELD(field, "line %d: %s of %s " - "is not defined in file description", - file->line, field->name, file->name); + const cbl_field_t *undefined = + symbol_unresolved_file_key(file, field->name); + int lineno = undefined? undefined->line : file->line; + ERROR_FIELD(undefined? undefined : field, + "line %d: %s of %s " + "is not defined in file description", + lineno, field->name, file->name); } return ifield; } ); @@ -4630,9 +4673,11 @@ file_status_status_of( file_status_t status ) { size_t n = COUNT_OF(file_status_fields); const file_status_field_t *fs, key { status }; - fs = (file_status_field_t*)lfind( &key, file_status_fields, - &n, sizeof(*fs), cbl_file_status_cmp ); - + fs = static_cast<file_status_field_t*>(lfind( &key, + file_status_fields, + &n, + sizeof(*fs), + cbl_file_status_cmp )); return fs? (long)fs->status : -1; } diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index 0b72b5c..c8ae32f 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -1894,6 +1894,10 @@ const cbl_label_t * symbol_program_local( const char called[] ); bool redefine_field( cbl_field_t *field ); +const cbl_field_t * +symbol_unresolved_file_key( const cbl_file_t * file, + const cbl_name_t key_field_name ); + static inline struct cbl_section_t * cbl_section_of( struct symbol_elem_t *e ) { assert(e && e->type == SymDataSection); @@ -2387,9 +2391,169 @@ enum cbl_call_convention_t { cbl_call_cobol_e = 'N', // native }; +int keyword_tok( const char * text, bool include_intrinsics = false ); +int redefined_token( const cbl_name_t name ); + +class current_tokens_t { + class tokenset_t { + // token_names is initialized from a generated header file. + std::vector<const char *>token_names; // position indicates token value + std::map <std::string, int> tokens; // aliases + std::set<std::string> cobol_words; // Anything in COBOL-WORDS may appear only once. + public: + static std::string + lowercase( const cbl_name_t name ) { + cbl_name_t lname; + std::transform(name, name + strlen(name) + 1, lname, ftolower); + return lname; + } + static std::string + uppercase( const cbl_name_t name ) { + cbl_name_t uname; + std::transform(name, name + strlen(name) + 1, uname, ftoupper); + return uname; + } + + public: + tokenset_t(); + int find( const cbl_name_t name, bool include_intrinsics ); + + bool equate( const YYLTYPE& loc, int token, + const cbl_name_t name, const cbl_name_t verb = "EQUATE") { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); + return false; + } + auto p = tokens.find(lowercase(name)); + bool fOK = p == tokens.end(); + if( fOK ) { // name not already in use + tokens[lname] = token; + dbgmsg("%s:%d: %d has alias %s", __func__, __LINE__, token, name); + } else { + error_msg(loc, "%s: %s already defined as a token", verb, name); + } + return fOK; + } + bool undefine( const YYLTYPE& loc, + const cbl_name_t name, const cbl_name_t verb = "UNDEFINE" ) { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); + return false; + } + + // Do not erase generic, multi-type tokens COMPUTATIONAL and BINARY_INTEGER. + if( binary_integer_usage_of(name) ) { + dbgmsg("%s:%d: generic %s remains valid as a token", __func__, __LINE__, name); + return true; + } + + auto p = tokens.find(lname); + bool fOK = p != tokens.end(); + if( fOK ) { // name in use + tokens.erase(p); + } else { + error_msg(loc, "%s: %s not defined as a token", verb, name); + } + dbgmsg("%s:%d: %s removed as a valid token name", __func__, __LINE__, name); + return fOK; + } + + bool substitute( const YYLTYPE& loc, + const cbl_name_t extant, int token, const cbl_name_t name ) { + return + equate( loc, token, name, "SUBSTITUTE" ) + && + undefine( loc, extant, "SUBSTITUTE" ); + } + bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS RESERVE: %s may appear but once", name); + return false; + } + tokens[lname] = -42; + return true; + } + int redefined_as( const cbl_name_t name ) { + auto lname( lowercase(name) ); + if( cobol_words.find(lname) != cobol_words.end() ) { + auto p = tokens.find(lname); + if( p != tokens.end() ) { + return p->second; + } + } + return 0; + } + const char * name_of( int tok ) const { + tok -= (255 + 3); + gcc_assert(0 <= tok && size_t(tok) < token_names.size()); + return tok < 0? "???" : token_names[tok]; + } + }; + + tokenset_t tokens; + public: + current_tokens_t() {} + int find( const cbl_name_t name, bool include_intrinsics ) { + return tokens.find(name, include_intrinsics); + } + bool equate( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { + int token; + if( 0 == (token = binary_integer_usage_of(keyword)) ) { + if( 0 == (token = keyword_tok(keyword)) ) { + error_msg(loc, "EQUATE %s: not a valid token", keyword); + return false; + } + } + auto name = keyword_alias_add(tokens.uppercase(keyword), + tokens.uppercase(alias)); + if( name != keyword ) { + error_msg(loc, "EQUATE: %s is already an alias for %s", alias, name.c_str()); + return false; + } + return tokens.equate(loc, token, alias); + } + bool undefine( const YYLTYPE& loc, cbl_name_t keyword ) { + return tokens.undefine(loc, keyword); + } + bool substitute( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { + int token; + if( 0 == (token = binary_integer_usage_of(keyword)) ) { + if( 0 == (token = keyword_tok(keyword)) ) { + error_msg(loc, "SUBSTITUTE %s: not a valid token", keyword); + return false; + } + } + auto name = keyword_alias_add(tokens.uppercase(keyword), + tokens.uppercase(alias)); + if( name != keyword ) { + error_msg(loc, "SUBSTITUTE: %s is already an alias for %s", alias, name.c_str()); + return false; + } + + dbgmsg("%s:%d: %s (%d) will have alias %s", __func__, __LINE__, keyword, token, alias); + return tokens.substitute(loc, keyword, token, alias); + } + bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { + return tokens.reserve(loc, name); + } + int redefined_as( const cbl_name_t name ) { + return tokens.redefined_as(name); + } + const char * name_of( int tok ) const { + return tokens.name_of(tok); + } +}; + cbl_call_convention_t current_call_convention(); +current_tokens_t& cdf_current_tokens(); -cbl_call_convention_t +void current_call_convention( cbl_call_convention_t convention); class procref_base_t { @@ -2433,9 +2597,6 @@ public: int line_number() const { return line; } }; -int keyword_tok( const char * text, bool include_intrinsics = false ); -int redefined_token( const cbl_name_t name ); - void procedure_definition_add( size_t program, const cbl_label_t *procedure ); void procedure_reference_add( const char *sect, const char *para, int line, size_t context ); @@ -2452,7 +2613,7 @@ symbol_field_same_as( cbl_field_t *tgt, const cbl_field_t *src ); size_t symbol_file_same_record_area( std::list<cbl_file_t*>& files ); bool symbol_currency_add( const char symbol[], const char sign[] = NULL ); -const char * symbol_currency( char symbol ); +const char * symbol_currency( char symbol = '\0' ); const char * symbol_type_str( enum symbol_type_t type ); const char * cbl_field_type_str( enum cbl_field_type_t type ); diff --git a/gcc/cobol/symfind.cc b/gcc/cobol/symfind.cc index 39df2a0..8141b22 100644 --- a/gcc/cobol/symfind.cc +++ b/gcc/cobol/symfind.cc @@ -48,7 +48,7 @@ extern int yydebug; static bool is_data_field( symbol_elem_t& e ) { if( e.type != SymField ) return false; - const auto f = cbl_field_of(&e); + const cbl_field_t *f = cbl_field_of(&e); if( f->name[0] == '\0' ) return false; if( is_filler(f) ) return false; @@ -129,7 +129,7 @@ finalize_symbol_map2() { for( auto& elem : symbol_map2 ) { auto& fields( elem.second ); fields.remove_if( []( auto isym ) { - const auto f = cbl_field_of(symbol_at(isym)); + const cbl_field_t *f = cbl_field_of(symbol_at(isym)); return f->type == FldInvalid; } ); if( fields.empty() ) empties.insert(elem.first); @@ -316,9 +316,9 @@ public: if( p != item.second.end() ) { // Preserve symbol's index at front of ancestor list. symbol_map_t::mapped_type shorter(1 + ancestors->size()); - auto p = shorter.begin(); - *p = item.second.front(); - shorter.insert( ++p, ancestors->begin(), ancestors->end() ); + auto p_l = shorter.begin(); + *p_l = item.second.front(); + shorter.insert( ++p_l, ancestors->begin(), ancestors->end() ); return make_pair(item.first, shorter); } } @@ -341,7 +341,7 @@ class in_scope { size_t program; static size_t prog_of( size_t program ) { - const auto L = cbl_label_of(symbol_at(program)); + const cbl_label_t *L = cbl_label_of(symbol_at(program)); return L->parent; } @@ -430,7 +430,7 @@ symbol_match2( size_t program, auto plist = symbol_map2.find(key); if( plist != symbol_map2.end() ) { for( auto candidate : plist->second ) { - const auto e = symbol_at(candidate); + const symbol_elem_t *e = symbol_at(candidate); if( name_has_names( e, names, local ) ) { fields.push_back( symbol_index(e) ); } @@ -504,7 +504,7 @@ symbol_match( size_t program, const std::list<const char *>& names ) { } auto inserted = output.insert(*p); if( ! inserted.second ) { - yyerror("%s is not a unique reference", key.name); + error_msg_direct("%s is not a unique reference", key.name); } } return output; diff --git a/gcc/cobol/token_names.h b/gcc/cobol/token_names.h index 4b24fc6..ca51510 100644 --- a/gcc/cobol/token_names.h +++ b/gcc/cobol/token_names.h @@ -1,5 +1,5 @@ // generated by ./token_names.h.gen ../../build/gcc/cobol/parse.h -// Thu May 8 18:53:33 EDT 2025 +// Tue Jul 8 19:21:28 EDT 2025 tokens = { { "identification", IDENTIFICATION_DIV }, // 258 { "environment", ENVIRONMENT_DIV }, // 259 @@ -137,558 +137,566 @@ tokens = { { "cdf-evaluate", CDF_EVALUATE }, // 388 { "cdf-when", CDF_WHEN }, // 389 { "cdf-end-evaluate", CDF_END_EVALUATE }, // 390 - { "call-cobol", CALL_COBOL }, // 391 - { "call-verbatim", CALL_VERBATIM }, // 392 - { "if", IF }, // 393 - { "then", THEN }, // 394 - { "else", ELSE }, // 395 - { "sentence", SENTENCE }, // 396 - { "accept", ACCEPT }, // 397 - { "add", ADD }, // 398 - { "alter", ALTER }, // 399 - { "call", CALL }, // 400 - { "cancel", CANCEL }, // 401 - { "close", CLOSE }, // 402 - { "compute", COMPUTE }, // 403 - { "continue", CONTINUE }, // 404 - { "delete", DELETE }, // 405 - { "display", DISPLAY }, // 406 - { "divide", DIVIDE }, // 407 - { "evaluate", EVALUATE }, // 408 - { "exit", EXIT }, // 409 - { "filler", FILLER_kw }, // 410 - { "goback", GOBACK }, // 411 - { "goto", GOTO }, // 412 - { "initialize", INITIALIZE }, // 413 - { "inspect", INSPECT }, // 414 - { "merge", MERGE }, // 415 - { "move", MOVE }, // 416 - { "multiply", MULTIPLY }, // 417 - { "open", OPEN }, // 418 - { "paragraph", PARAGRAPH }, // 419 - { "read", READ }, // 420 - { "release", RELEASE }, // 421 - { "return", RETURN }, // 422 - { "rewrite", REWRITE }, // 423 - { "search", SEARCH }, // 424 - { "set", SET }, // 425 - { "select", SELECT }, // 426 - { "sort", SORT }, // 427 - { "sort-merge", SORT_MERGE }, // 428 - { "string", STRING_kw }, // 429 - { "stop", STOP }, // 430 - { "subtract", SUBTRACT }, // 431 - { "start", START }, // 432 - { "unstring", UNSTRING }, // 433 - { "write", WRITE }, // 434 - { "when", WHEN }, // 435 - { "abs", ABS }, // 436 - { "access", ACCESS }, // 437 - { "acos", ACOS }, // 438 - { "actual", ACTUAL }, // 439 - { "advancing", ADVANCING }, // 440 - { "after", AFTER }, // 441 - { "all", ALL }, // 442 - { "allocate", ALLOCATE }, // 443 - { "alphabet", ALPHABET }, // 444 - { "alphabetic", ALPHABETIC }, // 445 - { "alphabetic-lower", ALPHABETIC_LOWER }, // 446 - { "alphabetic-upper", ALPHABETIC_UPPER }, // 447 - { "alphanumeric", ALPHANUMERIC }, // 448 - { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 449 - { "also", ALSO }, // 450 - { "alternate", ALTERNATE }, // 451 - { "annuity", ANNUITY }, // 452 - { "anum", ANUM }, // 453 - { "any", ANY }, // 454 - { "anycase", ANYCASE }, // 455 - { "apply", APPLY }, // 456 - { "are", ARE }, // 457 - { "area", AREA }, // 458 - { "areas", AREAS }, // 459 - { "as", AS }, // 460 - { "ascending", ASCENDING }, // 461 - { "activating", ACTIVATING }, // 462 - { "asin", ASIN }, // 463 - { "assign", ASSIGN }, // 464 - { "at", AT }, // 465 - { "atan", ATAN }, // 466 - { "based", BASED }, // 467 - { "baseconvert", BASECONVERT }, // 468 - { "before", BEFORE }, // 469 - { "binary", BINARY }, // 470 - { "bit", BIT }, // 471 - { "bit-of", BIT_OF }, // 472 - { "bit-to-char", BIT_TO_CHAR }, // 473 - { "blank", BLANK }, // 474 - { "block", BLOCK_kw }, // 475 - { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 476 - { "bottom", BOTTOM }, // 477 - { "by", BY }, // 478 - { "byte", BYTE }, // 479 - { "byte-length", BYTE_LENGTH }, // 480 - { "cf", CF }, // 481 - { "ch", CH }, // 482 - { "changed", CHANGED }, // 483 - { "char", CHAR }, // 484 - { "char-national", CHAR_NATIONAL }, // 485 - { "character", CHARACTER }, // 486 - { "characters", CHARACTERS }, // 487 - { "checking", CHECKING }, // 488 - { "class", CLASS }, // 489 - { "cobol", COBOL }, // 490 - { "code", CODE }, // 491 - { "code-set", CODESET }, // 492 - { "collating", COLLATING }, // 493 - { "column", COLUMN }, // 494 - { "combined-datetime", COMBINED_DATETIME }, // 495 - { "comma", COMMA }, // 496 - { "command-line", COMMAND_LINE }, // 497 - { "command-line-count", COMMAND_LINE_COUNT }, // 498 - { "commit", COMMIT }, // 499 - { "common", COMMON }, // 500 - { "concat", CONCAT }, // 501 - { "condition", CONDITION }, // 502 - { "configuration", CONFIGURATION_SECT }, // 503 - { "contains", CONTAINS }, // 504 - { "content", CONTENT }, // 505 - { "control", CONTROL }, // 506 - { "controls", CONTROLS }, // 507 - { "convert", CONVERT }, // 508 - { "converting", CONVERTING }, // 509 - { "corresponding", CORRESPONDING }, // 510 - { "cos", COS }, // 511 - { "count", COUNT }, // 512 - { "currency", CURRENCY }, // 513 - { "current", CURRENT }, // 514 - { "current-date", CURRENT_DATE }, // 515 - { "data", DATA }, // 516 - { "date", DATE }, // 517 - { "date-compiled", DATE_COMPILED }, // 518 - { "date-of-integer", DATE_OF_INTEGER }, // 519 - { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 520 - { "date-written", DATE_WRITTEN }, // 521 - { "day", DAY }, // 522 - { "day-of-integer", DAY_OF_INTEGER }, // 523 - { "day-of-week", DAY_OF_WEEK }, // 524 - { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 525 - { "dbcs", DBCS }, // 526 - { "de", DE }, // 527 - { "debugging", DEBUGGING }, // 528 - { "decimal-point", DECIMAL_POINT }, // 529 - { "declaratives", DECLARATIVES }, // 530 - { "default", DEFAULT }, // 531 - { "delimited", DELIMITED }, // 532 - { "delimiter", DELIMITER }, // 533 - { "depending", DEPENDING }, // 534 - { "descending", DESCENDING }, // 535 - { "detail", DETAIL }, // 536 - { "direct", DIRECT }, // 537 - { "direct-access", DIRECT_ACCESS }, // 538 - { "down", DOWN }, // 539 - { "duplicates", DUPLICATES }, // 540 - { "dynamic", DYNAMIC }, // 541 - { "e", E }, // 542 - { "ebcdic", EBCDIC }, // 543 - { "ec", EC }, // 544 - { "egcs", EGCS }, // 545 - { "entry", ENTRY }, // 546 - { "environment", ENVIRONMENT }, // 547 - { "equal", EQUAL }, // 548 - { "every", EVERY }, // 549 - { "examine", EXAMINE }, // 550 - { "exhibit", EXHIBIT }, // 551 - { "exp", EXP }, // 552 - { "exp10", EXP10 }, // 553 - { "extend", EXTEND }, // 554 - { "external", EXTERNAL }, // 555 - { "exception-file", EXCEPTION_FILE }, // 556 - { "exception-file-n", EXCEPTION_FILE_N }, // 557 - { "exception-location", EXCEPTION_LOCATION }, // 558 - { "exception-location-n", EXCEPTION_LOCATION_N }, // 559 - { "exception-statement", EXCEPTION_STATEMENT }, // 560 - { "exception-status", EXCEPTION_STATUS }, // 561 - { "factorial", FACTORIAL }, // 562 - { "false", FALSE_kw }, // 563 - { "fd", FD }, // 564 - { "file-control", FILE_CONTROL }, // 565 - { "file", FILE_KW }, // 566 - { "file-limit", FILE_LIMIT }, // 567 - { "final", FINAL }, // 568 - { "finally", FINALLY }, // 569 - { "find-string", FIND_STRING }, // 570 - { "first", FIRST }, // 571 - { "fixed", FIXED }, // 572 - { "footing", FOOTING }, // 573 - { "for", FOR }, // 574 - { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 575 - { "formatted-date", FORMATTED_DATE }, // 576 - { "formatted-datetime", FORMATTED_DATETIME }, // 577 - { "formatted-time", FORMATTED_TIME }, // 578 - { "form-overflow", FORM_OVERFLOW }, // 579 - { "free", FREE }, // 580 - { "fraction-part", FRACTION_PART }, // 581 - { "from", FROM }, // 582 - { "function", FUNCTION }, // 583 - { "generate", GENERATE }, // 584 - { "giving", GIVING }, // 585 - { "global", GLOBAL }, // 586 - { "go", GO }, // 587 - { "group", GROUP }, // 588 - { "heading", HEADING }, // 589 - { "hex", HEX }, // 590 - { "hex-of", HEX_OF }, // 591 - { "hex-to-char", HEX_TO_CHAR }, // 592 - { "high-values", HIGH_VALUES }, // 593 - { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 594 - { "hold", HOLD }, // 595 - { "ibm-360", IBM_360 }, // 596 - { "in", IN }, // 597 - { "include", INCLUDE }, // 598 - { "index", INDEX }, // 599 - { "indexed", INDEXED }, // 600 - { "indicate", INDICATE }, // 601 - { "initial", INITIAL_kw }, // 602 - { "initiate", INITIATE }, // 603 - { "input", INPUT }, // 604 - { "installation", INSTALLATION }, // 605 - { "interface", INTERFACE }, // 606 - { "integer", INTEGER }, // 607 - { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 608 - { "integer-of-date", INTEGER_OF_DATE }, // 609 - { "integer-of-day", INTEGER_OF_DAY }, // 610 - { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 611 - { "integer-part", INTEGER_PART }, // 612 - { "into", INTO }, // 613 - { "intrinsic", INTRINSIC }, // 614 - { "invoke", INVOKE }, // 615 - { "i-o", IO }, // 616 - { "i-o-control", IO_CONTROL }, // 617 - { "is", IS }, // 618 - { "isnt", ISNT }, // 619 - { "kanji", KANJI }, // 620 - { "key", KEY }, // 621 - { "label", LABEL }, // 622 - { "last", LAST }, // 623 - { "leading", LEADING }, // 624 - { "left", LEFT }, // 625 - { "length", LENGTH }, // 626 - { "length-of", LENGTH_OF }, // 627 - { "limit", LIMIT }, // 628 - { "limits", LIMITS }, // 629 - { "line", LINE }, // 630 - { "lines", LINES }, // 631 - { "line-counter", LINE_COUNTER }, // 632 - { "linage", LINAGE }, // 633 - { "linkage", LINKAGE }, // 634 - { "locale", LOCALE }, // 635 - { "locale-compare", LOCALE_COMPARE }, // 636 - { "locale-date", LOCALE_DATE }, // 637 - { "locale-time", LOCALE_TIME }, // 638 - { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 639 - { "local-storage", LOCAL_STORAGE }, // 640 - { "location", LOCATION }, // 641 - { "lock", LOCK }, // 642 - { "lock-on", LOCK_ON }, // 643 - { "log", LOG }, // 644 - { "log10", LOG10 }, // 645 - { "lower-case", LOWER_CASE }, // 646 - { "low-values", LOW_VALUES }, // 647 - { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 648 - { "lparen", LPAREN }, // 649 - { "manual", MANUAL }, // 650 - { "maxx", MAXX }, // 651 - { "mean", MEAN }, // 652 - { "median", MEDIAN }, // 653 - { "midrange", MIDRANGE }, // 654 - { "minn", MINN }, // 655 - { "multiple", MULTIPLE }, // 656 - { "mod", MOD }, // 657 - { "mode", MODE }, // 658 - { "module-name", MODULE_NAME }, // 659 - { "named", NAMED }, // 660 - { "nat", NAT }, // 661 - { "national", NATIONAL }, // 662 - { "national-edited", NATIONAL_EDITED }, // 663 - { "national-of", NATIONAL_OF }, // 664 - { "native", NATIVE }, // 665 - { "nested", NESTED }, // 666 - { "next", NEXT }, // 667 - { "no", NO }, // 668 - { "note", NOTE }, // 669 - { "nulls", NULLS }, // 670 - { "null", NULLS }, // 670 - { "nullptr", NULLPTR }, // 671 - { "numeric", NUMERIC }, // 672 - { "numeric-edited", NUMERIC_EDITED }, // 673 - { "numval", NUMVAL }, // 674 - { "numval-c", NUMVAL_C }, // 675 - { "numval-f", NUMVAL_F }, // 676 - { "occurs", OCCURS }, // 677 - { "of", OF }, // 678 - { "off", OFF }, // 679 - { "omitted", OMITTED }, // 680 - { "on", ON }, // 681 - { "only", ONLY }, // 682 - { "optional", OPTIONAL }, // 683 - { "options", OPTIONS }, // 684 - { "ord", ORD }, // 685 - { "order", ORDER }, // 686 - { "ord-max", ORD_MAX }, // 687 - { "ord-min", ORD_MIN }, // 688 - { "organization", ORGANIZATION }, // 689 - { "other", OTHER }, // 690 - { "otherwise", OTHERWISE }, // 691 - { "output", OUTPUT }, // 692 - { "packed-decimal", PACKED_DECIMAL }, // 693 - { "padding", PADDING }, // 694 - { "page", PAGE }, // 695 - { "page-counter", PAGE_COUNTER }, // 696 - { "pf", PF }, // 697 - { "ph", PH }, // 698 - { "pi", PI }, // 699 - { "pic", PIC }, // 700 - { "picture", PICTURE }, // 701 - { "plus", PLUS }, // 702 - { "present-value", PRESENT_VALUE }, // 703 - { "print-switch", PRINT_SWITCH }, // 704 - { "procedure", PROCEDURE }, // 705 - { "procedures", PROCEDURES }, // 706 - { "proceed", PROCEED }, // 707 - { "process", PROCESS }, // 708 - { "program-id", PROGRAM_ID }, // 709 - { "program", PROGRAM_kw }, // 710 - { "property", PROPERTY }, // 711 - { "prototype", PROTOTYPE }, // 712 - { "pseudotext", PSEUDOTEXT }, // 713 - { "quotes", QUOTES }, // 714 - { "quote", QUOTES }, // 714 - { "random", RANDOM }, // 715 - { "random-seed", RANDOM_SEED }, // 716 - { "range", RANGE }, // 717 - { "raise", RAISE }, // 718 - { "raising", RAISING }, // 719 - { "rd", RD }, // 720 - { "record", RECORD }, // 721 - { "recording", RECORDING }, // 722 - { "records", RECORDS }, // 723 - { "recursive", RECURSIVE }, // 724 - { "redefines", REDEFINES }, // 725 - { "reel", REEL }, // 726 - { "reference", REFERENCE }, // 727 - { "relative", RELATIVE }, // 728 - { "rem", REM }, // 729 - { "remainder", REMAINDER }, // 730 - { "remarks", REMARKS }, // 731 - { "removal", REMOVAL }, // 732 - { "renames", RENAMES }, // 733 - { "replace", REPLACE }, // 734 - { "replacing", REPLACING }, // 735 - { "report", REPORT }, // 736 - { "reporting", REPORTING }, // 737 - { "reports", REPORTS }, // 738 - { "repository", REPOSITORY }, // 739 - { "rerun", RERUN }, // 740 - { "reserve", RESERVE }, // 741 - { "restricted", RESTRICTED }, // 742 - { "resume", RESUME }, // 743 - { "reverse", REVERSE }, // 744 - { "reversed", REVERSED }, // 745 - { "rewind", REWIND }, // 746 - { "rf", RF }, // 747 - { "rh", RH }, // 748 - { "right", RIGHT }, // 749 - { "rounded", ROUNDED }, // 750 - { "run", RUN }, // 751 - { "same", SAME }, // 752 - { "screen", SCREEN }, // 753 - { "sd", SD }, // 754 - { "seconds-from-formatted-time", SECONDS_FROM_FORMATTED_TIME }, // 755 - { "seconds-past-midnight", SECONDS_PAST_MIDNIGHT }, // 756 - { "security", SECURITY }, // 757 - { "separate", SEPARATE }, // 758 - { "sequence", SEQUENCE }, // 759 - { "sequential", SEQUENTIAL }, // 760 - { "sharing", SHARING }, // 761 - { "simple-exit", SIMPLE_EXIT }, // 762 - { "sign", SIGN }, // 763 - { "sin", SIN }, // 764 - { "size", SIZE }, // 765 - { "smallest-algebraic", SMALLEST_ALGEBRAIC }, // 766 - { "source", SOURCE }, // 767 - { "source-computer", SOURCE_COMPUTER }, // 768 - { "special-names", SPECIAL_NAMES }, // 769 - { "sqrt", SQRT }, // 770 - { "stack", STACK }, // 771 - { "standard", STANDARD }, // 772 - { "standard-1", STANDARD_1 }, // 773 - { "standard-deviation", STANDARD_DEVIATION }, // 774 - { "standard-compare", STANDARD_COMPARE }, // 775 - { "status", STATUS }, // 776 - { "strong", STRONG }, // 777 - { "substitute", SUBSTITUTE }, // 778 - { "sum", SUM }, // 779 - { "symbol", SYMBOL }, // 780 - { "symbolic", SYMBOLIC }, // 781 - { "synchronized", SYNCHRONIZED }, // 782 - { "tally", TALLY }, // 783 - { "tallying", TALLYING }, // 784 - { "tan", TAN }, // 785 - { "terminate", TERMINATE }, // 786 - { "test", TEST }, // 787 - { "test-date-yyyymmdd", TEST_DATE_YYYYMMDD }, // 788 - { "test-day-yyyyddd", TEST_DAY_YYYYDDD }, // 789 - { "test-formatted-datetime", TEST_FORMATTED_DATETIME }, // 790 - { "test-numval", TEST_NUMVAL }, // 791 - { "test-numval-c", TEST_NUMVAL_C }, // 792 - { "test-numval-f", TEST_NUMVAL_F }, // 793 - { "than", THAN }, // 794 - { "time", TIME }, // 795 - { "times", TIMES }, // 796 - { "to", TO }, // 797 - { "top", TOP }, // 798 - { "top-level", TOP_LEVEL }, // 799 - { "tracks", TRACKS }, // 800 - { "track-area", TRACK_AREA }, // 801 - { "trailing", TRAILING }, // 802 - { "transform", TRANSFORM }, // 803 - { "trim", TRIM }, // 804 - { "true", TRUE_kw }, // 805 - { "try", TRY }, // 806 - { "turn", TURN }, // 807 - { "type", TYPE }, // 808 - { "typedef", TYPEDEF }, // 809 - { "ulength", ULENGTH }, // 810 - { "unbounded", UNBOUNDED }, // 811 - { "unit", UNIT }, // 812 - { "units", UNITS }, // 813 - { "unit-record", UNIT_RECORD }, // 814 - { "until", UNTIL }, // 815 - { "up", UP }, // 816 - { "upon", UPON }, // 817 - { "upos", UPOS }, // 818 - { "upper-case", UPPER_CASE }, // 819 - { "usage", USAGE }, // 820 - { "using", USING }, // 821 - { "usubstr", USUBSTR }, // 822 - { "usupplementary", USUPPLEMENTARY }, // 823 - { "utility", UTILITY }, // 824 - { "uuid4", UUID4 }, // 825 - { "uvalid", UVALID }, // 826 - { "uwidth", UWIDTH }, // 827 - { "value", VALUE }, // 828 - { "variance", VARIANCE }, // 829 - { "varying", VARYING }, // 830 - { "volatile", VOLATILE }, // 831 - { "when-compiled", WHEN_COMPILED }, // 832 - { "with", WITH }, // 833 - { "working-storage", WORKING_STORAGE }, // 834 - { "xml", XML }, // 835 - { "xmlgenerate", XMLGENERATE }, // 836 - { "xmlparse", XMLPARSE }, // 837 - { "year-to-yyyy", YEAR_TO_YYYY }, // 838 - { "yyyyddd", YYYYDDD }, // 839 - { "yyyymmdd", YYYYMMDD }, // 840 - { "arithmetic", ARITHMETIC }, // 841 - { "attribute", ATTRIBUTE }, // 842 - { "auto", AUTO }, // 843 - { "automatic", AUTOMATIC }, // 844 - { "away-from-zero", AWAY_FROM_ZERO }, // 845 - { "background-color", BACKGROUND_COLOR }, // 846 - { "bell", BELL }, // 847 - { "binary-encoding", BINARY_ENCODING }, // 848 - { "blink", BLINK }, // 849 - { "capacity", CAPACITY }, // 850 - { "center", CENTER }, // 851 - { "classification", CLASSIFICATION }, // 852 - { "cycle", CYCLE }, // 853 - { "decimal-encoding", DECIMAL_ENCODING }, // 854 - { "entry-convention", ENTRY_CONVENTION }, // 855 - { "eol", EOL }, // 856 - { "eos", EOS }, // 857 - { "erase", ERASE }, // 858 - { "expands", EXPANDS }, // 859 - { "float-binary", FLOAT_BINARY }, // 860 - { "float-decimal", FLOAT_DECIMAL }, // 861 - { "foreground-color", FOREGROUND_COLOR }, // 862 - { "forever", FOREVER }, // 863 - { "full", FULL }, // 864 - { "highlight", HIGHLIGHT }, // 865 - { "high-order-left", HIGH_ORDER_LEFT }, // 866 - { "high-order-right", HIGH_ORDER_RIGHT }, // 867 - { "ignoring", IGNORING }, // 868 - { "implements", IMPLEMENTS }, // 869 - { "initialized", INITIALIZED }, // 870 - { "intermediate", INTERMEDIATE }, // 871 - { "lc-all", LC_ALL_kw }, // 872 - { "lc-collate", LC_COLLATE_kw }, // 873 - { "lc-ctype", LC_CTYPE_kw }, // 874 - { "lc-messages", LC_MESSAGES_kw }, // 875 - { "lc-monetary", LC_MONETARY_kw }, // 876 - { "lc-numeric", LC_NUMERIC_kw }, // 877 - { "lc-time", LC_TIME_kw }, // 878 - { "lowlight", LOWLIGHT }, // 879 - { "nearest-away-from-zero", NEAREST_AWAY_FROM_ZERO }, // 880 - { "nearest-even", NEAREST_EVEN }, // 881 - { "nearest-toward-zero", NEAREST_TOWARD_ZERO }, // 882 - { "none", NONE }, // 883 - { "normal", NORMAL }, // 884 - { "numbers", NUMBERS }, // 885 - { "prefixed", PREFIXED }, // 886 - { "previous", PREVIOUS }, // 887 - { "prohibited", PROHIBITED }, // 888 - { "relation", RELATION }, // 889 - { "required", REQUIRED }, // 890 - { "reverse-video", REVERSE_VIDEO }, // 891 - { "rounding", ROUNDING }, // 892 - { "seconds", SECONDS }, // 893 - { "secure", SECURE }, // 894 - { "short", SHORT }, // 895 - { "signed", SIGNED_kw }, // 896 - { "standard-binary", STANDARD_BINARY }, // 897 - { "standard-decimal", STANDARD_DECIMAL }, // 898 - { "statement", STATEMENT }, // 899 - { "step", STEP }, // 900 - { "structure", STRUCTURE }, // 901 - { "toward-greater", TOWARD_GREATER }, // 902 - { "toward-lesser", TOWARD_LESSER }, // 903 - { "truncation", TRUNCATION }, // 904 - { "ucs-4", UCS_4 }, // 905 - { "underline", UNDERLINE }, // 906 - { "unsigned", UNSIGNED_kw }, // 907 - { "utf-16", UTF_16 }, // 908 - { "utf-8", UTF_8 }, // 909 - { "address", ADDRESS }, // 910 - { "end-accept", END_ACCEPT }, // 911 - { "end-add", END_ADD }, // 912 - { "end-call", END_CALL }, // 913 - { "end-compute", END_COMPUTE }, // 914 - { "end-delete", END_DELETE }, // 915 - { "end-display", END_DISPLAY }, // 916 - { "end-divide", END_DIVIDE }, // 917 - { "end-evaluate", END_EVALUATE }, // 918 - { "end-multiply", END_MULTIPLY }, // 919 - { "end-perform", END_PERFORM }, // 920 - { "end-read", END_READ }, // 921 - { "end-return", END_RETURN }, // 922 - { "end-rewrite", END_REWRITE }, // 923 - { "end-search", END_SEARCH }, // 924 - { "end-start", END_START }, // 925 - { "end-string", END_STRING }, // 926 - { "end-subtract", END_SUBTRACT }, // 927 - { "end-unstring", END_UNSTRING }, // 928 - { "end-write", END_WRITE }, // 929 - { "end-if", END_IF }, // 930 - { "thru", THRU }, // 931 - { "through", THRU }, // 931 - { "or", OR }, // 932 - { "and", AND }, // 933 - { "not", NOT }, // 934 - { "ne", NE }, // 935 - { "le", LE }, // 936 - { "ge", GE }, // 937 - { "pow", POW }, // 938 - { "neg", NEG }, // 939 + { "call-convention", CALL_CONVENTION }, // 391 + { "call-cobol", CALL_COBOL }, // 392 + { "call-verbatim", CALL_VERBATIM }, // 393 + { "cdf-push", CDF_PUSH }, // 394 + { "cdf-pop", CDF_POP }, // 395 + { "source-format", SOURCE_FORMAT }, // 396 + { "if", IF }, // 397 + { "then", THEN }, // 398 + { "else", ELSE }, // 399 + { "sentence", SENTENCE }, // 400 + { "accept", ACCEPT }, // 401 + { "add", ADD }, // 402 + { "alter", ALTER }, // 403 + { "call", CALL }, // 404 + { "cancel", CANCEL }, // 405 + { "close", CLOSE }, // 406 + { "compute", COMPUTE }, // 407 + { "continue", CONTINUE }, // 408 + { "delete", DELETE }, // 409 + { "display", DISPLAY }, // 410 + { "divide", DIVIDE }, // 411 + { "evaluate", EVALUATE }, // 412 + { "exit", EXIT }, // 413 + { "filler", FILLER_kw }, // 414 + { "goback", GOBACK }, // 415 + { "goto", GOTO }, // 416 + { "initialize", INITIALIZE }, // 417 + { "inspect", INSPECT }, // 418 + { "merge", MERGE }, // 419 + { "move", MOVE }, // 420 + { "multiply", MULTIPLY }, // 421 + { "open", OPEN }, // 422 + { "paragraph", PARAGRAPH }, // 423 + { "read", READ }, // 424 + { "release", RELEASE }, // 425 + { "return", RETURN }, // 426 + { "rewrite", REWRITE }, // 427 + { "search", SEARCH }, // 428 + { "set", SET }, // 429 + { "select", SELECT }, // 430 + { "sort", SORT }, // 431 + { "sort-merge", SORT_MERGE }, // 432 + { "string", STRING_kw }, // 433 + { "stop", STOP }, // 434 + { "subtract", SUBTRACT }, // 435 + { "start", START }, // 436 + { "unstring", UNSTRING }, // 437 + { "write", WRITE }, // 438 + { "when", WHEN }, // 439 + { "argument-number", ARGUMENT_NUMBER }, // 440 + { "argument-value", ARGUMENT_VALUE }, // 441 + { "environment-name", ENVIRONMENT_NAME }, // 442 + { "environment-value", ENVIRONMENT_VALUE }, // 443 + { "abs", ABS }, // 444 + { "access", ACCESS }, // 445 + { "acos", ACOS }, // 446 + { "actual", ACTUAL }, // 447 + { "advancing", ADVANCING }, // 448 + { "after", AFTER }, // 449 + { "all", ALL }, // 450 + { "allocate", ALLOCATE }, // 451 + { "alphabet", ALPHABET }, // 452 + { "alphabetic", ALPHABETIC }, // 453 + { "alphabetic-lower", ALPHABETIC_LOWER }, // 454 + { "alphabetic-upper", ALPHABETIC_UPPER }, // 455 + { "alphanumeric", ALPHANUMERIC }, // 456 + { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 457 + { "also", ALSO }, // 458 + { "alternate", ALTERNATE }, // 459 + { "annuity", ANNUITY }, // 460 + { "anum", ANUM }, // 461 + { "any", ANY }, // 462 + { "anycase", ANYCASE }, // 463 + { "apply", APPLY }, // 464 + { "are", ARE }, // 465 + { "area", AREA }, // 466 + { "areas", AREAS }, // 467 + { "as", AS }, // 468 + { "ascending", ASCENDING }, // 469 + { "activating", ACTIVATING }, // 470 + { "asin", ASIN }, // 471 + { "assign", ASSIGN }, // 472 + { "at", AT }, // 473 + { "atan", ATAN }, // 474 + { "based", BASED }, // 475 + { "baseconvert", BASECONVERT }, // 476 + { "before", BEFORE }, // 477 + { "binary", BINARY }, // 478 + { "bit", BIT }, // 479 + { "bit-of", BIT_OF }, // 480 + { "bit-to-char", BIT_TO_CHAR }, // 481 + { "blank", BLANK }, // 482 + { "block", BLOCK_kw }, // 483 + { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 484 + { "bottom", BOTTOM }, // 485 + { "by", BY }, // 486 + { "byte", BYTE }, // 487 + { "byte-length", BYTE_LENGTH }, // 488 + { "cf", CF }, // 489 + { "ch", CH }, // 490 + { "changed", CHANGED }, // 491 + { "char", CHAR }, // 492 + { "char-national", CHAR_NATIONAL }, // 493 + { "character", CHARACTER }, // 494 + { "characters", CHARACTERS }, // 495 + { "checking", CHECKING }, // 496 + { "class", CLASS }, // 497 + { "cobol", COBOL }, // 498 + { "code", CODE }, // 499 + { "code-set", CODESET }, // 500 + { "collating", COLLATING }, // 501 + { "column", COLUMN }, // 502 + { "combined-datetime", COMBINED_DATETIME }, // 503 + { "comma", COMMA }, // 504 + { "command-line", COMMAND_LINE }, // 505 + { "command-line-count", COMMAND_LINE_COUNT }, // 506 + { "commit", COMMIT }, // 507 + { "common", COMMON }, // 508 + { "concat", CONCAT }, // 509 + { "condition", CONDITION }, // 510 + { "configuration", CONFIGURATION_SECT }, // 511 + { "contains", CONTAINS }, // 512 + { "content", CONTENT }, // 513 + { "control", CONTROL }, // 514 + { "controls", CONTROLS }, // 515 + { "convert", CONVERT }, // 516 + { "converting", CONVERTING }, // 517 + { "corresponding", CORRESPONDING }, // 518 + { "cos", COS }, // 519 + { "count", COUNT }, // 520 + { "currency", CURRENCY }, // 521 + { "current", CURRENT }, // 522 + { "current-date", CURRENT_DATE }, // 523 + { "data", DATA }, // 524 + { "date", DATE }, // 525 + { "date-compiled", DATE_COMPILED }, // 526 + { "date-of-integer", DATE_OF_INTEGER }, // 527 + { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 528 + { "date-written", DATE_WRITTEN }, // 529 + { "day", DAY }, // 530 + { "day-of-integer", DAY_OF_INTEGER }, // 531 + { "day-of-week", DAY_OF_WEEK }, // 532 + { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 533 + { "dbcs", DBCS }, // 534 + { "de", DE }, // 535 + { "debugging", DEBUGGING }, // 536 + { "decimal-point", DECIMAL_POINT }, // 537 + { "declaratives", DECLARATIVES }, // 538 + { "default", DEFAULT }, // 539 + { "delimited", DELIMITED }, // 540 + { "delimiter", DELIMITER }, // 541 + { "depending", DEPENDING }, // 542 + { "descending", DESCENDING }, // 543 + { "detail", DETAIL }, // 544 + { "direct", DIRECT }, // 545 + { "direct-access", DIRECT_ACCESS }, // 546 + { "down", DOWN }, // 547 + { "duplicates", DUPLICATES }, // 548 + { "dynamic", DYNAMIC }, // 549 + { "e", E }, // 550 + { "ebcdic", EBCDIC }, // 551 + { "ec", EC }, // 552 + { "egcs", EGCS }, // 553 + { "entry", ENTRY }, // 554 + { "environment", ENVIRONMENT }, // 555 + { "equal", EQUAL }, // 556 + { "every", EVERY }, // 557 + { "examine", EXAMINE }, // 558 + { "exhibit", EXHIBIT }, // 559 + { "exp", EXP }, // 560 + { "exp10", EXP10 }, // 561 + { "extend", EXTEND }, // 562 + { "external", EXTERNAL }, // 563 + { "exception-file", EXCEPTION_FILE }, // 564 + { "exception-file-n", EXCEPTION_FILE_N }, // 565 + { "exception-location", EXCEPTION_LOCATION }, // 566 + { "exception-location-n", EXCEPTION_LOCATION_N }, // 567 + { "exception-statement", EXCEPTION_STATEMENT }, // 568 + { "exception-status", EXCEPTION_STATUS }, // 569 + { "factorial", FACTORIAL }, // 570 + { "false", FALSE_kw }, // 571 + { "fd", FD }, // 572 + { "file-control", FILE_CONTROL }, // 573 + { "file", FILE_KW }, // 574 + { "file-limit", FILE_LIMIT }, // 575 + { "final", FINAL }, // 576 + { "finally", FINALLY }, // 577 + { "find-string", FIND_STRING }, // 578 + { "first", FIRST }, // 579 + { "fixed", FIXED }, // 580 + { "footing", FOOTING }, // 581 + { "for", FOR }, // 582 + { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 583 + { "formatted-date", FORMATTED_DATE }, // 584 + { "formatted-datetime", FORMATTED_DATETIME }, // 585 + { "formatted-time", FORMATTED_TIME }, // 586 + { "form-overflow", FORM_OVERFLOW }, // 587 + { "free", FREE }, // 588 + { "fraction-part", FRACTION_PART }, // 589 + { "from", FROM }, // 590 + { "function", FUNCTION }, // 591 + { "generate", GENERATE }, // 592 + { "giving", GIVING }, // 593 + { "global", GLOBAL }, // 594 + { "go", GO }, // 595 + { "group", GROUP }, // 596 + { "heading", HEADING }, // 597 + { "hex", HEX }, // 598 + { "hex-of", HEX_OF }, // 599 + { "hex-to-char", HEX_TO_CHAR }, // 600 + { "high-values", HIGH_VALUES }, // 601 + { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 602 + { "hold", HOLD }, // 603 + { "ibm-360", IBM_360 }, // 604 + { "in", IN }, // 605 + { "include", INCLUDE }, // 606 + { "index", INDEX }, // 607 + { "indexed", INDEXED }, // 608 + { "indicate", INDICATE }, // 609 + { "initial", INITIAL_kw }, // 610 + { "initiate", INITIATE }, // 611 + { "input", INPUT }, // 612 + { "installation", INSTALLATION }, // 613 + { "interface", INTERFACE }, // 614 + { "integer", INTEGER }, // 615 + { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 616 + { "integer-of-date", INTEGER_OF_DATE }, // 617 + { "integer-of-day", INTEGER_OF_DAY }, // 618 + { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 619 + { "integer-part", INTEGER_PART }, // 620 + { "into", INTO }, // 621 + { "intrinsic", INTRINSIC }, // 622 + { "invoke", INVOKE }, // 623 + { "i-o", IO }, // 624 + { "i-o-control", IO_CONTROL }, // 625 + { "is", IS }, // 626 + { "isnt", ISNT }, // 627 + { "kanji", KANJI }, // 628 + { "key", KEY }, // 629 + { "label", LABEL }, // 630 + { "last", LAST }, // 631 + { "leading", LEADING }, // 632 + { "left", LEFT }, // 633 + { "length", LENGTH }, // 634 + { "length-of", LENGTH_OF }, // 635 + { "limit", LIMIT }, // 636 + { "limits", LIMITS }, // 637 + { "line", LINE }, // 638 + { "lines", LINES }, // 639 + { "line-counter", LINE_COUNTER }, // 640 + { "linage", LINAGE }, // 641 + { "linkage", LINKAGE }, // 642 + { "locale", LOCALE }, // 643 + { "locale-compare", LOCALE_COMPARE }, // 644 + { "locale-date", LOCALE_DATE }, // 645 + { "locale-time", LOCALE_TIME }, // 646 + { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 647 + { "local-storage", LOCAL_STORAGE }, // 648 + { "location", LOCATION }, // 649 + { "lock", LOCK }, // 650 + { "lock-on", LOCK_ON }, // 651 + { "log", LOG }, // 652 + { "log10", LOG10 }, // 653 + { "lower-case", LOWER_CASE }, // 654 + { "low-values", LOW_VALUES }, // 655 + { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 656 + { "lparen", LPAREN }, // 657 + { "manual", MANUAL }, // 658 + { "maxx", MAXX }, // 659 + { "mean", MEAN }, // 660 + { "median", MEDIAN }, // 661 + { "midrange", MIDRANGE }, // 662 + { "minn", MINN }, // 663 + { "multiple", MULTIPLE }, // 664 + { "mod", MOD }, // 665 + { "mode", MODE }, // 666 + { "module-name", MODULE_NAME }, // 667 + { "named", NAMED }, // 668 + { "nat", NAT }, // 669 + { "national", NATIONAL }, // 670 + { "national-edited", NATIONAL_EDITED }, // 671 + { "national-of", NATIONAL_OF }, // 672 + { "native", NATIVE }, // 673 + { "nested", NESTED }, // 674 + { "next", NEXT }, // 675 + { "no", NO }, // 676 + { "note", NOTE }, // 677 + { "nulls", NULLS }, // 678 + { "null", NULLS }, // 678 + { "nullptr", NULLPTR }, // 679 + { "numeric", NUMERIC }, // 680 + { "numeric-edited", NUMERIC_EDITED }, // 681 + { "numval", NUMVAL }, // 682 + { "numval-c", NUMVAL_C }, // 683 + { "numval-f", NUMVAL_F }, // 684 + { "occurs", OCCURS }, // 685 + { "of", OF }, // 686 + { "off", OFF }, // 687 + { "omitted", OMITTED }, // 688 + { "on", ON }, // 689 + { "only", ONLY }, // 690 + { "optional", OPTIONAL }, // 691 + { "options", OPTIONS }, // 692 + { "ord", ORD }, // 693 + { "order", ORDER }, // 694 + { "ord-max", ORD_MAX }, // 695 + { "ord-min", ORD_MIN }, // 696 + { "organization", ORGANIZATION }, // 697 + { "other", OTHER }, // 698 + { "otherwise", OTHERWISE }, // 699 + { "output", OUTPUT }, // 700 + { "packed-decimal", PACKED_DECIMAL }, // 701 + { "padding", PADDING }, // 702 + { "page", PAGE }, // 703 + { "page-counter", PAGE_COUNTER }, // 704 + { "pf", PF }, // 705 + { "ph", PH }, // 706 + { "pi", PI }, // 707 + { "pic", PIC }, // 708 + { "picture", PICTURE }, // 709 + { "plus", PLUS }, // 710 + { "present-value", PRESENT_VALUE }, // 711 + { "print-switch", PRINT_SWITCH }, // 712 + { "procedure", PROCEDURE }, // 713 + { "procedures", PROCEDURES }, // 714 + { "proceed", PROCEED }, // 715 + { "process", PROCESS }, // 716 + { "program-id", PROGRAM_ID }, // 717 + { "program", PROGRAM_kw }, // 718 + { "property", PROPERTY }, // 719 + { "prototype", PROTOTYPE }, // 720 + { "pseudotext", PSEUDOTEXT }, // 721 + { "quotes", QUOTES }, // 722 + { "quote", QUOTES }, // 722 + { "random", RANDOM }, // 723 + { "random-seed", RANDOM_SEED }, // 724 + { "range", RANGE }, // 725 + { "raise", RAISE }, // 726 + { "raising", RAISING }, // 727 + { "rd", RD }, // 728 + { "record", RECORD }, // 729 + { "recording", RECORDING }, // 730 + { "records", RECORDS }, // 731 + { "recursive", RECURSIVE }, // 732 + { "redefines", REDEFINES }, // 733 + { "reel", REEL }, // 734 + { "reference", REFERENCE }, // 735 + { "relative", RELATIVE }, // 736 + { "rem", REM }, // 737 + { "remainder", REMAINDER }, // 738 + { "remarks", REMARKS }, // 739 + { "removal", REMOVAL }, // 740 + { "renames", RENAMES }, // 741 + { "replace", REPLACE }, // 742 + { "replacing", REPLACING }, // 743 + { "report", REPORT }, // 744 + { "reporting", REPORTING }, // 745 + { "reports", REPORTS }, // 746 + { "repository", REPOSITORY }, // 747 + { "rerun", RERUN }, // 748 + { "reserve", RESERVE }, // 749 + { "restricted", RESTRICTED }, // 750 + { "resume", RESUME }, // 751 + { "reverse", REVERSE }, // 752 + { "reversed", REVERSED }, // 753 + { "rewind", REWIND }, // 754 + { "rf", RF }, // 755 + { "rh", RH }, // 756 + { "right", RIGHT }, // 757 + { "rounded", ROUNDED }, // 758 + { "run", RUN }, // 759 + { "same", SAME }, // 760 + { "screen", SCREEN }, // 761 + { "sd", SD }, // 762 + { "seconds-from-formatted-time", SECONDS_FROM_FORMATTED_TIME }, // 763 + { "seconds-past-midnight", SECONDS_PAST_MIDNIGHT }, // 764 + { "security", SECURITY }, // 765 + { "separate", SEPARATE }, // 766 + { "sequence", SEQUENCE }, // 767 + { "sequential", SEQUENTIAL }, // 768 + { "sharing", SHARING }, // 769 + { "simple-exit", SIMPLE_EXIT }, // 770 + { "sign", SIGN }, // 771 + { "sin", SIN }, // 772 + { "size", SIZE }, // 773 + { "smallest-algebraic", SMALLEST_ALGEBRAIC }, // 774 + { "source", SOURCE }, // 775 + { "source-computer", SOURCE_COMPUTER }, // 776 + { "special-names", SPECIAL_NAMES }, // 777 + { "sqrt", SQRT }, // 778 + { "stack", STACK }, // 779 + { "standard", STANDARD }, // 780 + { "standard-1", STANDARD_1 }, // 781 + { "standard-deviation", STANDARD_DEVIATION }, // 782 + { "standard-compare", STANDARD_COMPARE }, // 783 + { "status", STATUS }, // 784 + { "strong", STRONG }, // 785 + { "substitute", SUBSTITUTE }, // 786 + { "sum", SUM }, // 787 + { "symbol", SYMBOL }, // 788 + { "symbolic", SYMBOLIC }, // 789 + { "synchronized", SYNCHRONIZED }, // 790 + { "tally", TALLY }, // 791 + { "tallying", TALLYING }, // 792 + { "tan", TAN }, // 793 + { "terminate", TERMINATE }, // 794 + { "test", TEST }, // 795 + { "test-date-yyyymmdd", TEST_DATE_YYYYMMDD }, // 796 + { "test-day-yyyyddd", TEST_DAY_YYYYDDD }, // 797 + { "test-formatted-datetime", TEST_FORMATTED_DATETIME }, // 798 + { "test-numval", TEST_NUMVAL }, // 799 + { "test-numval-c", TEST_NUMVAL_C }, // 800 + { "test-numval-f", TEST_NUMVAL_F }, // 801 + { "than", THAN }, // 802 + { "time", TIME }, // 803 + { "times", TIMES }, // 804 + { "to", TO }, // 805 + { "top", TOP }, // 806 + { "top-level", TOP_LEVEL }, // 807 + { "tracks", TRACKS }, // 808 + { "track-area", TRACK_AREA }, // 809 + { "trailing", TRAILING }, // 810 + { "transform", TRANSFORM }, // 811 + { "trim", TRIM }, // 812 + { "true", TRUE_kw }, // 813 + { "try", TRY }, // 814 + { "turn", TURN }, // 815 + { "type", TYPE }, // 816 + { "typedef", TYPEDEF }, // 817 + { "ulength", ULENGTH }, // 818 + { "unbounded", UNBOUNDED }, // 819 + { "unit", UNIT }, // 820 + { "units", UNITS }, // 821 + { "unit-record", UNIT_RECORD }, // 822 + { "until", UNTIL }, // 823 + { "up", UP }, // 824 + { "upon", UPON }, // 825 + { "upos", UPOS }, // 826 + { "upper-case", UPPER_CASE }, // 827 + { "usage", USAGE }, // 828 + { "using", USING }, // 829 + { "usubstr", USUBSTR }, // 830 + { "usupplementary", USUPPLEMENTARY }, // 831 + { "utility", UTILITY }, // 832 + { "uuid4", UUID4 }, // 833 + { "uvalid", UVALID }, // 834 + { "uwidth", UWIDTH }, // 835 + { "value", VALUE }, // 836 + { "variance", VARIANCE }, // 837 + { "varying", VARYING }, // 838 + { "volatile", VOLATILE }, // 839 + { "when-compiled", WHEN_COMPILED }, // 840 + { "with", WITH }, // 841 + { "working-storage", WORKING_STORAGE }, // 842 + { "xml", XML }, // 843 + { "xmlgenerate", XMLGENERATE }, // 844 + { "xmlparse", XMLPARSE }, // 845 + { "year-to-yyyy", YEAR_TO_YYYY }, // 846 + { "yyyyddd", YYYYDDD }, // 847 + { "yyyymmdd", YYYYMMDD }, // 848 + { "arithmetic", ARITHMETIC }, // 849 + { "attribute", ATTRIBUTE }, // 850 + { "auto", AUTO }, // 851 + { "automatic", AUTOMATIC }, // 852 + { "away-from-zero", AWAY_FROM_ZERO }, // 853 + { "background-color", BACKGROUND_COLOR }, // 854 + { "bell", BELL }, // 855 + { "binary-encoding", BINARY_ENCODING }, // 856 + { "blink", BLINK }, // 857 + { "capacity", CAPACITY }, // 858 + { "center", CENTER }, // 859 + { "classification", CLASSIFICATION }, // 860 + { "cycle", CYCLE }, // 861 + { "decimal-encoding", DECIMAL_ENCODING }, // 862 + { "entry-convention", ENTRY_CONVENTION }, // 863 + { "eol", EOL }, // 864 + { "eos", EOS }, // 865 + { "erase", ERASE }, // 866 + { "expands", EXPANDS }, // 867 + { "float-binary", FLOAT_BINARY }, // 868 + { "float-decimal", FLOAT_DECIMAL }, // 869 + { "foreground-color", FOREGROUND_COLOR }, // 870 + { "forever", FOREVER }, // 871 + { "full", FULL }, // 872 + { "highlight", HIGHLIGHT }, // 873 + { "high-order-left", HIGH_ORDER_LEFT }, // 874 + { "high-order-right", HIGH_ORDER_RIGHT }, // 875 + { "ignoring", IGNORING }, // 876 + { "implements", IMPLEMENTS }, // 877 + { "initialized", INITIALIZED }, // 878 + { "intermediate", INTERMEDIATE }, // 879 + { "lc-all", LC_ALL_kw }, // 880 + { "lc-collate", LC_COLLATE_kw }, // 881 + { "lc-ctype", LC_CTYPE_kw }, // 882 + { "lc-messages", LC_MESSAGES_kw }, // 883 + { "lc-monetary", LC_MONETARY_kw }, // 884 + { "lc-numeric", LC_NUMERIC_kw }, // 885 + { "lc-time", LC_TIME_kw }, // 886 + { "lowlight", LOWLIGHT }, // 887 + { "nearest-away-from-zero", NEAREST_AWAY_FROM_ZERO }, // 888 + { "nearest-even", NEAREST_EVEN }, // 889 + { "nearest-toward-zero", NEAREST_TOWARD_ZERO }, // 890 + { "none", NONE }, // 891 + { "normal", NORMAL }, // 892 + { "numbers", NUMBERS }, // 893 + { "prefixed", PREFIXED }, // 894 + { "previous", PREVIOUS }, // 895 + { "prohibited", PROHIBITED }, // 896 + { "relation", RELATION }, // 897 + { "required", REQUIRED }, // 898 + { "reverse-video", REVERSE_VIDEO }, // 899 + { "rounding", ROUNDING }, // 900 + { "seconds", SECONDS }, // 901 + { "secure", SECURE }, // 902 + { "short", SHORT }, // 903 + { "signed", SIGNED_kw }, // 904 + { "standard-binary", STANDARD_BINARY }, // 905 + { "standard-decimal", STANDARD_DECIMAL }, // 906 + { "statement", STATEMENT }, // 907 + { "step", STEP }, // 908 + { "structure", STRUCTURE }, // 909 + { "toward-greater", TOWARD_GREATER }, // 910 + { "toward-lesser", TOWARD_LESSER }, // 911 + { "truncation", TRUNCATION }, // 912 + { "ucs-4", UCS_4 }, // 913 + { "underline", UNDERLINE }, // 914 + { "unsigned", UNSIGNED_kw }, // 915 + { "utf-16", UTF_16 }, // 916 + { "utf-8", UTF_8 }, // 917 + { "address", ADDRESS }, // 918 + { "end-accept", END_ACCEPT }, // 919 + { "end-add", END_ADD }, // 920 + { "end-call", END_CALL }, // 921 + { "end-compute", END_COMPUTE }, // 922 + { "end-delete", END_DELETE }, // 923 + { "end-display", END_DISPLAY }, // 924 + { "end-divide", END_DIVIDE }, // 925 + { "end-evaluate", END_EVALUATE }, // 926 + { "end-multiply", END_MULTIPLY }, // 927 + { "end-perform", END_PERFORM }, // 928 + { "end-read", END_READ }, // 929 + { "end-return", END_RETURN }, // 930 + { "end-rewrite", END_REWRITE }, // 931 + { "end-search", END_SEARCH }, // 932 + { "end-start", END_START }, // 933 + { "end-string", END_STRING }, // 934 + { "end-subtract", END_SUBTRACT }, // 935 + { "end-unstring", END_UNSTRING }, // 936 + { "end-write", END_WRITE }, // 937 + { "end-if", END_IF }, // 938 + { "thru", THRU }, // 939 + { "through", THRU }, // 939 + { "or", OR }, // 940 + { "and", AND }, // 941 + { "not", NOT }, // 942 + { "ne", NE }, // 943 + { "le", LE }, // 944 + { "ge", GE }, // 945 + { "pow", POW }, // 946 + { "neg", NEG }, // 947 }; // cppcheck-suppress useInitializationList @@ -826,553 +834,561 @@ token_names = { "CDF-EVALUATE", // 130 (388) "CDF-WHEN", // 131 (389) "CDF-END-EVALUATE", // 132 (390) - "CALL-COBOL", // 133 (391) - "CALL-VERBATIM", // 134 (392) - "IF", // 135 (393) - "THEN", // 136 (394) - "ELSE", // 137 (395) - "SENTENCE", // 138 (396) - "ACCEPT", // 139 (397) - "ADD", // 140 (398) - "ALTER", // 141 (399) - "CALL", // 142 (400) - "CANCEL", // 143 (401) - "CLOSE", // 144 (402) - "COMPUTE", // 145 (403) - "CONTINUE", // 146 (404) - "DELETE", // 147 (405) - "DISPLAY", // 148 (406) - "DIVIDE", // 149 (407) - "EVALUATE", // 150 (408) - "EXIT", // 151 (409) - "FILLER", // 152 (410) - "GOBACK", // 153 (411) - "GOTO", // 154 (412) - "INITIALIZE", // 155 (413) - "INSPECT", // 156 (414) - "MERGE", // 157 (415) - "MOVE", // 158 (416) - "MULTIPLY", // 159 (417) - "OPEN", // 160 (418) - "PARAGRAPH", // 161 (419) - "READ", // 162 (420) - "RELEASE", // 163 (421) - "RETURN", // 164 (422) - "REWRITE", // 165 (423) - "SEARCH", // 166 (424) - "SET", // 167 (425) - "SELECT", // 168 (426) - "SORT", // 169 (427) - "SORT-MERGE", // 170 (428) - "STRING", // 171 (429) - "STOP", // 172 (430) - "SUBTRACT", // 173 (431) - "START", // 174 (432) - "UNSTRING", // 175 (433) - "WRITE", // 176 (434) - "WHEN", // 177 (435) - "ABS", // 178 (436) - "ACCESS", // 179 (437) - "ACOS", // 180 (438) - "ACTUAL", // 181 (439) - "ADVANCING", // 182 (440) - "AFTER", // 183 (441) - "ALL", // 184 (442) - "ALLOCATE", // 185 (443) - "ALPHABET", // 186 (444) - "ALPHABETIC", // 187 (445) - "ALPHABETIC-LOWER", // 188 (446) - "ALPHABETIC-UPPER", // 189 (447) - "ALPHANUMERIC", // 190 (448) - "ALPHANUMERIC-EDITED", // 191 (449) - "ALSO", // 192 (450) - "ALTERNATE", // 193 (451) - "ANNUITY", // 194 (452) - "ANUM", // 195 (453) - "ANY", // 196 (454) - "ANYCASE", // 197 (455) - "APPLY", // 198 (456) - "ARE", // 199 (457) - "AREA", // 200 (458) - "AREAS", // 201 (459) - "AS", // 202 (460) - "ASCENDING", // 203 (461) - "ACTIVATING", // 204 (462) - "ASIN", // 205 (463) - "ASSIGN", // 206 (464) - "AT", // 207 (465) - "ATAN", // 208 (466) - "BASED", // 209 (467) - "BASECONVERT", // 210 (468) - "BEFORE", // 211 (469) - "BINARY", // 212 (470) - "BIT", // 213 (471) - "BIT-OF", // 214 (472) - "BIT-TO-CHAR", // 215 (473) - "BLANK", // 216 (474) - "BLOCK", // 217 (475) - "BOOLEAN-OF-INTEGER", // 218 (476) - "BOTTOM", // 219 (477) - "BY", // 220 (478) - "BYTE", // 221 (479) - "BYTE-LENGTH", // 222 (480) - "CF", // 223 (481) - "CH", // 224 (482) - "CHANGED", // 225 (483) - "CHAR", // 226 (484) - "CHAR-NATIONAL", // 227 (485) - "CHARACTER", // 228 (486) - "CHARACTERS", // 229 (487) - "CHECKING", // 230 (488) - "CLASS", // 231 (489) - "COBOL", // 232 (490) - "CODE", // 233 (491) - "CODE-SET", // 234 (492) - "COLLATING", // 235 (493) - "COLUMN", // 236 (494) - "COMBINED-DATETIME", // 237 (495) - "COMMA", // 238 (496) - "COMMAND-LINE", // 239 (497) - "COMMAND-LINE-COUNT", // 240 (498) - "COMMIT", // 241 (499) - "COMMON", // 242 (500) - "CONCAT", // 243 (501) - "CONDITION", // 244 (502) - "CONFIGURATION", // 245 (503) - "CONTAINS", // 246 (504) - "CONTENT", // 247 (505) - "CONTROL", // 248 (506) - "CONTROLS", // 249 (507) - "CONVERT", // 250 (508) - "CONVERTING", // 251 (509) - "CORRESPONDING", // 252 (510) - "COS", // 253 (511) - "COUNT", // 254 (512) - "CURRENCY", // 255 (513) - "CURRENT", // 256 (514) - "CURRENT-DATE", // 257 (515) - "DATA", // 258 (516) - "DATE", // 259 (517) - "DATE-COMPILED", // 260 (518) - "DATE-OF-INTEGER", // 261 (519) - "DATE-TO-YYYYMMDD", // 262 (520) - "DATE-WRITTEN", // 263 (521) - "DAY", // 264 (522) - "DAY-OF-INTEGER", // 265 (523) - "DAY-OF-WEEK", // 266 (524) - "DAY-TO-YYYYDDD", // 267 (525) - "DBCS", // 268 (526) - "DE", // 269 (527) - "DEBUGGING", // 270 (528) - "DECIMAL-POINT", // 271 (529) - "DECLARATIVES", // 272 (530) - "DEFAULT", // 273 (531) - "DELIMITED", // 274 (532) - "DELIMITER", // 275 (533) - "DEPENDING", // 276 (534) - "DESCENDING", // 277 (535) - "DETAIL", // 278 (536) - "DIRECT", // 279 (537) - "DIRECT-ACCESS", // 280 (538) - "DOWN", // 281 (539) - "DUPLICATES", // 282 (540) - "DYNAMIC", // 283 (541) - "E", // 284 (542) - "EBCDIC", // 285 (543) - "EC", // 286 (544) - "EGCS", // 287 (545) - "ENTRY", // 288 (546) - "ENVIRONMENT", // 289 (547) - "EQUAL", // 290 (548) - "EVERY", // 291 (549) - "EXAMINE", // 292 (550) - "EXHIBIT", // 293 (551) - "EXP", // 294 (552) - "EXP10", // 295 (553) - "EXTEND", // 296 (554) - "EXTERNAL", // 297 (555) - "EXCEPTION-FILE", // 298 (556) - "EXCEPTION-FILE-N", // 299 (557) - "EXCEPTION-LOCATION", // 300 (558) - "EXCEPTION-LOCATION-N", // 301 (559) - "EXCEPTION-STATEMENT", // 302 (560) - "EXCEPTION-STATUS", // 303 (561) - "FACTORIAL", // 304 (562) - "FALSE", // 305 (563) - "FD", // 306 (564) - "FILE-CONTROL", // 307 (565) - "FILE", // 308 (566) - "FILE-LIMIT", // 309 (567) - "FINAL", // 310 (568) - "FINALLY", // 311 (569) - "FIND-STRING", // 312 (570) - "FIRST", // 313 (571) - "FIXED", // 314 (572) - "FOOTING", // 315 (573) - "FOR", // 316 (574) - "FORMATTED-CURRENT-DATE", // 317 (575) - "FORMATTED-DATE", // 318 (576) - "FORMATTED-DATETIME", // 319 (577) - "FORMATTED-TIME", // 320 (578) - "FORM-OVERFLOW", // 321 (579) - "FREE", // 322 (580) - "FRACTION-PART", // 323 (581) - "FROM", // 324 (582) - "FUNCTION", // 325 (583) - "GENERATE", // 326 (584) - "GIVING", // 327 (585) - "GLOBAL", // 328 (586) - "GO", // 329 (587) - "GROUP", // 330 (588) - "HEADING", // 331 (589) - "HEX", // 332 (590) - "HEX-OF", // 333 (591) - "HEX-TO-CHAR", // 334 (592) - "HIGH-VALUES", // 335 (593) - "HIGHEST-ALGEBRAIC", // 336 (594) - "HOLD", // 337 (595) - "IBM-360", // 338 (596) - "IN", // 339 (597) - "INCLUDE", // 340 (598) - "INDEX", // 341 (599) - "INDEXED", // 342 (600) - "INDICATE", // 343 (601) - "INITIAL", // 344 (602) - "INITIATE", // 345 (603) - "INPUT", // 346 (604) - "INSTALLATION", // 347 (605) - "INTERFACE", // 348 (606) - "INTEGER", // 349 (607) - "INTEGER-OF-BOOLEAN", // 350 (608) - "INTEGER-OF-DATE", // 351 (609) - "INTEGER-OF-DAY", // 352 (610) - "INTEGER-OF-FORMATTED-DATE", // 353 (611) - "INTEGER-PART", // 354 (612) - "INTO", // 355 (613) - "INTRINSIC", // 356 (614) - "INVOKE", // 357 (615) - "I-O", // 358 (616) - "I-O-CONTROL", // 359 (617) - "IS", // 360 (618) - "ISNT", // 361 (619) - "KANJI", // 362 (620) - "KEY", // 363 (621) - "LABEL", // 364 (622) - "LAST", // 365 (623) - "LEADING", // 366 (624) - "LEFT", // 367 (625) - "LENGTH", // 368 (626) - "LENGTH-OF", // 369 (627) - "LIMIT", // 370 (628) - "LIMITS", // 371 (629) - "LINE", // 372 (630) - "LINES", // 373 (631) - "LINE-COUNTER", // 374 (632) - "LINAGE", // 375 (633) - "LINKAGE", // 376 (634) - "LOCALE", // 377 (635) - "LOCALE-COMPARE", // 378 (636) - "LOCALE-DATE", // 379 (637) - "LOCALE-TIME", // 380 (638) - "LOCALE-TIME-FROM-SECONDS", // 381 (639) - "LOCAL-STORAGE", // 382 (640) - "LOCATION", // 383 (641) - "LOCK", // 384 (642) - "LOCK-ON", // 385 (643) - "LOG", // 386 (644) - "LOG10", // 387 (645) - "LOWER-CASE", // 388 (646) - "LOW-VALUES", // 389 (647) - "LOWEST-ALGEBRAIC", // 390 (648) - "LPAREN", // 391 (649) - "MANUAL", // 392 (650) - "MAXX", // 393 (651) - "MEAN", // 394 (652) - "MEDIAN", // 395 (653) - "MIDRANGE", // 396 (654) - "MINN", // 397 (655) - "MULTIPLE", // 398 (656) - "MOD", // 399 (657) - "MODE", // 400 (658) - "MODULE-NAME", // 401 (659) - "NAMED", // 402 (660) - "NAT", // 403 (661) - "NATIONAL", // 404 (662) - "NATIONAL-EDITED", // 405 (663) - "NATIONAL-OF", // 406 (664) - "NATIVE", // 407 (665) - "NESTED", // 408 (666) - "NEXT", // 409 (667) - "NO", // 410 (668) - "NOTE", // 411 (669) - "NULLS", // 412 (670) - "NULLPTR", // 413 (671) - "NUMERIC", // 414 (672) - "NUMERIC-EDITED", // 415 (673) - "NUMVAL", // 416 (674) - "NUMVAL-C", // 417 (675) - "NUMVAL-F", // 418 (676) - "OCCURS", // 419 (677) - "OF", // 420 (678) - "OFF", // 421 (679) - "OMITTED", // 422 (680) - "ON", // 423 (681) - "ONLY", // 424 (682) - "OPTIONAL", // 425 (683) - "OPTIONS", // 426 (684) - "ORD", // 427 (685) - "ORDER", // 428 (686) - "ORD-MAX", // 429 (687) - "ORD-MIN", // 430 (688) - "ORGANIZATION", // 431 (689) - "OTHER", // 432 (690) - "OTHERWISE", // 433 (691) - "OUTPUT", // 434 (692) - "PACKED-DECIMAL", // 435 (693) - "PADDING", // 436 (694) - "PAGE", // 437 (695) - "PAGE-COUNTER", // 438 (696) - "PF", // 439 (697) - "PH", // 440 (698) - "PI", // 441 (699) - "PIC", // 442 (700) - "PICTURE", // 443 (701) - "PLUS", // 444 (702) - "PRESENT-VALUE", // 445 (703) - "PRINT-SWITCH", // 446 (704) - "PROCEDURE", // 447 (705) - "PROCEDURES", // 448 (706) - "PROCEED", // 449 (707) - "PROCESS", // 450 (708) - "PROGRAM-ID", // 451 (709) - "PROGRAM", // 452 (710) - "PROPERTY", // 453 (711) - "PROTOTYPE", // 454 (712) - "PSEUDOTEXT", // 455 (713) - "QUOTES", // 456 (714) - "RANDOM", // 457 (715) - "RANDOM-SEED", // 458 (716) - "RANGE", // 459 (717) - "RAISE", // 460 (718) - "RAISING", // 461 (719) - "RD", // 462 (720) - "RECORD", // 463 (721) - "RECORDING", // 464 (722) - "RECORDS", // 465 (723) - "RECURSIVE", // 466 (724) - "REDEFINES", // 467 (725) - "REEL", // 468 (726) - "REFERENCE", // 469 (727) - "RELATIVE", // 470 (728) - "REM", // 471 (729) - "REMAINDER", // 472 (730) - "REMARKS", // 473 (731) - "REMOVAL", // 474 (732) - "RENAMES", // 475 (733) - "REPLACE", // 476 (734) - "REPLACING", // 477 (735) - "REPORT", // 478 (736) - "REPORTING", // 479 (737) - "REPORTS", // 480 (738) - "REPOSITORY", // 481 (739) - "RERUN", // 482 (740) - "RESERVE", // 483 (741) - "RESTRICTED", // 484 (742) - "RESUME", // 485 (743) - "REVERSE", // 486 (744) - "REVERSED", // 487 (745) - "REWIND", // 488 (746) - "RF", // 489 (747) - "RH", // 490 (748) - "RIGHT", // 491 (749) - "ROUNDED", // 492 (750) - "RUN", // 493 (751) - "SAME", // 494 (752) - "SCREEN", // 495 (753) - "SD", // 496 (754) - "SECONDS-FROM-FORMATTED-TIME", // 497 (755) - "SECONDS-PAST-MIDNIGHT", // 498 (756) - "SECURITY", // 499 (757) - "SEPARATE", // 500 (758) - "SEQUENCE", // 501 (759) - "SEQUENTIAL", // 502 (760) - "SHARING", // 503 (761) - "SIMPLE-EXIT", // 504 (762) - "SIGN", // 505 (763) - "SIN", // 506 (764) - "SIZE", // 507 (765) - "SMALLEST-ALGEBRAIC", // 508 (766) - "SOURCE", // 509 (767) - "SOURCE-COMPUTER", // 510 (768) - "SPECIAL-NAMES", // 511 (769) - "SQRT", // 512 (770) - "STACK", // 513 (771) - "STANDARD", // 514 (772) - "STANDARD-1", // 515 (773) - "STANDARD-DEVIATION", // 516 (774) - "STANDARD-COMPARE", // 517 (775) - "STATUS", // 518 (776) - "STRONG", // 519 (777) - "SUBSTITUTE", // 520 (778) - "SUM", // 521 (779) - "SYMBOL", // 522 (780) - "SYMBOLIC", // 523 (781) - "SYNCHRONIZED", // 524 (782) - "TALLY", // 525 (783) - "TALLYING", // 526 (784) - "TAN", // 527 (785) - "TERMINATE", // 528 (786) - "TEST", // 529 (787) - "TEST-DATE-YYYYMMDD", // 530 (788) - "TEST-DAY-YYYYDDD", // 531 (789) - "TEST-FORMATTED-DATETIME", // 532 (790) - "TEST-NUMVAL", // 533 (791) - "TEST-NUMVAL-C", // 534 (792) - "TEST-NUMVAL-F", // 535 (793) - "THAN", // 536 (794) - "TIME", // 537 (795) - "TIMES", // 538 (796) - "TO", // 539 (797) - "TOP", // 540 (798) - "TOP-LEVEL", // 541 (799) - "TRACKS", // 542 (800) - "TRACK-AREA", // 543 (801) - "TRAILING", // 544 (802) - "TRANSFORM", // 545 (803) - "TRIM", // 546 (804) - "TRUE", // 547 (805) - "TRY", // 548 (806) - "TURN", // 549 (807) - "TYPE", // 550 (808) - "TYPEDEF", // 551 (809) - "ULENGTH", // 552 (810) - "UNBOUNDED", // 553 (811) - "UNIT", // 554 (812) - "UNITS", // 555 (813) - "UNIT-RECORD", // 556 (814) - "UNTIL", // 557 (815) - "UP", // 558 (816) - "UPON", // 559 (817) - "UPOS", // 560 (818) - "UPPER-CASE", // 561 (819) - "USAGE", // 562 (820) - "USING", // 563 (821) - "USUBSTR", // 564 (822) - "USUPPLEMENTARY", // 565 (823) - "UTILITY", // 566 (824) - "UUID4", // 567 (825) - "UVALID", // 568 (826) - "UWIDTH", // 569 (827) - "VALUE", // 570 (828) - "VARIANCE", // 571 (829) - "VARYING", // 572 (830) - "VOLATILE", // 573 (831) - "WHEN-COMPILED", // 574 (832) - "WITH", // 575 (833) - "WORKING-STORAGE", // 576 (834) - "XML", // 577 (835) - "XMLGENERATE", // 578 (836) - "XMLPARSE", // 579 (837) - "YEAR-TO-YYYY", // 580 (838) - "YYYYDDD", // 581 (839) - "YYYYMMDD", // 582 (840) - "ARITHMETIC", // 583 (841) - "ATTRIBUTE", // 584 (842) - "AUTO", // 585 (843) - "AUTOMATIC", // 586 (844) - "AWAY-FROM-ZERO", // 587 (845) - "BACKGROUND-COLOR", // 588 (846) - "BELL", // 589 (847) - "BINARY-ENCODING", // 590 (848) - "BLINK", // 591 (849) - "CAPACITY", // 592 (850) - "CENTER", // 593 (851) - "CLASSIFICATION", // 594 (852) - "CYCLE", // 595 (853) - "DECIMAL-ENCODING", // 596 (854) - "ENTRY-CONVENTION", // 597 (855) - "EOL", // 598 (856) - "EOS", // 599 (857) - "ERASE", // 600 (858) - "EXPANDS", // 601 (859) - "FLOAT-BINARY", // 602 (860) - "FLOAT-DECIMAL", // 603 (861) - "FOREGROUND-COLOR", // 604 (862) - "FOREVER", // 605 (863) - "FULL", // 606 (864) - "HIGHLIGHT", // 607 (865) - "HIGH-ORDER-LEFT", // 608 (866) - "HIGH-ORDER-RIGHT", // 609 (867) - "IGNORING", // 610 (868) - "IMPLEMENTS", // 611 (869) - "INITIALIZED", // 612 (870) - "INTERMEDIATE", // 613 (871) - "LC-ALL", // 614 (872) - "LC-COLLATE", // 615 (873) - "LC-CTYPE", // 616 (874) - "LC-MESSAGES", // 617 (875) - "LC-MONETARY", // 618 (876) - "LC-NUMERIC", // 619 (877) - "LC-TIME", // 620 (878) - "LOWLIGHT", // 621 (879) - "NEAREST-AWAY-FROM-ZERO", // 622 (880) - "NEAREST-EVEN", // 623 (881) - "NEAREST-TOWARD-ZERO", // 624 (882) - "NONE", // 625 (883) - "NORMAL", // 626 (884) - "NUMBERS", // 627 (885) - "PREFIXED", // 628 (886) - "PREVIOUS", // 629 (887) - "PROHIBITED", // 630 (888) - "RELATION", // 631 (889) - "REQUIRED", // 632 (890) - "REVERSE-VIDEO", // 633 (891) - "ROUNDING", // 634 (892) - "SECONDS", // 635 (893) - "SECURE", // 636 (894) - "SHORT", // 637 (895) - "SIGNED", // 638 (896) - "STANDARD-BINARY", // 639 (897) - "STANDARD-DECIMAL", // 640 (898) - "STATEMENT", // 641 (899) - "STEP", // 642 (900) - "STRUCTURE", // 643 (901) - "TOWARD-GREATER", // 644 (902) - "TOWARD-LESSER", // 645 (903) - "TRUNCATION", // 646 (904) - "UCS-4", // 647 (905) - "UNDERLINE", // 648 (906) - "UNSIGNED", // 649 (907) - "UTF-16", // 650 (908) - "UTF-8", // 651 (909) - "ADDRESS", // 652 (910) - "END-ACCEPT", // 653 (911) - "END-ADD", // 654 (912) - "END-CALL", // 655 (913) - "END-COMPUTE", // 656 (914) - "END-DELETE", // 657 (915) - "END-DISPLAY", // 658 (916) - "END-DIVIDE", // 659 (917) - "END-EVALUATE", // 660 (918) - "END-MULTIPLY", // 661 (919) - "END-PERFORM", // 662 (920) - "END-READ", // 663 (921) - "END-RETURN", // 664 (922) - "END-REWRITE", // 665 (923) - "END-SEARCH", // 666 (924) - "END-START", // 667 (925) - "END-STRING", // 668 (926) - "END-SUBTRACT", // 669 (927) - "END-UNSTRING", // 670 (928) - "END-WRITE", // 671 (929) - "END-IF", // 672 (930) - "THRU", // 673 (931) - "OR", // 674 (932) - "AND", // 675 (933) - "NOT", // 676 (934) - "NE", // 677 (935) - "LE", // 678 (936) - "GE", // 679 (937) - "POW", // 680 (938) - "NEG", // 681 (939) + "CALL-CONVENTION", // 133 (391) + "CALL-COBOL", // 134 (392) + "CALL-VERBATIM", // 135 (393) + "CDF-PUSH", // 136 (394) + "CDF-POP", // 137 (395) + "SOURCE-FORMAT", // 138 (396) + "IF", // 139 (397) + "THEN", // 140 (398) + "ELSE", // 141 (399) + "SENTENCE", // 142 (400) + "ACCEPT", // 143 (401) + "ADD", // 144 (402) + "ALTER", // 145 (403) + "CALL", // 146 (404) + "CANCEL", // 147 (405) + "CLOSE", // 148 (406) + "COMPUTE", // 149 (407) + "CONTINUE", // 150 (408) + "DELETE", // 151 (409) + "DISPLAY", // 152 (410) + "DIVIDE", // 153 (411) + "EVALUATE", // 154 (412) + "EXIT", // 155 (413) + "FILLER", // 156 (414) + "GOBACK", // 157 (415) + "GOTO", // 158 (416) + "INITIALIZE", // 159 (417) + "INSPECT", // 160 (418) + "MERGE", // 161 (419) + "MOVE", // 162 (420) + "MULTIPLY", // 163 (421) + "OPEN", // 164 (422) + "PARAGRAPH", // 165 (423) + "READ", // 166 (424) + "RELEASE", // 167 (425) + "RETURN", // 168 (426) + "REWRITE", // 169 (427) + "SEARCH", // 170 (428) + "SET", // 171 (429) + "SELECT", // 172 (430) + "SORT", // 173 (431) + "SORT-MERGE", // 174 (432) + "STRING", // 175 (433) + "STOP", // 176 (434) + "SUBTRACT", // 177 (435) + "START", // 178 (436) + "UNSTRING", // 179 (437) + "WRITE", // 180 (438) + "WHEN", // 181 (439) + "ARGUMENT-NUMBER", // 182 (440) + "ARGUMENT-VALUE", // 183 (441) + "ENVIRONMENT-NAME", // 184 (442) + "ENVIRONMENT-VALUE", // 185 (443) + "ABS", // 186 (444) + "ACCESS", // 187 (445) + "ACOS", // 188 (446) + "ACTUAL", // 189 (447) + "ADVANCING", // 190 (448) + "AFTER", // 191 (449) + "ALL", // 192 (450) + "ALLOCATE", // 193 (451) + "ALPHABET", // 194 (452) + "ALPHABETIC", // 195 (453) + "ALPHABETIC-LOWER", // 196 (454) + "ALPHABETIC-UPPER", // 197 (455) + "ALPHANUMERIC", // 198 (456) + "ALPHANUMERIC-EDITED", // 199 (457) + "ALSO", // 200 (458) + "ALTERNATE", // 201 (459) + "ANNUITY", // 202 (460) + "ANUM", // 203 (461) + "ANY", // 204 (462) + "ANYCASE", // 205 (463) + "APPLY", // 206 (464) + "ARE", // 207 (465) + "AREA", // 208 (466) + "AREAS", // 209 (467) + "AS", // 210 (468) + "ASCENDING", // 211 (469) + "ACTIVATING", // 212 (470) + "ASIN", // 213 (471) + "ASSIGN", // 214 (472) + "AT", // 215 (473) + "ATAN", // 216 (474) + "BASED", // 217 (475) + "BASECONVERT", // 218 (476) + "BEFORE", // 219 (477) + "BINARY", // 220 (478) + "BIT", // 221 (479) + "BIT-OF", // 222 (480) + "BIT-TO-CHAR", // 223 (481) + "BLANK", // 224 (482) + "BLOCK", // 225 (483) + "BOOLEAN-OF-INTEGER", // 226 (484) + "BOTTOM", // 227 (485) + "BY", // 228 (486) + "BYTE", // 229 (487) + "BYTE-LENGTH", // 230 (488) + "CF", // 231 (489) + "CH", // 232 (490) + "CHANGED", // 233 (491) + "CHAR", // 234 (492) + "CHAR-NATIONAL", // 235 (493) + "CHARACTER", // 236 (494) + "CHARACTERS", // 237 (495) + "CHECKING", // 238 (496) + "CLASS", // 239 (497) + "COBOL", // 240 (498) + "CODE", // 241 (499) + "CODE-SET", // 242 (500) + "COLLATING", // 243 (501) + "COLUMN", // 244 (502) + "COMBINED-DATETIME", // 245 (503) + "COMMA", // 246 (504) + "COMMAND-LINE", // 247 (505) + "COMMAND-LINE-COUNT", // 248 (506) + "COMMIT", // 249 (507) + "COMMON", // 250 (508) + "CONCAT", // 251 (509) + "CONDITION", // 252 (510) + "CONFIGURATION", // 253 (511) + "CONTAINS", // 254 (512) + "CONTENT", // 255 (513) + "CONTROL", // 256 (514) + "CONTROLS", // 257 (515) + "CONVERT", // 258 (516) + "CONVERTING", // 259 (517) + "CORRESPONDING", // 260 (518) + "COS", // 261 (519) + "COUNT", // 262 (520) + "CURRENCY", // 263 (521) + "CURRENT", // 264 (522) + "CURRENT-DATE", // 265 (523) + "DATA", // 266 (524) + "DATE", // 267 (525) + "DATE-COMPILED", // 268 (526) + "DATE-OF-INTEGER", // 269 (527) + "DATE-TO-YYYYMMDD", // 270 (528) + "DATE-WRITTEN", // 271 (529) + "DAY", // 272 (530) + "DAY-OF-INTEGER", // 273 (531) + "DAY-OF-WEEK", // 274 (532) + "DAY-TO-YYYYDDD", // 275 (533) + "DBCS", // 276 (534) + "DE", // 277 (535) + "DEBUGGING", // 278 (536) + "DECIMAL-POINT", // 279 (537) + "DECLARATIVES", // 280 (538) + "DEFAULT", // 281 (539) + "DELIMITED", // 282 (540) + "DELIMITER", // 283 (541) + "DEPENDING", // 284 (542) + "DESCENDING", // 285 (543) + "DETAIL", // 286 (544) + "DIRECT", // 287 (545) + "DIRECT-ACCESS", // 288 (546) + "DOWN", // 289 (547) + "DUPLICATES", // 290 (548) + "DYNAMIC", // 291 (549) + "E", // 292 (550) + "EBCDIC", // 293 (551) + "EC", // 294 (552) + "EGCS", // 295 (553) + "ENTRY", // 296 (554) + "ENVIRONMENT", // 297 (555) + "EQUAL", // 298 (556) + "EVERY", // 299 (557) + "EXAMINE", // 300 (558) + "EXHIBIT", // 301 (559) + "EXP", // 302 (560) + "EXP10", // 303 (561) + "EXTEND", // 304 (562) + "EXTERNAL", // 305 (563) + "EXCEPTION-FILE", // 306 (564) + "EXCEPTION-FILE-N", // 307 (565) + "EXCEPTION-LOCATION", // 308 (566) + "EXCEPTION-LOCATION-N", // 309 (567) + "EXCEPTION-STATEMENT", // 310 (568) + "EXCEPTION-STATUS", // 311 (569) + "FACTORIAL", // 312 (570) + "FALSE", // 313 (571) + "FD", // 314 (572) + "FILE-CONTROL", // 315 (573) + "FILE", // 316 (574) + "FILE-LIMIT", // 317 (575) + "FINAL", // 318 (576) + "FINALLY", // 319 (577) + "FIND-STRING", // 320 (578) + "FIRST", // 321 (579) + "FIXED", // 322 (580) + "FOOTING", // 323 (581) + "FOR", // 324 (582) + "FORMATTED-CURRENT-DATE", // 325 (583) + "FORMATTED-DATE", // 326 (584) + "FORMATTED-DATETIME", // 327 (585) + "FORMATTED-TIME", // 328 (586) + "FORM-OVERFLOW", // 329 (587) + "FREE", // 330 (588) + "FRACTION-PART", // 331 (589) + "FROM", // 332 (590) + "FUNCTION", // 333 (591) + "GENERATE", // 334 (592) + "GIVING", // 335 (593) + "GLOBAL", // 336 (594) + "GO", // 337 (595) + "GROUP", // 338 (596) + "HEADING", // 339 (597) + "HEX", // 340 (598) + "HEX-OF", // 341 (599) + "HEX-TO-CHAR", // 342 (600) + "HIGH-VALUES", // 343 (601) + "HIGHEST-ALGEBRAIC", // 344 (602) + "HOLD", // 345 (603) + "IBM-360", // 346 (604) + "IN", // 347 (605) + "INCLUDE", // 348 (606) + "INDEX", // 349 (607) + "INDEXED", // 350 (608) + "INDICATE", // 351 (609) + "INITIAL", // 352 (610) + "INITIATE", // 353 (611) + "INPUT", // 354 (612) + "INSTALLATION", // 355 (613) + "INTERFACE", // 356 (614) + "INTEGER", // 357 (615) + "INTEGER-OF-BOOLEAN", // 358 (616) + "INTEGER-OF-DATE", // 359 (617) + "INTEGER-OF-DAY", // 360 (618) + "INTEGER-OF-FORMATTED-DATE", // 361 (619) + "INTEGER-PART", // 362 (620) + "INTO", // 363 (621) + "INTRINSIC", // 364 (622) + "INVOKE", // 365 (623) + "I-O", // 366 (624) + "I-O-CONTROL", // 367 (625) + "IS", // 368 (626) + "ISNT", // 369 (627) + "KANJI", // 370 (628) + "KEY", // 371 (629) + "LABEL", // 372 (630) + "LAST", // 373 (631) + "LEADING", // 374 (632) + "LEFT", // 375 (633) + "LENGTH", // 376 (634) + "LENGTH-OF", // 377 (635) + "LIMIT", // 378 (636) + "LIMITS", // 379 (637) + "LINE", // 380 (638) + "LINES", // 381 (639) + "LINE-COUNTER", // 382 (640) + "LINAGE", // 383 (641) + "LINKAGE", // 384 (642) + "LOCALE", // 385 (643) + "LOCALE-COMPARE", // 386 (644) + "LOCALE-DATE", // 387 (645) + "LOCALE-TIME", // 388 (646) + "LOCALE-TIME-FROM-SECONDS", // 389 (647) + "LOCAL-STORAGE", // 390 (648) + "LOCATION", // 391 (649) + "LOCK", // 392 (650) + "LOCK-ON", // 393 (651) + "LOG", // 394 (652) + "LOG10", // 395 (653) + "LOWER-CASE", // 396 (654) + "LOW-VALUES", // 397 (655) + "LOWEST-ALGEBRAIC", // 398 (656) + "LPAREN", // 399 (657) + "MANUAL", // 400 (658) + "MAXX", // 401 (659) + "MEAN", // 402 (660) + "MEDIAN", // 403 (661) + "MIDRANGE", // 404 (662) + "MINN", // 405 (663) + "MULTIPLE", // 406 (664) + "MOD", // 407 (665) + "MODE", // 408 (666) + "MODULE-NAME", // 409 (667) + "NAMED", // 410 (668) + "NAT", // 411 (669) + "NATIONAL", // 412 (670) + "NATIONAL-EDITED", // 413 (671) + "NATIONAL-OF", // 414 (672) + "NATIVE", // 415 (673) + "NESTED", // 416 (674) + "NEXT", // 417 (675) + "NO", // 418 (676) + "NOTE", // 419 (677) + "NULLS", // 420 (678) + "NULLPTR", // 421 (679) + "NUMERIC", // 422 (680) + "NUMERIC-EDITED", // 423 (681) + "NUMVAL", // 424 (682) + "NUMVAL-C", // 425 (683) + "NUMVAL-F", // 426 (684) + "OCCURS", // 427 (685) + "OF", // 428 (686) + "OFF", // 429 (687) + "OMITTED", // 430 (688) + "ON", // 431 (689) + "ONLY", // 432 (690) + "OPTIONAL", // 433 (691) + "OPTIONS", // 434 (692) + "ORD", // 435 (693) + "ORDER", // 436 (694) + "ORD-MAX", // 437 (695) + "ORD-MIN", // 438 (696) + "ORGANIZATION", // 439 (697) + "OTHER", // 440 (698) + "OTHERWISE", // 441 (699) + "OUTPUT", // 442 (700) + "PACKED-DECIMAL", // 443 (701) + "PADDING", // 444 (702) + "PAGE", // 445 (703) + "PAGE-COUNTER", // 446 (704) + "PF", // 447 (705) + "PH", // 448 (706) + "PI", // 449 (707) + "PIC", // 450 (708) + "PICTURE", // 451 (709) + "PLUS", // 452 (710) + "PRESENT-VALUE", // 453 (711) + "PRINT-SWITCH", // 454 (712) + "PROCEDURE", // 455 (713) + "PROCEDURES", // 456 (714) + "PROCEED", // 457 (715) + "PROCESS", // 458 (716) + "PROGRAM-ID", // 459 (717) + "PROGRAM", // 460 (718) + "PROPERTY", // 461 (719) + "PROTOTYPE", // 462 (720) + "PSEUDOTEXT", // 463 (721) + "QUOTES", // 464 (722) + "RANDOM", // 465 (723) + "RANDOM-SEED", // 466 (724) + "RANGE", // 467 (725) + "RAISE", // 468 (726) + "RAISING", // 469 (727) + "RD", // 470 (728) + "RECORD", // 471 (729) + "RECORDING", // 472 (730) + "RECORDS", // 473 (731) + "RECURSIVE", // 474 (732) + "REDEFINES", // 475 (733) + "REEL", // 476 (734) + "REFERENCE", // 477 (735) + "RELATIVE", // 478 (736) + "REM", // 479 (737) + "REMAINDER", // 480 (738) + "REMARKS", // 481 (739) + "REMOVAL", // 482 (740) + "RENAMES", // 483 (741) + "REPLACE", // 484 (742) + "REPLACING", // 485 (743) + "REPORT", // 486 (744) + "REPORTING", // 487 (745) + "REPORTS", // 488 (746) + "REPOSITORY", // 489 (747) + "RERUN", // 490 (748) + "RESERVE", // 491 (749) + "RESTRICTED", // 492 (750) + "RESUME", // 493 (751) + "REVERSE", // 494 (752) + "REVERSED", // 495 (753) + "REWIND", // 496 (754) + "RF", // 497 (755) + "RH", // 498 (756) + "RIGHT", // 499 (757) + "ROUNDED", // 500 (758) + "RUN", // 501 (759) + "SAME", // 502 (760) + "SCREEN", // 503 (761) + "SD", // 504 (762) + "SECONDS-FROM-FORMATTED-TIME", // 505 (763) + "SECONDS-PAST-MIDNIGHT", // 506 (764) + "SECURITY", // 507 (765) + "SEPARATE", // 508 (766) + "SEQUENCE", // 509 (767) + "SEQUENTIAL", // 510 (768) + "SHARING", // 511 (769) + "SIMPLE-EXIT", // 512 (770) + "SIGN", // 513 (771) + "SIN", // 514 (772) + "SIZE", // 515 (773) + "SMALLEST-ALGEBRAIC", // 516 (774) + "SOURCE", // 517 (775) + "SOURCE-COMPUTER", // 518 (776) + "SPECIAL-NAMES", // 519 (777) + "SQRT", // 520 (778) + "STACK", // 521 (779) + "STANDARD", // 522 (780) + "STANDARD-1", // 523 (781) + "STANDARD-DEVIATION", // 524 (782) + "STANDARD-COMPARE", // 525 (783) + "STATUS", // 526 (784) + "STRONG", // 527 (785) + "SUBSTITUTE", // 528 (786) + "SUM", // 529 (787) + "SYMBOL", // 530 (788) + "SYMBOLIC", // 531 (789) + "SYNCHRONIZED", // 532 (790) + "TALLY", // 533 (791) + "TALLYING", // 534 (792) + "TAN", // 535 (793) + "TERMINATE", // 536 (794) + "TEST", // 537 (795) + "TEST-DATE-YYYYMMDD", // 538 (796) + "TEST-DAY-YYYYDDD", // 539 (797) + "TEST-FORMATTED-DATETIME", // 540 (798) + "TEST-NUMVAL", // 541 (799) + "TEST-NUMVAL-C", // 542 (800) + "TEST-NUMVAL-F", // 543 (801) + "THAN", // 544 (802) + "TIME", // 545 (803) + "TIMES", // 546 (804) + "TO", // 547 (805) + "TOP", // 548 (806) + "TOP-LEVEL", // 549 (807) + "TRACKS", // 550 (808) + "TRACK-AREA", // 551 (809) + "TRAILING", // 552 (810) + "TRANSFORM", // 553 (811) + "TRIM", // 554 (812) + "TRUE", // 555 (813) + "TRY", // 556 (814) + "TURN", // 557 (815) + "TYPE", // 558 (816) + "TYPEDEF", // 559 (817) + "ULENGTH", // 560 (818) + "UNBOUNDED", // 561 (819) + "UNIT", // 562 (820) + "UNITS", // 563 (821) + "UNIT-RECORD", // 564 (822) + "UNTIL", // 565 (823) + "UP", // 566 (824) + "UPON", // 567 (825) + "UPOS", // 568 (826) + "UPPER-CASE", // 569 (827) + "USAGE", // 570 (828) + "USING", // 571 (829) + "USUBSTR", // 572 (830) + "USUPPLEMENTARY", // 573 (831) + "UTILITY", // 574 (832) + "UUID4", // 575 (833) + "UVALID", // 576 (834) + "UWIDTH", // 577 (835) + "VALUE", // 578 (836) + "VARIANCE", // 579 (837) + "VARYING", // 580 (838) + "VOLATILE", // 581 (839) + "WHEN-COMPILED", // 582 (840) + "WITH", // 583 (841) + "WORKING-STORAGE", // 584 (842) + "XML", // 585 (843) + "XMLGENERATE", // 586 (844) + "XMLPARSE", // 587 (845) + "YEAR-TO-YYYY", // 588 (846) + "YYYYDDD", // 589 (847) + "YYYYMMDD", // 590 (848) + "ARITHMETIC", // 591 (849) + "ATTRIBUTE", // 592 (850) + "AUTO", // 593 (851) + "AUTOMATIC", // 594 (852) + "AWAY-FROM-ZERO", // 595 (853) + "BACKGROUND-COLOR", // 596 (854) + "BELL", // 597 (855) + "BINARY-ENCODING", // 598 (856) + "BLINK", // 599 (857) + "CAPACITY", // 600 (858) + "CENTER", // 601 (859) + "CLASSIFICATION", // 602 (860) + "CYCLE", // 603 (861) + "DECIMAL-ENCODING", // 604 (862) + "ENTRY-CONVENTION", // 605 (863) + "EOL", // 606 (864) + "EOS", // 607 (865) + "ERASE", // 608 (866) + "EXPANDS", // 609 (867) + "FLOAT-BINARY", // 610 (868) + "FLOAT-DECIMAL", // 611 (869) + "FOREGROUND-COLOR", // 612 (870) + "FOREVER", // 613 (871) + "FULL", // 614 (872) + "HIGHLIGHT", // 615 (873) + "HIGH-ORDER-LEFT", // 616 (874) + "HIGH-ORDER-RIGHT", // 617 (875) + "IGNORING", // 618 (876) + "IMPLEMENTS", // 619 (877) + "INITIALIZED", // 620 (878) + "INTERMEDIATE", // 621 (879) + "LC-ALL", // 622 (880) + "LC-COLLATE", // 623 (881) + "LC-CTYPE", // 624 (882) + "LC-MESSAGES", // 625 (883) + "LC-MONETARY", // 626 (884) + "LC-NUMERIC", // 627 (885) + "LC-TIME", // 628 (886) + "LOWLIGHT", // 629 (887) + "NEAREST-AWAY-FROM-ZERO", // 630 (888) + "NEAREST-EVEN", // 631 (889) + "NEAREST-TOWARD-ZERO", // 632 (890) + "NONE", // 633 (891) + "NORMAL", // 634 (892) + "NUMBERS", // 635 (893) + "PREFIXED", // 636 (894) + "PREVIOUS", // 637 (895) + "PROHIBITED", // 638 (896) + "RELATION", // 639 (897) + "REQUIRED", // 640 (898) + "REVERSE-VIDEO", // 641 (899) + "ROUNDING", // 642 (900) + "SECONDS", // 643 (901) + "SECURE", // 644 (902) + "SHORT", // 645 (903) + "SIGNED", // 646 (904) + "STANDARD-BINARY", // 647 (905) + "STANDARD-DECIMAL", // 648 (906) + "STATEMENT", // 649 (907) + "STEP", // 650 (908) + "STRUCTURE", // 651 (909) + "TOWARD-GREATER", // 652 (910) + "TOWARD-LESSER", // 653 (911) + "TRUNCATION", // 654 (912) + "UCS-4", // 655 (913) + "UNDERLINE", // 656 (914) + "UNSIGNED", // 657 (915) + "UTF-16", // 658 (916) + "UTF-8", // 659 (917) + "ADDRESS", // 660 (918) + "END-ACCEPT", // 661 (919) + "END-ADD", // 662 (920) + "END-CALL", // 663 (921) + "END-COMPUTE", // 664 (922) + "END-DELETE", // 665 (923) + "END-DISPLAY", // 666 (924) + "END-DIVIDE", // 667 (925) + "END-EVALUATE", // 668 (926) + "END-MULTIPLY", // 669 (927) + "END-PERFORM", // 670 (928) + "END-READ", // 671 (929) + "END-RETURN", // 672 (930) + "END-REWRITE", // 673 (931) + "END-SEARCH", // 674 (932) + "END-START", // 675 (933) + "END-STRING", // 676 (934) + "END-SUBTRACT", // 677 (935) + "END-UNSTRING", // 678 (936) + "END-WRITE", // 679 (937) + "END-IF", // 680 (938) + "THRU", // 681 (939) + "OR", // 682 (940) + "AND", // 683 (941) + "NOT", // 684 (942) + "NE", // 685 (943) + "LE", // 686 (944) + "GE", // 687 (945) + "POW", // 688 (946) + "NEG", // 689 (947) }; diff --git a/gcc/cobol/udf/stored-char-length.cbl b/gcc/cobol/udf/stored-char-length.cbl index 9ab3b14..66889d0 100644 --- a/gcc/cobol/udf/stored-char-length.cbl +++ b/gcc/cobol/udf/stored-char-length.cbl @@ -1,3 +1,6 @@ + >> PUSH source format + >>SOURCE format is fixed + * This function is in public domain. * Contributed by James K. Lowden of Cobolworx in August 2024 @@ -13,3 +16,4 @@ to Output-Value. End Function STORED-CHAR-LENGTH. + >> pop source format
\ No newline at end of file diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc index 23f605d..aed9483 100644 --- a/gcc/cobol/util.cc +++ b/gcc/cobol/util.cc @@ -34,29 +34,24 @@ * header files. */ -#include "cobol-system.h" -#include "coretypes.h" -#include "tree.h" +#include <cobol-system.h> +#include <coretypes.h> +#include <tree.h> #undef yy_flex_debug #include <langinfo.h> -#include "coretypes.h" -#include "version.h" -#include "demangle.h" -#include "intl.h" -#include "backtrace.h" -#include "diagnostic.h" -#include "diagnostic-color.h" -#include "diagnostic-url.h" -#include "diagnostic-metadata.h" -#include "diagnostic-path.h" -#include "edit-context.h" -#include "selftest.h" -#include "selftest-diagnostic.h" -#include "opts.h" +#include <coretypes.h> +#include <version.h> +#include <demangle.h> +#include <intl.h> +#include <backtrace.h> +#include <diagnostic.h> +#include <opts.h> #include "util.h" + #include "cbldiag.h" +#include "cdfval.h" #include "lexio.h" #include "../../libgcobol/ec.h" @@ -90,7 +85,7 @@ static inline char * get_current_dir_name () { /* Use libiberty's allocator here. */ - char *buf = (char *) xmalloc (PATH_MAX); + char *buf = static_cast<char *>(xmalloc (PATH_MAX)); return getcwd (buf, PATH_MAX); } #endif @@ -98,7 +93,7 @@ get_current_dir_name () /* * For printing messages, usually the size of the thing is some kind of string * length, and doesn't really need a size_t. For message formatting, use a - * simple unsigned long, and warn if that's no good. "gb4" here stands for + * simple unsigned long, and warn if that's no good. "gb4" here stands for * "4 Gigabytes". */ unsigned long @@ -110,7 +105,159 @@ gb4( size_t input ) { } return input; } - + +/* + * Most CDF Directives -- those that have state -- can be pushed and popped. + * This class maintains stacks of them, with each stack having a "default + * value" that may be updated, without push/pop, via a CDF directive or + * command-line option. A push to a stack pushes the default value onto it; a + * pop copies the top of the stack to the default value. + * + * Supported: + * CALL-CONVENTION + * COBOL-WORDS + * DEFINE + * DISPLAY + * IF + * POP + * PUSH + * SOURCE FORMAT + * TURN + * not supported + * EVALUATE + * FLAG-02 + * FLAG-14 + * LEAP-SECOND + * LISTING + * PAGE + * PROPAGATE + * REF-MOD-ZERO-LENGTH + * + * >>PUSH ALL calls the class's push() method. + * >>POP ALL calls the class's pop() method. + */ +class cdf_directives_t +{ + template <typename T> + class cdf_stack_t : private std::stack<T> { // cppcheck-suppress noConstructor + T default_value; + const T& top() const { return std::stack<T>::top(); } + bool empty() const { return std::stack<T>::empty(); } + public: + void value( const T& value ) { + T& output( empty()? default_value : std::stack<T>::top() ); // cppcheck-suppress constVariableReference + output = value; + dbgmsg("cdf_directives_t::%s: %s", __func__, str(output).c_str()); + } + T& value() { + return empty()? default_value : std::stack<T>::top(); + } + void push() { + std::stack<T>::push(value()); + dbgmsg("cdf_directives_t::%s: %s", __func__, str(top()).c_str()); + } + void pop() { + if( empty() ) { + error_msg(YYLTYPE(), "CDF stack empty"); // cppcheck-suppress syntaxError + return; + } + default_value = top(); + std::stack<T>::pop(); + dbgmsg("cdf_directives_t::%s: %s", __func__, str(default_value).c_str()); + } + protected: + static std::string str(cbl_call_convention_t arg) { + char output[2] = { static_cast<char>(arg) }; + return std::string("call-convention ") + output; + } + static std::string str(current_tokens_t) { + return "<cobol-words>"; + } + static std::string str(cdf_values_t) { + return "<dictionary>"; + } + static std::string str(source_format_t arg) { + return arg.description(); + } + static std::string str(cbl_enabled_exceptions_t) { + return "<enabled_exceptions>"; + } + }; + + public: + cdf_stack_t<cbl_call_convention_t> call_convention; + cdf_stack_t<current_tokens_t> cobol_words; + cdf_stack_t<cdf_values_t> dictionary; // DEFINE + cdf_stack_t<source_format_t> source_format; + cdf_stack_t<cbl_enabled_exceptions_t> enabled_exceptions; + + cdf_directives_t() { + call_convention.value() = cbl_call_cobol_e; + } + + void push() { + call_convention.push(); + cobol_words.push(); + dictionary.push(); + source_format.push(); + enabled_exceptions.push(); + } + void pop() { + call_convention.pop(); + cobol_words.pop(); + dictionary.pop(); + source_format.pop(); + enabled_exceptions.pop(); + } +}; +static cdf_directives_t cdf_directives; + +void +current_call_convention( cbl_call_convention_t convention) { + cdf_directives.call_convention.value(convention); +} +cbl_call_convention_t +current_call_convention() { + return cdf_directives.call_convention.value(); +} + +current_tokens_t& +cdf_current_tokens() { + return cdf_directives.cobol_words.value(); +} + +cdf_values_t& +cdf_dictionary() { + return cdf_directives.dictionary.value(); +} + +void +cobol_set_indicator_column( int column ) { + cdf_directives.source_format.value().indicator_column_set(column); +} +source_format_t& cdf_source_format() { + return cdf_directives.source_format.value(); +} + +cbl_enabled_exceptions_t& +cdf_enabled_exceptions() { + return cdf_directives.enabled_exceptions.value(); +} + +void cdf_push() { cdf_directives.push(); } +void cdf_push_call_convention() { cdf_directives.call_convention.push(); } +void cdf_push_current_tokens() { cdf_directives.cobol_words.push(); } +void cdf_push_dictionary() { cdf_directives.dictionary.push(); } +void cdf_push_enabled_exceptions() { cdf_directives.enabled_exceptions.push(); } +void cdf_push_source_format() { cdf_directives.source_format.push(); } + +void cdf_pop() { cdf_directives.pop(); } +void cdf_pop_call_convention() { cdf_directives.call_convention.pop(); } +void cdf_pop_current_tokens() { cdf_directives.cobol_words.pop(); } +void cdf_pop_dictionary() { cdf_directives.dictionary.pop(); } +void cdf_pop_enabled_exceptions() { cdf_directives.enabled_exceptions.pop(); } +void cdf_pop_source_format() { cdf_directives.source_format.pop(); } + const char * symbol_type_str( enum symbol_type_t type ) { @@ -839,7 +986,7 @@ cbl_field_t::report_invalid_initial_value(const YYLTYPE& loc) const { // 8 or more, we need do no further testing because we assume // everything fits. if( data.capacity < 8 ) { - const auto p = strchr(data.initial, symbol_decimal_point()); + const char *p = strchr(data.initial, symbol_decimal_point()); if( p && atoll(p+1) != 0 ) { error_msg(loc, "integer type %s VALUE '%s' " "requires integer VALUE", @@ -902,7 +1049,7 @@ cbl_field_t::report_invalid_initial_value(const YYLTYPE& loc) const { return TOUPPER(ch) == 'E'; } ); if( !has_exponent && data.precision() < pend - p ) { - error_msg(loc, "%s cannot represent VALUE %qs exactly (max %c%zu)", + error_msg(loc, "%s cannot represent VALUE %qs exactly (max %c%td)", name, data.initial, '.', pend - p); } } @@ -985,7 +1132,7 @@ literal_subscript_oob( const cbl_refer_t& r, size_t& isub /* output */) { pdim++; return ! occurs.subscript_ok(r.field); } ); - isub = psub - r.subscripts.begin(); + isub = psub - r.subscripts.begin(); return psub == r.subscripts.end()? NULL : dims[isub]; } @@ -998,12 +1145,12 @@ cbl_refer_t::subscripts_set( const std::list<cbl_refer_t>& subs ) { const char * cbl_refer_t::str() const { - static char subscripts[64]; - sprintf(subscripts, "(%u of " HOST_SIZE_T_PRINT_UNSIGNED " dimensions)", + static char subscripts_l[64]; + sprintf(subscripts_l, "(%u of " HOST_SIZE_T_PRINT_UNSIGNED " dimensions)", nsubscript(), (fmt_size_t)dimensions(field)); char *output = xasprintf("%s %s %s", field? field_str(field) : "(none)", - 0 < dimensions(field)? subscripts : "", + 0 < dimensions(field)? subscripts_l : "", is_refmod_reference()? "(refmod)" : "" ); return output; } @@ -1705,12 +1852,13 @@ date_time_fmt( const char input[] ) { { regex_t(), 'd', "^(" DATE_FMT_B "|" DATE_FMT_E ")$" }, { regex_t(), 't', "^(" TIME_FMT_B "|" TIME_FMT_E ")$" }, }; - int erc, cflags = REG_EXTENDED | REG_ICASE, eflags=0; + int cflags = REG_EXTENDED | REG_ICASE, eflags=0; regmatch_t m[5]; char result = 0; if( ! compiled ) { for( auto& fmt : fmts ) { + int erc; if( (erc = regcomp(&fmt.reg, fmt.pattern, cflags)) != 0 ) { char msg[80]; regerror(erc, &fmt.reg, msg, sizeof(msg)); @@ -1768,7 +1916,7 @@ class unique_stack : public std::stack<input_file_t> friend void cobol_set_pp_option(int opt); bool option_m; std::set<std::string> all_names; - + const char * no_wd( const char *wd, const char *name ) { int i; @@ -1779,7 +1927,7 @@ class unique_stack : public std::stack<input_file_t> public: unique_stack() : option_m(false) {} - + bool push( const value_type& value ) { auto ok = std::none_of( c.cbegin(), c.cend(), [value]( const auto& that ) { @@ -1813,8 +1961,8 @@ class unique_stack : public std::stack<input_file_t> const input_file_t& peek( size_t n ) const { gcc_assert( n < size() ); return c.at(size() - ++n); - } - + } + void option( int opt ) { // capture other preprocessor options eventually assert(opt == 'M'); option_m = true; @@ -1827,7 +1975,7 @@ class unique_stack : public std::stack<input_file_t> std::string input( top().name ); printf( "%s: ", input.c_str() ); for( const auto& name : all_names ) { - if( name != input ) + if( name != input ) printf( "\\\n\t%s ", name.c_str() ); } printf("\n"); @@ -1844,7 +1992,7 @@ void cobol_set_pp_option(int opt) { assert(opt == 'M'); input_filenames.option_m = true; } - + /* * Maintain a stack of input filenames. Ensure the files are unique (by * inode), to prevent copybook cycles. Before pushing a new name, Record the @@ -1855,7 +2003,7 @@ void cobol_set_pp_option(int opt) { * to enforce uniqueness, and the scanner to maintain line numbers. */ bool cobol_filename( const char *name, ino_t inode ) { - const line_map *lines = NULL; + //const line_map *lines = NULL; if( inode == 0 ) { auto p = old_filenames.find(name); if( p == old_filenames.end() ) { @@ -1865,8 +2013,10 @@ bool cobol_filename( const char *name, ino_t inode ) { } cbl_errx( "logic error: missing inode for %s", name); } - inode = p->second; - assert(inode != 0); + else { + inode = p->second; + assert(inode != 0); + } } linemap_add(line_table, LC_ENTER, sysp, name, 1); input_filename_vestige = name; @@ -1915,20 +2065,50 @@ cobol_filename_restore() { input_filenames.pop(); if( input_filenames.empty() ) return; - auto& input = input_filenames.top(); + const auto& input = input_filenames.top(); linemap_add(line_table, LC_LEAVE, sysp, NULL, 0); } -static location_t token_location; +static int first_line_minus_1 = 0; +static location_t token_location_minus_1 = 0; +static location_t token_location = 0; -location_t location_from_lineno() { return token_location; } +location_t current_token_location() { return token_location; } +location_t current_location_minus_one() { return token_location_minus_1; } +void current_location_minus_one_clear() + { + first_line_minus_1 = 0; + } template <typename LOC> static void gcc_location_set_impl( const LOC& loc ) { - token_location = linemap_line_start( line_table, loc.last_line, 80 ); + // Set the position to the first line & column in the location. + if( getenv("KILROY") ) + { + fprintf(stderr, "********** KILROY %d\n", loc.first_line); + } + + static location_t loc_m_1 = 0; + + token_location = linemap_line_start( line_table, loc.first_line, 80 ); token_location = linemap_position_for_column( line_table, loc.first_column); + + if( loc.first_line > first_line_minus_1 ) + { + // In order for GDB-COBOL to be able to step through COBOL code properly, + // it is sometimes necessary for the code at the beginning of a COBOL + // line to be using the location_t of the previous line. This is true, for + // example, when laying down the infrastructure code between the last + // statement of a paragraph and the code created at the beginning of the + // following paragragh. This code assumes that token_location values of + // interest are monotonic, and stores that prior value. + first_line_minus_1 = loc.first_line; + token_location_minus_1 = loc_m_1; + loc_m_1 = token_location; + } + location_dump(__func__, __LINE__, "parser", loc); } @@ -1969,9 +2149,14 @@ verify_format( const char gmsgid[] ) { } #endif -static const diagnostic_option_id option_zero; +static const diagnostics::option_id option_zero; size_t parse_error_inc(); +void gcc_location_dump() { + linemap_dump_location( line_table, token_location, stderr ); +} + + void ydferror( const char gmsgid[], ... ) ATTRIBUTE_GCOBOL_DIAG(1, 2); void @@ -1982,8 +2167,9 @@ ydferror( const char gmsgid[], ... ) { va_list ap; va_start (ap, gmsgid); rich_location richloc (line_table, token_location); - bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_zero, - gmsgid, &ap, DK_ERROR); + /*bool ret =*/ global_dc->diagnostic_impl (&richloc, nullptr, option_zero, + gmsgid, &ap, + diagnostics::kind::error); va_end (ap); } @@ -2008,10 +2194,7 @@ class temp_loc_t { gcc_location_set(loc); } explicit temp_loc_t( const YDFLTYPE& loc) : orig(token_location) { - YYLTYPE lloc = { - loc.first_line, loc.first_column, - loc.last_line, loc.last_column }; - gcc_location_set(lloc); + gcc_location_set(loc); } ~temp_loc_t() { if( orig != token_location ) { @@ -2041,7 +2224,8 @@ class temp_loc_t { va_start (ap, gmsgid); \ rich_location richloc (line_table, token_location); \ bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_zero, \ - gmsgid, &ap, DK_ERROR); \ + gmsgid, &ap, \ + diagnostics::kind::error); \ va_end (ap); \ global_dc->end_group(); @@ -2057,6 +2241,33 @@ void error_msg( const YDFLTYPE& loc, const char gmsgid[], ... ) { ERROR_MSG_BODY } +bool +warn_msg( const YYLTYPE& loc, const char gmsgid[], ... ) { + temp_loc_t looker(loc); + verify_format(gmsgid); + auto_diagnostic_group d; + va_list ap; + va_start (ap, gmsgid); + rich_location richloc (line_table, token_location); + auto ret = emit_diagnostic_valist( diagnostics::kind::warning, + token_location, + option_zero, gmsgid, &ap ); + va_end (ap); + return ret; +} + +void error_msg_direct( const char gmsgid[], ... ) { + verify_format(gmsgid); + parse_error_inc(); + auto_diagnostic_group d; + va_list ap; + va_start (ap, gmsgid); + /*auto ret = */emit_diagnostic_valist( diagnostics::kind::error, + token_location, + option_zero, gmsgid, &ap ); + va_end (ap); +} + void yyerror( const char gmsgid[], ... ) { temp_loc_t looker; @@ -2066,8 +2277,11 @@ yyerror( const char gmsgid[], ... ) { va_list ap; va_start (ap, gmsgid); rich_location richloc (line_table, token_location); - bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_zero, - gmsgid, &ap, DK_ERROR); + /*bool ret =*/ global_dc->diagnostic_impl ( &richloc, + nullptr, + option_zero, + gmsgid, + &ap, diagnostics::kind::error); va_end (ap); global_dc->end_group(); } @@ -2078,7 +2292,7 @@ yywarn( const char gmsgid[], ... ) { auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); - auto ret = emit_diagnostic_valist( DK_WARNING, token_location, + auto ret = emit_diagnostic_valist( diagnostics::kind::warning, token_location, option_zero, gmsgid, &ap ); va_end (ap); return ret; @@ -2276,8 +2490,11 @@ cbl_internal_error(const char *gmsgid, ...) { auto_diagnostic_group d; va_list ap; va_start(ap, gmsgid); - emit_diagnostic_valist( DK_ICE, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::ice, + token_location, option_zero, gmsgid, &ap ); va_end(ap); + abort(); // This unnecessary statement is needed so that [[noreturn]] + // // doesn't cause a warning. } void @@ -2286,7 +2503,8 @@ cbl_unimplementedw(const char *gmsgid, ...) { auto_diagnostic_group d; va_list ap; va_start(ap, gmsgid); - emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::sorry, + token_location, option_zero, gmsgid, &ap ); va_end(ap); } @@ -2296,7 +2514,8 @@ cbl_unimplemented(const char *gmsgid, ...) { auto_diagnostic_group d; va_list ap; va_start(ap, gmsgid); - emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::sorry, + token_location, option_zero, gmsgid, &ap ); va_end(ap); } @@ -2307,12 +2526,13 @@ cbl_unimplemented_at( const YYLTYPE& loc, const char *gmsgid, ... ) { auto_diagnostic_group d; va_list ap; va_start(ap, gmsgid); - emit_diagnostic_valist( DK_SORRY, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::sorry, + token_location, option_zero, gmsgid, &ap ); va_end(ap); } -/* - * analogs to err(3) and errx(3). +/* + * analogs to err(3) and errx(3). */ #pragma GCC diagnostic push @@ -2324,7 +2544,8 @@ cbl_err(const char *fmt, ...) { verify_format(gmsgid); va_list ap; va_start(ap, fmt); - emit_diagnostic_valist( DK_FATAL, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::fatal, + token_location, option_zero, gmsgid, &ap ); va_end(ap); } #pragma GCC diagnostic pop @@ -2335,7 +2556,8 @@ cbl_errx(const char *gmsgid, ...) { auto_diagnostic_group d; va_list ap; va_start(ap, gmsgid); - emit_diagnostic_valist( DK_FATAL, token_location, option_zero, gmsgid, &ap ); + emit_diagnostic_valist( diagnostics::kind::fatal, + token_location, option_zero, gmsgid, &ap ); va_end(ap); } @@ -2447,7 +2669,7 @@ static const std::set<std::string> reserved_words = { "VOLATILE", "XML", "END-START", - + // ISO 2023 keywords "ACCEPT", "ACCESS", diff --git a/gcc/cobol/util.h b/gcc/cobol/util.h index 165915a..d478ea2 100644 --- a/gcc/cobol/util.h +++ b/gcc/cobol/util.h @@ -33,7 +33,7 @@ void cbl_message(int fd, const char *format_string, ...) ATTRIBUTE_PRINTF_2; -void cbl_internal_error(const char *format_string, ...) +[[noreturn]] void cbl_internal_error(const char *format_string, ...) ATTRIBUTE_GCOBOL_DIAG(1, 2); void cbl_err(const char *format_string, ...) ATTRIBUTE_GCOBOL_DIAG(1, 2); @@ -49,7 +49,7 @@ void cobol_set_pp_option(int opt); void cobol_filename_restore(); const char * cobol_lineno( int ); -int cobol_lineno(); +int cobol_lineno(void); unsigned long gb4( size_t input ); @@ -59,5 +59,70 @@ as_voidp( P p ) { return static_cast<const void *>(p); } +/* + * The default source format, whether free or fixed, is determined + * heuristically by examining the PROGRAM-ID line, if it exists, in the first + * input file. If that file does not have such a line, the default is free + * format. Else the format is set to fixed if anything appears on that line + * that would prohibit parsing it as free format, + */ +class source_format_t { + bool first_file, explicitly; + int left, right; +public: + source_format_t() + : first_file(true), explicitly(false), left(0), right(0) + {} + void indicator_column_set( int column ) { + explicitly = true; + if( column == 0 ) right = 0; + if( column < 0 ) { + column = -column; + right = 73; + } + left = column; + } + + bool inference_pending() { + bool tf = first_file && !explicitly; + first_file = false; + return tf; + } + + void infer( const char *bol, bool want_reference_format ); + + inline bool is_fixed() const { return left == 7; } + inline bool is_reffmt() const { return is_fixed() && right == 73; } + inline bool is_free() const { return ! is_fixed(); } + + const char * description() const { + if( is_reffmt() ) return "REFERENCE"; + if( is_fixed() ) return "FIXED"; + if( is_free() ) return "FREE"; + gcc_unreachable(); + } + + inline int left_margin() { + return left == 0? left : left - 1; + } + inline int right_margin() { + return right == 0? right : right - 1; + } +}; + + +void cdf_push(); +void cdf_push_call_convention(); +void cdf_push_current_tokens(); +void cdf_push_dictionary(); +void cdf_push_enabled_exceptions(); +void cdf_push_source_format(); + +void cdf_pop(); +void cdf_pop_call_convention(); +void cdf_pop_current_tokens(); +void cdf_pop_dictionary(); +void cdf_pop_source_format(); +void cdf_pop_enabled_exceptions(); #endif |