diff options
Diffstat (limited to 'libgcobol')
-rw-r--r-- | libgcobol/ChangeLog | 508 | ||||
-rw-r--r-- | libgcobol/LICENSE | 27 | ||||
-rw-r--r-- | libgcobol/Makefile.am | 9 | ||||
-rw-r--r-- | libgcobol/Makefile.in | 14 | ||||
-rw-r--r-- | libgcobol/acinclude.m4 | 162 | ||||
-rw-r--r-- | libgcobol/charmaps.cc | 26 | ||||
-rw-r--r-- | libgcobol/common-defs.h | 211 | ||||
-rw-r--r-- | libgcobol/config.h.in | 46 | ||||
-rwxr-xr-x | libgcobol/configure | 755 | ||||
-rw-r--r-- | libgcobol/configure.ac | 82 | ||||
-rw-r--r-- | libgcobol/configure.tgt | 7 | ||||
-rw-r--r-- | libgcobol/constants.cc | 20 | ||||
-rw-r--r-- | libgcobol/ec.h | 1 | ||||
-rw-r--r-- | libgcobol/exceptl.h | 136 | ||||
-rw-r--r-- | libgcobol/gcobolio.h | 6 | ||||
-rw-r--r-- | libgcobol/gfileio.cc | 177 | ||||
-rw-r--r-- | libgcobol/gmath.cc | 445 | ||||
-rw-r--r-- | libgcobol/intrinsic.cc | 792 | ||||
-rw-r--r-- | libgcobol/io.cc | 11 | ||||
-rw-r--r-- | libgcobol/libgcobol-fp.h | 59 | ||||
-rw-r--r-- | libgcobol/libgcobol.cc | 2372 | ||||
-rw-r--r-- | libgcobol/libgcobol.h | 44 | ||||
-rw-r--r-- | libgcobol/libgcobol.spec.in | 2 | ||||
-rw-r--r-- | libgcobol/valconv.cc | 26 | ||||
-rw-r--r-- | libgcobol/valconv.h | 8 |
25 files changed, 4055 insertions, 1891 deletions
diff --git a/libgcobol/ChangeLog b/libgcobol/ChangeLog index 28cd912..e851b39 100644 --- a/libgcobol/ChangeLog +++ b/libgcobol/ChangeLog @@ -1,3 +1,511 @@ +2025-06-20 James K. Lowden <jklowden@cobolworx.com> + + * LICENSE: New file. + +2025-06-16 James K. Lowden <jklowden@cobolworx.com> + + PR cobol/120621 + * common-defs.h (class cbl_enabled_exceptions_t): Const parameter. + +2025-06-11 Robert Dubner <rdubner@symas.com> + + PR cobol/119975 + * intrinsic.cc (__gg__current_date): Eliminate CLOCK_REALTIME. + (__gg__seconds_past_midnight): Likewise. + (__gg__formatted_current_date): Likewise. + (__gg__random): Likewise. + (__gg__random_next): Likewise. + * libgcobol.cc: include <sys/time.h>. + (__gg__abort): Eliminate CLOCK_REALTIME. + (cobol_time): Likewise. + (get_time_nanoseconds): Rename. + (get_time_nanoseconds_local): Comment; Eliminate CLOCK_REALTIME. + (__gg__clock_gettime): Likewise. + (__gg__get_date_hhmmssff): Likewise. + * libgcobol.h (__gg__clock_gettime): Eliminate clockid_t from declaration. + +2025-06-06 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + * common-defs.h (enum cbl_file_mode_t): Whitespace. + (enum file_stmt_t): Likewise. + (ec_cmp): Likewise. + (struct cbl_declarative_t): Add "explicit" keyword. + (class cbl_enabled_exceptions_t): Whitespace. + * gfileio.cc: Remove cppcheck comment. + * libgcobol.cc (class ec_status_t): Add "explicit" keyword. + (match_declarative): Remove %zu. + (default_exception_handler): Likwise. + (__gg__check_fatal_exception): Exception overhead. + (__gg__exception_push): Remove %zu. + (__gg__exception_pop): Likewise. + (cbl_enabled_exception_t::dump): Likewise. + (__gg__match_exception): Exception overhead; remove %zu. + (cbl_enabled_exceptions_t::dump): Remove %zu. + (__gg__set_exception_environment): Likewise. + +2025-06-05 Robert Dubner <rdubner@symas.com> + + PR cobol/119975 + * configure.ac: AC_CHECK_LIB(rt, clock_gettime). + * config.h.in: Likewise. + * configure: Likewise. + * gfileio.cc: Remove in-line cppcheck-suppress. + * intrinsic.cc (timespec_to_string): Use guarded clock_gettime(). + (__gg__current_date): Likewise. + (__gg__seconds_past_midnight): Likewise. + (__gg__formatted_current_date): Likewise. + (__gg__random): Likewise. + (__gg__random_next): Likewise. + (__gg__when_compiled): Likewise. + * libgcobol.cc (cobol_time): Likewise. + (get_time_nanoseconds): Likewise. + (__gg__clock_gettime): Likewise. + (__gg__get_date_hhmmssff): Likewise. + * libgcobol.h (__gg__clock_gettime): Likewise. + (struct cbl_timespec): Likewise. + +2025-06-04 Robert Dubner <rdubner@symas.com> + + PR cobol/119323 + * charmaps.cc (__gg__raw_to_ascii): Eliminate cppcheck warnings. + (__gg__raw_to_ebcdic): Likewise. + (__gg__ebcdic_to_console): Likewise. + (__gg__console_to_ascii): Likewise. + (__gg__console_to_ebcdic): Likewise. + * common-defs.h (struct cbl_declarative_t): Likewise. + * gfileio.cc (get_filename): Likewise. + (max_value): Likewise. + (relative_file_delete_varying): Likewise. + (relative_file_delete): Likewise. + (read_an_indexed_record): Likewise. + (position_state_restore): Likewise. + (indexed_file_delete): Likewise. + (indexed_file_start): Likewise. + (sequential_file_rewrite): Likewise. + (relative_file_write_varying): Likewise. + (relative_file_write): Likewise. + (sequential_file_write): Likewise. + (indexed_file_write): Likewise. + (__io__file_write): Likewise. + (line_sequential_file_read): Likewise. + (indexed_file_read): Likewise. + (file_indexed_open): Likewise. + (__gg__file_reopen): Likewise. + * gmath.cc (conditional_stash): Likewise. + (__gg__pow): Likewise. + (multiply_int256_by_int64): Likewise. + (add_int256_to_int256): Likewise. + (divide_int256_by_int64): Likewise. + (squeeze_int256): Likewise. + (get_int256_from_qualified_field): Likewise. + (__gg__add_fixed_phase1): Likewise. + (__gg__addf1_fixed_phase2): Likewise. + (__gg__fixed_phase2_assign_to_c): Likewise. + (__gg__add_float_phase1): Likewise. + (__gg__addf1_float_phase2): Likewise. + (__gg__float_phase2_assign_to_c): Likewise. + (__gg__addf3): Likewise. + (__gg__subtractf1_fixed_phase2): Likewise. + (__gg__subtractf2_fixed_phase1): Likewise. + (__gg__subtractf1_float_phase2): Likewise. + (__gg__subtractf2_float_phase1): Likewise. + (__gg__subtractf3): Likewise. + (__gg__multiplyf1_phase1): Likewise. + (multiply_int128_by_int128): Likewise. + (__gg__multiplyf1_phase2): Likewise. + (__gg__multiplyf2): Likewise. + (shift_in_place128): Likewise. + (divide_int128_by_int128): Likewise. + (__gg__dividef1_phase2): Likewise. + (__gg__dividef23): Likewise. + (__gg__dividef45): Likewise. + * intrinsic.cc (struct input_state): Likewise. + (get_value_as_double_from_qualified_field): Likewise. + (kahan_summation): Likewise. + (variance): Likewise. + (get_all_time): Likewise. + (populate_ctm_from_date): Likewise. + (populate_ctm_from_time): Likewise. + (ftime_replace): Likewise. + (__gg__abs): Likewise. + (__gg__acos): Likewise. + (__gg__annuity): Likewise. + (__gg__asin): Likewise. + (__gg__atan): Likewise. + (__gg__byte_length): Likewise. + (__gg__char): Likewise. + (__gg__combined_datetime): Likewise. + (__gg__cos): Likewise. + (__gg__date_of_integer): Likewise. + (__gg__date_to_yyyymmdd): Likewise. + (__gg__day_of_integer): Likewise. + (__gg__day_to_yyyyddd): Likewise. + (__gg__exp): Likewise. + (__gg__exp10): Likewise. + (__gg__factorial): Likewise. + (__gg__formatted_current_date): Likewise. + (__gg__formatted_date): Likewise. + (__gg__formatted_datetime): Likewise. + (__gg__formatted_time): Likewise. + (__gg__integer): Likewise. + (__gg__integer_of_date): Likewise. + (__gg__integer_of_day): Likewise. + (__gg__integer_part): Likewise. + (__gg__fraction_part): Likewise. + (__gg__log): Likewise. + (__gg__log10): Likewise. + (__gg__max): Likewise. + (__gg__lower_case): Likewise. + (__gg__median): Likewise. + (__gg__min): Likewise. + (numval): Likewise. + (numval_c): Likewise. + (__gg__numval): Likewise. + (__gg__test_numval): Likewise. + (__gg__numval_c): Likewise. + (__gg__test_numval_c): Likewise. + (__gg__ord): Likewise. + (__gg__rem): Likewise. + (__gg__trim): Likewise. + (__gg__random): Likewise. + (__gg__reverse): Likewise. + (__gg__sign): Likewise. + (__gg__sin): Likewise. + (__gg__sqrt): Likewise. + (__gg__tan): Likewise. + (__gg__test_date_yyyymmdd): Likewise. + (__gg__test_day_yyyyddd): Likewise. + (__gg__upper_case): Likewise. + (__gg__year_to_yyyy): Likewise. + (gets_int): Likewise. + (gets_year): Likewise. + (gets_month): Likewise. + (gets_day): Likewise. + (gets_day_of_week): Likewise. + (gets_day_of_year): Likewise. + (gets_week): Likewise. + (gets_hours): Likewise. + (gets_minutes): Likewise. + (gets_seconds): Likewise. + (gets_nanoseconds): Likewise. + (fill_cobol_tm): Likewise. + (__gg__test_formatted_datetime): Likewise. + (__gg__integer_of_formatted_date): Likewise. + (__gg__seconds_from_formatted_time): Likewise. + (__gg__hex_of): Likewise. + (__gg__highest_algebraic): Likewise. + (__gg__lowest_algebraic): Likewise. + (floating_format_tester): Likewise. + (__gg__numval_f): Likewise. + (__gg__test_numval_f): Likewise. + (ismatch): Likewise. + (iscasematch): Likewise. + (strstr): Likewise. + (strcasestr): Likewise. + (strlaststr): Likewise. + (strcaselaststr): Likewise. + (__gg__substitute): Likewise. + (__gg__locale_compare): Likewise. + (__gg__locale_date): Likewise. + (__gg__locale_time): Likewise. + (__gg__locale_time_from_seconds): Likewise. + * libgcobol.cc (class ec_status_t): Likewise. + (__gg__set_truncation_mode): Likewise. + (malloc): Likewise. + (__gg__mabort): Likewise. + (__gg__resize_int_p): Likewise. + (__gg__resize_treeplet): Likewise. + (var_is_refmod): Likewise. + (value_is_too_big): Likewise. + (__gg__string_to_alpha_edited_ascii): Likewise. + (int128_to_field): Likewise. + (edited_to_binary): Likewise. + (get_binary_value_local): Likewise. + (__gg__get_date_yymmdd): Likewise. + (__gg__get_date_yyyymmdd): Likewise. + (__gg__get_date_yyddd): Likewise. + (__gg__get_yyyyddd): Likewise. + (__gg__get_date_dow): Likewise. + (get_scaled_rdigits): Likewise. + (format_for_display_internal): Likewise. + (compare_88): Likewise. + (get_float128): Likewise. + (compare_field_class): Likewise. + (compare_strings): Likewise. + (__gg__compare_2): Likewise. + (__gg__sort_table): Likewise. + (init_var_both): Likewise. + (alpha_to_alpha_move_from_location): Likewise. + (alpha_to_alpha_move): Likewise. + (__gg__move): Likewise. + (__gg__move_literala): Likewise. + (__gg__sort_workfile): Likewise. + (__gg__merge_files): Likewise. + (normalize_id): Likewise. + (inspect_backward_format_1): Likewise. + (__gg__inspect_format_1): Likewise. + (inspect_backward_format_2): Likewise. + (__gg__inspect_format_2): Likewise. + (__gg__inspect_format_4): Likewise. + (move_string): Likewise. + (__gg__string): Likewise. + (display_both): Likewise. + (__gg__display_string): Likewise. + (__gg__accept): Likewise. + (__gg__binary_value_from_qualified_field): Likewise. + (__gg__float128_from_qualified_field): Likewise. + (float128_to_int128): Likewise. + (float128_to_location): Likewise. + (__gg__set_initial_switch_value): Likewise. + (is_numeric_display_numeric): Likewise. + (is_packed_numeric): Likewise. + (is_alpha_a_number): Likewise. + (__gg__classify): Likewise. + (__gg__accept_envar): Likewise. + (__gg__set_envar): Likewise. + (command_line_plan_b): Likewise. + (__gg__get_command_line): Likewise. + (__gg__set_pointer): Likewise. + (__gg__ascii_to_internal_field): Likewise. + (__gg__internal_to_console_in_place): Likewise. + (__gg__routine_to_call): Likewise. + (__gg__fetch_call_by_value_value): Likewise. + (__gg__assign_value_from_stack): Likewise. + (__gg__literaln_alpha_compare): Likewise. + (string_in): Likewise. + (__gg__unstring): Likewise. + (local_ec_type_of): Likewise. + (struct exception_descr_t): Likewise. + (struct cbl_exception_t): Likewise. + (cbl_enabled_exception_t: Likewise.: Likewise.dump): Likewise. + (__gg__match_exception): Likewise. + (__gg__float128_from_location): Likewise. + (__gg__integer_from_float128): Likewise. + (__gg__set_exception_file): Likewise. + (__gg__func_exception_file): Likewise. + (__gg__set_exception_code): Likewise. + (__gg__is_float_infinite): Likewise. + (__gg__float32_from_128): Likewise. + (__gg__float32_from_64): Likewise. + (__gg__float64_from_128): Likewise. + (__gg__copy_as_big_endian): Likewise. + (__gg__get_figconst_data): Likewise. + (find_in_dirs): Likewise. + (__gg__function_handle_from_cobpath): Likewise. + (__gg__just_mangle_name): Likewise. + (__gg__function_handle_from_literal): Likewise. + (__gg__function_handle_from_name): Likewise. + (__gg__mirror_range): Likewise. + (__gg__deallocate): Likewise. + (__gg__allocate): Likewise. + (__gg__module_name): Likewise. + (__gg__set_env_name): Likewise. + (__gg__set_env_value): Likewise. + * libgcobol.h (__gg__mabort): Likewise. + (massert): Likewise. + (PTRCAST): Likewise. + (__gg__float128_from_location): Likewise. + (__gg__set_exception_file): Likewise. + (__gg__binary_value_from_qualified_field): Likewise. + (__gg__float128_from_qualified_field): Likewise. + * valconv.cc (__gg__realloc_if_necessary): Likewise. + (__gg__alphabet_create): Likewise. + (__gg__string_to_numeric_edited): Likewise. + (__gg__string_to_alpha_edited): Likewise. + * valconv.h: Likewise. + +2025-06-01 Robert Dubner <rdubner@symas.com> + + PR cobol/119524 + * libgcobol.cc (__gg__fprintf_stderr): New function. + +2025-05-20 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + * charmaps.cc: Switch to C++ includes. + * common-defs.h: Likewise. + * constants.cc: Likewise. + * ec.h: Remove #include <assert.h>. + * gcobolio.h (GCOBOLIO_H_): Switch to C++ includes. + * gfileio.cc: Likewise. + * gmath.cc: Likewise. + * intrinsic.cc: Comment formatting; C++ includes. + * io.cc: C++ includes. + * libgcobol.cc: (__gg__stash_exceptions): Eliminate. + * valconv.cc: Switch to C++ includes. + +2025-05-20 Robert Dubner <rdubner@symas.com> + + PR cobol/119885 + * intrinsic.cc: (__gg__sqrt): Change test from <= zero to < zero. + +2025-05-16 Robert Dubner <rdubner@symas.com> + + * common-defs.h (struct cbl_declarative_t): Eliminate blobl. + * libgcobol.cc (__gg__set_env_name): Code for ENVIRONMENT-NAME/VALUE. + (__gg__set_env_value): Likewise. + +2025-05-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * libgcobol.cc [!LOG_PERROR] (LOG_PERROR): Provide fallback. + +2025-05-11 Robert Dubner <rdubner@symas.com> + + PR cobol/119377 + * common-defs.h: (struct cbl_declaratives_t): Change "bool global" to + "uint32_t global". + +2025-05-10 Robert Dubner <rdubner@symas.com> + + * common-defs.h (ec_cmp): Delete "getenv("match_declarative")" calls. + (enabled_exception_match): Delete "getenv("match_declarative")" calls. + * libgcobol.cc: Eliminate __gg__odo_violation. + +2025-05-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac: Handle --enable-libgcobol. + Let it override LIBGCOBOL_SUPPORTED. + * configure: Regenerate. + +2025-05-06 Iain Sandoe <iain@sandoe.co.uk> + + * config.h.in: Regenerate. + * configure: Regenerate. + * configure.ac: Check for program_invocation_short_name and + and getprogname(). + * libgcobol.cc (default_exception_handler): When the platform + has program_invocation_short_name, use it otherwise fall + back to using getprogname() or a constant string (if neither + interface is available). + +2025-05-05 Robert Dubner <rdubner@symas.com> + + * charmaps.cc: Add #include <vector>. + * common-defs.h (COMMON_DEFS_H_): Add #include <stdio.h>. + (enum cbl_file_mode_t): Add file_mode_any_e. + (enum file_stmt_t): Created. + (cbl_file_mode_str): Add case for file_mode_any_e. + (ec_cmp): Exceptions. + (struct cbl_enabled_exception_t): Likewise. + (struct cbl_declarative_t): Likewise. + (class cbl_enabled_exceptions_array_t): Likewise. + (class cbl_enabled_exceptions_t): Likewise. + (struct cbl_enabled_exceptions_array_t): Likewise. + (enabled_exception_match): Likewise. + * constants.cc: Add #include <vector>. + * exceptl.h (struct cbl_exception_t): Removed. + (struct cbl_declarative_t): Removed. + (class ec_status_t): Removed. + * gcobolio.h: Add symbol_table_index to cblc_file_t. + * gfileio.cc: Add #include <vector> + (establish_status): Comment. + (__io__file_init): Handle symbol_table_index. + (__io__file_delete): Set file->prior_op. + (__io__file_rewrite): Likewise. + (__io__file_read): Likewise. + (__io__file_open): Likewise. + (__io__file_close): Likewise. + * gmath.cc: Include #include <vector>. + * intrinsic.cc: Include #include <vector>. + * libgcobol.cc: Multiple modifications for exceptions. + * valconv.cc: #include <vector>. + +2025-05-02 Jakub Jelinek <jakub@redhat.com> + + PR cobol/119364 + * valconv.cc (__gg__realloc_if_necessary): Use (new_size>>16)>>16; + instead of new_size>>32; to avoid warnings on 32-bit hosts. + * common-defs.h (enum cbl_field_attr_t): Use uint64_t + as underlying type rather than size_t. + * gcobolio.h (cblc_field_t): Change attr member type from size_t + to unsigned long long. + +2025-04-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac: Check for struct tm.tm_zone. + * configure, config.h.in: Regenerate. + * intrinsic.cc (__gg__formatted_current_date): Guard tm.tm_zone + use with HAVE_STRUCT_TM_TM_ZONE. + +2025-04-15 Andreas Schwab <schwab@suse.de> + + * configure.tgt: Set LIBGCOBOL_SUPPORTED for riscv64-*-linux* with + 64-bit multilib. + +2025-04-15 Jakub Jelinek <jakub@redhat.com> + Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR cobol/119244 + * acinclude.m4 (LIBGCOBOL_CHECK_FLOAT128): Ensure + libgcob_cv_have_float128 is not yes on targets with IEEE quad + long double. Don't check for --as-needed nor set LIBQUADSPEC + on targets which USE_IEC_60559. + * libgcobol-fp.h (FP128_FMT, strtofp128, strfromfp128): Define. + * intrinsic.cc (strtof128): Don't redefine. + (WEIRD_TRANSCENDENT_RETURN_VALUE): Use GCOB_FP128_LITERAL macro. + (__gg__numval_f): Use strtofp128 instead of strtof128. + * libgcobol.cc (strtof128): Don't redefine. + (format_for_display_internal): Use strfromfp128 instead of + strfromf128 or quadmath_snprintf and use FP128_FMT in the format + string. + (get_float128, __gg__compare_2, __gg__move, __gg__move_literala): + Use strtofp128 instead of strtof128. + * configure: Regenerate. + +2025-04-14 Andreas Schwab <schwab@suse.de> + + * libgcobol.cc (__gg__float64_from_128): Mark literal as float128 + literal. + +2025-04-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * valconv.cc (__gg__string_to_numeric_edited): Use strchr instead + of index. + +2025-04-12 Bob Dubner <rdubner@symas.com> + + PR cobol/119694 + * gfileio.cc: Eliminate getenv() calls. + * libgcobol.cc: Likewise. + +2025-04-10 Iain Sandoe <iain@sandoe.co.uk> + + * configure.tgt: Enable for x86_64 Darwin. + +2025-04-10 Iain Sandoe <iain@sandoe.co.uk> + + PR cobol/119244 + * Makefile.am: Add support for libquadmath. + * Makefile.in: Regenerate. + * acinclude.m4: Add support for libquadmath. + * config.h.in: Regenerate. + * configure: Regenerate. + * configure.ac: Configure libquadmath support. + * gmath.cc: Use GCOB_FP128 to represent the configured + 128b floating point type. Use FP128_FUNC to represent + the naming of intrinsics in the configure 128b floating + point type. Render literals with GCOB_FP128_LITERAL. + * intrinsic.cc: Likewise. + * libgcobol.cc: Likewise. + * libgcobol.h: Likewise. + * libgcobol-fp.h: New file. + * gfileio.cc: Include libgcobol-fp.h. + * libgcobol.spec.in: Add libquadmath configure output. + +2025-04-09 Bob Dubner <rdubner@symas.com> + + PR cobol/119682 + * common-defs.h: Define the REFER_T_REFMOD constant. + * intrinsic.cc: (__gg__max): Change the calls to __gg__compare_2(), + (__gg__min): Likewise, (__gg__ord_min): Likewise, + (__gg__ord_max): Likewise. + * libgcobol.cc: (__gg__compare_2): Change definition of calling + parameters, eliminate separate flag bit for ALL and ADDRESS_OF, + change comparison of alphanumeric to numeric when the numeric + is a refmod. + * libgcobol.h: Change declaration of __gg__compare_2. + 2025-04-05 Iain Sandoe <iain@sandoe.co.uk> * Makefile.am: Add libgcobol.spec and dependency. diff --git a/libgcobol/LICENSE b/libgcobol/LICENSE new file mode 100644 index 0000000..3937993 --- /dev/null +++ b/libgcobol/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2021-2025 Symas Corporation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. +* Neither the name of the Symas Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libgcobol/Makefile.am b/libgcobol/Makefile.am index 89d0519..0a17d20 100644 --- a/libgcobol/Makefile.am +++ b/libgcobol/Makefile.am @@ -46,7 +46,7 @@ libgcobol_la_SOURCES = \ WARN_CFLAGS = -W -Wall -Wwrite-strings -AM_CPPFLAGS = -I. -I$(srcdir) +AM_CPPFLAGS = -I. -I$(srcdir) $(LIBQUADINCLUDE) AM_CFLAGS = $(XCFLAGS) AM_CXXFLAGS = $(XCFLAGS) AM_CXXFLAGS += $(WARN_CFLAGS) @@ -62,9 +62,8 @@ endif # We want to link with the c++ runtime. libgcobol_la_LINK = $(CXXLINK) $(libgcobol_la_LDFLAGS) version_arg = -version-info $(LIBGCOBOL_VERSION) -libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LTLIBICONV) \ - $(extra_ldflags_libgcobol) $(LIBS) \ - $(version_arg) -libgcobol_la_DEPENDENCIES = libgcobol.spec +libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LIBQUADLIB) $(LTLIBICONV) \ + $(extra_ldflags_libgcobol) $(LIBS) $(version_arg) +libgcobol_la_DEPENDENCIES = libgcobol.spec $(LIBQUADLIB_DEP) endif BUILD_LIBGCOBOL diff --git a/libgcobol/Makefile.in b/libgcobol/Makefile.in index 88158cb..5fdc42c 100644 --- a/libgcobol/Makefile.in +++ b/libgcobol/Makefile.in @@ -288,6 +288,10 @@ LIBGCOBOL_VERSION = @LIBGCOBOL_VERSION@ LIBICONV = @LIBICONV@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ +LIBQUADINCLUDE = @LIBQUADINCLUDE@ +LIBQUADLIB = @LIBQUADLIB@ +LIBQUADLIB_DEP = @LIBQUADLIB_DEP@ +LIBQUADSPEC = @LIBQUADSPEC@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -317,6 +321,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPEC_LIBGCOBOL_DEPS = @SPEC_LIBGCOBOL_DEPS@ STRIP = @STRIP@ +USE_IEC_60559 = @USE_IEC_60559@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -402,7 +407,7 @@ gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) @BUILD_LIBGCOBOL_TRUE@ valconv.cc @BUILD_LIBGCOBOL_TRUE@WARN_CFLAGS = -W -Wall -Wwrite-strings -@BUILD_LIBGCOBOL_TRUE@AM_CPPFLAGS = -I. -I$(srcdir) +@BUILD_LIBGCOBOL_TRUE@AM_CPPFLAGS = -I. -I$(srcdir) $(LIBQUADINCLUDE) @BUILD_LIBGCOBOL_TRUE@AM_CFLAGS = $(XCFLAGS) @BUILD_LIBGCOBOL_TRUE@AM_CXXFLAGS = $(XCFLAGS) $(WARN_CFLAGS) \ @BUILD_LIBGCOBOL_TRUE@ -DIN_TARGET_LIBS -fno-strict-aliasing @@ -410,11 +415,10 @@ gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) # We want to link with the c++ runtime. @BUILD_LIBGCOBOL_TRUE@libgcobol_la_LINK = $(CXXLINK) $(libgcobol_la_LDFLAGS) @BUILD_LIBGCOBOL_TRUE@version_arg = -version-info $(LIBGCOBOL_VERSION) -@BUILD_LIBGCOBOL_TRUE@libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LTLIBICONV) \ -@BUILD_LIBGCOBOL_TRUE@ $(extra_ldflags_libgcobol) $(LIBS) \ -@BUILD_LIBGCOBOL_TRUE@ $(version_arg) +@BUILD_LIBGCOBOL_TRUE@libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LIBQUADLIB) $(LTLIBICONV) \ +@BUILD_LIBGCOBOL_TRUE@ $(extra_ldflags_libgcobol) $(LIBS) $(version_arg) -@BUILD_LIBGCOBOL_TRUE@libgcobol_la_DEPENDENCIES = libgcobol.spec +@BUILD_LIBGCOBOL_TRUE@libgcobol_la_DEPENDENCIES = libgcobol.spec $(LIBQUADLIB_DEP) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am diff --git a/libgcobol/acinclude.m4 b/libgcobol/acinclude.m4 index ed340c7..0e81b10 100644 --- a/libgcobol/acinclude.m4 +++ b/libgcobol/acinclude.m4 @@ -24,3 +24,165 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN],) AC_DEFUN([AC_LIBLTDL_CONVENIENCE],) AC_SUBST(LIBTOOL) ]) + +dnl Check whether we have a __float128 and _Float128 type +dnl Unashamedly plagiarized from libgfortran. + +AC_DEFUN([LIBGCOBOL_CHECK_FLOAT128], [ + LIBQUADSPEC= + LIBQUADLIB= + LIBQUADLIB_DEP= + LIBQUADINCLUDE= + USE_IEC_60559=no + + if test "x$enable_libquadmath_support" = "xno"; then + if test "x$have_iec_60559_libc_support" = "xyes"; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + fi + else + + AC_CACHE_CHECK([whether we have a usable _Float128 type], + libgcob_cv_have_float128, [ + GCC_TRY_COMPILE_OR_LINK([ +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381 +#error "long double is IEEE quad, no need for libquadmath" +#endif + + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + ],[ + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + ],[ + libgcob_cv_have_float128=yes + ],[ + libgcob_cv_have_float128=no +])]) + + if test "x$have_iec_60559_libc_support$enable_libquadmath_support$libgcob_cv_have_float128" = xyesdefaultyes; then + USE_IEC_60559=yes + fi + + if test "x$libgcob_cv_have_float128" = xyes; then + + if test "x$USE_IEC_60559" = xyes; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + else + AC_DEFINE(USE_QUADMATH, 1, [Define if *q APIs should be used for __float128.]) + fi + AC_DEFINE(HAVE_FLOAT128, 1, [Define if target has usable _Float128 and __float128 types.]) + + if test "x$USE_IEC_60559" != xyes; then + dnl Check whether -Wl,--as-needed resp. -Wl,-zignore is supported + dnl + dnl Turn warnings into error to avoid testsuite breakage. So enable + dnl AC_LANG_WERROR, but there's currently (autoconf 2.64) no way to turn + dnl it off again. As a workaround, save and restore werror flag like + dnl AC_PATH_XTRA. + dnl Cf. http://gcc.gnu.org/ml/gcc-patches/2010-05/msg01889.html + ac_xsave_[]_AC_LANG_ABBREV[]_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_flag + AC_CACHE_CHECK([whether --as-needed/-z ignore works], + [libgcob_cv_have_as_needed], + [ + # Test for native Solaris options first. + # No whitespace after -z to pass it through -Wl. + libgcob_cv_as_needed_option="-zignore" + libgcob_cv_no_as_needed_option="-zrecord" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + AC_LANG_WERROR + AC_LINK_IFELSE([AC_LANG_PROGRAM([])], + [libgcob_cv_have_as_needed=yes], + [libgcob_cv_have_as_needed=no]) + LDFLAGS="$save_LDFLAGS" + if test "x$libgcob_cv_have_as_needed" = xno; then + libgcob_cv_as_needed_option="--as-needed" + libgcob_cv_no_as_needed_option="--no-as-needed" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + AC_LANG_WERROR + AC_LINK_IFELSE([AC_LANG_PROGRAM([])], + [libgcob_cv_have_as_needed=yes], + [libgcob_cv_have_as_needed=no]) + LDFLAGS="$save_LDFLAGS" + fi + ac_[]_AC_LANG_ABBREV[]_werror_flag=$ac_xsave_[]_AC_LANG_ABBREV[]_werror_flag + ]) + + dnl Determine -Bstatic ... -Bdynamic etc. support from gfortran -### stderr. + touch conftest1.$ac_objext conftest2.$ac_objext + LQUADMATH=-lquadmath + $CXX -static-libgcobol -### -o conftest \ + conftest1.$ac_objext -lgcobol conftest2.$ac_objext 2>&1 >/dev/null \ + | grep "conftest1.$ac_objext.*conftest2.$ac_objext" > conftest.cmd + if grep "conftest1.$ac_objext.* -Bstatic -lgcobol -Bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-Bstatic} -lquadmath %{static-libquadmath:-Bdynamic}" + elif grep "conftest1.$ac_objext.* -bstatic -lgcobol -bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-bstatic} -lquadmath %{static-libquadmath:-bdynamic}" + elif grep "conftest1.$ac_objext.* -aarchive_shared -lgcobol -adefault .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-aarchive_shared} -lquadmath %{static-libquadmath:-adefault}" + elif grep "conftest1.$ac_objext.*libgcobol.a .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:libquadmath.a%s;:-lquadmath}" + fi + rm -f conftest1.$ac_objext conftest2.$ac_objext conftest conftest.cmd + + if test "x$libgcob_cv_have_as_needed" = xyes; then + if test "x$USE_IEC_60559" = xyes; then + LIBQUADSPEC="$libgcob_cv_as_needed_option $LQUADMATH $libgcob_cv_no_as_needed_option" + else + LIBQUADSPEC="%{static-libgcobol:$libgcob_cv_as_needed_option} $LQUADMATH %{static-libgcobol:$libgcob_cv_no_as_needed_option}" + fi + else + LIBQUADSPEC="$LQUADMATH" + fi + if test -f ../libquadmath/libquadmath.la; then + LIBQUADLIB=../libquadmath/libquadmath.la + LIBQUADLIB_DEP=../libquadmath/libquadmath.la + LIBQUADINCLUDE='-I$(srcdir)/../libquadmath' + else + LIBQUADLIB="-lquadmath" + fi + fi + else + if test "x$USE_IEC_60559" = xyes; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + fi + fi + + fi + + dnl For the spec file + AC_SUBST(LIBQUADSPEC) + AC_SUBST(LIBQUADLIB) + AC_SUBST(LIBQUADLIB_DEP) + AC_SUBST(LIBQUADINCLUDE) + AC_SUBST(USE_IEC_60559) +]) diff --git a/libgcobol/charmaps.cc b/libgcobol/charmaps.cc index d935b89..eb82609 100644 --- a/libgcobol/charmaps.cc +++ b/libgcobol/charmaps.cc @@ -29,14 +29,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <time.h> +#include <iconv.h> + +#include <cctype> +#include <clocale> +#include <cstdio> +#include <cstring> +#include <ctime> + #include <algorithm> #include <unordered_map> -#include <locale.h> -#include <iconv.h> +#include <vector> #include "ec.h" #include "common-defs.h" @@ -432,7 +435,7 @@ __gg__raw_to_ascii(char **dest, size_t *dest_size, const char *in, size_t length size_t code_point; // Pull the next code_point from the UTF-8 stream - long unicode_point = extract_next_code_point((const unsigned char *)in, + long unicode_point = extract_next_code_point(reinterpret_cast<const unsigned char *>(in), length, position ); @@ -494,7 +497,7 @@ __gg__raw_to_ebcdic(char **dest, size_t *dest_size, const char *in, size_t lengt } // Pull the next code_point from the UTF-8 stream - long unicode_point = extract_next_code_point( (const unsigned char *)in, + long unicode_point = extract_next_code_point( reinterpret_cast<const unsigned char *>(in), length, position ); // Check for that unicode code point in the subset of characters we @@ -719,7 +722,8 @@ char *__gg__ebcdic_to_console(char **dest, const size_t length) { static size_t ebcdic_size = MINIMUM_ALLOCATION_SIZE; - static char *ebcdic = (char *)malloc(ebcdic_size); + static char *ebcdic = static_cast<char *>(malloc(ebcdic_size)); + if(!ebcdic)abort(); __gg__realloc_if_necessary(&ebcdic, &ebcdic_size, length); memcpy(ebcdic, str, length); @@ -754,7 +758,7 @@ void __gg__console_to_ascii(char * const str, size_t length) size_t code_point; // Pull the next code_point from the UTF-8 stream long unicode_point - = extract_next_code_point( (const unsigned char *)str, + = extract_next_code_point( reinterpret_cast<const unsigned char *>(str), length, position ); if( unicode_point == -1 ) @@ -794,7 +798,7 @@ __gg__console_to_ebcdic(char * const str, size_t length) size_t code_point; // Pull the next code_point from the UTF-8 stream long unicode_point - = extract_next_code_point( (const unsigned char *)str, + = extract_next_code_point( reinterpret_cast<const unsigned char *>(str), length, position ); if( unicode_point == -1 ) diff --git a/libgcobol/common-defs.h b/libgcobol/common-defs.h index 6bf32ef..a78022a 100644 --- a/libgcobol/common-defs.h +++ b/libgcobol/common-defs.h @@ -30,7 +30,9 @@ #ifndef COMMON_DEFS_H_ #define COMMON_DEFS_H_ -#include <stdint.h> +#include <cassert> +#include <cstdio> +#include <cstdint> #include <list> #define COUNT_OF(X) (sizeof(X) / sizeof(X[0])) @@ -147,7 +149,7 @@ enum cbl_field_type_t { * A field is padded (in the unjustified direction) either with 0 or SPC. * (But maybe the fill character should just be an explicit character.) */ -enum cbl_field_attr_t : size_t { +enum cbl_field_attr_t : uint64_t { none_e = 0x0000000000, figconst_1_e = 0x0000000001, // This needs to be 1 - don't change the position figconst_2_e = 0x0000000002, // This needs to be 2 @@ -235,6 +237,7 @@ enum cbl_file_mode_t { file_mode_output_e = 'w', file_mode_extend_e = 'a', file_mode_io_e = '+', + file_mode_any_e, }; enum cbl_round_t { @@ -284,6 +287,16 @@ enum bitop_t { bit_xor_op, }; +enum file_stmt_t { + file_stmt_delete_e, + file_stmt_merge_e, + file_stmt_read_e, + file_stmt_rewrite_e, + file_stmt_sort_e, + file_stmt_start_e, + file_stmt_write_e, +}; + enum file_close_how_t { file_close_no_how_e = 0x00, file_close_removal_e = 0x01, @@ -376,6 +389,7 @@ cbl_file_mode_str( cbl_file_mode_t mode ) { case file_mode_output_e: return "file_mode_output_e: 'w'"; case file_mode_io_e: return "file_mode_io_e: '+'"; case file_mode_extend_e: return "file_mode_extend_e: 'a'"; + case file_mode_any_e: return "file_mode_any_e"; } return "???"; }; @@ -388,58 +402,161 @@ enum module_type_t { module_toplevel_e, }; - -static inline bool -ec_cmp( ec_type_t raised, ec_type_t mask ) +/* + * Compare a "raised" EC to an enabled EC or of a declarative. "raised" may in + * fact not be raised; in the compiler this function is used to compare a TURN + * directive to the list of enabled ECs. + */ +static bool +ec_cmp( ec_type_t raised, ec_type_t ec ) { - if( raised == mask ) return true; + if( raised == ec ) return true; - // Do not match on only the low byte. - if( 0 < (~EC_ALL_E & static_cast<uint32_t>(mask)) ) return false; + // If both low bytes are nonzero, we had to match exactly, above. + if( (~EC_ALL_E & static_cast<uint32_t>(raised)) + && + (~EC_ALL_E & static_cast<uint32_t>(ec)) ) { + return false; + } - return 0 != ( static_cast<uint32_t>(raised) - & - static_cast<uint32_t>(mask) ); + // Level 1 and 2 have low byte of zero. + // If one low byte is zero, see if they're the same kind. + return 0xFF < ( static_cast<uint32_t>(raised) + & + static_cast<uint32_t>(ec) ); } struct cbl_enabled_exception_t { - bool enabled, location; + bool location; ec_type_t ec; size_t file; cbl_enabled_exception_t() - : enabled(false) - , location(false) + : location(false) , ec(ec_none_e) , file(0) {} - cbl_enabled_exception_t( bool enabled, bool location, - ec_type_t ec, size_t file = 0 ) - : enabled(enabled) - , location(location) + cbl_enabled_exception_t( bool location, ec_type_t ec, size_t file = 0 ) + : location(location) , ec(ec) , file(file) {} - // sort by ec and file, not enablement + // sort by ec and file bool operator<( const cbl_enabled_exception_t& that ) const { if( ec == that.ec ) return file < that.file; return ec < that.ec; } - // match on ec and file, not enablement + // match on ec and file bool operator==( const cbl_enabled_exception_t& that ) const { return ec == that.ec && file == that.file; } + + void dump( int i ) const; }; +struct cbl_declarative_t { + enum { files_max = 16 }; + size_t section; // implies program + bool global; + ec_type_t type; + uint32_t nfile, files[files_max]; + cbl_file_mode_t mode; + + explicit cbl_declarative_t( cbl_file_mode_t mode = file_mode_none_e ) + : section(0) + , global(false) + , type(ec_none_e) + , nfile(0) + , mode(mode) + { + std::fill(files, files + COUNT_OF(files), 0); + } + explicit cbl_declarative_t( ec_type_t type ) + : section(0) + , global(false) + , type(type) + , nfile(0) + , mode(file_mode_none_e) + { + std::fill(files, files + COUNT_OF(files), 0); + } + + cbl_declarative_t( size_t section, ec_type_t type, + const std::list<size_t>& files, + cbl_file_mode_t mode, + bool global = false ) + : section(section), global(global) + , type(type) + , nfile(files.size()) + , mode(mode) + { + assert( files.size() <= COUNT_OF(this->files) ); + std::fill(this->files, this->files + COUNT_OF(this->files), 0); + if( nfile > 0 ) { + std::copy( files.begin(), files.end(), this->files ); + } + } + cbl_declarative_t( const cbl_declarative_t& that ) + : section(that.section) + , global(that.global) + , type(that.type) + , nfile(that.nfile) + , mode(that.mode) + { + std::fill(files, files + COUNT_OF(files), 0); + if( nfile > 0 ) { + std::copy( that.files, that.files + nfile, this->files ); + } + } + cbl_declarative_t& operator=(const cbl_declarative_t&) = default; + + std::vector<uint64_t> encode() const; + + /* + * Sort file names before file modes, and file modes before non-IO. + */ + bool operator<( const cbl_declarative_t& that ) const { + // file name declaratives first, in section order + if( nfile != 0 ) { + if( that.nfile != 0 ) return section < that.section; + return true; + } + // file mode declaratives between file name declaratives and non-IO + if( mode != file_mode_none_e ) { + if( that.nfile != 0 ) return false; + if( that.mode == file_mode_none_e ) return true; + return section < that.section; + } + // all others by section, after names and modes + if( that.nfile != 0 ) return false; + if( that.mode != file_mode_none_e ) return false; + return section < that.section; + } -class cbl_enabled_exceptions_array_t; + // TRUE if there are no files to match, or the provided file is in the list. + bool match_file( size_t file ) const { + static const uint32_t * pend = files + nfile; + + return nfile == 0 || pend != std::find(files, files + nfile, file); + } + + // USE Format 1 names a file mode, or at least one file, and not an EC. + bool is_format_1() const { + return mode != file_mode_none_e; + } +}; + +typedef std::vector<cbl_declarative_t> cbl_declaratives_t; class cbl_enabled_exceptions_t : protected std::set<cbl_enabled_exception_t> { - friend cbl_enabled_exceptions_array_t; - void apply( const cbl_enabled_exception_t& elem ) { + void apply( bool enabled, const cbl_enabled_exception_t& elem ) { + if( ! enabled ) { + erase(elem); + return; + } auto inserted = insert( elem ); if( ! inserted.second ) { erase(inserted.first); @@ -448,57 +565,35 @@ class cbl_enabled_exceptions_t : protected std::set<cbl_enabled_exception_t> } public: - bool turn_on_off( bool enabled, bool location, ec_type_t type, - std::set<size_t> files ); + cbl_enabled_exceptions_t() {} + cbl_enabled_exceptions_t( size_t nec, const cbl_enabled_exception_t *ecs ) + : std::set<cbl_enabled_exception_t>(ecs, ecs + nec) + {} + void turn_on_off( bool enabled, bool location, ec_type_t type, + const std::set<size_t>& files ); - const cbl_enabled_exception_t * match( ec_type_t type, size_t file = 0 ); + const cbl_enabled_exception_t * match( ec_type_t ec, size_t file = 0 ) const; void dump() const; + void dump( const char tag[] ) const; + uint32_t status() const; void clear() { std::set<cbl_enabled_exception_t>::clear(); } bool empty() const { return std::set<cbl_enabled_exception_t>::empty(); } size_t size() const { return std::set<cbl_enabled_exception_t>::size(); } + std::vector<uint64_t> encode() const; + cbl_enabled_exceptions_t& decode( const std::vector<uint64_t>& encoded ); + cbl_enabled_exceptions_t& operator=( const cbl_enabled_exceptions_t& ) = default; }; extern cbl_enabled_exceptions_t enabled_exceptions; -/* - * This class is passed to the runtime function evaluating the raised exception. - * It is constructed in genapi.cc from the compile-time table. - */ -struct cbl_enabled_exceptions_array_t { - size_t nec; - cbl_enabled_exception_t *ecs; - - cbl_enabled_exceptions_array_t( size_t nec, cbl_enabled_exception_t *ecs ) - : nec(nec), ecs(ecs) {} - - cbl_enabled_exceptions_array_t( const cbl_enabled_exceptions_t& input = - cbl_enabled_exceptions_t() ) - : nec(input.size()) - , ecs(NULL) - { - if( ! input.empty() ) { - ecs = new cbl_enabled_exception_t[nec]; - std::copy(input.begin(), input.end(), ecs); - } - } - - cbl_enabled_exceptions_array_t& - operator=( const cbl_enabled_exceptions_array_t& input); - - - bool match( ec_type_t ec, size_t file = 0 ) const; - - size_t nbytes() const { return nec * sizeof(ecs[0]); } -}; - template <typename T> T enabled_exception_match( T beg, T end, ec_type_t type, size_t file ) { - cbl_enabled_exception_t input( true, true, // don't matter + cbl_enabled_exception_t input( true, // doesn't matter type, file ); auto output = std::find(beg, end, input); if( output == end ) { diff --git a/libgcobol/config.h.in b/libgcobol/config.h.in index d61ff7a..1b511d0 100644 --- a/libgcobol/config.h.in +++ b/libgcobol/config.h.in @@ -3,12 +3,43 @@ /* Define to 1 if the target assembler supports thread-local storage. */ #undef HAVE_CC_TLS +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the <complex.h> header file. */ +#undef HAVE_COMPLEX_H + +/* Define to 1 if you have the declaration of `program_invocation_short_name', + and to 0 if you don't. */ +#undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the <errno.h> header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the <fenv.h> header file. */ +#undef HAVE_FENV_H + +/* Define if target has usable _Float128 and __float128 types. */ +#undef HAVE_FLOAT128 + +/* Define to 1 if you have the <floatingpoint.h> header file. */ +#undef HAVE_FLOATINGPOINT_H + +/* Define to 1 if you have the <fptrap.h> header file. */ +#undef HAVE_FPTRAP_H + +/* Define to 1 if you have the `getprogname' function. */ +#undef HAVE_GETPROGNAME + /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV +/* Define to 1 if you have the <ieeefp.h> header file. */ +#undef HAVE_IEEEFP_H + /* Define to 1 if you have the `initstate_r' function. */ #undef HAVE_INITSTATE_R @@ -36,6 +67,9 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H +/* Define to 1 if you have the `strfromf128' function. */ +#undef HAVE_STRFROMF128 + /* Define to 1 if you have the `strfromf32' function. */ #undef HAVE_STRFROMF32 @@ -48,6 +82,12 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the `strtof128' function. */ +#undef HAVE_STRTOF128 + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#undef HAVE_STRUCT_TM_TM_ZONE + /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H @@ -88,6 +128,12 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define if IEC 60559 *f128 APIs should be used for _Float128. */ +#undef USE_IEC_60559 + +/* Define if *q APIs should be used for __float128. */ +#undef USE_QUADMATH + /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE diff --git a/libgcobol/configure b/libgcobol/configure index 1715b98..7271517 100755 --- a/libgcobol/configure +++ b/libgcobol/configure @@ -629,13 +629,21 @@ ac_includes_default="\ # include <unistd.h> #endif" +ac_header_list= ac_func_list= +ac_cxx_werror_flag= +ac_cxx_werror_flag= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS SPEC_LIBGCOBOL_DEPS get_gcc_base_ver +USE_IEC_60559 +LIBQUADINCLUDE +LIBQUADLIB_DEP +LIBQUADLIB +LIBQUADSPEC extra_ldflags_libgcobol LIBGCOBOL_VERSION BUILD_LIBGCOBOL_FALSE @@ -780,6 +788,7 @@ enable_option_checking enable_multilib enable_maintainer_mode enable_silent_rules +enable_libgcobol enable_version_specific_runtime_libs enable_dependency_tracking enable_shared @@ -793,6 +802,7 @@ with_toolexeclibdir enable_rpath with_libiconv_prefix with_libiconv_type +enable_libquadmath with_gcc_major_version_only ' ac_precious_vars='build_alias @@ -1429,6 +1439,7 @@ Optional Features: sometimes confusing) to the casual installer --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") + --enable-libgcobol Enable libgcobol --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory @@ -1445,6 +1456,7 @@ Optional Features: install libraries with @rpath/library-name, requires rpaths to be added to executables --disable-rpath do not hardcode runtime library paths + --disable-libquadmath disable libquadmath support for libgcobol Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -2339,6 +2351,83 @@ rm -f conftest.val } # ac_fn_cxx_compute_int +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_check_decl LINENO SYMBOL VAR INCLUDES +# ----------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_cxx_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_decl + # ac_fn_cxx_check_func LINENO FUNC VAR # ------------------------------------ # Tests whether FUNC exists, setting the cache variable VAR accordingly @@ -2408,6 +2497,63 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func + +# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES +# ------------------------------------------------------ +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_cxx_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -2692,12 +2838,22 @@ $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi +as_fn_append ac_header_list " floatingpoint.h" +as_fn_append ac_header_list " ieeefp.h" +as_fn_append ac_header_list " fenv.h" +as_fn_append ac_header_list " fptrap.h" +as_fn_append ac_header_list " complex.h" +as_fn_append ac_header_list " stdlib.h" +as_fn_append ac_header_list " errno.h" +as_fn_append ac_func_list " getprogname" as_fn_append ac_func_list " random_r" as_fn_append ac_func_list " srandom_r" as_fn_append ac_func_list " initstate_r" as_fn_append ac_func_list " setstate_r" as_fn_append ac_func_list " strfromf32" as_fn_append ac_func_list " strfromf64" +as_fn_append ac_func_list " strtof128" +as_fn_append ac_func_list " strfromf128" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -3569,6 +3725,16 @@ END fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-libgcobol" >&5 +$as_echo_n "checking for --enable-libgcobol... " >&6; } +# Check whether --enable-libgcobol was given. +if test "${enable_libgcobol+set}" = set; then : + enableval=$enable_libgcobol; +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_libgcobol" >&5 +$as_echo "$enable_libgcobol" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5 $as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; } # Check whether --enable-version-specific-runtime-libs was given. @@ -11644,7 +11810,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11647 "configure" +#line 11813 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11750,7 +11916,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11753 "configure" +#line 11919 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16641,6 +16807,14 @@ _ACEOF unset LIBGCOBOL_SUPPORTED . ${srcdir}/configure.tgt +# Decide if it's usable. +case $LIBGCOBOL_SUPPORTED:$enable_libgcobol in +*:no) use_libgcobol=no ;; +*:yes) use_libgcobol=yes ;; +yes:*) use_libgcobol=yes ;; +*:*) use_libgcobol=no ;; +esac + # ----------------- # __int128 support # ----------------- @@ -16733,7 +16907,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcobol_cv_have_int128" >&5 $as_echo "$libgcobol_cv_have_int128" >&6; } - if test "x$LIBGCOBOL_SUPPORTED" = xyes && test "x$libgcobol_cv_have_int128" = xyes; then + if test "x$use_libgcobol" = xyes && test "x$libgcobol_cv_have_int128" = xyes; then BUILD_LIBGCOBOL_TRUE= BUILD_LIBGCOBOL_FALSE='#' else @@ -16861,9 +17035,189 @@ if test "$ac_res" != no; then : fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cosf128" >&5 -$as_echo_n "checking for library containing cosf128... " >&6; } -if ${ac_cv_search_cosf128+:} false; then : + +# libgcobol soname version +LIBGCOBOL_VERSION=1:0:0 + + +## added, currently unused. +# VERSION_SUFFIX=$(echo $LIBGCOBOL_VERSION | tr ':' '.' ) +# AC_SUBST(VERSION_SUFFIX) +## end added + +extra_ldflags_libgcobol= +case $host in + *-*-darwin*) + extra_ldflags_libgcobol=-Wl,-U,___cobol_main ;; + *) ;; +esac + + + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + +# Look for a way to represent the program name +# First, check the GLIBC case +ac_fn_cxx_check_decl "$LINENO" "program_invocation_short_name" "ac_cv_have_decl_program_invocation_short_name" " +#if HAVE_ERRNO_H +# define _GNU_SOURCE +# include <errno.h> +#endif + +" +if test "x$ac_cv_have_decl_program_invocation_short_name" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME $ac_have_decl +_ACEOF + + +# Check an alternate + + + + for ac_func in $ac_func_list +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +# These are GLIBC + + + + + + + + + + +# Some functions we check to figure out if the libc Float128 support +# is adequate. + +# These are C23. + + + + + + +# These are GLIBC. + + + + + +# We need to make sure to check libc before adding libm. +libgcobol_have_sinf128=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sinf128" >&5 +$as_echo_n "checking for library containing sinf128... " >&6; } +if ${ac_cv_search_sinf128+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sinf128 (); +int +main () +{ +return sinf128 (); + ; + return 0; +} +_ACEOF +for ac_lib in '' c m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_sinf128=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sinf128+:} false; then : + break +fi +done +if ${ac_cv_search_sinf128+:} false; then : + +else + ac_cv_search_sinf128=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sinf128" >&5 +$as_echo "$ac_cv_search_sinf128" >&6; } +ac_res=$ac_cv_search_sinf128 +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + libgcobol_have_sinf128=yes +fi + +libgcobol_have_cacosf128=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cacosf128" >&5 +$as_echo_n "checking for library containing cacosf128... " >&6; } +if ${ac_cv_search_cacosf128+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -16876,11 +17230,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char cosf128 (); +char cacosf128 (); int main () { -return cosf128 (); +return cacosf128 (); ; return 0; } @@ -16896,79 +17250,406 @@ for ac_lib in '' c m; do as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 fi if ac_fn_cxx_try_link "$LINENO"; then : - ac_cv_search_cosf128=$ac_res + ac_cv_search_cacosf128=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if ${ac_cv_search_cosf128+:} false; then : + if ${ac_cv_search_cacosf128+:} false; then : break fi done -if ${ac_cv_search_cosf128+:} false; then : +if ${ac_cv_search_cacosf128+:} false; then : else - ac_cv_search_cosf128=no + ac_cv_search_cacosf128=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cosf128" >&5 -$as_echo "$ac_cv_search_cosf128" >&6; } -ac_res=$ac_cv_search_cosf128 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cacosf128" >&5 +$as_echo "$ac_cv_search_cacosf128" >&6; } +ac_res=$ac_cv_search_cacosf128 if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + libgcobol_have_cacosf128=yes +fi + +# Copied from gcc/configure.ac. 2025-06-05 R.J.Dubner +# At least for glibc, clock_gettime is in librt. But don't pull that +# in if it still doesn't give us the function we want. +ac_cv_func_clock_gettime=no +if test $ac_cv_func_clock_gettime = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if ${ac_cv_lib_rt_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 +$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } +if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : + LIBS="-lrt $LIBS" -# libgcobol soname version -LIBGCOBOL_VERSION=1:0:0 +$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h +fi -## added, currently unused. -# VERSION_SUFFIX=$(echo $LIBGCOBOL_VERSION | tr ':' '.' ) -# AC_SUBST(VERSION_SUFFIX) -## end added +fi -extra_ldflags_libgcobol= -case $host in - *-*-darwin*) - extra_ldflags_libgcobol=-Wl,-U,___cobol_main ;; - *) ;; -esac +have_iec_60559_libc_support=no +if test "x$ac_cv_func_strtof128$ac_cv_func_strfromf128" = xyesyes \ + && test "x$libgcobol_have_sinf128$libgcobol_have_cacosf128" = xyesyes; then + have_iec_60559_libc_support=yes +fi +# Check whether libquadmath should be used +# Check whether --enable-libquadmath was given. +if test "${enable_libquadmath+set}" = set; then : + enableval=$enable_libquadmath; ENABLE_LIBQUADMATH_SUPPORT=$enableval +else + if test "x$have_iec_60559_libc_support" = xyes; then + ENABLE_LIBQUADMATH_SUPPORT=default +else + ENABLE_LIBQUADMATH_SUPPORT=yes +fi +fi -# These are GLIBC +enable_libquadmath_support= +if test "${ENABLE_LIBQUADMATH_SUPPORT}" = "no" ; then + enable_libquadmath_support=no +elif test "${ENABLE_LIBQUADMATH_SUPPORT}" = "default" ; then + enable_libquadmath_support=default +fi + LIBQUADSPEC= + LIBQUADLIB= + LIBQUADLIB_DEP= + LIBQUADINCLUDE= + USE_IEC_60559=no + if test "x$enable_libquadmath_support" = "xno"; then + if test "x$have_iec_60559_libc_support" = "xyes"; then - for ac_func in $ac_func_list -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + fi + else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have a usable _Float128 type" >&5 +$as_echo_n "checking whether we have a usable _Float128 type... " >&6; } +if ${libgcob_cv_have_float128+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test x$gcc_no_link = xyes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381 +#error "long double is IEEE quad, no need for libquadmath" +#endif + + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + +int +main () +{ + + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + + ; + return 0; +} _ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + libgcob_cv_have_float128=yes + +else + + libgcob_cv_have_float128=no fi -done +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381 +#error "long double is IEEE quad, no need for libquadmath" +#endif + + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + +int +main () +{ + + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + libgcob_cv_have_float128=yes + +else + + libgcob_cv_have_float128=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcob_cv_have_float128" >&5 +$as_echo "$libgcob_cv_have_float128" >&6; } + + if test "x$have_iec_60559_libc_support$enable_libquadmath_support$libgcob_cv_have_float128" = xyesdefaultyes; then + USE_IEC_60559=yes + fi + + if test "x$libgcob_cv_have_float128" = xyes; then + + if test "x$USE_IEC_60559" = xyes; then + +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + else + +$as_echo "#define USE_QUADMATH 1" >>confdefs.h + + fi + +$as_echo "#define HAVE_FLOAT128 1" >>confdefs.h + + + if test "x$USE_IEC_60559" != xyes; then + ac_xsave_cxx_werror_flag=$ac_cxx_werror_flag + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether --as-needed/-z ignore works" >&5 +$as_echo_n "checking whether --as-needed/-z ignore works... " >&6; } +if ${libgcob_cv_have_as_needed+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Test for native Solaris options first. + # No whitespace after -z to pass it through -Wl. + libgcob_cv_as_needed_option="-zignore" + libgcob_cv_no_as_needed_option="-zrecord" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no +ac_cxx_werror_flag=yes + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int +main () +{ + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + libgcob_cv_have_as_needed=yes +else + libgcob_cv_have_as_needed=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + if test "x$libgcob_cv_have_as_needed" = xno; then + libgcob_cv_as_needed_option="--as-needed" + libgcob_cv_no_as_needed_option="--no-as-needed" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + +ac_cxx_werror_flag=yes + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int +main () +{ + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + libgcob_cv_have_as_needed=yes +else + libgcob_cv_have_as_needed=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + fi + ac_cxx_werror_flag=$ac_xsave_cxx_werror_flag + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcob_cv_have_as_needed" >&5 +$as_echo "$libgcob_cv_have_as_needed" >&6; } + + touch conftest1.$ac_objext conftest2.$ac_objext + LQUADMATH=-lquadmath + $CXX -static-libgcobol -### -o conftest \ + conftest1.$ac_objext -lgcobol conftest2.$ac_objext 2>&1 >/dev/null \ + | grep "conftest1.$ac_objext.*conftest2.$ac_objext" > conftest.cmd + if grep "conftest1.$ac_objext.* -Bstatic -lgcobol -Bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-Bstatic} -lquadmath %{static-libquadmath:-Bdynamic}" + elif grep "conftest1.$ac_objext.* -bstatic -lgcobol -bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-bstatic} -lquadmath %{static-libquadmath:-bdynamic}" + elif grep "conftest1.$ac_objext.* -aarchive_shared -lgcobol -adefault .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-aarchive_shared} -lquadmath %{static-libquadmath:-adefault}" + elif grep "conftest1.$ac_objext.*libgcobol.a .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:libquadmath.a%s;:-lquadmath}" + fi + rm -f conftest1.$ac_objext conftest2.$ac_objext conftest conftest.cmd + + if test "x$libgcob_cv_have_as_needed" = xyes; then + if test "x$USE_IEC_60559" = xyes; then + LIBQUADSPEC="$libgcob_cv_as_needed_option $LQUADMATH $libgcob_cv_no_as_needed_option" + else + LIBQUADSPEC="%{static-libgcobol:$libgcob_cv_as_needed_option} $LQUADMATH %{static-libgcobol:$libgcob_cv_no_as_needed_option}" + fi + else + LIBQUADSPEC="$LQUADMATH" + fi + if test -f ../libquadmath/libquadmath.la; then + LIBQUADLIB=../libquadmath/libquadmath.la + LIBQUADLIB_DEP=../libquadmath/libquadmath.la + LIBQUADINCLUDE='-I$(srcdir)/../libquadmath' + else + LIBQUADLIB="-lquadmath" + fi + fi + else + if test "x$USE_IEC_60559" = xyes; then + +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + fi + fi + + fi -# These are C23, and might not be available in libc. +# struct tm tm_zone is a POSIX.1-2024 addition. +ac_fn_cxx_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include <time.h> +" +if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then : +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TM_TM_ZONE 1 +_ACEOF + + +fi if test "${multilib}" = "yes"; then diff --git a/libgcobol/configure.ac b/libgcobol/configure.ac index ca56997..acfca7e 100644 --- a/libgcobol/configure.ac +++ b/libgcobol/configure.ac @@ -40,6 +40,11 @@ AM_MAINTAINER_MODE AM_INIT_AUTOMAKE([1.15.1 no-define foreign no-dist -Wall -Wno-portability]) +AC_MSG_CHECKING([for --enable-libgcobol]) +AC_ARG_ENABLE(libgcobol, + [AS_HELP_STRING([--enable-libgcobol], [Enable libgcobol])]) +AC_MSG_RESULT($enable_libgcobol) + AC_MSG_CHECKING([for --enable-version-specific-runtime-libs]) AC_ARG_ENABLE(version-specific-runtime-libs, AS_HELP_STRING([--enable-version-specific-runtime-libs], @@ -138,6 +143,14 @@ AC_CHECK_SIZEOF([void *]) unset LIBGCOBOL_SUPPORTED . ${srcdir}/configure.tgt +# Decide if it's usable. +case $LIBGCOBOL_SUPPORTED:$enable_libgcobol in +*:no) use_libgcobol=no ;; +*:yes) use_libgcobol=yes ;; +yes:*) use_libgcobol=yes ;; +*:*) use_libgcobol=no ;; +esac + # ----------------- # __int128 support # ----------------- @@ -164,12 +177,11 @@ AC_CACHE_CHECK([whether __int128 is supported], [libgcobol_cv_have_int128], libgcobol_cv_have_int128=no ])]) -AM_CONDITIONAL(BUILD_LIBGCOBOL, [test "x$LIBGCOBOL_SUPPORTED" = xyes && test "x$libgcobol_cv_have_int128" = xyes]) +AM_CONDITIONAL(BUILD_LIBGCOBOL, [test "x$use_libgcobol" = xyes && test "x$libgcobol_cv_have_int128" = xyes]) # Check if functions are available in libc before adding extra libs. AC_SEARCH_LIBS([malloc], [c]) AC_SEARCH_LIBS([clock_gettime], [c rt]) -AC_SEARCH_LIBS([cosf128], [c m]) # libgcobol soname version LIBGCOBOL_VERSION=1:0:0 @@ -188,12 +200,76 @@ case $host in esac AC_SUBST(extra_ldflags_libgcobol) +AC_CHECK_HEADERS_ONCE(floatingpoint.h ieeefp.h fenv.h fptrap.h \ +complex.h stdlib.h errno.h) + +# Look for a way to represent the program name +# First, check the GLIBC case +AC_CHECK_DECLS([program_invocation_short_name], , ,[ +#if HAVE_ERRNO_H +# define _GNU_SOURCE +# include <errno.h> +#endif +]) + +# Check an alternate +AC_CHECK_FUNCS_ONCE(getprogname) + # These are GLIBC AC_CHECK_FUNCS_ONCE(random_r srandom_r initstate_r setstate_r) -# These are C23, and might not be available in libc. +# Some functions we check to figure out if the libc Float128 support +# is adequate. + +# These are C23. AC_CHECK_FUNCS_ONCE(strfromf32 strfromf64) +# These are GLIBC. +AC_CHECK_FUNCS_ONCE(strtof128 strfromf128) +# We need to make sure to check libc before adding libm. +libgcobol_have_sinf128=no +AC_SEARCH_LIBS([sinf128], [c m], libgcobol_have_sinf128=yes) +libgcobol_have_cacosf128=no +AC_SEARCH_LIBS([cacosf128], [c m], libgcobol_have_cacosf128=yes) + +# Copied from gcc/configure.ac. 2025-06-05 R.J.Dubner +# At least for glibc, clock_gettime is in librt. But don't pull that +# in if it still doesn't give us the function we want. +ac_cv_func_clock_gettime=no +if test $ac_cv_func_clock_gettime = no; then + AC_CHECK_LIB(rt, clock_gettime, + [LIBS="-lrt $LIBS" + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, + [Define to 1 if you have the `clock_gettime' function.])]) +fi + +have_iec_60559_libc_support=no +if test "x$ac_cv_func_strtof128$ac_cv_func_strfromf128" = xyesyes \ + && test "x$libgcobol_have_sinf128$libgcobol_have_cacosf128" = xyesyes; then + have_iec_60559_libc_support=yes +fi + +# Check whether libquadmath should be used +AC_ARG_ENABLE(libquadmath, +AS_HELP_STRING([--disable-libquadmath], + [disable libquadmath support for libgcobol]), +ENABLE_LIBQUADMATH_SUPPORT=$enableval, +if test "x$have_iec_60559_libc_support" = xyes; then + ENABLE_LIBQUADMATH_SUPPORT=default +else + ENABLE_LIBQUADMATH_SUPPORT=yes +fi) +enable_libquadmath_support= +if test "${ENABLE_LIBQUADMATH_SUPPORT}" = "no" ; then + enable_libquadmath_support=no +elif test "${ENABLE_LIBQUADMATH_SUPPORT}" = "default" ; then + enable_libquadmath_support=default +fi +LIBGCOBOL_CHECK_FLOAT128 + +# struct tm tm_zone is a POSIX.1-2024 addition. +AC_CHECK_MEMBERS([struct tm.tm_zone],,,[#include <time.h>]) + if test "${multilib}" = "yes"; then multilib_arg="--enable-multilib" else diff --git a/libgcobol/configure.tgt b/libgcobol/configure.tgt index c5e263a..a239252 100644 --- a/libgcobol/configure.tgt +++ b/libgcobol/configure.tgt @@ -34,7 +34,12 @@ case "${target}" in LIBGCOBOL_SUPPORTED=yes fi ;; - x86_64-*-linux* | i?86-*-linux*) + riscv64-*-linux*) + if test x$ac_cv_sizeof_void_p = x8; then + LIBGCOBOL_SUPPORTED=yes + fi + ;; + x86_64-*-linux* | i?86-*-linux* | x86_64-*-darwin*) if test x$ac_cv_sizeof_void_p = x8; then LIBGCOBOL_SUPPORTED=yes fi diff --git a/libgcobol/constants.cc b/libgcobol/constants.cc index d37c791..eebfd21 100644 --- a/libgcobol/constants.cc +++ b/libgcobol/constants.cc @@ -27,18 +27,22 @@ * (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 <ctype.h> -#include <errno.h> + #include <fcntl.h> -#include <math.h> -#include <fenv.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> #include <unistd.h> + +#include <cctype> +#include <cerrno> +#include <cmath> +#include <cfenv> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> + #include <algorithm> #include <unordered_map> +#include <vector> #include "ec.h" #include "io.h" diff --git a/libgcobol/ec.h b/libgcobol/ec.h index 69d9731..4315d19 100644 --- a/libgcobol/ec.h +++ b/libgcobol/ec.h @@ -33,7 +33,6 @@ #define _CBL_EC_H_ #include <set> -#include <assert.h> #define EC_ALL_E 0xFFFFFF00 diff --git a/libgcobol/exceptl.h b/libgcobol/exceptl.h index 3580903..dcad545 100644 --- a/libgcobol/exceptl.h +++ b/libgcobol/exceptl.h @@ -117,140 +117,4 @@ extern ec_descr_t *__gg__exception_table_end; */ -// SymException -struct cbl_exception_t { - size_t program, file; - ec_type_t type; - cbl_file_mode_t mode; -}; - - -struct cbl_declarative_t { - enum { files_max = 16 }; - size_t section; // implies program - bool global; - ec_type_t type; - uint32_t nfile, files[files_max]; - cbl_file_mode_t mode; - - cbl_declarative_t( cbl_file_mode_t mode = file_mode_none_e ) - : section(0), global(false), type(ec_none_e) - , nfile(0) - , mode(mode) - { - std::fill(files, files + COUNT_OF(files), 0); - } - cbl_declarative_t( ec_type_t type ) - : section(0), global(false), type(type) - , nfile(0) - , mode(file_mode_none_e) - { - std::fill(files, files + COUNT_OF(files), 0); - } - - cbl_declarative_t( size_t section, ec_type_t type, - const std::list<size_t>& files, - cbl_file_mode_t mode, bool global = false ) - : section(section), global(global), type(type) - , nfile(files.size()) - , mode(mode) - { - assert( files.size() <= COUNT_OF(this->files) ); - std::fill(this->files, this->files + COUNT_OF(this->files), 0); - if( nfile > 0 ) { - std::copy( files.begin(), files.end(), this->files ); - } - } - cbl_declarative_t( const cbl_declarative_t& that ) - : section(that.section), global(that.global), type(that.type) - , nfile(that.nfile) - , mode(that.mode) - { - std::fill(files, files + COUNT_OF(files), 0); - if( nfile > 0 ) { - std::copy( that.files, that.files + nfile, this->files ); - } - } - - /* - * Sort file names before file modes, and file modes before non-IO. - */ - bool operator<( const cbl_declarative_t& that ) const { - // file name declaratives first, in section order - if( nfile != 0 ) { - if( that.nfile != 0 ) return section < that.section; - return true; - } - // file mode declaratives between file name declaratives and non-IO - if( mode != file_mode_none_e ) { - if( that.nfile != 0 ) return false; - if( that.mode == file_mode_none_e ) return true; - return section < that.section; - } - // all others by section, after names and modes - if( that.nfile != 0 ) return false; - if( that.mode != file_mode_none_e ) return false; - return section < that.section; - } - - // TRUE if there are no files to match, or the provided file is in the list. - bool match_file( size_t file ) const { - static const auto pend = files + nfile; - - return nfile == 0 || pend != std::find(files, files + nfile, file); - } - - // USE Format 1 names a file mode, or at least one file, and not an EC. - bool is_format_1() const { - assert(type != ec_none_e || nfile > 0 || mode != file_mode_none_e); - return nfile > 0 || mode != file_mode_none_e; - } -}; - - -/* - * ec_status_t represents the runtime exception condition status for - * any statement. Prior to execution, the generated code - * clears "type", and sets "source_file" and "lineno". - * - * If the statement includes some kind of ON ERROR - * clause, the generated code sets "handled" to the exception type - * handled by that clause, else it sets "handled" to ec_none_e. - * - * Post-execution, the generated code sets "type" to the appropriate - * exception, if any. The match-exception logic compares any raised - * exception to the set of declaratives, and returns a symbol-table - * index to the matching declarative, if any. - */ -class ec_status_t { - char msg[132]; -public: - ec_type_t type, handled; - cbl_name_t statement; // e.g., "ADD" - size_t lineno; - const char *source_file; - - ec_status_t() - : type(ec_none_e) - , handled(ec_none_e) - , lineno(0) - , source_file(NULL) - { - msg[0] = statement[0] = '\0'; - } - - ec_status_t& update(); - ec_status_t& enable( unsigned int mask ); - - const char * exception_location() { - snprintf(msg, sizeof(msg), "%s:%zu: '%s'", source_file, lineno, statement); - return msg; - } - ec_type_t unhandled() const { - return ec_type_t(static_cast<unsigned int>(type) - & - ~static_cast<unsigned int>(handled)); - } -}; - #endif diff --git a/libgcobol/gcobolio.h b/libgcobol/gcobolio.h index f1a26a2..2ca8883 100644 --- a/libgcobol/gcobolio.h +++ b/libgcobol/gcobolio.h @@ -30,7 +30,8 @@ #ifndef GCOBOLIO_H_ #define GCOBOLIO_H_ -#include <stdio.h> +#include <cstdio> + #include <map> #include <unordered_map> #include <vector> @@ -55,7 +56,7 @@ typedef struct cblc_field_t struct cblc_field_t *parent;// This field's immediate parent field size_t occurs_lower; // non-zero for a table size_t occurs_upper; // non-zero for a table - size_t attr; // See cbl_field_attr_t + unsigned long long attr; // See cbl_field_attr_t signed char type; // A one-byte copy of cbl_field_type_t signed char level; // This variable's level in the naming heirarchy signed char digits; // Digits specified in PIC string; e.g. 5 for 99v999 @@ -96,6 +97,7 @@ typedef struct cblc_file_t { // This structure must match the code in structs.cc char *name; // This is the name of the structure; might be the name of an environment variable + size_t symbol_table_index; // of the related cbl_field_t structure char *filename; // The name of the file to be opened FILE *file_pointer; // The FILE *pointer cblc_field_t *default_record; // The record_area diff --git a/libgcobol/gfileio.cc b/libgcobol/gfileio.cc index ed250c4..51a73cd 100644 --- a/libgcobol/gfileio.cc +++ b/libgcobol/gfileio.cc @@ -27,20 +27,24 @@ * (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 <ctype.h> -#include <ctype.h> + #include <err.h> -#include <errno.h> #include <fcntl.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> #include <unistd.h> + +#include <cctype> +#include <cerrno> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> + #include <algorithm> +#include <vector> #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "io.h" @@ -187,11 +191,12 @@ handle_errno(cblc_file_t *file, const char *function, const char *msg) static char * -get_filename( cblc_file_t *file, +get_filename( const cblc_file_t *file, int is_quoted) { static size_t fname_size = MINIMUM_ALLOCATION_SIZE; - static char *fname = (char *)malloc(MINIMUM_ALLOCATION_SIZE); + static char *fname = static_cast<char *>(malloc(MINIMUM_ALLOCATION_SIZE)); + massert(fname); fname = internal_to_console(&fname, &fname_size, file->filename, @@ -201,14 +206,15 @@ get_filename( cblc_file_t *file, { // We have been given something that might be the name of an // environment variable that contains the filename: - char *p_from_environment = getenv(fname); + const char *p_from_environment = getenv(fname); if( p_from_environment ) { if( strlen(p_from_environment)+1 > fname_size ) { fname_size = strlen(p_from_environment)+1; free(fname); - fname = (char *)malloc(fname_size); + fname = static_cast<char *>(malloc(fname_size)); + massert(fname); } strcpy(fname, p_from_environment); } @@ -252,7 +258,7 @@ establish_status(cblc_file_t *file, long read_location) 0, truncation_e, NULL); - // Set the EC-EXCEPTION accoring the status code + // Set the EC-EXCEPTION according to the status code __gg__set_exception_file(file); } @@ -268,7 +274,7 @@ __gg__set_user_status(cblc_field_t *ustatus, cblc_file_t *file) } static long -max_value(cblc_field_t *key) +max_value(const cblc_field_t *key) { long retval; if( key->digits ) @@ -298,6 +304,7 @@ void __gg__file_init( cblc_file_t *file, const char *name, + size_t symbol_table_index, cblc_field_t **keys, int *key_numbers, int *uniques, @@ -318,6 +325,7 @@ __gg__file_init( if( !(file->flags & file_flag_initialized_e) ) { file->name = strdup(name); + file->symbol_table_index = symbol_table_index; file->filename = NULL ; file->file_pointer = NULL ; file->keys = keys; @@ -531,7 +539,8 @@ relative_file_delete_varying(cblc_file_t *file, bool is_random) size_t payload_length; - unsigned char *stash = (unsigned char *)malloc(file->default_record->capacity); + unsigned char *stash = static_cast<unsigned char *>(malloc(file->default_record->capacity)); + massert(stash); memcpy(stash, file->default_record->data, file->default_record->capacity); long starting_pos = ftell(file->file_pointer); @@ -631,7 +640,7 @@ done: memcpy(file->default_record->data, stash, file->default_record->capacity); free(stash); fseek(file->file_pointer, starting_pos, SEEK_SET); - + file->prior_op = file_op_delete; establish_status(file, -1); } @@ -648,7 +657,8 @@ relative_file_delete(cblc_file_t *file, bool is_random) char record_marker; - unsigned char *stash = (unsigned char *)malloc(file->default_record->capacity); + unsigned char *stash = static_cast<unsigned char *>(malloc(file->default_record->capacity)); + massert(stash); memcpy(stash, file->default_record->data, file->default_record->capacity); long starting_pos = ftell(file->file_pointer); @@ -740,6 +750,7 @@ done: memcpy(file->default_record->data, stash, file->default_record->capacity); free(stash); fseek(file->file_pointer, starting_pos, SEEK_SET); + file->prior_op = file_op_delete; establish_status(file, -1); } @@ -822,7 +833,7 @@ read_an_indexed_record( cblc_file_t *file, goto done; } - record_length = ach[0]<<8; + record_length = static_cast<long>(ach[0])<<8; record_length += ach[1]; if(ach[2] != 0) { @@ -899,7 +910,7 @@ position_state_preserve(cblc_file_t *file, position_state_t &state) } static void -position_state_restore(cblc_file_t *file, position_state_t &state) +position_state_restore(cblc_file_t *file, const position_state_t &state) { file->recent_key = state.recent_key; fseek(file->file_pointer, state.starting_position, SEEK_SET); @@ -966,7 +977,8 @@ indexed_file_delete(cblc_file_t *file, bool is_random) // and the record area itself are unchanged by the delete operation. // So, we save the current record area: - stash = (unsigned char *)malloc(file->record_area_max); + stash = static_cast<unsigned char *>(malloc(file->record_area_max)); + massert(stash); memcpy(stash, file->default_record->data, file->record_area_max); // And the position state of our file @@ -1044,8 +1056,6 @@ indexed_file_delete(cblc_file_t *file, bool is_random) // we find one, we check to see if the keys match. If the keys don't // match, then we have to remove the existing one from the index. - std::vector<unsigned char> the_key - = file_indexed_make_key(file, key_number); bool deleting = true; while(deleting) { @@ -1062,6 +1072,7 @@ indexed_file_delete(cblc_file_t *file, bool is_random) deleting = true; break; } + it++; } } @@ -1094,9 +1105,11 @@ done: memcpy(file->default_record->data, stash, file->record_area_min); free(stash); stash = NULL; + file->prior_op = file_op_delete; position_state_restore(file, position_state); } + file->prior_op = file_op_delete; establish_status(file, -1); } @@ -1123,7 +1136,6 @@ __io__file_delete(cblc_file_t *file, bool is_random) { file->flags |= file_flag_existed_e; } - file->prior_op = file_op_delete; } static void @@ -1226,7 +1238,7 @@ indexed_file_start( cblc_file_t *file, file->io_status = FsErrno; } } - else if( result < 0 ) + else // if( result < 0 ) { // The index is less than the key. if( relop == lt_op @@ -1528,12 +1540,12 @@ done: file->flags |= file_flag_existed_e; } + file->prior_op = file_op_start; establish_status(file, fpos); if( file->io_status < FhNotOkay ) { file->flags |= file_flag_existed_e; } - file->prior_op = file_op_start; } static void @@ -1648,7 +1660,7 @@ sequential_file_rewrite( cblc_file_t *file, size_t length ) if( file->record_area_min != file->record_area_max ) { - unsigned char preamble[4] = + const unsigned char preamble[4] = { (unsigned char)(bytes_to_write>>8), (unsigned char)(bytes_to_write), @@ -1678,10 +1690,8 @@ sequential_file_rewrite( cblc_file_t *file, size_t length ) done: // Per the standard, return the file location pointer back to whence it came: fseek(file->file_pointer, starting_position, SEEK_SET); - if( handle_ferror(file, __func__, "fseek() error") ) - { - goto done; - } + handle_ferror(file, __func__, "fseek() error"); + file->prior_op = file_op_rewrite; establish_status(file, starting_position); } @@ -1797,10 +1807,8 @@ relative_file_rewrite_varying( cblc_file_t *file, bool is_random ) done: // Per the standard, return the file location pointer back to whence it came: fseek(file->file_pointer, starting_position, SEEK_SET); - if( handle_ferror(file, __func__, "fseek() error") ) - { - goto done; - } + handle_ferror(file, __func__, "fseek() error"); + file->prior_op = file_op_rewrite; establish_status(file, starting_position); } @@ -1900,10 +1908,8 @@ relative_file_rewrite( cblc_file_t *file, size_t length, bool is_random ) done: // Per the standard, return the file location pointer back to whence it came: fseek(file->file_pointer, starting_position, SEEK_SET); - if( handle_ferror(file, __func__, "fseek() error") ) - { - goto done; - } + handle_ferror(file, __func__, "fseek() error"); + file->prior_op = file_op_rewrite; establish_status(file, starting_position); } @@ -2172,7 +2178,7 @@ done: { position_state_restore(file, position_state); } - + file->prior_op = file_op_rewrite; establish_status(file, fpos); file->prior_read_location = -1; } @@ -2203,12 +2209,11 @@ __io__file_rewrite(cblc_file_t *file, size_t length, bool is_random) { file->flags |= file_flag_existed_e; } - file->prior_op = file_op_rewrite; } static void relative_file_write_varying(cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, bool is_random) { @@ -2351,12 +2356,13 @@ relative_file_write_varying(cblc_file_t *file, } done: + file->prior_op = file_op_write; establish_status(file, -1); } static void relative_file_write(cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, bool is_random) { @@ -2371,7 +2377,7 @@ relative_file_write(cblc_file_t *file, file->io_status = FsErrno; long necessary_file_size; - unsigned char achPostamble[] = {internal_cr, internal_newline}; + const unsigned char achPostamble[] = {internal_cr, internal_newline}; relative_file_parameters rfp; @@ -2484,12 +2490,13 @@ relative_file_write(cblc_file_t *file, } done: + file->prior_op = file_op_write; establish_status(file, -1); } static void sequential_file_write(cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, int after, int lines) @@ -2605,7 +2612,7 @@ sequential_file_write(cblc_file_t *file, { // Because of the min/max mismatch, we require a preamble: // The first two bytes are the big-endian character count - unsigned char preamble[4] = + const unsigned char preamble[4] = { (unsigned char)(characters_to_write>>8), (unsigned char)(characters_to_write), @@ -2671,12 +2678,13 @@ sequential_file_write(cblc_file_t *file, } done: + file->prior_op = file_op_write; establish_status(file, -1); } static void indexed_file_write( cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, bool is_random) { @@ -2747,13 +2755,13 @@ indexed_file_write( cblc_file_t *file, // We are allowed to do the write, but only if there will be no key // violations as a result: - for(size_t key_number=1; - key_number<file->supplemental->indexes.size(); - key_number++) + for(size_t keynum=1; + keynum<file->supplemental->indexes.size(); + keynum++) { - if( file->supplemental->uniques[key_number] ) + if( file->supplemental->uniques[keynum] ) { - long record_position = file_indexed_first_position(file, key_number); + long record_position = file_indexed_first_position(file, keynum); if( record_position != -1 ) { // No can do, because we already have a unique key with that value @@ -2838,12 +2846,13 @@ indexed_file_write( cblc_file_t *file, file_indexed_update_indices(file, position_to_write); done: + file->prior_op = file_op_write; establish_status(file, -1); } static void __io__file_write( cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, int after, int lines, @@ -2924,12 +2933,12 @@ __io__file_write( cblc_file_t *file, break; } done: + file->prior_op = file_op_write; establish_status(file, -1); if( file->io_status < FhNotOkay ) { file->flags |= file_flag_existed_e; } - file->prior_op = file_op_write; } static void @@ -2977,7 +2986,7 @@ line_sequential_file_read( cblc_file_t *file) { break; } - if( ch == file->delimiter || ch == EOF ) + if( ch == EOF ) { hit_eof = true; clearerr(file->file_pointer); @@ -3073,6 +3082,7 @@ line_sequential_file_read( cblc_file_t *file) NULL); } done: + file->prior_op = file_op_read; establish_status(file, fpos); } @@ -3185,6 +3195,7 @@ sequential_file_read( cblc_file_t *file) NULL); } done: + file->prior_op = file_op_read; establish_status(file, fpos); return characters_read; } @@ -3372,6 +3383,7 @@ done: truncation_e, NULL); } + file->prior_op = file_op_read; establish_status(file, fpos); } @@ -3570,6 +3582,7 @@ done: truncation_e, NULL); } + file->prior_op = file_op_read; establish_status(file, fpos); } @@ -3637,6 +3650,7 @@ indexed_file_read( cblc_file_t *file, goto done; } + // cppcheck-suppress derefInvalidIteratorRedundantCheck fpos = file_index->current_iterator->second; if( file_index->current_iterator == file_index->key_to_position.end() ) @@ -3718,6 +3732,7 @@ indexed_file_read( cblc_file_t *file, // We are ready to proceed + // cppcheck-suppress derefInvalidIteratorRedundantCheck fpos = file_index->current_iterator->second; if( file_index->current_iterator == file_index->key_to_position.end() ) { @@ -3763,6 +3778,7 @@ done: truncation_e, NULL); } + file->prior_op = file_op_read; establish_status(file, fpos); } @@ -3791,6 +3807,7 @@ __io__file_read(cblc_file_t *file, { file->io_status = FsReadError; // "46" } + file->prior_op = file_op_read; establish_status(file, -1); return; } @@ -3809,12 +3826,14 @@ __io__file_read(cblc_file_t *file, { file->io_status = FsReadError; // "46" } + file->prior_op = file_op_read; establish_status(file, -1); } else { // This is a format 2 read file->io_status = FsNotFound; // "23" + file->prior_op = file_op_read; establish_status(file, -1); } return; @@ -3825,6 +3844,7 @@ __io__file_read(cblc_file_t *file, { // Attempting to read a file that isn't open file->io_status = FsReadNotOpen; // "47" + file->prior_op = file_op_read; establish_status(file, -1); return; } @@ -3833,6 +3853,7 @@ __io__file_read(cblc_file_t *file, { // The file is open, but not in INPUT or I-O mode: file->io_status = FsReadNotOpen; // "47" + file->prior_op = file_op_read; establish_status(file, -1); return; } @@ -3875,7 +3896,6 @@ __io__file_read(cblc_file_t *file, { file->flags |= file_flag_existed_e; } - file->prior_op = file_op_read; } static void @@ -3907,7 +3927,6 @@ file_indexed_open(cblc_file_t *file) { if( file->key_numbers[index] != current_key_number ) { - file_index_t file_index; file->supplemental->indexes.push_back(file_index); current_key_number = file->key_numbers[index]; file->supplemental->uniques.push_back(file->uniques[index]); @@ -3937,7 +3956,8 @@ file_indexed_open(cblc_file_t *file) // We need to open the file for reading, and build the // maps for each index: static size_t fname_size = MINIMUM_ALLOCATION_SIZE; - static char *fname = (char *)malloc(fname_size); + static char *fname = static_cast<char *>(malloc(fname_size)); + massert(fname); internal_to_console(&fname, &fname_size, @@ -3954,7 +3974,8 @@ file_indexed_open(cblc_file_t *file) } // Stash the existing record area: - stash = (unsigned char *)malloc(file->record_area_max); + stash = static_cast<unsigned char *>(malloc(file->record_area_max)); + massert(stash); memcpy( stash, file->default_record->data, file->record_area_max); @@ -4054,34 +4075,6 @@ file_indexed_close(cblc_file_t *file) file->supplemental = NULL; } -static void -report_open_failure(const char *type, - const char *structure_name, - const char *filename) - { - bool quiet = true; - if( !quiet ) - { - if( getenv(filename) ) - { - fprintf(stderr, - "Trying to 'OPEN %s %s %s -> \"%s\"', which doesn't exist\n", - type, - structure_name, - filename, - getenv(filename)); - } - else - { - fprintf(stderr, - "Trying to 'OPEN %s %s \"%s\"', which doesn't exist\n", - type, - structure_name, - filename); - } - } - } - extern "C" void __gg__file_reopen(cblc_file_t *file, int mode_char) @@ -4124,7 +4117,8 @@ __gg__file_reopen(cblc_file_t *file, int mode_char) } static size_t fname_size = MINIMUM_ALLOCATION_SIZE; - static char *fname = (char *)malloc(fname_size); + static char *fname = static_cast<char *>(malloc(fname_size)); + massert(fname) internal_to_console(&fname, &fname_size, file->filename, @@ -4210,7 +4204,6 @@ __gg__file_reopen(cblc_file_t *file, int mode_char) } else { - report_open_failure("INPUT", file->name, trimmed_name); file->io_status = FsNoFile; // "35" goto done; } @@ -4252,7 +4245,6 @@ __gg__file_reopen(cblc_file_t *file, int mode_char) else { // Trying to extend a non-optional non-existing file is against the rules - report_open_failure("EXTEND", file->name, trimmed_name); file->io_status = FsNoFile; // "35" goto done; } @@ -4268,7 +4260,6 @@ __gg__file_reopen(cblc_file_t *file, int mode_char) } else { - report_open_failure("I-O", file->name, trimmed_name); file->io_status = FsNoFile; // "35" goto done; } @@ -4357,8 +4348,8 @@ __io__file_open(cblc_file_t *file, __gg__file_reopen(file, mode_char); } - establish_status(file, -1); file->prior_op = file_op_open; + establish_status(file, -1); } static void @@ -4417,8 +4408,8 @@ __io__file_close( cblc_file_t *file, int how ) file->filename = NULL; done: - establish_status(file, fpos); file->prior_op = file_op_close; + establish_status(file, fpos); } static cblc_file_t *stashed; @@ -4481,7 +4472,7 @@ public: typedef void (read_t)( cblc_file_t *file, int where ); typedef void (write_t)( cblc_file_t *file, - unsigned char *location, + const unsigned char *location, size_t length, int after, int lines, diff --git a/libgcobol/gmath.cc b/libgcobol/gmath.cc index fb2eae3..8a9880b 100644 --- a/libgcobol/gmath.cc +++ b/libgcobol/gmath.cc @@ -27,26 +27,30 @@ * (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 <ctype.h> -#include <errno.h> + #include <fcntl.h> -#include <math.h> -#include <fenv.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> #include <unistd.h> + +#include <cctype> +#include <cerrno> +#include <cmath> +#include <cfenv> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> + #include <algorithm> +#include <vector> #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" #include "io.h" #include "gcobolio.h" #include "libgcobol.h" -#include "common-defs.h" #include "gmath.h" #include "gcobolio.h" @@ -54,10 +58,6 @@ #include <sys/stat.h> #include <sys/types.h> -#ifdef __aarch64__ -#define __float128 _Float128 -#endif - #define MAX_INTERMEDIATE_BITS 126 #define MAX_INTERMEDIATE_DECIMALS 16 @@ -88,7 +88,8 @@ conditional_stash( cblc_field_t *destination, // This is slightly more complex, because in the event of a // SIZE ERROR. we need to leave the original value untouched - unsigned char *stash = (unsigned char *)malloc(destination_s); + unsigned char *stash = static_cast<unsigned char *>(malloc(destination_s)); + massert(stash); memcpy(stash, destination->data+destination_o, destination_s); __gg__int128_to_qualified_field(destination, @@ -114,7 +115,7 @@ conditional_stash( cblc_field_t *destination, size_t destination_o, size_t destination_s, bool on_error_flag, - _Float128 value, + GCOB_FP128 value, cbl_round_t rounded) { int retval = compute_error_none; @@ -132,7 +133,9 @@ conditional_stash( cblc_field_t *destination, { // This is slightly more complex, because in the event of a // SIZE ERROR. we need to leave the original value untouched - unsigned char *stash = (unsigned char *)malloc(destination_s); + assert(destination_s); + unsigned char *stash = static_cast<unsigned char *>(malloc(destination_s)); + massert(stash); memcpy(stash, destination->data+destination_o, destination_s); __gg__float128_to_qualified_field(destination, destination_o, @@ -150,15 +153,10 @@ conditional_stash( cblc_field_t *destination, return retval; } - -#if defined(__aarch64__) -# define __float128 _Float128 /* double */ -#endif - static -_Float128 -divide_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +divide_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { if( b_value == 0 ) @@ -187,9 +185,9 @@ divide_helper_float(_Float128 a_value, } static -_Float128 -multiply_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +multiply_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value *= b_value; @@ -210,9 +208,9 @@ multiply_helper_float(_Float128 a_value, } static -_Float128 -addition_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +addition_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value += b_value; @@ -233,9 +231,9 @@ addition_helper_float(_Float128 a_value, } static -_Float128 -subtraction_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +subtraction_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value -= b_value; @@ -261,24 +259,24 @@ __gg__pow( cbl_arith_format_t, size_t, size_t, size_t, - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; - cblc_field_t **B = __gg__treeplet_2f; - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; - - _Float128 avalue = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); - _Float128 bvalue = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); - _Float128 tgt_value; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; + cblc_field_t **B = __gg__treeplet_2f; + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; + + GCOB_FP128 avalue = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); + GCOB_FP128 bvalue = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 tgt_value; if( avalue == 0 && bvalue == 0 ) { @@ -295,7 +293,7 @@ __gg__pow( cbl_arith_format_t, // Calculate our answer, in floating point: errno = 0; feclearexcept(FE_ALL_EXCEPT); - tgt_value = powf128(avalue, bvalue); + tgt_value = FP128_FUNC(pow)(avalue, bvalue); if( errno || fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) ) { // One of a large number of errors took place. See math_error(7) and @@ -373,8 +371,8 @@ multiply_int256_by_int64(int256 &product, const uint64_t multiplier) for(int i=0; i<4; i++) { uint128 temp = (uint128)product.i64[i] * multiplier; - product.i64[i] = *(uint64_t *)(&temp); - overflows[i+1] = *(uint64_t *)((uint8_t *)(&temp) + 8); + product.i64[i] = *PTRCAST(uint64_t, &temp); + overflows[i+1] = *PTRCAST(uint64_t, PTRCAST(uint8_t, &temp) + 8); } for(int i=1; i<4; i++) @@ -391,7 +389,7 @@ multiply_int256_by_int64(int256 &product, const uint64_t multiplier) } static int -add_int256_to_int256(int256 &sum, const int256 addend) +add_int256_to_int256(int256 &sum, const int256 &addend) { uint128 overflows[3] = {}; for(int i=0; i<2; i++) @@ -456,10 +454,11 @@ divide_int256_by_int64(int256 &val, uint64_t divisor) for( int i=3; i>=0; i-- ) { // Left shift temp 64 bits: - *(uint64_t *)(((uint8_t *)&temp)+8) = *(uint64_t *)(((uint8_t *)&temp)+0); + *PTRCAST(uint64_t, ((PTRCAST(uint8_t, &temp))+8)) + = *PTRCAST(uint64_t, ((PTRCAST(uint8_t, &temp))+0)); // Put the high digit of val into the bottom of temp - *(uint64_t *)(((uint8_t *)&temp)+0) = val.i64[i]; + *PTRCAST(uint64_t, ((PTRCAST(uint8_t, &temp))+0)) = val.i64[i]; // Divide that combinary by divisor to get the new digits val.i64[i] = temp / divisor; @@ -474,7 +473,8 @@ squeeze_int256(int256 &val, int &rdigits) { int overflow = 0; // It has been decreed that at this juncture the result must fit into - // MAX_FIXED_POINT_DIGITS. If the result does not, we have an OVERFLOW error. + // MAX_FIXED_POINT_DIGITS. If the result does not, we have an OVERFLOW + // error. int is_negative = val.data[31] & 0x80; if( is_negative ) @@ -482,9 +482,9 @@ squeeze_int256(int256 &val, int &rdigits) negate_int256(val); } - // As long as there are some decimal places left, we hold our nose and right- - // shift a too-large value rightward by decimal digits. In other words, we - // truncate the fractional part to make room for the integer part: + // As long as there are some decimal places left, we hold our nose and + // right-shift a too-large value rightward by decimal digits. In other + // words, we truncate the fractional part to make room for the integer part: while(rdigits > 0 && val.i128[1] ) { divide_int256_by_int64(val, 10UL); @@ -509,7 +509,7 @@ squeeze_int256(int256 &val, int &rdigits) // These sixteen bytes comprise the binary value of 10^38 static const uint8_t C1038[] = {0x00, 0x00, 0x00, 0x00, 0x40, 0x22, 0x8a, 0x09, 0x7a, 0xc4, 0x86, 0x5a, 0xa8, 0x4c, 0x3b, 0x4b}; - static const uint128 biggest = *(uint128 *)C1038; + static const uint128 biggest = *reinterpret_cast<const uint128 *>(C1038); // If we still have some rdigits to throw away, we can keep shrinking // the value: @@ -545,7 +545,7 @@ squeeze_int256(int256 &val, int &rdigits) static void get_int256_from_qualified_field(int256 &var, int &rdigits, - cblc_field_t *field, + const cblc_field_t *field, size_t field_o, size_t field_s) { @@ -568,7 +568,7 @@ get_int256_from_qualified_field(int256 &var, static int256 phase1_result; static int phase1_rdigits; -static _Float128 phase1_result_float; +static GCOB_FP128 phase1_result_float; extern "C" void @@ -576,7 +576,7 @@ __gg__add_fixed_phase1( cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *, + const cbl_round_t *, int , int *compute_error ) @@ -585,9 +585,9 @@ __gg__add_fixed_phase1( cbl_arith_format_t , // The result goes into the temporary phase1_result. - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; // Let us prime the pump with the first value of A[] get_int256_from_qualified_field(phase1_result, phase1_rdigits, A[0], A_o[0], A_s[0]); @@ -605,7 +605,6 @@ __gg__add_fixed_phase1( cbl_arith_format_t , if( phase1_rdigits > temp_rdigits ) { scale_int256_by_digits(temp, phase1_rdigits - temp_rdigits); - temp_rdigits = phase1_rdigits; } else if( phase1_rdigits < temp_rdigits ) { @@ -633,14 +632,14 @@ __gg__addf1_fixed_phase2( cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; // This is the assignment phase of an ADD Format 1 @@ -654,11 +653,11 @@ __gg__addf1_fixed_phase2( cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); // Pick up the target - _Float128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); value_a += value_b; @@ -685,7 +684,6 @@ __gg__addf1_fixed_phase2( cbl_arith_format_t , if( rdigits_a > rdigits_b ) { scale_int256_by_digits(value_b, rdigits_a - rdigits_b); - rdigits_b = rdigits_a; } else if( rdigits_a < rdigits_b ) { @@ -718,16 +716,16 @@ __gg__fixed_phase2_assign_to_c( cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { // This is the assignment phase of an ADD Format 2 - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; // We take phase1_result and put it into C @@ -740,7 +738,7 @@ __gg__fixed_phase2_assign_to_c( cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], @@ -776,7 +774,7 @@ __gg__add_float_phase1( cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *, + const cbl_round_t *, int , int *compute_error ) @@ -785,9 +783,9 @@ __gg__add_float_phase1( cbl_arith_format_t , // The result goes into the temporary phase1_result_ffloat. - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; // Let us prime the pump with the first value of A[] phase1_result_float = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); @@ -796,7 +794,7 @@ __gg__add_float_phase1( cbl_arith_format_t , for( size_t i=1; i<nA; i++ ) { - _Float128 temp = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); + GCOB_FP128 temp = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); phase1_result_float = addition_helper_float(phase1_result_float, temp, compute_error); @@ -809,20 +807,20 @@ __gg__addf1_float_phase2( cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); // This is the assignment phase of an ADD Format 2 // We take phase1_result and accumulate it into C - _Float128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); temp = addition_helper_float(temp, phase1_result_float, compute_error); *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], on_size_error, @@ -836,14 +834,14 @@ __gg__float_phase2_assign_to_c( cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); // This is the assignment phase of an ADD Format 2 @@ -861,7 +859,7 @@ __gg__addf3(cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) @@ -869,13 +867,13 @@ __gg__addf3(cbl_arith_format_t , // This is an ADD Format 3. Each A[i] gets accumulated into each C[i]. When // both are fixed, we do fixed arithmetic. When either is a FldFloat, we // do floating-point arithmetic. - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); @@ -883,8 +881,8 @@ __gg__addf3(cbl_arith_format_t , { if( A[i]->type == FldFloat || C[i]->type == FldFloat ) { - _Float128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); - _Float128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); + GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); value_a = addition_helper_float(value_a, value_b, compute_error); @@ -911,7 +909,6 @@ __gg__addf3(cbl_arith_format_t , if( rdigits_a > rdigits_b ) { scale_int256_by_digits(value_b, rdigits_a - rdigits_b); - rdigits_b = rdigits_a; } else if( rdigits_a < rdigits_b ) { @@ -945,14 +942,14 @@ __gg__subtractf1_fixed_phase2(cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; // This is the assignment phase of an ADD Format 1 @@ -966,11 +963,11 @@ __gg__subtractf1_fixed_phase2(cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); // Pick up the target - _Float128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); value_b -= value_a; @@ -1002,7 +999,6 @@ __gg__subtractf1_fixed_phase2(cbl_arith_format_t , else if( rdigits_a < rdigits_b ) { scale_int256_by_digits(value_a, rdigits_b - rdigits_a); - rdigits_a = rdigits_b; } // The two numbers have the same number of rdigits. It's now safe to add @@ -1030,16 +1026,16 @@ __gg__subtractf2_fixed_phase1(cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { // This is the calculation phase of a fixed-point SUBTRACT Format 2 - cblc_field_t **B = __gg__treeplet_2f; - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; + cblc_field_t **B = __gg__treeplet_2f; + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; // Add up all the A values __gg__add_fixed_phase1( not_expected_e , @@ -1070,7 +1066,6 @@ __gg__subtractf2_fixed_phase1(cbl_arith_format_t , else if( rdigits_a < rdigits_b ) { scale_int256_by_digits(value_a, rdigits_b - rdigits_a); - rdigits_a = rdigits_b; } // The two numbers have the same number of rdigits. It's now safe to add @@ -1086,27 +1081,26 @@ __gg__subtractf2_fixed_phase1(cbl_arith_format_t , phase1_rdigits = rdigits_b; } - extern "C" void __gg__subtractf1_float_phase2(cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); // This is the assignment phase of an ADD Format 2 // We take phase1_result and subtract it from C - _Float128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); temp = subtraction_helper_float(temp, phase1_result_float, compute_error); *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], on_size_error, @@ -1114,23 +1108,22 @@ __gg__subtractf1_float_phase2(cbl_arith_format_t , *rounded++); } - extern "C" void __gg__subtractf2_float_phase1(cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { // This is the calculation phase of a fixed-point SUBTRACT Format 2 - cblc_field_t **B = __gg__treeplet_2f; - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; + cblc_field_t **B = __gg__treeplet_2f; + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; // Add up all the A values __gg__add_float_phase1( not_expected_e , @@ -1143,7 +1136,7 @@ __gg__subtractf2_float_phase1(cbl_arith_format_t , ); // Subtract that from the B value: - _Float128 value_b = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); // The two numbers have the same number of rdigits. It's now safe to add // them. @@ -1156,7 +1149,7 @@ __gg__subtractf3( cbl_arith_format_t , size_t nA, size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) @@ -1164,12 +1157,12 @@ __gg__subtractf3( cbl_arith_format_t , // This is an ADD Format 3. Each A[i] gets accumulated into each C[i]. Each // SUBTRACTION is treated separately. - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); @@ -1177,8 +1170,8 @@ __gg__subtractf3( cbl_arith_format_t , { if( A[i]->type == FldFloat || C[i]->type == FldFloat) { - _Float128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); - _Float128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); + GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); value_b = subtraction_helper_float(value_b, value_a, compute_error); @@ -1210,7 +1203,6 @@ __gg__subtractf3( cbl_arith_format_t , else if( rdigits_a < rdigits_b ) { scale_int256_by_digits(value_a, rdigits_b - rdigits_a); - rdigits_a = rdigits_b; } // The two numbers have the same number of rdigits. It's now safe to add @@ -1235,7 +1227,7 @@ __gg__subtractf3( cbl_arith_format_t , } static bool multiply_intermediate_is_float; -static _Float128 multiply_intermediate_float; +static GCOB_FP128 multiply_intermediate_float; static __int128 multiply_intermediate_int128; static int multiply_intermediate_rdigits; @@ -1245,16 +1237,16 @@ __gg__multiplyf1_phase1(cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *, + const cbl_round_t *, int , int *) { // We are getting just the one value, which we are converting to the necessary // intermediate form - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; if( A[0]->type == FldFloat ) { @@ -1279,7 +1271,8 @@ void multiply_int128_by_int128(int256 &ABCD, __int128 ab_value, __int128 cd_value) { - int is_negative = ( ((uint8_t *)(&ab_value))[15]^((uint8_t *)(&cd_value))[15]) & 0x80; + int is_negative = ( (PTRCAST(uint8_t, (&ab_value)))[15] + ^(PTRCAST(uint8_t, (&cd_value)))[15]) & 0x80; if( ab_value < 0 ) { ab_value = -ab_value; @@ -1295,10 +1288,10 @@ void multiply_int128_by_int128(int256 &ABCD, uint128 BD; // Let's extract the digits. - uint64_t a = *(uint64_t *)((unsigned char *)(&ab_value)+8); - uint64_t b = *(uint64_t *)((unsigned char *)(&ab_value)+0); - uint64_t c = *(uint64_t *)((unsigned char *)(&cd_value)+8); - uint64_t d = *(uint64_t *)((unsigned char *)(&cd_value)+0); + uint64_t a = *PTRCAST(uint64_t, (PTRCAST(unsigned char, (&ab_value))+8)); + uint64_t b = *PTRCAST(uint64_t, (PTRCAST(unsigned char, (&ab_value))+0)); + uint64_t c = *PTRCAST(uint64_t, (PTRCAST(unsigned char, (&cd_value))+8)); + uint64_t d = *PTRCAST(uint64_t, (PTRCAST(unsigned char, (&cd_value))+0)); // multiply (a0 + b) * (c0 + d) @@ -1339,20 +1332,20 @@ __gg__multiplyf1_phase2(cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; - _Float128 a_value; - _Float128 b_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; if( multiply_intermediate_is_float ) { @@ -1374,10 +1367,10 @@ __gg__multiplyf1_phase2(cbl_arith_format_t , if( C[0]->type == FldFloat ) { // gixed * float - a_value = (_Float128) multiply_intermediate_int128; + a_value = (GCOB_FP128) multiply_intermediate_int128; if( multiply_intermediate_rdigits ) { - a_value /= (_Float128)__gg__power_of_ten(multiply_intermediate_rdigits); + a_value /= (GCOB_FP128)__gg__power_of_ten(multiply_intermediate_rdigits); } b_value = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); goto float_float; @@ -1420,14 +1413,13 @@ __gg__multiplyf1_phase2(cbl_arith_format_t , if( error_this_time && on_size_error) { *compute_error |= error_this_time; - rounded++; } else { *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], on_size_error, a_value, - *rounded++); + *rounded); } done: return; @@ -1439,32 +1431,32 @@ __gg__multiplyf2( cbl_arith_format_t , size_t , size_t , size_t nC, - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; - cblc_field_t **B = __gg__treeplet_2f; - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; + cblc_field_t **B = __gg__treeplet_2f; + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); bool got_float = false; - _Float128 product_float; + GCOB_FP128 product_float; int256 product_fix; int product_fix_digits; if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); - _Float128 b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); + GCOB_FP128 b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); product_float = multiply_helper_float(a_value, b_value, compute_error); got_float = true; } @@ -1522,7 +1514,7 @@ shift_in_place128(uint8_t *buf, int size, int bits) uint128 temp; uint128 overflow = 0; - uint128 *as128 = (uint128 *)buf; + uint128 *as128 = PTRCAST(uint128, buf); for( size_t i=0; i<places; i++ ) { @@ -1603,7 +1595,7 @@ divide_int128_by_int128(int256 "ient, } // We are going to be referencing the 64-bit pices of the 128-bit divisor: - uint64_t *divisor64 = (uint64_t *)&divisor; + uint64_t *divisor64 = PTRCAST(uint64_t, &divisor); quotient.i128[1] = 0; quotient.i128[0] = dividend; @@ -1672,12 +1664,11 @@ divide_int128_by_int128(int256 "ient, int bits_to_shift = 0; int i=15; - while( ((uint8_t *)(&divisor))[i] == 0 ) + while( (PTRCAST(uint8_t, &divisor))[i] == 0 ) { i -= 1; bits_to_shift += 8; - } - uint8_t tail = ((uint8_t *)(&divisor))[i]; + } uint8_t tail = ( PTRCAST(uint8_t, &divisor) )[i]; while( !(tail & 0x80) ) { bits_to_shift += 1; @@ -1686,9 +1677,8 @@ divide_int128_by_int128(int256 "ient, // Shift both the numerator and the divisor that number of bits - shift_in_place128((uint8_t *)&numerator, sizeof(numerator), bits_to_shift); - shift_in_place128((uint8_t *)&divisor, sizeof(divisor), bits_to_shift); - + shift_in_place128( PTRCAST(uint8_t, &numerator), sizeof(numerator), bits_to_shift); + shift_in_place128( PTRCAST(uint8_t, &divisor), sizeof(divisor), bits_to_shift); // We are now ready to do the guess-multiply-subtract loop. We know that // the result will have two places, so we know we are going to go through @@ -1705,7 +1695,7 @@ divide_int128_by_int128(int256 "ient, // We develop our guess for a quotient by dividing the top two places of // the numerator area by C uint128 temp; - uint64_t *temp64 = (uint64_t *)&temp; + uint64_t *temp64 = PTRCAST(uint64_t, &temp); temp64[1] = numerator.i64[q_place+2]; temp64[0] = numerator.i64[q_place+1]; @@ -1719,10 +1709,10 @@ divide_int128_by_int128(int256 "ient, subber[2] = 0; // Start with the bottom 128 bits of the "subber" - *(uint128 *)subber = (uint128) divisor64[0] * quotient.i64[q_place]; + *PTRCAST(uint128, subber) = (uint128) divisor64[0] * quotient.i64[q_place]; // Get the next 128 bits of subber - temp = (uint128) divisor64[1] * quotient.i64[q_place]; + temp = (uint128) divisor64[1] * quotient.i64[q_place]; // Add the top of the first product to the bottom of the second: subber[1] += temp64[0]; @@ -1743,20 +1733,20 @@ divide_int128_by_int128(int256 "ient, // the numerator: uint64_t borrow = 0; - for(size_t i=0; i<3; i++) + for(size_t j=0; j<3; j++) { - if( numerator.i64[q_place + i] == 0 && borrow ) + if( numerator.i64[q_place + j] == 0 && borrow ) { // We are subtracting from zero and we have a borrow. Leave the // borrow on and just do the subtraction: - numerator.i64[q_place + i] -= subber[i]; + numerator.i64[q_place + j] -= subber[j]; } else { - uint64_t stash = numerator.i64[q_place + i]; - numerator.i64[q_place + i] -= borrow; - numerator.i64[q_place + i] -= subber[i]; - if( numerator.i64[q_place + i] > stash ) + uint64_t stash = numerator.i64[q_place + j]; + numerator.i64[q_place + j] -= borrow; + numerator.i64[q_place + j] -= subber[j]; + if( numerator.i64[q_place + j] > stash ) { // After subtracting, the value got bigger, which means we have // to borrow from the next value to the left @@ -1780,21 +1770,21 @@ divide_int128_by_int128(int256 "ient, { // We need to add subber back into the numerator area uint64_t carry = 0; - for(size_t i=0; i<3; i++) + for(size_t ii=0; ii<3; ii++) { - if( numerator.i64[q_place + i] == 0xFFFFFFFFFFFFFFFFUL && carry ) + if( numerator.i64[q_place + ii] == 0xFFFFFFFFFFFFFFFFUL && carry ) { // We are at the top and have a carry. Just leave the carry on // and do the addition: - numerator.i64[q_place + i] += subber[i]; + numerator.i64[q_place + ii] += subber[ii]; } else { // We are not at the top. - uint64_t stash = numerator.i64[q_place + i]; - numerator.i64[q_place + i] += carry; - numerator.i64[q_place + i] += subber[i]; - if( numerator.i64[q_place + i] < stash ) + uint64_t stash = numerator.i64[q_place + ii]; + numerator.i64[q_place + ii] += carry; + numerator.i64[q_place + ii] += subber[ii]; + if( numerator.i64[q_place + ii] < stash ) { // The addition caused the result to get smaller, meaning that // we wrapped around: @@ -1822,20 +1812,20 @@ __gg__dividef1_phase2(cbl_arith_format_t , size_t , size_t , size_t , - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; - _Float128 a_value; - _Float128 b_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; if( multiply_intermediate_is_float ) { @@ -1857,10 +1847,10 @@ __gg__dividef1_phase2(cbl_arith_format_t , if( C[0]->type == FldFloat ) { // gixed * float - a_value = (_Float128) multiply_intermediate_int128; + a_value = (GCOB_FP128) multiply_intermediate_int128; if( multiply_intermediate_rdigits ) { - a_value /= (_Float128)__gg__power_of_ten(multiply_intermediate_rdigits); + a_value /= (GCOB_FP128)__gg__power_of_ten(multiply_intermediate_rdigits); } b_value = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); goto float_float; @@ -1909,14 +1899,13 @@ __gg__dividef1_phase2(cbl_arith_format_t , if( error_this_time && on_size_error) { - rounded++; } else { *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], on_size_error, b_value, - *rounded++); + *rounded); } done: return; @@ -1928,29 +1917,29 @@ __gg__dividef23(cbl_arith_format_t , size_t , size_t , size_t nC, - cbl_round_t *rounded, + const cbl_round_t *rounded, int on_error_flag, int *compute_error ) { - cblc_field_t **A = __gg__treeplet_1f; - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; - cblc_field_t **B = __gg__treeplet_2f; - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; - cblc_field_t **C = __gg__treeplet_3f; - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **A = __gg__treeplet_1f; + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; + cblc_field_t **B = __gg__treeplet_2f; + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; + cblc_field_t **C = __gg__treeplet_3f; + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value; - _Float128 b_value; - _Float128 c_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; + GCOB_FP128 c_value; a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); c_value = divide_helper_float(a_value, b_value, &error_this_time); @@ -2014,24 +2003,24 @@ __gg__dividef45(cbl_arith_format_t , int *compute_error ) { - cblc_field_t **A = __gg__treeplet_1f; // Numerator - size_t *A_o = __gg__treeplet_1o; - size_t *A_s = __gg__treeplet_1s; - cblc_field_t **B = __gg__treeplet_2f; // Denominator - size_t *B_o = __gg__treeplet_2o; - size_t *B_s = __gg__treeplet_2s; - cblc_field_t **C = __gg__treeplet_3f; // Has remainder, then quotient - size_t *C_o = __gg__treeplet_3o; - size_t *C_s = __gg__treeplet_3s; + cblc_field_t **A = __gg__treeplet_1f; // Numerator + const size_t *A_o = __gg__treeplet_1o; + const size_t *A_s = __gg__treeplet_1s; + cblc_field_t **B = __gg__treeplet_2f; // Denominator + const size_t *B_o = __gg__treeplet_2o; + const size_t *B_s = __gg__treeplet_2s; + cblc_field_t **C = __gg__treeplet_3f; // Has remainder, then quotient + const size_t *C_o = __gg__treeplet_3o; + const size_t *C_s = __gg__treeplet_3s; bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value; - _Float128 b_value; - _Float128 c_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; + GCOB_FP128 c_value; a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); c_value = divide_helper_float(a_value, b_value, &error_this_time); diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc index e0bd333..81ae638 100644 --- a/libgcobol/intrinsic.cc +++ b/libgcobol/intrinsic.cc @@ -28,23 +28,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Operational note for COBOL intrinsic functions: - - In general, the parameters to these functions are cblc_field_t pointers - along with an offset, size, and for some functions the "allflags", which - indicate that the variable is a table that was referenced as TABL(ALL) +/* COBOL intrinsic functions. + * + * In general, the parameters to these functions are cblc_field_t pointers + * along with an offset, size, and for some functions the "allflags", which + * indicate that the variable is a table that was referenced as TABL(ALL) + */ +#include <langinfo.h> - */ +#include <cctype> +#include <cmath> +#include <cstring> +#include <ctime> -#include <time.h> -#include <math.h> #include <algorithm> -#include <cctype> -#include <langinfo.h> -#include <string.h> +#include <vector> #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -53,11 +55,12 @@ #include "libgcobol.h" #include "charmaps.h" + #pragma GCC diagnostic ignored "-Wformat-truncation" #define JD_OF_1601_01_02 2305812.5 -#define WEIRD_TRANSCENDENT_RETURN_VALUE (0.0Q) +#define WEIRD_TRANSCENDENT_RETURN_VALUE GCOB_FP128_LITERAL (0.0) #define NO_RDIGITS (0) struct cobol_tm @@ -164,7 +167,7 @@ JD_to_DOW(double JD) static char * -timespec_to_string(char *retval, struct timespec &tp) +timespec_to_string(char *retval, struct cbl_timespec &tp) { /* Returns a 21-character string: @@ -245,9 +248,12 @@ struct input_state nsubscript = N; if(N) { - subscript_alls = (bool *) malloc(nsubscript); - subscripts = (size_t *)malloc(nsubscript); - subscript_limits = (size_t *)malloc(nsubscript); + subscript_alls = static_cast<bool *>(malloc(nsubscript)); + subscripts = static_cast<size_t *>(malloc(nsubscript)); + subscript_limits = static_cast<size_t *>(malloc(nsubscript)); + massert(subscript_alls); + massert(subscripts); + massert(subscript_limits); } done = false; } @@ -375,7 +381,7 @@ year_to_yyyy(int arg1, int arg2, int arg3) static double -get_value_as_double_from_qualified_field( cblc_field_t *input, +get_value_as_double_from_qualified_field( const cblc_field_t *input, size_t input_o, size_t input_s) { @@ -406,11 +412,11 @@ get_value_as_double_from_qualified_field( cblc_field_t *input, } static -_Float128 kahan_summation(size_t ncount, +GCOB_FP128 kahan_summation(size_t ncount, cblc_field_t **source, - size_t *source_o, - size_t *source_s, - int *flags, + const size_t *source_o, + const size_t *source_s, + const int *flags, size_t *k_count) { // We use compensated addition. Look up Kahan summation. @@ -420,11 +426,11 @@ _Float128 kahan_summation(size_t ncount, // an aggressive optimizing compiler from just making it go away. *k_count = 0; - _Float128 sum = 0; - volatile _Float128 kahan_c = 0; - _Float128 input; - _Float128 y; - _Float128 t; + GCOB_FP128 sum = 0; + volatile GCOB_FP128 kahan_c = 0; + GCOB_FP128 input; + GCOB_FP128 y; + GCOB_FP128 t; for(size_t i=0; i<ncount; i++) { @@ -452,24 +458,24 @@ _Float128 kahan_summation(size_t ncount, } static -_Float128 +GCOB_FP128 variance( size_t ncount, cblc_field_t **source, - size_t *source_o, - size_t *source_s, - int *flags) + const size_t *source_o, + const size_t *source_s, + const int *flags) { // In order to avoid catastrophic cancellation, we are going to use an // algorithm that is a bit wasteful of time, but is described as particularly // robust. - _Float128 retval = 0; + GCOB_FP128 retval = 0; if( ncount ) { // First, we calculate the mean of the input variables, which we will use // as an offset in the second stage: size_t k_count; - _Float128 offset = kahan_summation( ncount, + GCOB_FP128 offset = kahan_summation( ncount, source, source_o, source_s, @@ -480,11 +486,11 @@ variance( size_t ncount, // Next, we use Welford's algorithm on the residuals: size_t count = 0; - _Float128 mean = 0; - _Float128 M2 = 0; - _Float128 delta; - _Float128 delta2; - _Float128 newValue; + GCOB_FP128 mean = 0; + GCOB_FP128 M2 = 0; + GCOB_FP128 delta; + GCOB_FP128 delta2; + GCOB_FP128 newValue; for(size_t i=0; i<ncount; i++) { @@ -544,14 +550,14 @@ get_all_time( char *stime, // days of January show up in the final week of the prior year. sprintf(stime, - "%4.4u%2.2u%2.2uT" // YYYYMMSS - "%2.2u%2.2u%2.2u" // hhmmss - ".%9.9u" // .sssssssss - "%c%2.2u%2.2u" // +hhmm - "W%2.2u" // Www - "%1u" // DOW [1-7], 1 for Monday - "%3.3u" // DDD day of year, 001 - 365,366 - "%4.4u", // ZZZZ Year for YYYY-Www-D + "%4.4d%2.2d%2.2dT" // YYYYMMSS + "%2.2d%2.2d%2.2d" // hhmmss + ".%9.9d" // .sssssssss + "%c%2.2d%2.2d" // +hhmm + "W%2.2d" // Www + "%1d" // DOW [1-7], 1 for Monday + "%3.3d" // DDD day of year, 001 - 365,366 + "%4.4d", // ZZZZ Year for YYYY-Www-D ctm.YYYY, ctm.MM, ctm.DD, @@ -684,7 +690,7 @@ populate_ctm_from_JD(struct cobol_tm &ctm, double JD ) static void populate_ctm_from_date( struct cobol_tm &ctm, - cblc_field_t *pdate, + const cblc_field_t *pdate, size_t pdate_offset, size_t pdate_size) { @@ -718,10 +724,10 @@ populate_ctm_from_double_time(struct cobol_tm &ctm, double time) static void populate_ctm_from_time( struct cobol_tm &ctm, - cblc_field_t *ptime, + const cblc_field_t *ptime, size_t ptime_o, size_t ptime_s, - cblc_field_t *poffset, + const cblc_field_t *poffset, size_t poffset_o, size_t poffset_s) { @@ -788,8 +794,10 @@ convert_to_zulu(cobol_tm &ctm) static void -ftime_replace(char *dest, char const * const dest_end, - char const *source, char const * const source_end, +ftime_replace(char *dest, + char const * const dest_end, + char const * source, + char const * const source_end, char const * const ftime) { // This routine is highly dependent on the source format being correct. @@ -953,12 +961,12 @@ ftime_replace(char *dest, char const * const dest_end, extern "C" void __gg__abs(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ABS - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); @@ -975,22 +983,22 @@ __gg__abs(cblc_field_t *dest, extern "C" void __gg__acos( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ACOS - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value < -1.00Q || value > +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.00) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = acosf128(value); + value = FP128_FUNC(acos)(value); } __gg__float128_to_field( dest, @@ -1002,21 +1010,21 @@ __gg__acos( cblc_field_t *dest, extern "C" void __gg__annuity(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { // FUNCTION ANNUITY - _Float128 retval = 0; + GCOB_FP128 retval = 0; - _Float128 val1 = fabsf128(__gg__float128_from_qualified_field(arg1, + GCOB_FP128 val1 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg1, arg1_offset, arg1_size)); - _Float128 val2 = fabsf128(__gg__float128_from_qualified_field(arg2, + GCOB_FP128 val2 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg2, arg2_offset, arg2_size)); if( val2 > 0) @@ -1031,7 +1039,7 @@ __gg__annuity(cblc_field_t *dest, } else { - retval = val1 / (1- powf128( (1+val1), -val2 )); + retval = val1 / (1- FP128_FUNC(pow)( (1+val1), -val2 )); } } else @@ -1047,25 +1055,25 @@ __gg__annuity(cblc_field_t *dest, extern "C" void __gg__asin( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ASIN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value < -1.0Q || value > +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.0) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = asinf128(value); + value = FP128_FUNC(asin)(value); } __gg__float128_to_field( dest, @@ -1077,18 +1085,18 @@ __gg__asin( cblc_field_t *dest, extern "C" void __gg__atan( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION ATAN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = atanf128(value); + value = FP128_FUNC(atan)(value); __gg__float128_to_field( dest, value, @@ -1099,7 +1107,7 @@ __gg__atan( cblc_field_t *dest, extern "C" void __gg__byte_length(cblc_field_t *dest, - cblc_field_t */*source*/, + const cblc_field_t */*source*/, size_t /*source_offset*/, size_t source_size) { @@ -1115,7 +1123,7 @@ __gg__byte_length(cblc_field_t *dest, extern "C" void __gg__char( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1140,10 +1148,10 @@ __gg__char( cblc_field_t *dest, extern "C" void __gg__combined_datetime(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -1189,16 +1197,16 @@ __gg__concat( cblc_field_t *dest, extern "C" void __gg__cos(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION COS - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = cosf128(value); + value = FP128_FUNC(cos)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1210,8 +1218,8 @@ void __gg__current_date(cblc_field_t *dest) { // FUNCTION CURRENT-DATE - struct timespec tp = {}; - __gg__clock_gettime(CLOCK_REALTIME, &tp); // time_t tv_sec; long tv_nsec + struct cbl_timespec tp = {}; + __gg__clock_gettime(&tp); // time_t tv_sec; long tv_nsec char retval[DATE_STRING_BUFFER_SIZE]; timespec_to_string(retval, tp); @@ -1224,11 +1232,11 @@ void __gg__seconds_past_midnight(cblc_field_t *dest) { // SECONDS-PAST-MIDNIGHT - struct timespec tp = {}; + struct cbl_timespec tp = {}; struct tm tm; __int128 retval=0; - __gg__clock_gettime(CLOCK_REALTIME, &tp); // time_t tv_sec; long tv_nsec + __gg__clock_gettime(&tp); // time_t tv_sec; long tv_nsec localtime_r(&tp.tv_sec, &tm); retval += tm.tm_hour; @@ -1248,7 +1256,7 @@ __gg__seconds_past_midnight(cblc_field_t *dest) extern "C" void __gg__date_of_integer(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1274,13 +1282,13 @@ __gg__date_of_integer(cblc_field_t *dest, extern "C" void __gg__date_to_yyyymmdd( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -1305,7 +1313,7 @@ __gg__date_to_yyyymmdd( cblc_field_t *dest, extern "C" void __gg__day_of_integer( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1334,13 +1342,13 @@ __gg__day_of_integer( cblc_field_t *dest, extern "C" void __gg__day_to_yyyyddd( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -1368,7 +1376,8 @@ void __gg__e(cblc_field_t *dest) { // FUNCTION E - static _Float128 e = 2.7182818284590452353602874713526624977572Q; + static GCOB_FP128 e + = GCOB_FP128_LITERAL(2.7182818284590452353602874713526624977572); __gg__float128_to_field(dest, e, truncation_e, @@ -1378,16 +1387,16 @@ __gg__e(cblc_field_t *dest) extern "C" void __gg__exp(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION EXP - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = expf128(value); + value = FP128_FUNC(exp)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1397,16 +1406,16 @@ __gg__exp(cblc_field_t *dest, extern "C" void __gg__exp10(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION EXP10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = powf128(10.0Q, value); + value = FP128_FUNC(pow)(GCOB_FP128_LITERAL(10.0), value); __gg__float128_to_field(dest, value, truncation_e, @@ -1416,7 +1425,7 @@ __gg__exp10(cblc_field_t *dest, extern "C" void __gg__factorial(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1447,24 +1456,24 @@ __gg__factorial(cblc_field_t *dest, extern "C" void __gg__formatted_current_date( cblc_field_t *dest, // Destination string - cblc_field_t *input, // datetime format + const cblc_field_t *input, // datetime format size_t input_offset, size_t input_size) { - // FUNCTION CURRENT-DATE + // FUNCTION FORMATTED-CURRENT-DATE // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; memset(d, internal_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(input->data+input_offset); - char *format_end = format + input_size; + const char *format = PTRCAST(char, (input->data+input_offset)); + const char *format_end = format + input_size; bool is_zulu = false; - char *p = format; + const char *p = format; while( p < format_end ) { int ch = *p++; @@ -1475,11 +1484,13 @@ __gg__formatted_current_date( cblc_field_t *dest, // Destination string } } - struct timespec ts = {}; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + struct cbl_timespec ts = {}; + __gg__clock_gettime(&ts); struct tm tm = {}; +#ifdef HAVE_STRUCT_TM_TM_ZONE tm.tm_zone = "GMT"; +#endif if( is_zulu ) { gmtime_r(&ts.tv_sec, &tm); @@ -1506,23 +1517,23 @@ __gg__formatted_current_date( cblc_field_t *dest, // Destination string extern "C" void __gg__formatted_date(cblc_field_t *dest, // Destination string - cblc_field_t *arg1, // datetime format + const cblc_field_t *arg1, // datetime format size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, // integer date + const cblc_field_t *arg2, // integer date size_t arg2_offset, size_t arg2_size) { // FUNCTION FORMATTED-DATE // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; memset(d, internal_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(arg1->data+arg1_offset); - char *format_end = format + arg1_size; + char *format = PTRCAST(char, (arg1->data+arg1_offset)); + const char *format_end = format + arg1_size; struct cobol_tm ctm = {}; @@ -1544,16 +1555,16 @@ __gg__formatted_date(cblc_field_t *dest, // Destination string extern "C" void __gg__formatted_datetime( cblc_field_t *dest, // Destination string - cblc_field_t *par1, // datetime format + const cblc_field_t *par1, // datetime format size_t par1_o, size_t par1_s, - cblc_field_t *par2, // integer date + const cblc_field_t *par2, // integer date size_t par2_o, size_t par2_s, - cblc_field_t *par3, // numeric time + const cblc_field_t *par3, // numeric time size_t par3_o, size_t par3_s, - cblc_field_t *par4, // optional offset in seconds + const cblc_field_t *par4, // optional offset in seconds size_t par4_o, size_t par4_s ) @@ -1561,12 +1572,12 @@ __gg__formatted_datetime( cblc_field_t *dest, // Destination string // FUNCTION FORMATTED-DATETIME // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; + char *d = PTRCAST(char, (dest->data)); + const char *dend = d + dest->capacity; memset(d, internal_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(par1->data+par1_o); + char *format = PTRCAST(char, (par1->data+par1_o)); char *format_end = format + par1_s; trim_trailing_spaces(format, format_end); bool is_zulu = is_zulu_format(format, format_end); @@ -1599,13 +1610,13 @@ __gg__formatted_datetime( cblc_field_t *dest, // Destination string extern "C" void __gg__formatted_time( cblc_field_t *dest,// Destination string - cblc_field_t *par1, // datetime format + const cblc_field_t *par1, // datetime format size_t par1_o, size_t par1_s, - cblc_field_t *par2,// numeric time + const cblc_field_t *par2,// numeric time size_t par2_o, size_t par2_s, - cblc_field_t *par4, // optional offset in seconds + const cblc_field_t *par4, // optional offset in seconds size_t par4_o, size_t par4_s) @@ -1613,12 +1624,12 @@ __gg__formatted_time( cblc_field_t *dest,// Destination string // FUNCTION FORMATTED-TIME // Establish the destination, and set it to spaces - char *d = (char *)dest->data; - char *dend = d + dest->capacity; + char *d = PTRCAST(char, dest->data); + const char *dend = d + dest->capacity; memset(d, internal_space, dest->capacity); // Establish the formatting string: - char *format = (char *)(par1->data+par1_o); + char *format = PTRCAST(char, (par1->data+par1_o)); char *format_end = format + par1_s; trim_trailing_spaces(format, format_end); bool is_zulu = is_zulu_format(format, format_end); @@ -1653,15 +1664,15 @@ __gg__formatted_time( cblc_field_t *dest,// Destination string extern "C" void __gg__integer(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = floorf128(value); + value = FP128_FUNC(floor)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1671,7 +1682,7 @@ __gg__integer(cblc_field_t *dest, extern "C" void __gg__integer_of_date(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1726,7 +1737,7 @@ __gg__integer_of_date(cblc_field_t *dest, extern "C" void __gg__integer_of_day( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -1753,15 +1764,15 @@ __gg__integer_of_day( cblc_field_t *dest, extern "C" void __gg__integer_part( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - _Float128 retval = floorf128(fabsf128(value)); + GCOB_FP128 retval = FP128_FUNC(floor)(FP128_FUNC(fabs)(value)); if( value < 0 ) { @@ -1776,12 +1787,12 @@ __gg__integer_part( cblc_field_t *dest, extern "C" void __gg__fraction_part(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); bool is_negative = false; @@ -1791,7 +1802,7 @@ __gg__fraction_part(cblc_field_t *dest, value = -value; } - _Float128 retval = value - floorf128(value); + GCOB_FP128 retval = value - FP128_FUNC(floor)(value); if( is_negative ) { @@ -1805,13 +1816,13 @@ __gg__fraction_part(cblc_field_t *dest, extern "C" void -__gg__log( cblc_field_t *dest, - cblc_field_t *source, - size_t source_offset, - size_t source_size) +__gg__log(cblc_field_t *dest, + const cblc_field_t *source, + size_t source_offset, + size_t source_size) { // FUNCTION LOG - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1820,7 +1831,7 @@ __gg__log( cblc_field_t *dest, } else { - _Float128 retval = logf128(value); + GCOB_FP128 retval = FP128_FUNC(log)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1830,13 +1841,13 @@ __gg__log( cblc_field_t *dest, extern "C" void -__gg__log10( cblc_field_t *dest, - cblc_field_t *source, - size_t source_offset, - size_t source_size) +__gg__log10(cblc_field_t *dest, + const cblc_field_t *source, + size_t source_offset, + size_t source_size) { // FUNCTION LOG10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1845,7 +1856,7 @@ __gg__log10( cblc_field_t *dest, } else { - _Float128 retval = log10f128(value); + GCOB_FP128 retval = FP128_FUNC(log10)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1864,8 +1875,8 @@ __gg__max(cblc_field_t *dest, || __gg__treeplet_1f[0]->type == FldLiteralA) ) { cblc_field_t *best_field ; - unsigned char *best_location ; - size_t best_length ; + unsigned char *best_location = nullptr ; + size_t best_length = 0 ; int best_attr ; int best_flags ; @@ -1925,13 +1936,15 @@ __gg__max(cblc_field_t *dest, } } + __gg__adjust_dest_size(dest, best_length); dest->type = FldAlphanumeric; + assert(best_location); memcpy(dest->data, best_location, best_length); } else { - _Float128 retval; + GCOB_FP128 retval; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -1948,7 +1961,7 @@ __gg__max(cblc_field_t *dest, } else { - _Float128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); + GCOB_FP128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); if( candidate >= retval ) { retval = candidate; @@ -1971,7 +1984,7 @@ __gg__max(cblc_field_t *dest, extern "C" void __gg__lower_case( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { @@ -1979,10 +1992,10 @@ __gg__lower_case( cblc_field_t *dest, size_t source_length = input_size; memset(dest->data, internal_space, dest_length); memcpy(dest->data, input->data+input_offset, std::min(dest_length, source_length)); - internal_to_ascii((char *)dest->data, dest_length); + internal_to_ascii( PTRCAST(char, dest->data), dest_length); std::transform(dest->data, dest->data + dest_length, dest->data, [](unsigned char c) { return std::tolower(c); }); - ascii_to_internal_str((char *)dest->data, dest_length); + ascii_to_internal_str( PTRCAST(char, dest->data), dest_length); } extern "C" @@ -1992,7 +2005,7 @@ __gg__mean( cblc_field_t *dest, { // FUNCTION MEAN size_t k_count; - _Float128 sum = kahan_summation(ninputs, + GCOB_FP128 sum = kahan_summation(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -2021,7 +2034,8 @@ __gg__median( cblc_field_t *dest, size_t list_size = 1; - _Float128 *the_list = (_Float128 *)malloc(list_size *sizeof(_Float128)); + GCOB_FP128 *the_list = static_cast<GCOB_FP128 *>(malloc(list_size *sizeof(GCOB_FP128))); + massert(the_list); size_t k_count = 0; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2034,9 +2048,11 @@ __gg__median( cblc_field_t *dest, if(k_count >= list_size) { list_size *= 2; - the_list = (_Float128 *)realloc(the_list, list_size *sizeof(_Float128)); + the_list = PTRCAST(GCOB_FP128, realloc(the_list, list_size *sizeof(GCOB_FP128))); + massert(the_list); } + assert(the_list); the_list[k_count] = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); @@ -2050,7 +2066,7 @@ __gg__median( cblc_field_t *dest, } std::sort(the_list, the_list+k_count); - _Float128 retval; + GCOB_FP128 retval; size_t i=k_count/2; if( k_count & 1 ) { @@ -2073,9 +2089,9 @@ __gg__midrange( cblc_field_t *dest, size_t ncount) { // FUNCTION MIDRANGE - _Float128 val; - _Float128 min=0; - _Float128 max=0; + GCOB_FP128 val; + GCOB_FP128 min=0; + GCOB_FP128 max=0; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2102,7 +2118,7 @@ __gg__midrange( cblc_field_t *dest, } } } - _Float128 retval = (min + max)/2.0; + GCOB_FP128 retval = (min + max)/2.0; __gg__float128_to_field(dest, retval, truncation_e, @@ -2119,11 +2135,11 @@ __gg__min(cblc_field_t *dest, if( ( __gg__treeplet_1f[0]->type == FldAlphanumeric || __gg__treeplet_1f[0]->type == FldLiteralA) ) { - cblc_field_t *best_field ; - unsigned char *best_location ; - size_t best_length ; - int best_attr ; - int best_flags ; + cblc_field_t *best_field ; + unsigned char *best_location = nullptr ; + size_t best_length = 0 ; + int best_attr ; + int best_flags ; bool first_time = true; assert(ncount); @@ -2183,11 +2199,12 @@ __gg__min(cblc_field_t *dest, __gg__adjust_dest_size(dest, best_length); dest->type = FldAlphanumeric; + assert(best_location); memcpy(dest->data, best_location, best_length); } else { - _Float128 retval; + GCOB_FP128 retval; bool first_time = true; assert(ncount); for(size_t i=0; i<ncount; i++) @@ -2204,7 +2221,7 @@ __gg__min(cblc_field_t *dest, } else { - _Float128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); + GCOB_FP128 candidate = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); if( candidate < retval ) { retval = candidate; @@ -2271,15 +2288,15 @@ __gg__mod(cblc_field_t *dest, static int numval( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { // Returns the one-based character position of a bad character // returns zero if it is okay - char *p = (char *)(input->data + input_offset); - char *pend = p + input_size; + const char *p = PTRCAST(char, (input->data + input_offset)); + const char *pend = p + input_size; int errpos = 0; __int128 retval = 0; @@ -2562,21 +2579,21 @@ numval( cblc_field_t *dest, static int numval_c( cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) { size_t errcode = 0; - char *pstart = (char *)(src->data+src_offset); + char *pstart = PTRCAST(char, (src->data+src_offset)); char *pend = pstart + src_size; char *p = pstart; - _Float128 retval = 0; + GCOB_FP128 retval = 0; int sign = 0; int rdigits = 0; int rdigit_bump = 0; @@ -2587,7 +2604,7 @@ numval_c( cblc_field_t *dest, char *currency_end; if( crcy ) { - currency_start = (char *)(crcy->data+crcy_offset); + currency_start = PTRCAST(char, (crcy->data+crcy_offset)); currency_end = currency_start + crcy_size; } else @@ -2801,7 +2818,6 @@ numval_c( cblc_field_t *dest, if( sign ) { // A second sign isn't allowed - state = final_space; errcode = p - pstart; p = pend; } @@ -2869,7 +2885,7 @@ numval_c( cblc_field_t *dest, extern "C" void __gg__numval( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -2883,7 +2899,7 @@ __gg__numval( cblc_field_t *dest, extern "C" void __gg__test_numval(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -2898,10 +2914,10 @@ __gg__test_numval(cblc_field_t *dest, extern "C" void __gg__numval_c( cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) @@ -2918,10 +2934,10 @@ __gg__numval_c( cblc_field_t *dest, extern "C" void __gg__test_numval_c(cblc_field_t *dest, - cblc_field_t *src, + const cblc_field_t *src, size_t src_offset, size_t src_size, - cblc_field_t *crcy, + const cblc_field_t *crcy, size_t crcy_offset, size_t crcy_size ) @@ -2943,12 +2959,12 @@ __gg__test_numval_c(cblc_field_t *dest, extern "C" void __gg__ord(cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t /*input_size*/) { // We get our input in internal_character form. - char *arg = (char *)(input->data + input_offset); + const char *arg = PTRCAST(char, (input->data + input_offset)); // The ORD function takes a single-character string and returns the // ordinal position of that character. @@ -3146,7 +3162,8 @@ __gg__pi(cblc_field_t *dest) { // FUNCTION PI - static _Float128 pi = 3.141592653589793238462643383279502884Q; + static GCOB_FP128 pi + = GCOB_FP128_LITERAL(3.141592653589793238462643383279502884); __gg__float128_to_field(dest, pi, truncation_e, @@ -3158,10 +3175,10 @@ void __gg__present_value(cblc_field_t *dest, size_t ncount) { - _Float128 discount = 0;; - _Float128 denom = 1; + GCOB_FP128 discount = 0;; + GCOB_FP128 denom = 1; - _Float128 retval = 0; + GCOB_FP128 retval = 0; bool first_time = true; for(size_t i=0; i<ncount; i++) { @@ -3172,19 +3189,19 @@ __gg__present_value(cblc_field_t *dest, if(first_time) { first_time = false; - _Float128 arg1 = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], + GCOB_FP128 arg1 = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); - if( arg1 <= -1.0Q ) + if( arg1 <= GCOB_FP128_LITERAL(-1.0) ) { exception_raise(ec_argument_function_e); break; } - discount = 1.0Q / (1.0Q + arg1); + discount = GCOB_FP128_LITERAL(1.0) / (GCOB_FP128_LITERAL(1.0) + arg1); } else { - _Float128 arg = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], + GCOB_FP128 arg = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], __gg__treeplet_1o[i], __gg__treeplet_1s[i]); denom *= discount; @@ -3210,9 +3227,9 @@ __gg__range(cblc_field_t *dest, { // FUNCTION RANGE bool first_time = true; - _Float128 val; - _Float128 min; - _Float128 max; + GCOB_FP128 val; + GCOB_FP128 min; + GCOB_FP128 max; assert(ncount > 0); for(size_t i=0; i<ncount; i++) @@ -3240,7 +3257,7 @@ __gg__range(cblc_field_t *dest, } } - _Float128 retval = max - min; + GCOB_FP128 retval = max - min; __gg__float128_to_field(dest, retval, truncation_e, @@ -3250,10 +3267,10 @@ __gg__range(cblc_field_t *dest, extern "C" void __gg__rem(cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_offset, size_t par1_size, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_offset, size_t par2_size) { @@ -3264,15 +3281,15 @@ __gg__rem(cblc_field_t *dest, // The ISO spec says: // ((argument-1) – ((argument-2) * FUNCTION INTEGER-PART ((argument-1) / (argument-2)))) - _Float128 arg1 = __gg__float128_from_qualified_field( par1, + GCOB_FP128 arg1 = __gg__float128_from_qualified_field( par1, par1_offset, par1_size); - _Float128 arg2 = __gg__float128_from_qualified_field( par2, + GCOB_FP128 arg2 = __gg__float128_from_qualified_field( par2, par2_offset, par2_size); - _Float128 intpart; - _Float128 retval; + GCOB_FP128 intpart; + GCOB_FP128 retval; if( arg2 == 0 ) { exception_raise(ec_argument_function_e); @@ -3280,7 +3297,7 @@ __gg__rem(cblc_field_t *dest, } else { - modff128(arg1 / arg2, &intpart); + FP128_FUNC(modf)(arg1 / arg2, &intpart); retval = arg1 - arg2 * intpart; } @@ -3293,10 +3310,10 @@ __gg__rem(cblc_field_t *dest, extern "C" void __gg__trim( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -3322,7 +3339,7 @@ __gg__trim( cblc_field_t *dest, // No matter what, we want to find the leftmost non-space and the // rightmost non-space: - char *left = (char *)(arg1->data+arg1_offset); + char *left = PTRCAST(char, (arg1->data+arg1_offset)); char *right = left + arg1_size-1; // Find left and right: the first and last non-spaces @@ -3345,13 +3362,13 @@ __gg__trim( cblc_field_t *dest, { // We want to leave any trailing spaces, so we return 'right' to its // original value: - right = (char *)(arg1->data+arg1_offset) + arg1_size-1; + right = PTRCAST(char, (arg1->data+arg1_offset)) + arg1_size-1; } else if( type == TRAILING ) { // We want to leave any leading spaces, so we return 'left' to its // original value: - left = (char *)(arg1->data+arg1_offset); + left = PTRCAST(char, (arg1->data+arg1_offset)); } if( left > right ) @@ -3371,9 +3388,9 @@ __gg__trim( cblc_field_t *dest, // compiler believes the capacity to be at compile-time. But we obviously // think it'll be okay. - char *dest_left = (char *)dest->data; + char *dest_left = PTRCAST(char, dest->data); char *dest_right = dest_left + dest->capacity - 1; - char *dest_end = dest_left + dest->capacity; + const char *dest_end = dest_left + dest->capacity; while( dest_left <= dest_right && left <= right ) { @@ -3396,7 +3413,7 @@ static unsigned seed = 0; extern "C" void __gg__random( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { @@ -3415,8 +3432,8 @@ __gg__random( cblc_field_t *dest, buf->state = NULL; state = (char *)malloc(state_len); - struct timespec ts; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + struct cbl_timespec ts; + __gg__clock_gettime(&ts); initstate_r( ts.tv_nsec, state, state_len, buf); } int seed = (int)__gg__binary_value_from_qualified_field(&rdigits, @@ -3455,8 +3472,8 @@ __gg__random_next(cblc_field_t *dest) buf = (random_data *)malloc(sizeof(struct random_data)); buf->state = NULL; state = (char *)malloc(state_len); - struct timespec ts; - __gg__clock_gettime(CLOCK_REALTIME, &ts); + struct cbl_timespec ts; + __gg__clock_gettime(&ts); initstate_r( ts.tv_nsec, state, state_len, buf); } random_r(buf, &retval_31); @@ -3473,7 +3490,7 @@ __gg__random_next(cblc_field_t *dest) extern "C" void __gg__reverse(cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { @@ -3494,13 +3511,13 @@ __gg__reverse(cblc_field_t *dest, extern "C" void __gg__sign( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SIGN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); @@ -3527,17 +3544,17 @@ __gg__sign( cblc_field_t *dest, extern "C" void __gg__sin(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SIN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = sinf128(value); + value = FP128_FUNC(sin)(value); __gg__float128_to_field(dest, value, @@ -3548,23 +3565,23 @@ __gg__sin(cblc_field_t *dest, extern "C" void __gg__sqrt( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION SQRT - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value <= 0.0Q ) + if( value < GCOB_FP128_LITERAL(0.0) ) { exception_raise(ec_argument_function_e); } else { - value = sqrtf128(value); + value = FP128_FUNC(sqrt)(value); } __gg__float128_to_field(dest, @@ -3579,12 +3596,12 @@ __gg__standard_deviation( cblc_field_t *dest, size_t ninputs) { // FUNCTION STANDARD-DEVIATION - _Float128 retval = variance(ninputs, + GCOB_FP128 retval = variance(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, __gg__fourplet_flags); - retval = sqrtf128(retval); + retval = FP128_FUNC(sqrt)(retval); __gg__float128_to_field(dest, retval, @@ -3599,7 +3616,7 @@ __gg__sum(cblc_field_t *dest, { // FUNCTION SUM size_t k_count; - _Float128 sum = kahan_summation(ninputs, + GCOB_FP128 sum = kahan_summation(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -3614,16 +3631,16 @@ __gg__sum(cblc_field_t *dest, extern "C" void __gg__tan(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { // FUNCTION TAN - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = tanf128(value); + value = FP128_FUNC(tan)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -3633,7 +3650,7 @@ __gg__tan(cblc_field_t *dest, extern "C" void __gg__test_date_yyyymmdd( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -3643,14 +3660,8 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, source_offset, source_size); int retval; - int dd = yyyymmdd % 100; int mmdd = yyyymmdd % 10000; int mm = mmdd / 100; - int yyyy = yyyymmdd / 10000; - int jy; - int jm; - int jd; - double JD; if( yyyymmdd < 16010000 || yyyymmdd > 99999999 ) { retval = 1; @@ -3661,6 +3672,13 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, } else { + int dd = yyyymmdd % 100; + int yyyy = yyyymmdd / 10000; + int jy; + int jm; + int jd; + double JD; + // If there is something wrong with the number of days per month for a // given year, the Julian Date conversion won't reverse properly. // For example, January 32 will come back as February 1 @@ -3685,7 +3703,7 @@ __gg__test_date_yyyymmdd( cblc_field_t *dest, extern "C" void __gg__test_day_yyyyddd( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { @@ -3723,7 +3741,7 @@ __gg__test_day_yyyyddd( cblc_field_t *dest, extern "C" void __gg__upper_case( cblc_field_t *dest, - cblc_field_t *input, + const cblc_field_t *input, size_t input_offset, size_t input_size) { @@ -3731,10 +3749,10 @@ __gg__upper_case( cblc_field_t *dest, size_t source_length = input_size; memset(dest->data, internal_space, dest_length); memcpy(dest->data, input->data+input_offset, std::min(dest_length, source_length)); - internal_to_ascii((char *)dest->data, dest_length); + internal_to_ascii( PTRCAST(char, dest->data), dest_length); std::transform(dest->data, dest->data + dest_length, dest->data, [](unsigned char c) { return std::toupper(c); }); - ascii_to_internal_str((char *)dest->data, dest_length); + ascii_to_internal_str( PTRCAST(char, dest->data), dest_length); } extern "C" @@ -3743,7 +3761,7 @@ __gg__variance( cblc_field_t *dest, size_t ncount) { // FUNCTION VARIANCE - _Float128 retval = variance(ncount, + GCOB_FP128 retval = variance(ncount, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -3758,7 +3776,7 @@ extern "C" void __gg__when_compiled(cblc_field_t *dest, size_t tv_sec, long tv_nsec) { - struct timespec tp = {}; + struct cbl_timespec tp = {}; tp.tv_sec = tv_sec; tp.tv_nsec = tv_nsec; char retval[DATE_STRING_BUFFER_SIZE]; @@ -3770,13 +3788,13 @@ __gg__when_compiled(cblc_field_t *dest, size_t tv_sec, long tv_nsec) extern "C" void __gg__year_to_yyyy( cblc_field_t *dest, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_o, size_t par1_s, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_o, size_t par2_s, - cblc_field_t *par3, + const cblc_field_t *par3, size_t par3_o, size_t par3_s) { @@ -3797,7 +3815,7 @@ __gg__year_to_yyyy( cblc_field_t *dest, static int -gets_int(int ndigits, char *p, char *pend, int *digits) +gets_int(int ndigits, const char *p, const char *pend, int *digits) { // This routine returns the value of the integer at p. If there is something // wrong with the integer, it returns a negative number, the value being the @@ -3828,7 +3846,7 @@ gets_int(int ndigits, char *p, char *pend, int *digits) static int -gets_year(char *p, char *pend, struct cobol_tm &ctm) +gets_year(const char *p, const char *pend, struct cobol_tm &ctm) { // Populates ctm.YYYY, ctm.days_in_year, and ctm.weeks_in_year, which are // all determined by the YYYY value. @@ -3848,10 +3866,6 @@ gets_year(char *p, char *pend, struct cobol_tm &ctm) { return 2; } - if( digits[0] == 0 && digits[1] < 5) - { - return 2; - } if( digits[2] == -1 ) { return 3; @@ -3896,7 +3910,7 @@ gets_year(char *p, char *pend, struct cobol_tm &ctm) static int -gets_month(char *p, char *pend, struct cobol_tm &ctm) +gets_month(const char *p, const char *pend, struct cobol_tm &ctm) { // Populates ctm.MM @@ -3943,7 +3957,7 @@ gets_month(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day(char *p, char *pend, struct cobol_tm &ctm) +gets_day(const char *p, const char *pend, struct cobol_tm &ctm) { // Populates ctm.DD, ctm.day_of_week, ctm.week_of_year, ctm.day_of_week @@ -3961,48 +3975,45 @@ gets_day(char *p, char *pend, struct cobol_tm &ctm) { return 2; } - if(DD >= 0) + if( DD >= 0 ) { - if( DD >= 0 ) + if( DD == 0) { - if( DD == 0) - { - // If zero, we know we failed at the second '0' in "00" - retval = 2; - } - else if( DD >= 40) + // If zero, we know we failed at the second '0' in "00" + retval = 2; + } + else if( DD >= 40) + { + // 40 or more, then we knew there was trouble at the first digit + retval = 1; + } + else if(ctm.MM == 2 && DD >=30) + { + // It's February, so if we see 3x we know on the 3 that we are in + // error: + retval = 1; + } + else + { + static const int month_days[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; + int days_in_month = month_days[ctm.MM]; + if( ctm.MM == 2 && ctm.days_in_year == 366 ) { - // 40 or more, then we knew there was trouble at the first digit - retval = 1; + days_in_month = 29; } - else if(ctm.MM == 2 && DD >=30) + + if( DD > days_in_month ) { - // It's February, so if we see 3x we know on the 3 that we are in - // error: - retval = 1; + retval = 2; } else { - static const int month_days[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; - int days_in_month = month_days[ctm.MM]; - if( ctm.MM == 2 && ctm.days_in_year == 366 ) - { - days_in_month = 29; - } - - if( DD > days_in_month ) - { - retval = 2; - } - else - { - // We have a good YYYY-MM-DD - ctm.DD = DD; - double JD = YMD_to_JD(ctm.YYYY, ctm.MM, DD); - double JD_Jan0 = YMD_to_JD(ctm.YYYY, 1, 0); - ctm.day_of_year = (int)(JD - JD_Jan0); - ctm.day_of_week = JD_to_DOW(JD); - } + // We have a good YYYY-MM-DD + ctm.DD = DD; + double JD = YMD_to_JD(ctm.YYYY, ctm.MM, DD); + double JD_Jan0 = YMD_to_JD(ctm.YYYY, 1, 0); + ctm.day_of_year = (int)(JD - JD_Jan0); + ctm.day_of_week = JD_to_DOW(JD); } } } @@ -4015,7 +4026,7 @@ gets_day(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day_of_week(char *p, char *pend, struct cobol_tm &ctm) +gets_day_of_week(const char *p, const char *pend, struct cobol_tm &ctm) { // This is just a simple D, for day-of-week. The COBOL spec is that // it be 1 to 7, 1 being Monday @@ -4064,7 +4075,7 @@ gets_day_of_week(char *p, char *pend, struct cobol_tm &ctm) static int -gets_day_of_year(char *p, char *pend, struct cobol_tm &ctm) +gets_day_of_year(const char *p, const char *pend, struct cobol_tm &ctm) { // This is a three-digit day-of-year, 001 through 365,366 int digits[3]; @@ -4121,7 +4132,7 @@ gets_day_of_year(char *p, char *pend, struct cobol_tm &ctm) static int -gets_week(char *p, char *pend, struct cobol_tm &ctm) +gets_week(const char *p, const char *pend, struct cobol_tm &ctm) { // This is a two-digit value, 01 through 52,53 int digits[2]; @@ -4161,7 +4172,10 @@ gets_week(char *p, char *pend, struct cobol_tm &ctm) static int -gets_hours(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) +gets_hours( const char *p, + const char *pend, + struct cobol_tm &ctm, + bool in_offset) { // This is a two-digit value, 01 through 23 int digits[2]; @@ -4206,7 +4220,10 @@ gets_hours(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) static int -gets_minutes(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) +gets_minutes( const char *p, + const char *pend, + struct cobol_tm &ctm, + bool in_offset) { // This is a two-digit value, 01 through 59 int digits[2]; @@ -4244,7 +4261,7 @@ gets_minutes(char *p, char *pend, struct cobol_tm &ctm, bool in_offset) static int -gets_seconds(char *p, char *pend, struct cobol_tm &ctm) +gets_seconds(const char *p, const char *pend, struct cobol_tm &ctm) { // This is a two-digit value, 01 through 59 int digits[2]; @@ -4274,7 +4291,11 @@ gets_seconds(char *p, char *pend, struct cobol_tm &ctm) static int -gets_nanoseconds(char *f, char *f_end, char *p, char *pend, struct cobol_tm &ctm) +gets_nanoseconds( const char *f, + const char *f_end, + const char *p, + const char *pend, + struct cobol_tm &ctm) { // Because nanoseconds digits to the right of the decimal point can vary from // one digit to our implementation-specific limit of nine characters, this @@ -4286,7 +4307,7 @@ gets_nanoseconds(char *f, char *f_end, char *p, char *pend, struct cobol_tm &ctm int ncount = 0; int nanoseconds = 0; - char *pinit = p; + const char *pinit = p; while( f < f_end && *f == internal_s && p < pend ) { f += 1; @@ -4318,19 +4339,19 @@ gets_nanoseconds(char *f, char *f_end, char *p, char *pend, struct cobol_tm &ctm static int fill_cobol_tm(cobol_tm &ctm, - cblc_field_t *par1, + const cblc_field_t *par1, size_t par1_offset, size_t par1_size, - cblc_field_t *par2, + const cblc_field_t *par2, size_t par2_offset, size_t par2_size) { // Establish the formatting string: - char *format = (char *)(par1->data+par1_offset); + char *format = PTRCAST(char, (par1->data+par1_offset)); char *format_end = format + par1_size; // Establish the string to be checked: - char *source = (char *)(par2->data+par2_offset); + char *source = PTRCAST(char, (par2->data+par2_offset)); char *source_end = source + par2_size; // Let's eliminate trailing spaces... @@ -4580,10 +4601,10 @@ proceed: extern "C" void __gg__test_formatted_datetime(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) @@ -4603,10 +4624,10 @@ __gg__test_formatted_datetime(cblc_field_t *dest, extern "C" void __gg__integer_of_formatted_date(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -4638,10 +4659,10 @@ __gg__integer_of_formatted_date(cblc_field_t *dest, extern "C" void __gg__seconds_from_formatted_time(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_offset, size_t arg1_size, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_offset, size_t arg2_size) { @@ -4666,7 +4687,7 @@ __gg__seconds_from_formatted_time(cblc_field_t *dest, extern "C" void __gg__hex_of(cblc_field_t *dest, - cblc_field_t *field, + const cblc_field_t *field, size_t field_offset, size_t field_size) { @@ -4684,7 +4705,7 @@ __gg__hex_of(cblc_field_t *dest, extern "C" void __gg__highest_algebraic(cblc_field_t *dest, - cblc_field_t *var, + const cblc_field_t *var, size_t, size_t) { @@ -4726,7 +4747,7 @@ __gg__highest_algebraic(cblc_field_t *dest, extern "C" void __gg__lowest_algebraic( cblc_field_t *dest, - cblc_field_t *var, + const cblc_field_t *var, size_t, size_t) { @@ -4788,7 +4809,7 @@ __gg__lowest_algebraic( cblc_field_t *dest, } static int -floating_format_tester(char const * const f, char * const f_end) +floating_format_tester(char const * const f, char const * const f_end) { int retval = -1; char decimal_point = __gg__get_decimal_point(); @@ -4976,13 +4997,13 @@ floating_format_tester(char const * const f, char * const f_end) extern "C" void __gg__numval_f( cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { - _Float128 value = 0; - char *data = (char * )(source->data + source_offset); - char *data_end = data + source_size; + GCOB_FP128 value = 0; + const char *data = PTRCAST(char, (source->data + source_offset)); + const char *data_end = data + source_size; int error = floating_format_tester(data, data_end); @@ -5004,7 +5025,7 @@ __gg__numval_f( cblc_field_t *dest, } } *p++ = '\0'; - value = strtof128(ach, NULL); + value = strtofp128(ach, NULL); } __gg__float128_to_field(dest, value, @@ -5015,12 +5036,12 @@ __gg__numval_f( cblc_field_t *dest, extern "C" void __gg__test_numval_f(cblc_field_t *dest, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size) { - char *data = (char * )(source->data + source_offset); - char *data_end = data + source_size; + const char *data = PTRCAST(char, (source->data + source_offset)); + const char *data_end = data + source_size; int error = floating_format_tester(data, data_end); @@ -5032,7 +5053,7 @@ __gg__test_numval_f(cblc_field_t *dest, } static bool -ismatch(char *a1, char *a2, char *b1, char *b2) +ismatch(const char *a1, const char *a2, const char *b1, const char *b2) { bool retval = true; while( a1 < a2 && b1 < b2 ) @@ -5046,7 +5067,7 @@ ismatch(char *a1, char *a2, char *b1, char *b2) } static bool -iscasematch(char *a1, char *a2, char *b1, char *b2) +iscasematch(const char *a1, const char *a2, const char *b1, const char *b2) { bool retval = true; while( a1 < a2 && b1 < b2 ) @@ -5059,11 +5080,15 @@ iscasematch(char *a1, char *a2, char *b1, char *b2) return retval; } -static char * -strstr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strstr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(ismatch(haystack, haystack_e, needle, needle_e)) @@ -5076,11 +5101,15 @@ strstr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strcasestr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strcasestr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(iscasematch(haystack, haystack_e, needle, needle_e)) @@ -5093,11 +5122,15 @@ strcasestr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strlaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strlaststr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(ismatch(haystack, haystack_e, needle, needle_e)) @@ -5109,11 +5142,15 @@ strlaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) return retval; } -static char * -strcaselaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) +static +const char * +strcaselaststr( const char *haystack, + const char *haystack_e, + const char *needle, + const char *needle_e) { - char *retval = NULL; - char *pend = haystack_e - (needle_e - needle); + const char *retval = NULL; + const char *pend = haystack_e - (needle_e - needle); while( haystack <= pend ) { if(iscasematch(haystack, haystack_e, needle, needle_e)) @@ -5127,13 +5164,13 @@ strcaselaststr(char *haystack, char *haystack_e, char *needle, char *needle_e) extern "C" -void __gg__substitute(cblc_field_t *dest, - cblc_field_t *arg1_f, - size_t arg1_o, - size_t arg1_s, - size_t N, - uint8_t *control - ) +void +__gg__substitute( cblc_field_t *dest, + const cblc_field_t *arg1_f, + size_t arg1_o, + size_t arg1_s, + size_t N, + const uint8_t *control) { // arg2 is the Group 1 triplet. // arg3 is the Group 2 triplet @@ -5141,19 +5178,22 @@ void __gg__substitute(cblc_field_t *dest, size_t *arg2_o = __gg__treeplet_1o; size_t *arg2_s = __gg__treeplet_1s; cblc_field_t **arg3_f = __gg__treeplet_2f; - size_t *arg3_o = __gg__treeplet_2o; - size_t *arg3_s = __gg__treeplet_2s; + const size_t *arg3_o = __gg__treeplet_2o; + const size_t *arg3_s = __gg__treeplet_2s; - ssize_t retval_size = 256; - char *retval = (char *)malloc(retval_size); + ssize_t retval_size; + retval_size = 256; + char *retval = static_cast<char *>(malloc(retval_size)); + massert(retval); *retval = '\0'; - char *haystack = (char *)(arg1_f->data + arg1_o); - char *haystack_e = haystack + arg1_s; + const char *haystack = PTRCAST(char, (arg1_f->data + arg1_o)); + const char *haystack_e = haystack + arg1_s; ssize_t outdex = 0; - char **pflasts = (char **)malloc(N * sizeof(char *)); + const char **pflasts = static_cast<const char **>(malloc(N * sizeof(char *))); + massert(pflasts); if( arg1_s == 0 ) { @@ -5174,15 +5214,15 @@ void __gg__substitute(cblc_field_t *dest, { pflasts[i] = strcasestr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else if( control[i] & substitute_last_e) { pflasts[i] = strcaselaststr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else { @@ -5195,15 +5235,15 @@ void __gg__substitute(cblc_field_t *dest, { pflasts[i] = strstr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else if( control[i] & substitute_last_e) { pflasts[i] = strlaststr(haystack, haystack_e, - (char *)(arg2_f[i]->data+arg2_o[i]), - (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]); + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])), + PTRCAST(char, (arg2_f[i]->data+arg2_o[i])) + arg2_s[i]); } else { @@ -5223,7 +5263,8 @@ void __gg__substitute(cblc_field_t *dest, > retval_size ) { retval_size *= 2; - retval = (char *)realloc(retval, retval_size); + retval = static_cast<char *>(realloc(retval, retval_size)); + massert(retval); } // We checked earlier for FIRST/LAST matches @@ -5238,8 +5279,8 @@ void __gg__substitute(cblc_field_t *dest, continue; } - char *needle = (char *)(arg2_f[i]->data+arg2_o[i]); - char *needle_e = (char *)(arg2_f[i]->data+arg2_o[i]) + arg2_s[i]; + const char *needle = PTRCAST(char, arg2_f[i]->data+arg2_o[i]); + const char *needle_e = PTRCAST(char, arg2_f[i]->data+arg2_o[i]) + arg2_s[i]; matched = (control[i] & substitute_anycase_e) && iscasematch( haystack, haystack_e, @@ -5267,7 +5308,8 @@ void __gg__substitute(cblc_field_t *dest, while( outdex + 1 > retval_size ) { retval_size *= 2; - retval = (char *)realloc(retval, retval_size); + retval = static_cast<char *>(realloc(retval, retval_size)); + massert(retval); } retval[outdex++] = *haystack++; } @@ -5284,13 +5326,13 @@ void __gg__substitute(cblc_field_t *dest, extern "C" void __gg__locale_compare( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t arg1_s, - cblc_field_t *arg2, + const cblc_field_t *arg2, size_t arg2_o, size_t arg2_s, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/ ) @@ -5341,10 +5383,10 @@ __gg__locale_compare( cblc_field_t *dest, extern "C" void __gg__locale_date(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t /*arg1_s*/, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) { @@ -5377,10 +5419,10 @@ __gg__locale_date(cblc_field_t *dest, extern "C" void __gg__locale_time(cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t /*arg1_s*/, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) @@ -5413,10 +5455,10 @@ __gg__locale_time(cblc_field_t *dest, extern "C" void __gg__locale_time_from_seconds( cblc_field_t *dest, - cblc_field_t *arg1, + const cblc_field_t *arg1, size_t arg1_o, size_t arg1_s, - cblc_field_t *arg_locale, + const cblc_field_t *arg_locale, size_t /*arg_locale_o*/, size_t /*arg_locale_s*/) { @@ -5432,7 +5474,7 @@ __gg__locale_time_from_seconds( cblc_field_t *dest, // Default locale tm tm = {}; - int rdigits; + int rdigits=0; long seconds = (long)__gg__binary_value_from_qualified_field(&rdigits, arg1, arg1_o, diff --git a/libgcobol/io.cc b/libgcobol/io.cc index 95e1d02..9b07309 100644 --- a/libgcobol/io.cc +++ b/libgcobol/io.cc @@ -31,11 +31,12 @@ #include "config.h" #include "io.h" -#include "stdio.h" -#include "stdlib.h" -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> + +#include <cstdio> +#include <cstdlib> +#include <cerrno> +#include <cstdbool> +#include <cstdint> /* * The Cobol runtime support is responsible to set the file status diff --git a/libgcobol/libgcobol-fp.h b/libgcobol/libgcobol-fp.h new file mode 100644 index 0000000..fcfa0a7 --- /dev/null +++ b/libgcobol/libgcobol-fp.h @@ -0,0 +1,59 @@ +/* Copyright The GNU Toolchain Authors. */ + +/* This file is part of the GNU COBOL runtime library (libgcobol). + +libgcobol is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +libgcobol is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* You must include "config.h" before this file. */ + +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381 +// Use long double, l suffix on calls, l or L suffix in literals +# define GCOB_FP128 long double +# define GCOB_FP128_LITERAL(lit) (lit ## l) +# define FP128_FUNC(funcname) funcname ## l +# define FP128_FMT "L" +# define strtofp128(nptr, endptr) strtold(nptr, endptr) +# define strfromfp128(str, n, format, fp) snprintf(str, n, format, fp) +#elif __FLT128_MANT_DIG__ == 113 && __FLT128_MIN_EXP__ == -16381 \ + && defined(USE_IEC_60559) +// Use _Float128, f128 suffix on calls, f128 or F128 suffix on literals +# define GCOB_FP128 _Float128 +# define GCOB_FP128_LITERAL(lit) (lit ## f128) +# define FP128_FUNC(funcname) funcname ## f128 +# define FP128_FMT "" +# define strtofp128(nptr, endptr) strtof128(nptr, endptr) +# define strfromfp128(str, n, format, fp) strfromf128(str, n, format, fp) +#elif __FLT128_MANT_DIG__ == 113 && __FLT128_MIN_EXP__ == -16381 +// Use __float128, q suffix on calls, q or Q suffix on literals +# define GCOB_FP128 __float128 +# define GCOB_FP128_LITERAL(lit) (lit ## q) +# define FP128_FUNC(funcname) funcname ## q +# define FP128_FMT "Q" +# define strtofp128(nptr, endptr) strtoflt128(nptr, endptr) +# define strfromfp128(str, n, format, fp) quadmath_snprintf(str, n, format, fp) +#else +# error "libgcobol requires 128b floating point" +#endif + +#if USE_QUADMATH +/* We will assume that unless we found the 128 to/from string and some + representative trig functions, we need libquadmath to support those. */ +# include "quadmath.h" +#endif diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index f7fa7a7..81b5b7a 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -27,29 +27,35 @@ * (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 <ctype.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <math.h> -#include <fenv.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <vector> #include <algorithm> -#include <unordered_map> +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> #include <set> +#include <stack> #include <string> +#include <unordered_map> +#include <vector> + +#include <dirent.h> +#include <dlfcn.h> +#include <err.h> +#include <fcntl.h> +#include <fenv.h> +#include <math.h> // required for fpclassify(3), not in cmath #include <setjmp.h> #include <signal.h> -#include <dlfcn.h> -#include <dirent.h> -#include <sys/resource.h> +#include <syslog.h> +#include <unistd.h> +#include <stdarg.h> +#if __has_include(<errno.h>) +# include <errno.h> // for program_invocation_short_name +#endif #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -59,15 +65,19 @@ #include "gfileio.h" #include "charmaps.h" #include "valconv.h" - #include <sys/mman.h> +#include <sys/resource.h> #include <sys/stat.h> #include <sys/types.h> - +#include <sys/time.h> #include <execinfo.h> - #include "exceptl.h" +/* BSD extension. */ +#if !defined(LOG_PERROR) +#define LOG_PERROR 0 +#endif + #if !defined (HAVE_STRFROMF32) # if __FLT_MANT_DIG__ == 24 && __FLT_MAX_EXP__ == 128 static int @@ -92,6 +102,14 @@ strfromf64 (char *s, size_t n, const char *f, double v) # endif #endif +// Enable Declarative tracing via "match_declarative" environment variable. +#if defined(MATCH_DECLARATIVE) || true +# undef MATCH_DECLARATIVE +# define MATCH_DECLARATIVE getenv("match_declarative") +#else +# define MATCH_DECLARATIVE (nullptr) +#endif + // This couldn't be defined in symbols.h because it conflicts with a LEVEL66 // in parse.h #define LEVEL66 (66) @@ -106,8 +124,6 @@ strfromf64 (char *s, size_t n, const char *f, double v) // These global values are established as the COBOL program executes int __gg__exception_code = 0 ; -int __gg__exception_handled = 0 ; -int __gg__exception_file_number = 0 ; int __gg__exception_file_status = 0 ; const char *__gg__exception_file_name = NULL ; const char *__gg__exception_program_id = NULL ; @@ -118,10 +134,14 @@ int __gg__exception_line_number = 0 ; const char *__gg__exception_statement = NULL ; int __gg__default_compute_error = 0 ; int __gg__rdigits = 0 ; -int __gg__odo_violation = 0 ; int __gg__nop = 0 ; int __gg__main_called = 0 ; +// During SORT operations, we don't want the end-of-file condition, which +// happens as a matter of course, from setting the EOF exception condition. +// Setting this variable to 'true' suppresses the error condition. +static bool sv_suppress_eof_ec = false; + // What follows are arrays that are used by features like INSPECT, STRING, // UNSTRING, and, particularly, arithmetic_operation. These features are // characterized by having unknown, and essentially unlimited, numbers of @@ -170,18 +190,23 @@ size_t * __gg__treeplet_4s = NULL ; // used to keep track of local variables. size_t __gg__unique_prog_id = 0 ; -// These values are the persistent stashed versions of the global values -static int stashed_exception_code; -static int stashed_exception_handled; -static int stashed_exception_file_number; -static int stashed_exception_file_status; -static const char *stashed_exception_file_name; -static const char *stashed_exception_program_id; -static const char *stashed_exception_section; -static const char *stashed_exception_paragraph; -static const char *stashed_exception_source_file; -static int stashed_exception_line_number; -static const char *stashed_exception_statement; +// Whenever an exception status is set, a snapshot of the current statement +// location information are established in the "last_exception..." variables. +// This is in accordance with the ISO requirements of "14.6.13.1.1 General" that +// describe how a "last exception status" is maintained. +// other "location" information +static int last_exception_code; +static const char *last_exception_program_id; +static const char *last_exception_section; +static const char *last_exception_paragraph; +static const char *last_exception_source_file; +static int last_exception_line_number; +static const char *last_exception_statement; +// These variables are similar, and are established when an exception is +// raised for a file I-O operation. +static cblc_file_prior_op_t last_exception_file_operation; +static file_status_t last_exception_file_status; +static const char *last_exception_file_name; static int sv_from_raise_statement = 0; @@ -204,47 +229,221 @@ void *__gg__entry_location = NULL; // nested PERFORM PROC statements. void *__gg__exit_address = NULL; +/* + * ec_status_t represents the runtime exception condition status for + * any statement. There are 4 states: + * 1. initial, all zeros + * 2. updated, copy global EC state for by Declarative and/or default + * 3. matched, Declarative found, isection nonzero + * 4. handled, where handled == type + * + * If the statement includes some kind of ON ERROR + * clause that covers it, the generated code does not raise an EC. + * + * The status is updated by __gg_match_exception if it runs, else + * __gg__check_fatal_exception. + * + * If a Declarative is matched, its section number is passed to handled_by(), + * which does two things: + * 1. sets isection to record the declarative + * 2. for a nonfatal EC, sets handled, indication no further action is needed + * + * A Declarative may use RESUME, which clears ec_status, which is a "handled" state. + * + * Default processing ensures return to initial state. + */ +class ec_status_t { + public: + struct file_status_t { + size_t ifile; + cblc_file_prior_op_t operation; + cbl_file_mode_t mode; + cblc_field_t *user_status; + const char * filename; + file_status_t() + : ifile(0) + , operation(file_op_none) + , mode(file_mode_none_e) + , user_status(nullptr) + , filename(nullptr) + {} + explicit file_status_t( const cblc_file_t *file ) + : ifile(file->symbol_table_index) + , operation(file->prior_op) + , mode(cbl_file_mode_t(file->mode_char)) + , user_status(file->user_status) + , filename(file->filename) + {} + const char * op_str() const { + switch( operation ) { + case file_op_none: return "none"; + case file_op_open: return "open"; + case file_op_close: return "close"; + case file_op_start: return "start"; + case file_op_read: return "read"; + case file_op_write: return "write"; + case file_op_rewrite: return "rewrite"; + case file_op_delete: return "delete"; + } + return "???"; + } + }; + private: + char msg[132]; + ec_type_t type, handled; + size_t isection; + cbl_enabled_exceptions_t enabled; + cbl_declaratives_t declaratives; + struct file_status_t file; + public: + int lineno; + const char *source_file; + cbl_name_t statement; // e.g., "ADD" + + ec_status_t() + : type(ec_none_e) + , handled(ec_none_e) + , isection(0) + , lineno(0) + , source_file(NULL) + { + msg[0] = statement[0] = '\0'; + } + + bool is_fatal() const; + ec_status_t& update(); + + bool is_enabled() const { return enabled.match(type); } + bool is_enabled( ec_type_t ec) const { return enabled.match(ec); } + ec_status_t& handled_by( size_t declarative_section ) { + isection = declarative_section; + // A fatal exception remains unhandled unless RESUME clears it. + if( ! is_fatal() ) { + handled = type; + } + return *this; + } + ec_status_t& clear() { + handled = type = ec_none_e; + isection = 0; + lineno = 0; + msg[0] = statement[0] = '\0'; + return *this; + } + bool unset() const { return isection == 0 && lineno == 0; } + + void reset_environment() const; + ec_status_t& copy_environment(); + + // Return the EC's type if it is *not* handled. + ec_type_t unhandled() const { + bool was_handled = ec_cmp(type, handled); + return was_handled? ec_none_e : type; + } + + bool done() const { return unhandled() == ec_none_e; } + + const file_status_t& file_status() const { return file; } + + const char * exception_location() { + snprintf(msg, sizeof(msg), "%s:%d: '%s'", source_file, lineno, statement); + return msg; + } +}; + +/* + * Capture the global EC status at the beginning of Declarative matching. While + * executing the Declarative, push the current status on a stack. When the + * Declarative returns, restore EC status from the stack. + * + * If the Declarative includes a RESUME statement, it clears the on-stack + * status, thus avoiding any default handling. + */ static ec_status_t ec_status; +static std::stack<ec_status_t> ec_stack; + +static cbl_enabled_exceptions_t enabled_ECs; +static cbl_declaratives_t declaratives; static const ec_descr_t * local_ec_type_descr( ec_type_t type ) { auto p = std::find( __gg__exception_table, __gg__exception_table_end, type ); if( p == __gg__exception_table_end ) { + warnx("%s:%d: no such EC value %08x", __func__, __LINE__, type); __gg__abort("Fell off the end of the __gg__exception_table"); } return p; } +cblc_file_t * __gg__file_stashed(); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +// Keep this debugging function around for when it is needed static const char * local_ec_type_str( ec_type_t type ) { if( type == ec_none_e ) return "EC-NONE"; auto p = local_ec_type_descr(type); return p->name; } +#pragma GCC diagnostic pop -ec_status_t& ec_status_t::update() { - handled = ec_type_t(__gg__exception_handled); - type = ec_type_t(__gg__exception_code); - __gg__exception_code = ec_none_e; - source_file = __gg__exception_source_file; - lineno = __gg__exception_line_number; +bool +ec_status_t::is_fatal() const { + auto descr = local_ec_type_descr(type); + return descr->disposition == ec_category_fatal_e; +} + +ec_status_t& +ec_status_t::update() { + handled = ec_none_e; + type = ec_type_t(__gg__exception_code); + source_file = __gg__exception_source_file; + lineno = __gg__exception_line_number; if( __gg__exception_statement ) { snprintf(statement, sizeof(statement), "%s", __gg__exception_statement); } + cblc_file_t *stashed = __gg__file_stashed(); + this->file = stashed? file_status_t(stashed) : file_status_t(); - if( type != ec_none_e && getenv("match_declarative") ) { - warnx( "ec_status_t::update:%d: EC %s by %s handled %02X " , __LINE__, + if( type != ec_none_e && MATCH_DECLARATIVE ) { + warnx( "ec_status_t::update:%d: EC %s by %s (handled %s) " , __LINE__, local_ec_type_str(type), __gg__exception_statement? statement : "<none>", - handled ); // might be file-status, not ec_type_t + local_ec_type_str(handled) ); } + this->enabled = ::enabled_ECs; + this->declaratives = ::declaratives; + return *this; } +ec_status_t& +ec_status_t::copy_environment() { + this->enabled = ::enabled_ECs; + this->declaratives = ::declaratives; + return *this; +} + +void +ec_status_t::reset_environment() const { + ::enabled_ECs = enabled; + ::declaratives = declaratives; +} + + +// This is the default truncation mode static cbl_truncation_mode truncation_mode = trunc_std_e; +extern "C" +void +__gg__set_truncation_mode(cbl_truncation_mode trunc_mode) + { + truncation_mode = trunc_mode; + } + struct program_state { // These are the run-time values of these characters. @@ -350,7 +549,6 @@ void *malloc(size_t a) void *retval = malloc(a); fprintf(stderr, " --malloc(%p)-- ", retval); return retval; - return retval; } #endif @@ -361,6 +559,12 @@ __gg__abort(const char *msg) abort(); } +void +__gg__mabort() + { + __gg__abort("Memory allocation error\n"); + } + extern "C" char __gg__get_decimal_point() @@ -391,7 +595,7 @@ __gg__resize_int_p( size_t *size, if( new_size > *size ) { *size = new_size; - *block = (int *)realloc(*block, new_size * sizeof(int)); + *block = static_cast<int *>(realloc(*block, new_size * sizeof(int))); } } @@ -406,36 +610,36 @@ __gg__resize_treeplet(int ngroup, if( new_size > treeplet_1_size ) { treeplet_1_size = new_size; - __gg__treeplet_1f = (cblc_field_t **)realloc(__gg__treeplet_1f, new_size * sizeof(cblc_field_t *)); - __gg__treeplet_1o = (size_t *)realloc(__gg__treeplet_1o, new_size * sizeof(size_t)); - __gg__treeplet_1s = (size_t *)realloc(__gg__treeplet_1s, new_size * sizeof(size_t)); + __gg__treeplet_1f = static_cast<cblc_field_t **>(realloc(__gg__treeplet_1f, new_size * sizeof(cblc_field_t *))); + __gg__treeplet_1o = static_cast<size_t *>(realloc(__gg__treeplet_1o, new_size * sizeof(size_t))); + __gg__treeplet_1s = static_cast<size_t *>(realloc(__gg__treeplet_1s, new_size * sizeof(size_t))); } break; case 2: if( new_size > treeplet_2_size ) { treeplet_2_size = new_size; - __gg__treeplet_2f = (cblc_field_t **)realloc(__gg__treeplet_2f, new_size * sizeof(cblc_field_t *)); - __gg__treeplet_2o = (size_t *)realloc(__gg__treeplet_2o, new_size * sizeof(size_t)); - __gg__treeplet_2s = (size_t *)realloc(__gg__treeplet_2s, new_size * sizeof(size_t)); + __gg__treeplet_2f = static_cast<cblc_field_t **>(realloc(__gg__treeplet_2f, new_size * sizeof(cblc_field_t *))); + __gg__treeplet_2o = static_cast<size_t *>(realloc(__gg__treeplet_2o, new_size * sizeof(size_t))); + __gg__treeplet_2s = static_cast<size_t *>(realloc(__gg__treeplet_2s, new_size * sizeof(size_t))); } break; case 3: if( new_size > treeplet_3_size ) { treeplet_3_size = new_size; - __gg__treeplet_3f = (cblc_field_t **)realloc(__gg__treeplet_3f, new_size * sizeof(cblc_field_t *)); - __gg__treeplet_3o = (size_t *)realloc(__gg__treeplet_3o, new_size * sizeof(size_t)); - __gg__treeplet_3s = (size_t *)realloc(__gg__treeplet_3s, new_size * sizeof(size_t)); + __gg__treeplet_3f = static_cast<cblc_field_t **>(realloc(__gg__treeplet_3f, new_size * sizeof(cblc_field_t *))); + __gg__treeplet_3o = static_cast<size_t *>(realloc(__gg__treeplet_3o, new_size * sizeof(size_t))); + __gg__treeplet_3s = static_cast<size_t *>(realloc(__gg__treeplet_3s, new_size * sizeof(size_t))); } break; case 4: if( new_size > treeplet_4_size ) { treeplet_4_size = new_size; - __gg__treeplet_4f = (cblc_field_t **)realloc(__gg__treeplet_4f, new_size * sizeof(cblc_field_t *)); - __gg__treeplet_4o = (size_t *)realloc(__gg__treeplet_4o, new_size * sizeof(size_t)); - __gg__treeplet_4s = (size_t *)realloc(__gg__treeplet_4s, new_size * sizeof(size_t)); + __gg__treeplet_4f = static_cast<cblc_field_t **>(realloc(__gg__treeplet_4f, new_size * sizeof(cblc_field_t *))); + __gg__treeplet_4o = static_cast<size_t *>(realloc(__gg__treeplet_4o, new_size * sizeof(size_t))); + __gg__treeplet_4s = static_cast<size_t *>(realloc(__gg__treeplet_4s, new_size * sizeof(size_t))); } break; } @@ -553,7 +757,7 @@ __gg__init_program_state() } static int -var_is_refmod( cblc_field_t *var ) +var_is_refmod( const cblc_field_t *var ) { return (var->attr & refmod_e) != 0; } @@ -722,9 +926,9 @@ __gg__binary_to_string_internal(char *result, int digits, __int128 value) } static bool -value_is_too_big( cblc_field_t *var, - __int128 value, - int source_rdigits) +value_is_too_big(const cblc_field_t *var, + __int128 value, + int source_rdigits) { // This routine is in support of arithmetic ON SIZE ERROR. It returns // TRUE if var hasn't enough bytes to hold the decimal representation @@ -861,12 +1065,13 @@ is_sign_bit_on(char ch) extern "C" void -__gg__string_to_alpha_edited_ascii( char *dest, - char *source, - int slength, - char *picture) +__gg__string_to_alpha_edited_ascii( char *dest, + const char *source, + int slength, + const char *picture) { - char *dupe = (char *)malloc(slength); + char *dupe = static_cast<char *>(malloc(slength)); + massert(dupe); memcpy(dupe, source, slength); ascii_to_internal_str(dupe, slength); __gg__string_to_alpha_edited(dest, dupe, slength, picture); @@ -881,10 +1086,12 @@ int128_to_int128_rounded( cbl_round_t rounded, int *compute_error) { // value is signed, and is scaled to the target - _Float128 fpart = _Float128(remainder) / _Float128(factor); + GCOB_FP128 fpart = ((GCOB_FP128)remainder) / ((GCOB_FP128)factor); __int128 retval = value; - if(rounded == nearest_even_e && fpart != -0.5Q && fpart != 0.5Q ) + if(rounded == nearest_even_e + && fpart != GCOB_FP128_LITERAL (-0.5) + && fpart != GCOB_FP128_LITERAL (0.5)) { // "bankers rounding" has been requested. // @@ -905,14 +1112,14 @@ int128_to_int128_rounded( cbl_round_t rounded, // 0.5 through 0.9 becomes 1 if( value < 0 ) { - if( fpart <= -0.5Q ) + if( fpart <= GCOB_FP128_LITERAL(-0.5) ) { retval -= 1; } } else { - if( fpart >= 0.5Q ) + if( fpart >= GCOB_FP128_LITERAL(0.5) ) { retval += 1; } @@ -946,14 +1153,14 @@ int128_to_int128_rounded( cbl_round_t rounded, // 0.6 through 0.9 becomes 1 if( value < 0 ) { - if( fpart < -0.5Q ) + if( fpart < GCOB_FP128_LITERAL(-0.5) ) { retval -= 1; } } else { - if( fpart > 0.5Q ) + if( fpart > GCOB_FP128_LITERAL(0.5) ) { retval += 1; } @@ -1035,15 +1242,17 @@ int128_to_int128_rounded( cbl_round_t rounded, static __int128 f128_to_i128_rounded( cbl_round_t rounded, - _Float128 value, + GCOB_FP128 value, int *compute_error) { // value is signed, and is scaled to the target - _Float128 ipart; - _Float128 fpart = modff128(value, &ipart); + GCOB_FP128 ipart; + GCOB_FP128 fpart = FP128_FUNC(modf)(value, &ipart); __int128 retval = (__int128)ipart; - if(rounded == nearest_even_e && fpart != -0.5Q && fpart != 0.5Q ) + if(rounded == nearest_even_e + && fpart != GCOB_FP128_LITERAL (-0.5) + && fpart != GCOB_FP128_LITERAL (0.5)) { // "bankers rounding" has been requested. // @@ -1064,14 +1273,14 @@ f128_to_i128_rounded( cbl_round_t rounded, // 0.5 through 0.9 becomes 1 if( value < 0 ) { - if( fpart <= -0.5Q ) + if( fpart <= GCOB_FP128_LITERAL (-0.5) ) { retval -= 1; } } else { - if( fpart >= 0.5Q ) + if( fpart >= GCOB_FP128_LITERAL (0.5) ) { retval += 1; } @@ -1105,14 +1314,14 @@ f128_to_i128_rounded( cbl_round_t rounded, // 0.6 through 0.9 becomes 1 if( value < 0 ) { - if( fpart < -0.5Q ) + if( fpart < GCOB_FP128_LITERAL (-0.5) ) { retval -= 1; } } else { - if( fpart > 0.5Q ) + if( fpart > GCOB_FP128_LITERAL (0.5) ) { retval += 1; } @@ -1217,7 +1426,7 @@ int128_to_field(cblc_field_t *var, { float tvalue = (float)value; tvalue /= (float)__gg__power_of_ten(source_rdigits); - *(float *)location = tvalue; + *PTRCAST(float, location) = tvalue; break; } @@ -1225,7 +1434,7 @@ int128_to_field(cblc_field_t *var, { double tvalue = (double)value; tvalue /= (double)__gg__power_of_ten(source_rdigits); - *(double *)location = tvalue; + *PTRCAST(double, location) = tvalue; break; } @@ -1276,8 +1485,8 @@ int128_to_field(cblc_field_t *var, { value = -value; } - _Float128 tvalue = (_Float128 )value; - tvalue /= (_Float128 )__gg__power_of_ten(source_rdigits); + GCOB_FP128 tvalue = (GCOB_FP128 )value; + tvalue /= (GCOB_FP128 )__gg__power_of_ten(source_rdigits); // *(_Float128 *)location = tvalue; // memcpy because *(_Float128 *) requires a 16-byte boundary. memcpy(location, &tvalue, 16); @@ -1289,8 +1498,6 @@ int128_to_field(cblc_field_t *var, default: { - bool size_error = false; - int target_rdigits = var->rdigits; if( var->attr & intermediate_e && var->type == FldNumericBin5) { @@ -1380,6 +1587,7 @@ int128_to_field(cblc_field_t *var, else { // Value is now scaled to the target's target_rdigits + bool size_error = false; int is_negative = value < 0 ; @@ -1409,8 +1617,9 @@ int128_to_field(cblc_field_t *var, // Note that sending a signed value to an alphanumeric strips off // any plus or minus signs. - size_error = __gg__binary_to_string_internal( (char *)location, - length, value); + size_error = __gg__binary_to_string_internal( + PTRCAST(char, location), + length, value); break; case FldNumericDisplay: @@ -1426,7 +1635,7 @@ int128_to_field(cblc_field_t *var, { // The sign character goes into the first location size_error = - __gg__binary_to_string_internal((char *)(location+1), + __gg__binary_to_string_internal(PTRCAST(char, location+1), length-1, value); location[0] = sign_ch; } @@ -1434,8 +1643,8 @@ int128_to_field(cblc_field_t *var, { // The sign character goes into the last location size_error = - __gg__binary_to_string_internal( (char *)location, - length-1, value); + __gg__binary_to_string_internal(PTRCAST(char, location), + length-1, value); location[length-1] = sign_ch; } } @@ -1444,7 +1653,7 @@ int128_to_field(cblc_field_t *var, // The sign information is not separate, so we put it into // the number size_error = - __gg__binary_to_string_internal(( char *)location, + __gg__binary_to_string_internal(PTRCAST(char, location), length, value); if( size_error && is_negative ) @@ -1480,7 +1689,8 @@ int128_to_field(cblc_field_t *var, else { // It's a simple positive number - size_error = __gg__binary_to_string_internal( (char *)location, + size_error = __gg__binary_to_string_internal( PTRCAST(char, + location), length, value); } @@ -1503,12 +1713,12 @@ int128_to_field(cblc_field_t *var, // Convert that string according to the PICTURE clause size_error |= __gg__string_to_numeric_edited( - (char *)location, + PTRCAST(char, location), ach, target_rdigits, is_negative, var->picture); - ascii_to_internal_str((char *)location, var->capacity); + ascii_to_internal_str( PTRCAST(char, location), var->capacity); } break; @@ -1544,7 +1754,7 @@ int128_to_field(cblc_field_t *var, // Convert that string according to the PICTURE clause __gg__string_to_alpha_edited( - (char *)location, + PTRCAST(char, location), ach, strlen(ach), var->picture); @@ -1660,11 +1870,11 @@ int128_to_field(cblc_field_t *var, } static __int128 -edited_to_binary( const char *ps_, +edited_to_binary( char *ps_, int length, int *rdigits) { - const unsigned char *ps = (const unsigned char *)ps_; + const unsigned char *ps = const_cast<const unsigned char *>(PTRCAST(unsigned char, ps_)); // This routine is used for converting NumericEdited strings to // binary. @@ -1690,8 +1900,6 @@ edited_to_binary( const char *ps_, __int128 result = 0; - unsigned char ch; - // We need to check the last two characters. If CR or DB, then the result // is negative: if( length >= 2) @@ -1712,7 +1920,7 @@ edited_to_binary( const char *ps_, while( index < length ) { - ch = ps[index++] & 0xFF; + unsigned char ch = ps[index++] & 0xFF; if( ch == ascii_to_internal(__gg__decimal_point) ) { delta_r = 1; @@ -1734,11 +1942,7 @@ edited_to_binary( const char *ps_, } } - if( result == 0 ) - { - hyphen = 0; - } - else if( hyphen ) + if( hyphen ) { result = -result; } @@ -1768,7 +1972,7 @@ big_endian_to_binary_signed( } // move the bytes of psource into retval, flipping them end-to-end - unsigned char *dest = (unsigned char *)&retval; + unsigned char *dest = PTRCAST(unsigned char, &retval); while(capacity > 0) { *dest++ = psource[--capacity]; @@ -1832,7 +2036,7 @@ big_endian_to_binary_unsigned( __int128 retval = 0 ; // move the bytes of psource into retval, flipping them end-to-end - unsigned char *dest = (unsigned char *)&retval; + unsigned char *dest = PTRCAST(unsigned char, &retval); while(capacity > 0) { *dest++ = psource[--capacity]; @@ -1842,10 +2046,10 @@ big_endian_to_binary_unsigned( static __int128 -get_binary_value_local( int *rdigits, - cblc_field_t *resolved_var, - unsigned char *resolved_location, - size_t resolved_length) +get_binary_value_local( int *rdigits, + const cblc_field_t *resolved_var, + unsigned char *resolved_location, + size_t resolved_length) { __int128 retval = 0; @@ -1866,7 +2070,8 @@ get_binary_value_local( int *rdigits, case FldGroup : case FldAlphanumeric : // Read the data area as a dirty string: - retval = __gg__dirty_to_binary_internal( (const char *)resolved_location, + retval = __gg__dirty_to_binary_internal( PTRCAST(const char, + resolved_location), resolved_length, rdigits ); break; @@ -1893,8 +2098,8 @@ get_binary_value_local( int *rdigits, // Turn all the bits on memset( &retval, 0xFF, sizeof(retval) ); - // Make it positive - ((unsigned char *)&retval)[sizeof(retval)-1] = 0x3F; + // Make it positive by turning off the highest order bit: + (PTRCAST(unsigned char, &retval))[sizeof(retval)-1] = 0x3F; *rdigits = resolved_var->rdigits; } else @@ -1931,7 +2136,8 @@ get_binary_value_local( int *rdigits, // We know where the decimal point is because of rdigits. Because // we know that it a clean string of ASCII digits, we can use the // dirty converter: - retval = __gg__dirty_to_binary_internal((const char *)resolved_location, + retval = __gg__dirty_to_binary_internal(PTRCAST(const char, + resolved_location), resolved_length, rdigits ); *rdigits = resolved_var->rdigits; @@ -1947,7 +2153,7 @@ get_binary_value_local( int *rdigits, break; case FldNumericEdited : - retval = edited_to_binary( (const char *)resolved_location, + retval = edited_to_binary( PTRCAST(char, resolved_location), resolved_length, rdigits); break; @@ -1956,13 +2162,13 @@ get_binary_value_local( int *rdigits, if( resolved_var->attr & signable_e) { retval = big_endian_to_binary_signed( - (const unsigned char *)resolved_location, + PTRCAST(const unsigned char, resolved_location), resolved_length); } else { retval = big_endian_to_binary_unsigned( - (const unsigned char *)resolved_location, + PTRCAST(const unsigned char, resolved_location), resolved_length); } *rdigits = resolved_var->rdigits; @@ -1990,13 +2196,13 @@ get_binary_value_local( int *rdigits, if( resolved_var->attr & signable_e) { retval = little_endian_to_binary_signed( - (const unsigned char *)resolved_location, + PTRCAST(const unsigned char, resolved_location), resolved_length); } else { retval = little_endian_to_binary_unsigned( - (const unsigned char *)resolved_location, + PTRCAST(const unsigned char, resolved_location), resolved_length); } *rdigits = resolved_var->rdigits; @@ -2084,8 +2290,8 @@ get_binary_value_local( int *rdigits, static time_t cobol_time() { - struct timespec tp; - __gg__clock_gettime(CLOCK_REALTIME, &tp); + struct cbl_timespec tp; + __gg__clock_gettime(&tp); return tp.tv_sec; } @@ -2096,7 +2302,7 @@ __gg__get_date_yymmdd() char ach[32]; time_t t = cobol_time(); - struct tm *local = localtime(&t); + const struct tm *local = localtime(&t); sprintf(ach, "%2.2d%2.2d%2.2d", @@ -2115,7 +2321,7 @@ __gg__get_date_yyyymmdd() char ach[32]; time_t t = cobol_time(); - struct tm *local = localtime(&t); + const struct tm *local = localtime(&t); sprintf(ach, "%4.4d%2.2d%2.2d", @@ -2134,7 +2340,7 @@ __gg__get_date_yyddd() char ach[32]; time_t t = cobol_time(); - struct tm *local = localtime(&t); + const struct tm *local = localtime(&t); sprintf(ach, "%2.2d%3.3d", @@ -2152,7 +2358,7 @@ __gg__get_yyyyddd() char ach[32]; time_t t = cobol_time(); - struct tm *local = localtime(&t); + const struct tm *local = localtime(&t); sprintf(ach, "%4.4d%3.3d", @@ -2170,7 +2376,7 @@ __gg__get_date_dow() char ach[32]; time_t t = cobol_time(); - struct tm *local = localtime(&t); + const struct tm *local = localtime(&t); sprintf(ach, "%1.1d", @@ -2197,12 +2403,51 @@ int_from_digits(const char * &p, int ndigits) return retval; } +// For testing purposes, this undef causes the use of gettimeofday(). +// #undef HAVE_CLOCK_GETTIME + +static uint64_t +get_time_nanoseconds_local() +{ + // This code was unabashedly stolen from gcc/timevar.cc. + // It returns the Unix epoch with nine decimal places. + + /* Note: I am perplexed. I have been examining the gcc Makefiles and + configure.ac files, and I am unable to locate where HAVE_GETTIMEOFDAY + is established. There have been issues compiling on MacOS, where + apparently clock_gettime() is not available. But I don't see exactly + how gettimeofday() gets used, instead. But without the ability to + compile on a MacOS system, I am fumbling along as best I can. + + I decided to simply replace clock_gettime() with getttimeofday() when + clock_gettime() isn't available, even though gcc/timevar.cc handles + the situation differently. + + -- Bob Dubner, 2025-06-11*/ + + uint64_t retval = 0; + +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + clock_gettime (CLOCK_REALTIME, &ts); + retval = ts.tv_sec * 1000000000 + ts.tv_nsec; + return retval; +//#endif +//#ifdef HAVE_GETTIMEOFDAY +#else + struct timeval tv; + gettimeofday (&tv, NULL); + retval = tv.tv_sec * 1000000000 + tv.tv_usec * 1000; + return retval; +#endif + return retval; +} extern "C" void -__gg__clock_gettime(clockid_t clk_id, struct timespec *tp) +__gg__clock_gettime(struct cbl_timespec *tp) { - const char *p = getenv("COB_CURRENT_DATE"); + const char *p = getenv("GCOBOL_CURRENT_DATE"); if( p ) { @@ -2230,7 +2475,9 @@ __gg__clock_gettime(clockid_t clk_id, struct timespec *tp) } else { - clock_gettime(clk_id, tp); + uint64_t ns = get_time_nanoseconds_local(); + tp->tv_sec = ns/1000000000; + tp->tv_nsec = ns%1000000000; } } @@ -2240,8 +2487,8 @@ __gg__get_date_hhmmssff() { char ach[32]; - struct timespec tv; - __gg__clock_gettime(CLOCK_REALTIME, &tv); + struct cbl_timespec tv; + __gg__clock_gettime(&tv); struct tm tm; localtime_r(&tv.tv_sec, &tm); @@ -2270,20 +2517,19 @@ int __gg__setop_compare( const char *candidate, int capacity, - const char *domain) + char *domain) { // This routine is called to compare the characters of 'candidate' // against the list of character pairs in 'domain' int retval = 0; - int ch; int l; int h; - const char *d; + char *d; for(int i=0; i<capacity; i++) { - ch = (*candidate++ & 0xFF); + int ch = (*candidate++ & 0xFF); d = domain; while(*d) { @@ -2295,7 +2541,7 @@ __gg__setop_compare( // See the comments in genapi.cc::get_class_condition_string // to see how this string was encoded. - l = (int)strtoll(d, (char **)&d, 16); + l = (int)strtoll(d, reinterpret_cast<char **>(&d), 16); if( l < 0 ) { l = -l; @@ -2304,7 +2550,7 @@ __gg__setop_compare( if( *d == '/' ) { d += 1; - h = (int)strtoll(d, (char **)&d, 16); + h = (int)strtoll(d, reinterpret_cast<char **>(&d), 16); if( h < 0 ) { h = -h; @@ -2573,7 +2819,7 @@ __gg__dirty_to_binary_internal( const char *dirty, } extern "C" -_Float128 +GCOB_FP128 __gg__dirty_to_float( const char *dirty, int length) { @@ -2589,7 +2835,7 @@ __gg__dirty_to_float( const char *dirty, // It also can handle 12345E-2 notation. - _Float128 retval = 0; + GCOB_FP128 retval = 0; int rdigits = 0; int hyphen = 0; @@ -2754,7 +3000,7 @@ void psz_to_internal(char *psz) } static int -get_scaled_rdigits(cblc_field_t *field) +get_scaled_rdigits(const cblc_field_t *field) { int retval; if( !(field->attr & scaled_e) ) @@ -2859,7 +3105,7 @@ format_for_display_internal(char **dest, break; } - unsigned char *running_location = actual_location; + const unsigned char *running_location = actual_location; // We need the counts of digits to the left and right of the decimal point int rdigits = get_scaled_rdigits(var); @@ -2874,7 +3120,6 @@ format_for_display_internal(char **dest, rdigits += ldigits; } - int index = 0; // This is the running index into our output destination if( rdigits ) { // We need room for the inside decimal point @@ -2891,6 +3136,7 @@ format_for_display_internal(char **dest, if( actual_location ) { + int index = 0; // This is the running index into our output destination if( var->attr & signable_e ) { if( var->attr & separate_e ) @@ -2935,7 +3181,7 @@ format_for_display_internal(char **dest, // the user. if( (*dest)[index-1] != (char)DEGENERATE_HIGH_VALUE ) { - turn_sign_bit_off((unsigned char *)&ch); + turn_sign_bit_off( PTRCAST(unsigned char, &ch)); } (*dest)[index++] = ch; } @@ -2959,7 +3205,7 @@ format_for_display_internal(char **dest, char ch = *running_location++; if( (*dest)[index-1] != (char)DEGENERATE_HIGH_VALUE ) { - turn_sign_bit_off((unsigned char *)&ch); + turn_sign_bit_off(PTRCAST(unsigned char, &ch)); } (*dest)[index++] = ch; } @@ -3068,11 +3314,9 @@ format_for_display_internal(char **dest, } __gg__realloc_if_necessary(dest, dest_size, nsize); - bool is_signed = value < 0; - if( var->attr & signable_e ) { - if( is_signed ) + if( value < 0 ) { (*dest)[index++] = internal_minus; } @@ -3104,7 +3348,7 @@ format_for_display_internal(char **dest, actual_location, actual_length); char ach[64]; - sprintf(ach, "%lu", (size_t)value); + sprintf(ach, "%lu", (unsigned long)value); __gg__realloc_if_necessary(dest, dest_size, strlen(ach)+1); strcpy(*dest, ach); } @@ -3160,7 +3404,7 @@ format_for_display_internal(char **dest, // side, and 9999999 and then 1E+7 on the high side // 10,000,000 = 1E7 char ach[64]; - _Float32 floatval = *(_Float32 *)actual_location; + _Float32 floatval = *PTRCAST(_Float32, actual_location); strfromf32(ach, sizeof(ach), "%.9E", floatval); char *p = strchr(ach, 'E'); if( !p ) @@ -3200,7 +3444,7 @@ format_for_display_internal(char **dest, // We will also format numbers so that we produce 0.01 and 1E-3 on the low // side, and 9999999 and then 1E+15 on the high side char ach[64]; - _Float64 floatval = *(_Float64 *)actual_location; + _Float64 floatval = *PTRCAST(_Float64, actual_location); strfromf64(ach, sizeof(ach), "%.17E", floatval); char *p = strchr(ach, 'E'); if( !p ) @@ -3244,9 +3488,9 @@ format_for_display_internal(char **dest, // We can't use *(_Float64 *)actual_location; // That uses the SSE registers, which won't work if the source isn't // on a 16-bit boundary. - _Float128 floatval; + GCOB_FP128 floatval; memcpy(&floatval, actual_location, 16); - strfromf128(ach, sizeof(ach), "%.36E", floatval); + strfromfp128(ach, sizeof(ach), "%.36" FP128_FMT "E", floatval); char *p = strchr(ach, 'E'); if( !p ) { @@ -3268,8 +3512,8 @@ format_for_display_internal(char **dest, int precision = 36 - exp; char achFormat[24]; - sprintf(achFormat, "%%.%df", precision); - strfromf128(ach, sizeof(ach), achFormat, floatval); + sprintf(achFormat, "%%.%d" FP128_FMT "f", precision); + strfromfp128(ach, sizeof(ach), achFormat, floatval); } __gg__remove_trailing_zeroes(ach); __gg__realloc_if_necessary(dest, dest_size, strlen(ach)+1); @@ -3294,7 +3538,8 @@ format_for_display_internal(char **dest, if( var->attr & scaled_e && var->type != FldNumericDisplay ) { static size_t buffer_size = MINIMUM_ALLOCATION_SIZE; - static char * buffer = (char *)malloc(buffer_size); + static char *buffer = static_cast<char *>(malloc(buffer_size)); + massert(buffer); if( var->rdigits > 0) { // We have something like 123 or +123. We need to insert a decimal @@ -3353,7 +3598,7 @@ format_for_display_internal(char **dest, { p2 += 1; } - strcpy((char *)p1, (char *)p2); + strcpy(PTRCAST(char, p1), PTRCAST(char, p2)); } done: @@ -3402,7 +3647,8 @@ compare_88( const char *list, { // We are working with a figurative constant - test = (char *)malloc(conditional_length); + test = static_cast<char *>(malloc(conditional_length)); + massert(test); test_len = conditional_length; // This is where we handle the zero-length strings that // nonetheless can magically be expanded into figurative @@ -3439,14 +3685,16 @@ compare_88( const char *list, else if( list_len < conditional_length ) { // 'list' is too short; we have to right-fill with spaces: - test = (char *)malloc(conditional_length); + test = static_cast<char *>(malloc(conditional_length)); + massert(test); test_len = conditional_length; memset(test, internal_space, conditional_length); memcpy(test, list, list_len); } else { - test = (char *)malloc(list_len); + test = static_cast<char *>(malloc(list_len)); + massert(test); test_len = list_len; memcpy(test, list, list_len); } @@ -3459,7 +3707,9 @@ compare_88( const char *list, } else { - cmpval = cstrncmp(test, (char *)conditional_location, conditional_length); + cmpval = cstrncmp (test, + PTRCAST(char, conditional_location), + conditional_length); if( cmpval == 0 && (int)strlen(test) != conditional_length ) { // When strncmp returns 0, the actual smaller string is the @@ -3481,20 +3731,20 @@ compare_88( const char *list, return cmpval; } -static _Float128 -get_float128( cblc_field_t *field, +static GCOB_FP128 +get_float128( const cblc_field_t *field, unsigned char *location ) { - _Float128 retval=0; + GCOB_FP128 retval=0; if(field->type == FldFloat ) { switch( field->capacity ) { case 4: - retval = *(_Float32 *)location; + retval = *PTRCAST(_Float32 , location); break; case 8: - retval = *(_Float64 *)location; + retval = *PTRCAST(_Float64 , location); break; case 16: // retval = *(_Float128 *)location; doesn't work, because the SSE @@ -3508,25 +3758,26 @@ get_float128( cblc_field_t *field, { if( __gg__decimal_point == '.' ) { - retval = strtof128(field->initial, NULL); + retval = strtofp128(field->initial, NULL); } else { // We need to replace any commas with periods static size_t size = 128; - static char *buffer = (char *)malloc(size); + static char *buffer = static_cast<char *>(malloc(size)); while( strlen(field->initial)+1 > size ) { size *= 2; - buffer = (char *)malloc(size); + buffer = static_cast<char *>(malloc(size)); } + massert(buffer); strcpy(buffer, field->initial); char *p = strchr(buffer, ','); if(p) { *p = '.'; } - retval = strtof128(buffer, NULL); + retval = strtofp128(buffer, NULL); } } else @@ -3564,7 +3815,7 @@ compare_field_class(cblc_field_t *conditional, conditional, conditional_location, conditional_length); - char *walker = list->initial; + const char *walker = list->initial; while(*walker) { char left_flag; @@ -3710,8 +3961,8 @@ compare_field_class(cblc_field_t *conditional, case FldFloat: { - _Float128 value = get_float128(conditional, conditional_location) ; - char *walker = list->initial; + GCOB_FP128 fp128 = get_float128(conditional, conditional_location) ; + const char *walker = list->initial; while(*walker) { char left_flag; @@ -3734,7 +3985,7 @@ compare_field_class(cblc_field_t *conditional, walker = right + right_len; - _Float128 left_value; + GCOB_FP128 left_value; if( left_flag == 'F' && left[0] == 'Z' ) { left_value = 0; @@ -3745,7 +3996,7 @@ compare_field_class(cblc_field_t *conditional, left_len); } - _Float128 right_value; + GCOB_FP128 right_value; if( right_flag == 'F' && right[0] == 'Z' ) { right_value = 0; @@ -3756,7 +4007,7 @@ compare_field_class(cblc_field_t *conditional, right_len); } - if( left_value <= value && value <= right_value ) + if( left_value <= fp128 && fp128 <= right_value ) { retval = 0; break; @@ -3836,12 +4087,12 @@ local_is_alpha(int type, bool address_of) static int -compare_strings(char *left_string, - size_t left_length, - bool left_all, - char *right_string, - size_t right_length, - bool right_all) +compare_strings(const char *left_string, + size_t left_length, + bool left_all, + const char *right_string, + size_t right_length, + bool right_all) { int retval = 0; size_t i = 0; @@ -4095,16 +4346,18 @@ __gg__compare_2(cblc_field_t *left_side, retval = 0; retval = value < 0 ? -1 : retval; retval = value > 0 ? 1 : retval; + compare = true; break; } case FldFloat: { - _Float128 value = __gg__float128_from_location(left_side, + GCOB_FP128 value = __gg__float128_from_location(left_side, left_location); retval = 0; retval = value < 0 ? -1 : retval; retval = value > 0 ? 1 : retval; + compare = true; break; } @@ -4123,9 +4376,7 @@ __gg__compare_2(cblc_field_t *left_side, compare = true; break; } - compare = true; goto fixup_retval; - break; } } } @@ -4140,10 +4391,10 @@ __gg__compare_2(cblc_field_t *left_side, if( local_is_alpha(left_side->type, left_address_of) && local_is_alpha(right_side->type, right_address_of) ) { - retval = compare_strings( (char *)left_location, + retval = compare_strings( reinterpret_cast<char *>(left_location), left_length, left_all, - (char *)right_location, + reinterpret_cast<char *>(right_location), right_length, right_all ); @@ -4157,8 +4408,8 @@ __gg__compare_2(cblc_field_t *left_side, if( left_side->type == FldFloat && right_side->type == FldFloat ) { // One or the other of the numerics is a FldFloat - _Float128 left_value = __gg__float128_from_location(left_side, left_location); - _Float128 right_value = __gg__float128_from_location(right_side, right_location); + GCOB_FP128 left_value = __gg__float128_from_location(left_side, left_location); + GCOB_FP128 right_value = __gg__float128_from_location(right_side, right_location); retval = 0; retval = left_value < right_value ? -1 : retval; retval = left_value > right_value ? 1 : retval; @@ -4170,8 +4421,8 @@ __gg__compare_2(cblc_field_t *left_side, { // The left side is a FldFloat; the other is another type of numeric: int rdecimals; - _Float128 left_value; - _Float128 right_value; + GCOB_FP128 left_value; + GCOB_FP128 right_value; if( right_side->type == FldLiteralN) { @@ -4179,12 +4430,13 @@ __gg__compare_2(cblc_field_t *left_side, // literal to be the same flavor as the left side: // We need to replace any commas with periods static size_t size = 128; - static char *buffer = (char *)malloc(size); + static char *buffer = static_cast<char *>(malloc(size)); while( strlen(right_side->initial)+1 > size ) { size *= 2; - buffer = (char *)malloc(size); + buffer = static_cast<char *>(malloc(size)); } + massert(buffer); strcpy(buffer, right_side->initial); if( __gg__decimal_point == ',' ) { @@ -4202,31 +4454,31 @@ __gg__compare_2(cblc_field_t *left_side, { case 4: { - _Float32 left_value = *(_Float32 *)left_location; - _Float32 right_value = strtof32(buffer, NULL); + _Float32 left_value4 = *PTRCAST(_Float32, left_location); + _Float32 right_value4 = strtof(buffer, NULL); retval = 0; - retval = left_value < right_value ? -1 : retval; - retval = left_value > right_value ? 1 : retval; + retval = left_value4 < right_value4 ? -1 : retval; + retval = left_value4 > right_value4 ? 1 : retval; break; } case 8: { - _Float64 left_value = *(_Float64 *)left_location; - _Float64 right_value = strtof64(buffer, NULL); + _Float64 left_value8 = *PTRCAST(_Float64, left_location); + _Float64 right_value8 = strtod(buffer, NULL); retval = 0; - retval = left_value < right_value ? -1 : retval; - retval = left_value > right_value ? 1 : retval; + retval = left_value8 < right_value8 ? -1 : retval; + retval = left_value8 > right_value8 ? 1 : retval; break; } case 16: { //_Float128 left_value = *(_Float128 *)left_location; - _Float128 left_value; - memcpy(&left_value, left_location, 16); - _Float128 right_value = strtof128(buffer, NULL); + GCOB_FP128 left_value16; + memcpy(&left_value16, left_location, 16); + GCOB_FP128 right_value16 = strtofp128(buffer, NULL); retval = 0; - retval = left_value < right_value ? -1 : retval; - retval = left_value > right_value ? 1 : retval; + retval = left_value16 < right_value16 ? -1 : retval; + retval = left_value16 > right_value16 ? 1 : retval; break; } } @@ -4308,13 +4560,13 @@ __gg__compare_2(cblc_field_t *left_side, // The right side is numeric. Sometimes people write code where they // take the refmod of a numeric displays. If somebody did that here, // just do a complete straight-up character by character comparison: - + if( right_refmod ) { - retval = compare_strings( (char *)left_location, + retval = compare_strings( reinterpret_cast<char *>(left_location), left_length, left_all, - (char *)right_location, + reinterpret_cast<char *>(right_location), right_length, right_all); compare = true; @@ -4332,12 +4584,13 @@ __gg__compare_2(cblc_field_t *left_side, // VAL5 EQUAL "005" is TRUE if( left_side->type == FldLiteralA ) { - left_location = (unsigned char *)left_side->data; + left_location = reinterpret_cast<unsigned char *>(left_side->data); left_length = left_side->capacity; } static size_t right_string_size = MINIMUM_ALLOCATION_SIZE; - static char *right_string = (char *)malloc(right_string_size); + static char *right_string + = static_cast<char *>(malloc(right_string_size)); right_string = format_for_display_internal( &right_string, @@ -4361,7 +4614,7 @@ __gg__compare_2(cblc_field_t *left_side, left_length -= 1; } - char *right_fixed; + const char *right_fixed; if( *right_string == internal_plus || *right_string == internal_minus ) { right_fixed = right_string + 1; @@ -4371,7 +4624,7 @@ __gg__compare_2(cblc_field_t *left_side, right_fixed = right_string; } - retval = compare_strings( (char *)left_location, + retval = compare_strings( reinterpret_cast<char *>(left_location), left_length, left_all, right_fixed, @@ -4604,16 +4857,16 @@ sort_contents(unsigned char *contents, extern "C" void -__gg__sort_table( cblc_field_t *table, - size_t table_o, - size_t depending_on, - size_t nkeys, - cblc_field_t **keys, - size_t *ascending, - int duplicates ) +__gg__sort_table( const cblc_field_t *table, + size_t table_o, + size_t depending_on, + size_t nkeys, + cblc_field_t **keys, + size_t *ascending, + int duplicates ) { size_t buffer_size = 128; - unsigned char *contents = (unsigned char *)malloc(buffer_size); + unsigned char *contents = static_cast<unsigned char *>(malloc(buffer_size)); size_t offset = 0; std::vector<size_t>offsets; size_t record_size = table->capacity; @@ -4625,7 +4878,7 @@ __gg__sort_table( cblc_field_t *table, while( offset + sizeof(size_t) + record_size > buffer_size ) { buffer_size *= 2; - contents = (unsigned char *)realloc(contents, buffer_size); + contents = static_cast<unsigned char *>(realloc(contents, buffer_size)); } offsets.push_back(offset); memcpy(contents+offset, &record_size, sizeof(size_t)); @@ -4705,7 +4958,7 @@ init_var_both(cblc_field_t *var, { //fprintf(stderr, "ABORTING on %2.2d %s %d\n", var->level, var->name, var->type); //abort(); - var->data = (unsigned char *)malloc(var->capacity); + var->data = static_cast<unsigned char *>(malloc(var->capacity)); } // Set the "initialized" bit, which is tested in parser_symbol_add to make @@ -4731,11 +4984,11 @@ init_var_both(cblc_field_t *var, // We need to convert the options to the internal native codeset size_t buffer_size = 4; - char *buffer = (char *)malloc(buffer_size); + char *buffer = static_cast<char *>(malloc(buffer_size)); size_t index = 0; - cblc_field_t *parent = var->parent; + const cblc_field_t *parent = var->parent; switch(parent->type) { case FldGroup: @@ -4745,9 +4998,9 @@ init_var_both(cblc_field_t *var, while(*walker) { static size_t first_size = MINIMUM_ALLOCATION_SIZE; - static char *first = (char *)malloc(first_size); + static char *first = static_cast<char *>(malloc(first_size)); static size_t last_size = MINIMUM_ALLOCATION_SIZE; - static char *last = (char *)malloc(last_size); + static char *last = static_cast<char *>(malloc(last_size)); if( (*walker & 0xFF) == 0xFF ) { strcpy(first, walker); @@ -4770,7 +5023,7 @@ init_var_both(cblc_field_t *var, while(index + strlen(first) + strlen(last) + 3 > buffer_size) { buffer_size *= 2; - buffer = (char *)realloc(buffer, buffer_size); + buffer = static_cast<char *>(realloc(buffer, buffer_size)); } strcpy(buffer+index, first); index += strlen(first) + 1; @@ -4783,7 +5036,7 @@ init_var_both(cblc_field_t *var, } if( index > 0 ) { - buffer = (char *)realloc(buffer, index); + buffer = static_cast<char *>(realloc(buffer, index)); local_initial = buffer; } } @@ -4823,7 +5076,7 @@ init_var_both(cblc_field_t *var, // memory to the default. But if a parent has been initialized, we must not // touch our memory: bool a_parent_initialized = false; - if( var->data && !explicitly ) + if( !explicitly ) { while(parent) { @@ -5039,7 +5292,7 @@ init_var_both(cblc_field_t *var, __gg__abort("Unknown variable type"); } - char *location = (char *)save_the_location; + char *location = reinterpret_cast<char *>(save_the_location); there_is_more = false; size_t i=0; @@ -5065,7 +5318,7 @@ init_var_both(cblc_field_t *var, } } - outer_location = (unsigned char *)location; + outer_location = reinterpret_cast<unsigned char *>(location); } while(there_is_more); var->data = save_the_location; @@ -5112,7 +5365,7 @@ alpha_to_alpha_move_from_location(cblc_field_t *field, // and dest are alphanumeric dest_length = dest_length ? dest_length : field->capacity; - char *to = (char *)field->data + dest_offset; + char *to = reinterpret_cast<char *>(field->data + dest_offset); const char *from = source_location; size_t count = std::min(dest_length, source_length); @@ -5208,7 +5461,7 @@ static void alpha_to_alpha_move(cblc_field_t *dest, size_t dest_offset, size_t dest_size, - cblc_field_t *source, + const cblc_field_t *source, size_t source_offset, size_t source_size, bool source_move_all) @@ -5216,7 +5469,7 @@ alpha_to_alpha_move(cblc_field_t *dest, alpha_to_alpha_move_from_location( dest, dest_offset, dest_size, - (char *)(source->data + source_offset), + reinterpret_cast<char *>(source->data + source_offset), source_size, source_move_all); } @@ -5250,13 +5503,9 @@ __gg__move( cblc_field_t *fdest, { int size_error = 0; // This is the return value - bool moved = true; - __int128 value; int rdigits; - size_t min_length; - cbl_figconst_t source_figconst = (cbl_figconst_t)(fsource->attr & FIGCONST_MASK); cbl_field_type_t dest_type = (cbl_field_type_t)fdest->type; @@ -5300,7 +5549,7 @@ __gg__move( cblc_field_t *fdest, * standard COBOL and its use should be avoided */ - int special_char; + int special_char = 0; // quiets cppcheck if( source_figconst == low_value_e ) { special_char = ascii_to_internal(__gg__low_value_character); @@ -5323,6 +5572,8 @@ __gg__move( cblc_field_t *fdest, } else { + size_t min_length; + bool moved = true; switch( dest_type ) { case FldGroup: @@ -5403,9 +5654,6 @@ __gg__move( cblc_field_t *fdest, // alphanumeric. We ignore any sign bit, and just // move the characters: - int rdigits; - __int128 value; - size_t source_digits = fsource->digits + ( fsource->rdigits < 0 @@ -5571,7 +5819,7 @@ __gg__move( cblc_field_t *fdest, fsource, source_offset, source_size); - sprintf(ach, "%lu", (size_t)value); + sprintf(ach, "%lu", (unsigned long)value); char *pach = ach; @@ -5695,37 +5943,37 @@ __gg__move( cblc_field_t *fdest, { rdigits = get_scaled_rdigits(fdest); bool negative = false; - __int128 value=0; + __int128 value128 = 0; switch(fsource->capacity) { case 4: { - _Float32 val = *(_Float32 *)(fsource->data+source_offset); + _Float32 val = *PTRCAST(_Float32, fsource->data+source_offset); if(val < 0) { negative = true; val = -val; } - val *= (_Float32)__gg__power_of_ten(rdigits); - value = (__int128)val; + val *= static_cast<_Float32>(__gg__power_of_ten(rdigits)); + value128 = (__int128)val; break; } case 8: { - _Float64 val = *(_Float64 *)(fsource->data+source_offset); + _Float64 val = *PTRCAST(_Float64, fsource->data+source_offset); if(val < 0) { negative = true; val = -val; } val *= (_Float32)__gg__power_of_ten(rdigits); - value = (__int128)val; + value128 = (__int128)val; break; } case 16: { //_Float128 val = *(_Float128 *)(fsource->data+source_offset); - _Float128 val; + GCOB_FP128 val; memcpy(&val, fsource->data+source_offset, 16); if(val < 0) { @@ -5733,19 +5981,19 @@ __gg__move( cblc_field_t *fdest, val = -val; } val *= (_Float32)__gg__power_of_ten(rdigits); - value = (__int128)val; + value128 = (__int128)val; break; } } if( negative ) { - value = -value; + value128 = -value128; } __gg__int128_to_qualified_field( fdest, dest_offset, dest_size, - value, + value128, rdigits, rounded, &size_error ); @@ -5813,30 +6061,30 @@ __gg__move( cblc_field_t *fdest, // We are converted a floating-point value fixed-point rdigits = get_scaled_rdigits(fdest); - _Float128 value=0; + GCOB_FP128 fp128=0; switch(fsource->capacity) { case 4: { - value = *(_Float32 *)(fsource->data+source_offset); + fp128 = *reinterpret_cast<_Float32 *>(fsource->data+source_offset); break; } case 8: { - value = *(_Float64 *)(fsource->data+source_offset); + fp128 = *reinterpret_cast<_Float64 *>(fsource->data+source_offset); break; } case 16: { // value = *(_Float128 *)(fsource->data+source_offset); - memcpy(&value, fsource->data+source_offset, 16); + memcpy(&fp128, fsource->data+source_offset, 16); break; } } __gg__float128_to_qualified_field( fdest, dest_offset, - value, + fp128, rounded, &size_error); break; @@ -5867,9 +6115,6 @@ __gg__move( cblc_field_t *fdest, case FldNumericDisplay: { - int rdigits; - __int128 value; - int source_digits = fsource->digits + (fsource->rdigits<0 ? -fsource->rdigits : 0) ; // Pick up the absolute value of the source @@ -5890,7 +6135,7 @@ __gg__move( cblc_field_t *fdest, } // And move them into place: - __gg__string_to_alpha_edited( (char *)(fdest->data+dest_offset), + __gg__string_to_alpha_edited( reinterpret_cast<char *>(fdest->data+dest_offset), ach, source_digits, fdest->picture); @@ -5900,7 +6145,7 @@ __gg__move( cblc_field_t *fdest, default: { static size_t display_string_size = MINIMUM_ALLOCATION_SIZE; - static char *display_string = (char *)malloc(display_string_size); + static char *display_string = static_cast<char *>(malloc(display_string_size)); size_t display_string_length = dest_size; __gg__realloc_if_necessary( &display_string, @@ -5933,12 +6178,12 @@ __gg__move( cblc_field_t *fdest, &display_string, &display_string_size, fsource, - (unsigned char *)(fsource->data+source_offset), + reinterpret_cast<unsigned char *>(fsource->data+source_offset), source_size, source_flags && REFER_T_ADDRESS_OF); display_string_length = strlen(display_string); } - __gg__string_to_alpha_edited( (char *)(fdest->data+dest_offset), + __gg__string_to_alpha_edited( reinterpret_cast<char *>(fdest->data+dest_offset), display_string, display_string_length, fdest->picture); @@ -5963,22 +6208,21 @@ __gg__move( cblc_field_t *fdest, { case 4: { - *(float *)(fdest->data+dest_offset) = strtof32(ach, NULL); + *PTRCAST(float, fdest->data+dest_offset) = strtod(ach, NULL); break; } case 8: { - *(double *)(fdest->data+dest_offset) = strtof64(ach, NULL); + *PTRCAST(double, fdest->data+dest_offset) = strtod(ach, NULL); break; } case 16: { - //*(_Float128 *)(fdest->data+dest_offset) = strtof128(ach, NULL); - _Float128 t = strtof128(ach, NULL); + //*(_Float128 *)(fdest->data+dest_offset) = strtofp128(ach, NULL); + GCOB_FP128 t = strtofp128(ach, NULL); memcpy(fdest->data+dest_offset, &t, 16); break; } - break; } break; } @@ -6107,7 +6351,7 @@ __gg__move_literala(cblc_field_t *field, case FldAlphaEdited: { static size_t display_string_size = MINIMUM_ALLOCATION_SIZE; - static char *display_string = (char *)malloc(display_string_size); + static char *display_string = static_cast<char *>(malloc(display_string_size)); __gg__realloc_if_necessary( &display_string, &display_string_size, @@ -6116,7 +6360,7 @@ __gg__move_literala(cblc_field_t *field, memset(display_string, internal_space, display_string_size); size_t len = std::min(display_string_size, strlen); memcpy(display_string, str, len); - __gg__string_to_alpha_edited( (char *)(field->data+field_offset), + __gg__string_to_alpha_edited( reinterpret_cast<char *>(field->data+field_offset), display_string, field_size, field->picture); @@ -6133,21 +6377,20 @@ __gg__move_literala(cblc_field_t *field, { case 4: { - *(float *)(field->data+field_offset) = strtof32(ach, NULL); + *PTRCAST(float, field->data+field_offset) = strtod(ach, NULL); break; } case 8: { - *(double *)(field->data+field_offset) = strtof64(ach, NULL); + *PTRCAST(double, field->data+field_offset) = strtod(ach, NULL); break; } case 16: { - _Float128 t = strtof128(ach, NULL); + GCOB_FP128 t = strtofp128(ach, NULL); memcpy(field->data+field_offset, &t, 16); break; } - break; } break; } @@ -6179,6 +6422,7 @@ __gg__file_sort_ff_input( cblc_file_t *workfile, // We are going to read records from input and write them to workfile. These // files are already open. + sv_suppress_eof_ec = true; for(;;) { // Read the data from the input file into its record_area @@ -6211,6 +6455,7 @@ __gg__file_sort_ff_input( cblc_file_t *workfile, before_advancing, 0); // non-random } + sv_suppress_eof_ec = false; } extern "C" @@ -6225,6 +6470,7 @@ __gg__file_sort_ff_output( cblc_file_t *output, // Make sure workfile is positioned at the beginning __gg__file_reopen(workfile, 'r'); + sv_suppress_eof_ec = true; for(;;) { __gg__file_read( workfile, @@ -6246,6 +6492,7 @@ __gg__file_sort_ff_output( cblc_file_t *output, advancing, 0); // 1 would be is_random } + sv_suppress_eof_ec = false; } extern "C" @@ -6264,12 +6511,13 @@ __gg__sort_workfile(cblc_file_t *workfile, // Read the file into memory size_t buffer_size = 128; - unsigned char *contents = (unsigned char *)malloc(buffer_size); + unsigned char *contents = static_cast<unsigned char *>(malloc(buffer_size)); size_t offset = 0; std::vector<size_t>offsets; size_t bytes_read; size_t bytes_to_write; + sv_suppress_eof_ec = true; for(;;) { __gg__file_read(workfile, @@ -6293,7 +6541,7 @@ __gg__sort_workfile(cblc_file_t *workfile, while( offset + sizeof(size_t) + bytes_read > buffer_size ) { buffer_size *= 2; - contents = (unsigned char *)realloc(contents, buffer_size); + contents = static_cast<unsigned char *>(realloc(contents, buffer_size)); } offsets.push_back(offset); @@ -6305,6 +6553,7 @@ __gg__sort_workfile(cblc_file_t *workfile, memcpy(contents+offset, workfile->default_record->data, bytes_read); offset += bytes_read; } + sv_suppress_eof_ec = false; sort_contents(contents, offsets, @@ -6391,7 +6640,8 @@ __gg__merge_files( cblc_file_t *workfile, return; } - unsigned char *prior_winner = (unsigned char *)malloc(the_biggest); + unsigned char *prior_winner = static_cast<unsigned char *>(malloc(the_biggest)); + massert(prior_winner); *prior_winner = '\0'; for(;;) @@ -6571,7 +6821,7 @@ normalize_id( const cblc_field_t *refer, if( refer ) { - unsigned char *data = refer->data + refer_o; + const unsigned char *data = refer->data + refer_o; cbl_figconst_t figconst = (cbl_figconst_t)(refer->attr & FIGCONST_MASK); @@ -6812,7 +7062,7 @@ the_alpha_and_omega_backward( const normalized_operand &id_before, static void -inspect_backward_format_1(size_t integers[]) +inspect_backward_format_1(const size_t integers[]) { size_t int_index = 0; size_t cblc_index = 0; @@ -6825,9 +7075,9 @@ inspect_backward_format_1(size_t integers[]) std::vector<id_2_result> id_2_results(n_identifier_2); // Pick up identifier_1, which is the string being inspected - cblc_field_t *id1 = __gg__treeplet_1f[cblc_index]; - size_t id1_o = __gg__treeplet_1o[cblc_index]; - size_t id1_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id1 = __gg__treeplet_1f[cblc_index]; + size_t id1_o = __gg__treeplet_1o[cblc_index]; + size_t id1_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; // normalize it, according to the language specification. normalized_operand normalized_id_1 = normalize_id(id1, id1_o, id1_s); @@ -6860,19 +7110,19 @@ inspect_backward_format_1(size_t integers[]) // We are counting characters. There is no identifier-3, // but we we hard-code the length to one to represent a // single character. - comparand next_comparand; + comparand next_comparand = {}; next_comparand.id_2_index = i; next_comparand.operation = operation; next_comparand.identifier_3.length = 1; - cblc_field_t *id4_before = __gg__treeplet_1f [cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f [cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; normalized_operand normalized_id_4_before @@ -6904,23 +7154,23 @@ inspect_backward_format_1(size_t integers[]) for(size_t k=0; k<pair_count; k++) { - comparand next_comparand; + comparand next_comparand = {}; next_comparand.id_2_index = i; next_comparand.operation = operation; - cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; - size_t id3_o = __gg__treeplet_1o[cblc_index]; - size_t id3_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; + size_t id3_o = __gg__treeplet_1o[cblc_index]; + size_t id3_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_3 @@ -7161,9 +7411,9 @@ __gg__inspect_format_1(int backward, size_t integers[]) std::vector<id_2_result> id_2_results(n_identifier_2); // Pick up identifier_1, which is the string being inspected - cblc_field_t *id1 = __gg__treeplet_1f[cblc_index]; - size_t id1_o = __gg__treeplet_1o[cblc_index]; - size_t id1_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id1 = __gg__treeplet_1f[cblc_index]; + size_t id1_o = __gg__treeplet_1o[cblc_index]; + size_t id1_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; // normalize it, according to the language specification. normalized_operand normalized_id_1 @@ -7197,19 +7447,19 @@ __gg__inspect_format_1(int backward, size_t integers[]) // We are counting characters. There is no identifier-3, // but we we hard-code the length to one to represent a // single character. - comparand next_comparand; + comparand next_comparand = {}; next_comparand.id_2_index = i; next_comparand.operation = operation; next_comparand.identifier_3.length = 1; - cblc_field_t *id4_before = __gg__treeplet_1f [cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f [cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; normalized_operand normalized_id_4_before @@ -7241,23 +7491,23 @@ __gg__inspect_format_1(int backward, size_t integers[]) for(size_t k=0; k<pair_count; k++) { - comparand next_comparand; + comparand next_comparand = {}; next_comparand.id_2_index = i; next_comparand.operation = operation; - cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; - size_t id3_o = __gg__treeplet_1o[cblc_index]; - size_t id3_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; + size_t id3_o = __gg__treeplet_1o[cblc_index]; + size_t id3_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_3 @@ -7486,7 +7736,7 @@ __gg__inspect_format_1(int backward, size_t integers[]) static void -inspect_backward_format_2(size_t integers[]) +inspect_backward_format_2(const size_t integers[]) { size_t int_index = 0; size_t cblc_index = 0; @@ -7516,22 +7766,22 @@ inspect_backward_format_2(size_t integers[]) { case bound_characters_e: { - comparand next_comparand; + comparand next_comparand = {}; next_comparand.operation = operation; - cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; - size_t id5_o = __gg__treeplet_1o[cblc_index]; - size_t id5_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; + size_t id5_o = __gg__treeplet_1o[cblc_index]; + size_t id5_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_5 @@ -7567,27 +7817,27 @@ inspect_backward_format_2(size_t integers[]) for(size_t k=0; k<pair_count; k++) { - comparand next_comparand; + comparand next_comparand = {}; next_comparand.operation = operation; - cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; - size_t id3_o = __gg__treeplet_1o[cblc_index]; - size_t id3_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; + size_t id3_o = __gg__treeplet_1o[cblc_index]; + size_t id3_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; - size_t id5_o = __gg__treeplet_1o[cblc_index]; - size_t id5_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; + size_t id5_o = __gg__treeplet_1o[cblc_index]; + size_t id5_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_3 = normalize_id(id3, id3_o, id3_s); @@ -7864,22 +8114,22 @@ __gg__inspect_format_2(int backward, size_t integers[]) { case bound_characters_e: { - comparand next_comparand; + comparand next_comparand = {} ; next_comparand.operation = operation; - cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; - size_t id5_o = __gg__treeplet_1o[cblc_index]; - size_t id5_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; + size_t id5_o = __gg__treeplet_1o[cblc_index]; + size_t id5_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f [cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_5 @@ -7915,27 +8165,27 @@ __gg__inspect_format_2(int backward, size_t integers[]) for(size_t k=0; k<pair_count; k++) { - comparand next_comparand; + comparand next_comparand = {}; next_comparand.operation = operation; - cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; - size_t id3_o = __gg__treeplet_1o[cblc_index]; - size_t id3_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id3 = __gg__treeplet_1f[cblc_index]; + size_t id3_o = __gg__treeplet_1o[cblc_index]; + size_t id3_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; - size_t id5_o = __gg__treeplet_1o[cblc_index]; - size_t id5_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id5 = __gg__treeplet_1f[cblc_index]; + size_t id5_o = __gg__treeplet_1o[cblc_index]; + size_t id5_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; - size_t id4_before_o = __gg__treeplet_1o[cblc_index]; - size_t id4_before_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_before = __gg__treeplet_1f[cblc_index]; + size_t id4_before_o = __gg__treeplet_1o[cblc_index]; + size_t id4_before_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; - cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; - size_t id4_after_o = __gg__treeplet_1o[cblc_index]; - size_t id4_after_s = __gg__treeplet_1s[cblc_index]; + const cblc_field_t *id4_after = __gg__treeplet_1f[cblc_index]; + size_t id4_after_o = __gg__treeplet_1o[cblc_index]; + size_t id4_after_s = __gg__treeplet_1s[cblc_index]; cblc_index += 1; next_comparand.identifier_3 = normalize_id(id3, id3_o, id3_s); @@ -8210,12 +8460,12 @@ __gg__inspect_format_4( int backward, static size_t psz_before_size = MINIMUM_ALLOCATION_SIZE; static size_t psz_figstring_size = MINIMUM_ALLOCATION_SIZE; - static char *psz_input = (char *)malloc(psz_input_size ); - static char *psz_original = (char *)malloc(psz_original_size ); - static char *psz_replacement = (char *)malloc(psz_replacement_size); - static char *psz_after = (char *)malloc(psz_after_size ); - static char *psz_before = (char *)malloc(psz_before_size ); - static char *psz_figstring = (char *)malloc(psz_figstring_size ); + static char *psz_input = static_cast<char *>(malloc(psz_input_size )); + static char *psz_original = static_cast<char *>(malloc(psz_original_size )); + static char *psz_replacement = static_cast<char *>(malloc(psz_replacement_size)); + static char *psz_after = static_cast<char *>(malloc(psz_after_size )); + static char *psz_before = static_cast<char *>(malloc(psz_before_size )); + static char *psz_figstring = static_cast<char *>(malloc(psz_figstring_size )); bool all = replacement_size == (size_t)(-1LL); if( all ) @@ -8309,7 +8559,7 @@ __gg__inspect_format_4( int backward, } char *pstart = NULL; - char *pend = NULL; + const char *pend = NULL; if( backward ) { if( strlen(psz_before) ) @@ -8402,7 +8652,7 @@ move_string(cblc_field_t *field, case FldAlphanumeric: case FldAlphaEdited: { - char *to = (char *)(field->data + offset); + char *to = reinterpret_cast<char *>(field->data + offset); size_t dest_length = length ? length : field->capacity; size_t source_length = strlen_from; size_t count = std::min(dest_length, source_length); @@ -8511,7 +8761,7 @@ brute_force_trim(char *str) extern "C" int -__gg__string(size_t integers[]) +__gg__string(const size_t integers[]) { // The first integer is the count of identifier-2 values. Call it N // The following N integers are the counts of each of the identifier-1 values, @@ -8525,12 +8775,11 @@ __gg__string(size_t integers[]) // And so on cblc_field_t **ref = __gg__treeplet_1f; - size_t *ref_o = __gg__treeplet_1o; - size_t *ref_s = __gg__treeplet_1s; + const size_t *ref_o = __gg__treeplet_1o; + const size_t *ref_s = __gg__treeplet_1s; static const int INDEX_OF_POINTER = 1; - size_t index_int = 0; size_t index_cblc = 0 ; char figlow[2] = {ascii_to_internal(__gg__low_value_character), 0x00}; @@ -8548,15 +8797,13 @@ __gg__string(size_t integers[]) fighigh[0] = ascii_to_internal(__gg__high_value_character); } - // Pick up the number of identifier-2 values - size_t N = integers[index_int++]; // Pick up the target - cblc_field_t *tgt = ref[index_cblc]; - size_t tgt_o = ref_o[index_cblc]; - size_t tgt_s = ref_s[index_cblc]; + const cblc_field_t *tgt = ref[index_cblc]; + size_t tgt_o = ref_o[index_cblc]; + size_t tgt_s = ref_s[index_cblc]; index_cblc += 1; - char *dest = (char *)(tgt->data + tgt_o); + char *dest = reinterpret_cast<char *>(tgt->data + tgt_o); ssize_t dest_length = tgt_s; // Skip over the index of POINTER: @@ -8583,18 +8830,23 @@ __gg__string(size_t integers[]) { // We are go for looping through identifier-2 values: + size_t index_int = 0; + + // Pick up the number of identifier-2 values + size_t N = integers[index_int++]; + for( size_t i=0; i<N; i++ ) { size_t M = integers[index_int++]; // Pick up the identifier_2 DELIMITED BY value - cblc_field_t *id2 = ref[index_cblc]; - size_t id2_o = ref_o[index_cblc]; - size_t id2_s = ref_s[index_cblc]; + const cblc_field_t *id2 = ref[index_cblc]; + size_t id2_o = ref_o[index_cblc]; + size_t id2_s = ref_s[index_cblc]; index_cblc += 1; char *piece; - char *piece_end; + const char *piece_end; cbl_figconst_t figconst = (cbl_figconst_t) ( id2 ? (id2->attr & FIGCONST_MASK) : 0 ); @@ -8621,24 +8873,24 @@ __gg__string(size_t integers[]) piece_end = piece + 1; break; default: - piece = id2 ? (char *)(id2->data + id2_o) : NULL; + piece = id2 ? reinterpret_cast<char *>(id2->data + id2_o) : NULL; piece_end = id2 ? piece + id2_s : NULL; break; } - for(size_t i=0; i<M; i++) + for(size_t j=0; j<M; j++) { // Pick up the next identifier-1 source string: - cblc_field_t *id1 = ref[index_cblc]; + const cblc_field_t *id1 = ref[index_cblc]; size_t id1_o = ref_o[index_cblc]; size_t id1_s = ref_s[index_cblc]; index_cblc += 1; - const char *whole = id1 ? (const char *)(id1->data + id1_o): NULL ; + const char *whole = id1 ? reinterpret_cast<char *>(id1->data + id1_o): NULL ; const char *whole_end = id1 ? whole + id1_s : NULL; // As usual, we need to cope with figurative constants: - cbl_figconst_t figconst = (cbl_figconst_t) ( id1 ? (id1->attr & FIGCONST_MASK) : 0 ); + figconst = (cbl_figconst_t) ( id1 ? (id1->attr & FIGCONST_MASK) : 0 ); switch( figconst ) { case low_value_e: @@ -8671,11 +8923,7 @@ __gg__string(size_t integers[]) whole, whole_end); if(found) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" - char *wfound = (char *)found; -#pragma GCC diagnostic pop - whole_end = wfound; + whole_end = found; } } while(whole < whole_end) @@ -8725,7 +8973,7 @@ display_both(cblc_field_t *field, int advance ) { static size_t display_string_size = MINIMUM_ALLOCATION_SIZE; - static char *display_string = (char *)malloc(display_string_size); + static char *display_string = static_cast<char *>(malloc(display_string_size)); format_for_display_internal(&display_string, &display_string_size, @@ -8736,7 +8984,7 @@ display_both(cblc_field_t *field, // Let's honor the locale of the system, as best we can: static size_t converted_size = MINIMUM_ALLOCATION_SIZE; - static char *converted = (char *)malloc(converted_size); + static char *converted = static_cast<char *>(malloc(converted_size)); internal_to_console(&converted, &converted_size, display_string, strlen(display_string)); @@ -8746,7 +8994,7 @@ display_both(cblc_field_t *field, if(ss == -1) { fprintf(stderr, "__gg__display() %s %p\n", field->name, qual_data); - fprintf(stderr, "__gg__display() %zd\n", converted_size); + fprintf(stderr, "__gg__display() %ld\n", static_cast<long>(converted_size)); fprintf(stderr, "__gg__display() "); for(size_t i=0; i<converted_size; i++) { @@ -8758,9 +9006,9 @@ display_both(cblc_field_t *field, if( advance ) { - ss = write( file_descriptor, - "\n", - 1); + write( file_descriptor, + "\n", + 1); } } @@ -8774,7 +9022,7 @@ __gg__display( cblc_field_t *field, { display_both( field, field->data + offset, - size ? size : field->capacity, + size, 0, file_descriptor, advance); @@ -8799,20 +9047,20 @@ __gg__display_clean(cblc_field_t *field, extern "C" void -__gg__display_string( int file_descriptor, - char *str, - size_t length, - int advance ) +__gg__display_string( int file_descriptor, + const char *str, + size_t length, + int advance ) { // Let's honor the locale of the system, as best we can: static size_t converted_size = MINIMUM_ALLOCATION_SIZE; - static char *converted = (char *)malloc(converted_size); + static char *converted = static_cast<char *>(malloc(converted_size)); size_t max_possible = 2 * length; if( max_possible > converted_size ) { converted_size = max_possible; - converted = (char *)realloc(converted, converted_size); + converted = static_cast<char *>(realloc(converted, converted_size)); } __gg__ascii_to_console(&converted, &converted_size, str, length); @@ -8828,8 +9076,6 @@ __gg__display_string( int file_descriptor, } } -#pragma GCC diagnostic push - static char * mangler_core(const char *s, const char *eos) @@ -8950,7 +9196,8 @@ __gg__accept( enum special_name_t special_e, } } - char *buffer = (char *)malloc(max_chars+1); + char *buffer = static_cast<char *>(malloc(max_chars+1)); + massert(buffer); memset(buffer, ascii_space, max_chars); buffer[max_chars] = NULLCH; size_t i = 0; @@ -9116,7 +9363,7 @@ __gg__binary_value_from_field( int *rdigits, extern "C" __int128 __gg__binary_value_from_qualified_field(int *rdigits, - cblc_field_t *var, + const cblc_field_t *var, size_t offset, size_t size) { @@ -9127,10 +9374,10 @@ __gg__binary_value_from_qualified_field(int *rdigits, } extern "C" -_Float128 +GCOB_FP128 __gg__float128_from_field( cblc_field_t *field ) { - _Float128 retval=0; + GCOB_FP128 retval=0; if( field->type == FldFloat || field->type == FldLiteralN ) { retval = get_float128(field, field->data); @@ -9138,20 +9385,20 @@ __gg__float128_from_field( cblc_field_t *field ) else { int rdigits; - retval = (_Float128)__gg__binary_value_from_field(&rdigits, field); + retval = (GCOB_FP128)__gg__binary_value_from_field(&rdigits, field); if( rdigits ) { - retval /= (_Float128)__gg__power_of_ten(rdigits); + retval /= (GCOB_FP128)__gg__power_of_ten(rdigits); } } return retval; } extern "C" -_Float128 -__gg__float128_from_qualified_field( cblc_field_t *field, size_t offset, size_t size) +GCOB_FP128 +__gg__float128_from_qualified_field(const cblc_field_t *field, size_t offset, size_t size) { - _Float128 retval=0; + GCOB_FP128 retval=0; if( field->type == FldFloat || field->type == FldLiteralN ) { retval = get_float128(field, field->data+offset); @@ -9159,10 +9406,10 @@ __gg__float128_from_qualified_field( cblc_field_t *field, size_t offset, size_t else { int rdigits; - retval = (_Float128)__gg__binary_value_from_qualified_field(&rdigits, field, offset, size); + retval = (GCOB_FP128)__gg__binary_value_from_qualified_field(&rdigits, field, offset, size); if( rdigits ) { - retval /= (_Float128)__gg__power_of_ten(rdigits); + retval /= (GCOB_FP128)__gg__power_of_ten(rdigits); } } return retval; @@ -9226,11 +9473,11 @@ __gg__int128_to_qualified_field(cblc_field_t *tgt, } static __int128 -float128_to_int128( int *rdigits, - cblc_field_t *field, - _Float128 value, - cbl_round_t rounded, - int *compute_error) +float128_to_int128( int *rdigits, + const cblc_field_t *field, + GCOB_FP128 value, + cbl_round_t rounded, + int *compute_error) { __int128 retval = 0; if( value == INFINITY ) @@ -9253,7 +9500,7 @@ float128_to_int128( int *rdigits, // get away with. // Calculate the number of digits to the left of the decimal point: - int digits = (int)(floorf128(logf128(fabsf128(value)))+1); + int digits = (int)(FP128_FUNC(floor)(FP128_FUNC(log)(FP128_FUNC(fabs)(value)))+1); // Make sure it is not a negative number digits = std::max(0, digits); @@ -9270,12 +9517,12 @@ float128_to_int128( int *rdigits, // We now multiply our value by 10**rdigits, in order to make the // floating-point value have the same magnitude as our target __int128 - value *= powf128(10.0Q, (_Float128)(*rdigits)); + value *= FP128_FUNC(pow)(GCOB_FP128_LITERAL (10.0), (GCOB_FP128)(*rdigits)); // We are ready to cast value to an __int128. But this value could be // too large to fit, which is an error condition we want to flag: - if( fabsf128(value) >= 1.0E38Q ) + if( FP128_FUNC(fabs)(value) >= GCOB_FP128_LITERAL (1.0E38) ) { *compute_error = compute_error_overflow; } @@ -9292,7 +9539,7 @@ static void float128_to_location( cblc_field_t *tgt, unsigned char *data, size_t size, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -9303,8 +9550,8 @@ float128_to_location( cblc_field_t *tgt, switch(tgt->capacity) { case 4: - if( fabsf128(value) == (_Float128)INFINITY - || fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY + || FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { if( compute_error ) { @@ -9312,22 +9559,22 @@ float128_to_location( cblc_field_t *tgt, } if( value < 0 ) { - *(float *)(data) = -INFINITY; + *PTRCAST(float, data) = -INFINITY; } else { - *(float *)(data) = INFINITY; + *PTRCAST(float, data) = INFINITY; } } else { - *(float *)(data) = (float)value; + *PTRCAST(float, data) = static_cast<float>(value); } break; case 8: - if( fabsf128(value) == (_Float128)INFINITY - || fabsf128(value) > 1.7976931348623157E308Q ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY + || FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (1.7976931348623157E308) ) { if( compute_error ) { @@ -9335,21 +9582,21 @@ float128_to_location( cblc_field_t *tgt, } if( value < 0 ) { - *(double *)(data) = -INFINITY; + *PTRCAST(double, data) = -INFINITY; } else { - *(double *)(data) = INFINITY; + *PTRCAST(double, data) = INFINITY; } } else { - *(double *)(data) = (double)value; + *PTRCAST(double, data) = static_cast<double>(value); } break; case 16: - if( fabsf128(value) == (_Float128)INFINITY ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY ) { if( compute_error ) { @@ -9378,7 +9625,7 @@ float128_to_location( cblc_field_t *tgt, digits = tgt->digits; } - _Float128 maximum; + GCOB_FP128 maximum; if( digits ) { @@ -9387,7 +9634,7 @@ float128_to_location( cblc_field_t *tgt, // When digits is zero, this is a binary value without a PICTURE string. // we don't truncate in that case - if( digits && fabsf128(value) >= maximum ) + if( digits && FP128_FUNC(fabs)(value) >= maximum ) { *compute_error |= compute_error_truncate; } @@ -9415,7 +9662,7 @@ float128_to_location( cblc_field_t *tgt, extern "C" void __gg__float128_to_field(cblc_field_t *tgt, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -9431,7 +9678,7 @@ extern "C" void __gg__float128_to_qualified_field(cblc_field_t *tgt, size_t tgt_offset, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -9545,7 +9792,7 @@ __gg__set_initial_switch_value( ) __int128 bit = 1; char ach[129]; memset(ach, 0, sizeof(ach)); - char *p = getenv("UPSI"); + const char *p = getenv("UPSI"); if( p ) { snprintf(ach, sizeof(ach), "%s", p); @@ -9578,7 +9825,7 @@ is_numeric_display_numeric(cblc_field_t *field, size_t offset, size_t size) bool leading = !!(field->attr & leading_e); bool separate = !!(field->attr & separate_e); - char *digits = (char *)(field->data + offset); + char *digits = reinterpret_cast<char *>(field->data + offset); char *digits_e = digits + size; if( leading && separate && signable ) @@ -9650,13 +9897,13 @@ is_numeric_display_numeric(cblc_field_t *field, size_t offset, size_t size) } static int -is_packed_numeric(cblc_field_t *field, size_t offset, size_t size) +is_packed_numeric(const cblc_field_t *field, size_t offset, size_t size) { int retval = 1; bool is_comp6 = !!(field->attr&packed_no_sign_e); int digits = field->digits; bool signable = !!(field->attr & signable_e); - unsigned char *bytes = field->data + offset; + const unsigned char *bytes = field->data + offset; int nybble = 0; int nybble_e = nybble + digits; @@ -9725,10 +9972,12 @@ is_packed_numeric(cblc_field_t *field, size_t offset, size_t size) } static int -is_alpha_a_number(cblc_field_t *field, size_t offset, size_t size) +is_alpha_a_number(const cblc_field_t *field, + size_t offset, + size_t size) { int retval = 1; - unsigned char *bytes = (field->data + offset); + const unsigned char *bytes = (field->data + offset); for( size_t i=0; i<size; i++ ) { unsigned char ch = bytes[i]; @@ -9752,7 +10001,7 @@ __gg__classify( classify_t type, // The default answer is TRUE int retval = 1; - const unsigned char *alpha = (unsigned char *)(field->data+offset); + const unsigned char *alpha = reinterpret_cast<unsigned char *>(field->data+offset); size_t str_length = size; @@ -9902,7 +10151,7 @@ __gg__accept_envar( cblc_field_t *tgt, if( env_length < name_length+1 ) { env_length = name_length+1; - env = (char *)realloc(env, env_length); + env = static_cast<char *>(realloc(env, env_length)); } memcpy(env, name->data + name_offset, name_length); env[name_length] = '\0'; @@ -9914,7 +10163,7 @@ __gg__accept_envar( cblc_field_t *tgt, __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env)); // Pick up the environment variable, and convert it to the internal codeset - char *p = getenv(trimmed_env); + const char *p = getenv(trimmed_env); if(p) { char *pp = strdup(p); @@ -9953,14 +10202,17 @@ __gg__set_envar(cblc_field_t *name, if( env_length < name_length+1 ) { env_length = name_length+1; - env = (char *)realloc(env, env_length); + env = static_cast<char *>(realloc(env, env_length)); } if( val_length < value_length+1 ) { val_length = value_length+1; - val = (char *)realloc(val, val_length); + val = static_cast<char *>(realloc(val, val_length)); } + massert(val); + massert(env); + // The name and the value arrive in the internal codeset: memcpy(env, name->data+name_offset , name_length); env[name_length] = '\0'; @@ -10029,15 +10281,15 @@ command_line_plan_b() if( bytes_read ) { char *p = input; - char *p_end = p + bytes_read; + const char *p_end = p + bytes_read; char prior_char = '\0'; while( p < p_end ) { if( prior_char == '\0' ) { stashed_argc += 1; - stashed_argv = (char **)realloc(stashed_argv, - stashed_argc * sizeof(char *)); + stashed_argv = static_cast<char **>(realloc(stashed_argv, + stashed_argc * sizeof(char *))); stashed_argv[stashed_argc-1] = p; } prior_char = *p++; @@ -10108,7 +10360,8 @@ __gg__get_command_line( cblc_field_t *field, int retcode; command_line_plan_b(); size_t length = 1; - char *retval = (char *)malloc(length); + char *retval = static_cast<char *>(malloc(length)); + massert(retval); *retval = NULLCH; for( int i=1; i<stashed_argc; i++ ) @@ -10116,7 +10369,8 @@ __gg__get_command_line( cblc_field_t *field, while( strlen(retval) + strlen(stashed_argv[i]) + 2 > length ) { length *= 2; - retval = (char *)realloc(retval, length); + retval = static_cast<char *>(realloc(retval, length)); + massert(retval); } if( *retval ) { @@ -10144,12 +10398,12 @@ __gg__get_command_line( cblc_field_t *field, extern "C" void -__gg__set_pointer(cblc_field_t *target, - size_t target_o, - int target_flags, - cblc_field_t *source, - size_t source_o, - int source_flags) +__gg__set_pointer(cblc_field_t *target, + size_t target_o, + int target_flags, + const cblc_field_t *source, + size_t source_o, + int source_flags) { void *source_address; if( source_flags & REFER_T_ADDRESS_OF ) @@ -10162,7 +10416,7 @@ __gg__set_pointer(cblc_field_t *target, // This is SET <something> TO POINTER if( source ) { - source_address = *(void **)(source->data + source_o); + source_address = *reinterpret_cast<void **>(source->data + source_o); } else { @@ -10175,7 +10429,7 @@ __gg__set_pointer(cblc_field_t *target, { // This is SET ADDRESS OF target TO .... // We know it has to be an unqualified LINKAGE level 01 or level 77 - target->data = (unsigned char *)source_address; + target->data = reinterpret_cast<unsigned char *>(source_address); // The caller will propogate data + offset to their children. } else @@ -10186,12 +10440,12 @@ __gg__set_pointer(cblc_field_t *target, // This is [almost certainly] INITIALIZE <pointer> when -fdefaultbyte // was specified. memset( target->data+target_o, - *(unsigned char *)source_address, + *reinterpret_cast<unsigned char *>(source_address), target->capacity); } else { - *(void **)(target->data+target_o) = source_address; + *reinterpret_cast<void **>(target->data+target_o) = source_address; } } } @@ -10274,7 +10528,7 @@ extern "C" void __gg__ascii_to_internal_field(cblc_field_t *var) { - ascii_to_internal_str((char *)var->data, var->capacity); + ascii_to_internal_str(reinterpret_cast<char *>(var->data), var->capacity); } extern "C" @@ -10326,7 +10580,7 @@ void __gg__internal_to_console_in_place(char *loc, size_t length) { static size_t dest_size = MINIMUM_ALLOCATION_SIZE; - static char *dest = (char *)malloc(dest_size); + static char *dest = static_cast<char *>(malloc(dest_size)); internal_to_console(&dest, &dest_size, loc, length); memcpy(loc, dest, length); @@ -10334,8 +10588,8 @@ __gg__internal_to_console_in_place(char *loc, size_t length) extern "C" int -__gg__routine_to_call(char *name, - int program_id) +__gg__routine_to_call(const char *name, + int program_id) { // The list of names is sorted, so at the very least this should be replaced // with a binary search: @@ -10351,10 +10605,10 @@ __gg__routine_to_call(char *name, char **names = *(it->second); int retval = -1; - int i=0; if( names ) { + int i=0; while(*names) { if( strstr(*names, name) ) @@ -10376,14 +10630,14 @@ __gg__routine_to_call(char *name, extern "C" __int128 -__gg__fetch_call_by_value_value(cblc_field_t *field, +__gg__fetch_call_by_value_value(const cblc_field_t *field, size_t field_o, size_t field_s) { int rdigits; - unsigned char *data = field->data + field_o; - size_t length = field_s; + unsigned char *data = field->data + field_o; + const size_t length = field_s; __int128 retval = 0; switch(field->type) @@ -10392,7 +10646,7 @@ __gg__fetch_call_by_value_value(cblc_field_t *field, case FldAlphanumeric: case FldAlphaEdited: case FldLiteralA: - retval = *(char *)data; + retval = *reinterpret_cast<char *>(data); break; case FldFloat: @@ -10400,16 +10654,16 @@ __gg__fetch_call_by_value_value(cblc_field_t *field, switch(length) { case 4: - *(float *)(&retval) = *(float *)data; + *PTRCAST(float, &retval) = *PTRCAST(float, data); break; case 8: - *(double *)(&retval) = *(double *)data; + *PTRCAST(double, &retval) = *PTRCAST(double, data); break; case 16: // *(_Float128 *)(&retval) = double(*(_Float128 *)data); - _Float128 t; + GCOB_FP128 t; memcpy(&t, data, 16); memcpy(&retval, &t, 16); break; @@ -10461,16 +10715,16 @@ __gg__assign_value_from_stack(cblc_field_t *dest, __int128 parameter) switch(dest->capacity) { case 4: - *(float *)(dest->data) = *(float *)¶meter; + *PTRCAST(float, dest->data) = *PTRCAST(float, (¶meter)); break; case 8: - *(double *)(dest->data) = *(double *)¶meter; + *PTRCAST(double, dest->data) = *PTRCAST(double, (¶meter)); break; case 16: // *(_Float128 *)(dest->data) = *(_Float128 *)¶meter; - _Float128 t; + GCOB_FP128 t; memcpy(&t, ¶meter, 16); memcpy(dest->data, &t, 16); break; @@ -10499,28 +10753,31 @@ __gg__assign_value_from_stack(cblc_field_t *dest, __int128 parameter) extern "C" int -__gg__literaln_alpha_compare(char *left_side, - cblc_field_t *right, - size_t offset, - size_t length, - int flags) +__gg__literaln_alpha_compare(const char *left_side, + const cblc_field_t *right, + size_t offset, + size_t length, + int flags) { int retval; if( length == 0 ) { length = right->capacity; } - retval = compare_strings( (char *)left_side, + retval = compare_strings( left_side, strlen(left_side), false, - (char *)right->data + offset, + reinterpret_cast<char *>((right->data + offset)), length, !!(flags & REFER_T_MOVE_ALL) ); return retval; } static char * -string_in(char *str, char *str_e, char *frag, char *frag_e) +string_in( char *str, + const char *str_e, + const char *frag, + const char *frag_e) { // This simple routine could be improved. Instead of using memcmp, we could // use established, albeit complex, techniques of string searching: @@ -10550,11 +10807,11 @@ string_in(char *str, char *str_e, char *frag, char *frag_e) extern "C" int -__gg__unstring( cblc_field_t *id1, // The string being unstring - size_t id1_o, - size_t id1_s, +__gg__unstring( const cblc_field_t *id1, // The string being unstring + size_t id1_o, + size_t id1_s, size_t ndelimiteds, // The number of DELIMITED entries - char *all_flags, // The number of ALL flags, one per ndelimiteds + const char *all_flags, // The number of ALL flags, one per ndelimiteds size_t nreceivers, // The number of DELIMITER receivers cblc_field_t *id7, // The index of characters, both for starting updated at end size_t id7_o, @@ -10573,18 +10830,22 @@ __gg__unstring( cblc_field_t *id1, // The string being unstring // resolved. Each might have an identifier-5 delimiter, and each might have // an identifier-6 count. - cblc_field_t **id2 = __gg__treeplet_1f; // The delimiting strings; one per ndelimiteds - size_t *id2_o = __gg__treeplet_1o; - size_t *id2_s = __gg__treeplet_1s; - cblc_field_t **id4 = __gg__treeplet_2f; // The delimited string; one per nreceiver - size_t *id4_o = __gg__treeplet_2o; - size_t *id4_s = __gg__treeplet_2s; - cblc_field_t **id5 = __gg__treeplet_3f; // The delimiting string; one per receiver - size_t *id5_o = __gg__treeplet_3o; - size_t *id5_s = __gg__treeplet_3s; - cblc_field_t **id6 = __gg__treeplet_4f; // The count of characters examined; one per receiver - size_t *id6_o = __gg__treeplet_4o; - size_t *id6_s = __gg__treeplet_4s; + // The delimiting strings; one per ndelimiteds + cblc_field_t **id2 = __gg__treeplet_1f; + const size_t *id2_o = __gg__treeplet_1o; + const size_t *id2_s = __gg__treeplet_1s; + // The delimited string; one per nreceiver + cblc_field_t **id4 = __gg__treeplet_2f; + const size_t *id4_o = __gg__treeplet_2o; + const size_t *id4_s = __gg__treeplet_2s; + // The delimiting string; one per receiver + cblc_field_t **id5 = __gg__treeplet_3f; + const size_t *id5_o = __gg__treeplet_3o; + const size_t *id5_s = __gg__treeplet_3s; + // The count of characters examined; one per receiver + cblc_field_t **id6 = __gg__treeplet_4f; + const size_t *id6_o = __gg__treeplet_4o; + const size_t *id6_s = __gg__treeplet_4s; // Initialize the state variables int overflow = 0; @@ -10627,8 +10888,8 @@ __gg__unstring( cblc_field_t *id1, // The string being unstring goto done; } - left = (char *)(id1->data+id1_o) + pointer-1; - right = (char *)(id1->data+id1_o) + id1_s; + left = reinterpret_cast<char *>(id1->data+id1_o) + pointer-1; + right = reinterpret_cast<char *>(id1->data+id1_o) + id1_s; if( ndelimiteds == 0 ) { @@ -10726,8 +10987,9 @@ __gg__unstring( cblc_field_t *id1, // The string being unstring default: pfound = string_in( left, right, - (char *)(id2[i]->data+id2_o[i]), - (char *)(id2[i]->data+id2_o[i]) + id2_s[i]); + reinterpret_cast<char *>(id2[i]->data+id2_o[i]), + reinterpret_cast<char *>((id2[i]->data+id2_o[i]) + + id2_s[i])); break; } @@ -10804,7 +11066,7 @@ __gg__unstring( cblc_field_t *id1, // The string being unstring else { move_string(id5[nreceiver], id5_o[nreceiver], id5_s[nreceiver], - (char *)(id2[ifound]->data+id2_o[ifound]), + reinterpret_cast<char *>(id2[ifound]->data+id2_o[ifound]), id2_s[ifound]); } } @@ -10898,57 +11160,29 @@ int __gg__is_canceled(size_t function_pointer) static inline ec_type_t local_ec_type_of( file_status_t status ) { - ec_type_t retval; int status10 = (int)status / 10; - if( !(status10 < 10 && status10 >= 0) ) + assert( 0 <= status10 ); // was enum, can't be negative. + if( 10 < status10 ) { __gg__abort("local_ec_type_of(): status10 out of range"); } - switch(status10) - { - case 0: - // This actually should be ec_io_warning_e, but that's new for ISO 1989:2013 - retval = ec_none_e; - break; - case 1: - retval = ec_io_at_end_e; - break; - case 2: - retval = ec_io_invalid_key_e; - break; - case 3: - retval = ec_io_permanent_error_e; - break; - case 4: - retval = ec_io_logic_error_e; - break; - case 5: - retval = ec_io_record_operation_e; - break; - case 6: - retval = ec_io_file_sharing_e; - break; - case 7: - retval = ec_io_record_content_e; - break; - case 9: - retval = ec_io_imp_e; - break; - - default: - retval = ec_none_e; - break; - } - return retval; - } -bool -cbl_enabled_exceptions_array_t::match( ec_type_t ec, size_t file ) const { - auto output = enabled_exception_match( ecs, ecs + nec, ec, file ); - return output < ecs + nec? output->enabled : false; -} + static const std::vector<ec_type_t> ec_by_status { + /* 0 */ ec_none_e, // ec_io_warning_e if low byte is nonzero + /* 1 */ ec_io_at_end_e, + /* 2 */ ec_io_invalid_key_e, + /* 3 */ ec_io_permanent_error_e, + /* 4 */ ec_io_logic_error_e, + /* 5 */ ec_io_record_operation_e, + /* 6 */ ec_io_file_sharing_e, + /* 7 */ ec_io_record_content_e, + /* 8 */ ec_none_e, // unused, not defined by ISO + /* 9 */ ec_io_imp_e, + }; + assert(ec_by_status.size() == 10); -static cbl_enabled_exceptions_array_t enabled_ECs; + return ec_by_status[status10]; + } /* * Store and report the enabled exceptions. @@ -10957,288 +11191,411 @@ static cbl_enabled_exceptions_array_t enabled_ECs; */ struct exception_descr_t { bool location; - std::set<size_t> files; + //std::set<size_t> files; +}; + +struct cbl_exception_t { +// size_t program, + size_t file; + ec_type_t type; + cbl_file_mode_t mode; }; /* * Compare the raised exception, cbl_exception_t, to the USE critera - * of a declarative, cbl_declarative_t. Return FALSE if the exception - * raised was already handled by the statement that provoked the - * exception, as indicated by the "handled" file status. - * - * This copes with I/O exceptions: ec_io_e and friends. + * of a declarative, cbl_declarative_t. */ - -class match_file_declarative { - const cbl_exception_t& oops; - const ec_type_t handled_type; - protected: - bool handled() const { - return oops.type == handled_type || oops.type == ec_none_e; +static bool +match_declarative( bool enabled, + const cbl_exception_t& raised, + const cbl_declarative_t& dcl ) +{ + if( MATCH_DECLARATIVE && raised.type) { + warnx("match_declarative: checking: ec %s vs. dcl %s (%s enabled and %s format_1)", + local_ec_type_str(raised.type), + local_ec_type_str(dcl.type), + enabled? "is" : "not", + dcl.is_format_1()? "is" : "not"); } - public: - match_file_declarative( const cbl_exception_t& oops, file_status_t handled ) - : oops(oops), handled_type( local_ec_type_of(handled) ) - {} + if( ! (enabled || dcl.is_format_1()) ) return false; - bool operator()( const cbl_declarative_t& dcl ) { + bool matches = ec_cmp(raised.type, (dcl.type)); - if( getenv("match_declarative") && oops.type) { - warnx("match_file_declarative: checking: oops %s dcl %s (handled %s) ", - local_ec_type_str(oops.type), - local_ec_type_str(dcl.type), - local_ec_type_str(handled_type)); - } - - // Declarative is for the raised exception and not handled by the statement. - if( handled() ) return false; - bool matches = enabled_ECs.match(dcl.type); + if( matches && dcl.nfile > 0 ) { + matches = dcl.match_file(raised.file); + } + // Having matched, the EC must either be enabled, or + // the Declarative must be USE Format 1. + if( matches ) { // I/O declaratives match by file or mode, not EC. if( dcl.is_format_1() ) { // declarative is for particular files or mode - if( dcl.nfile > 0 ) { - matches = dcl.match_file(oops.file); - } else { - matches = oops.mode == dcl.mode; + if( dcl.nfile == 0 ) { + matches = raised.mode == dcl.mode; } + } else { + matches = enabled; } - if( matches && getenv("match_declarative") ) { - warnx(" matches exception %s (file %zu mode %s)", - local_ec_type_str(oops.type), - oops.file, - cbl_file_mode_str(oops.mode)); + if( matches && MATCH_DECLARATIVE ) { + warnx(" matches exception %s (file %u mode %s)", + local_ec_type_str(raised.type), + static_cast<unsigned int>(raised.file), + cbl_file_mode_str(raised.mode)); } - - return matches; } -}; - -cblc_file_t * __gg__file_stashed(); -static ec_type_t ec_raised_and_handled; + return matches; +} +/* + * The default exception handler is called if: + * 1. The EC is enabled and was not handled by a Declarative, or + * 2. The EC is EC-I-O and was not handled by a Format-1 Declarative, or + * 3. The EC is EC-I-O, associated with a file, and is not OPEN or CLOSE. + */ static void -default_exception_handler( ec_type_t ec) +default_exception_handler( ec_type_t ec ) { +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + /* Declared in errno.h, when available. */ + static const char * const ident = program_invocation_short_name; +#elif defined (HAVE_GETPROGNAME) + /* Declared in stdlib.h. */ + static const char * const ident = getprogname(); +#else + /* Avoid a NULL entry. */ + static const char * const ident = "unnamed_COBOL_program"; +#endif + static bool first_time = true; + static const int priority = LOG_INFO, option = LOG_PERROR, facility = LOG_USER; + ec_disposition_t disposition = ec_category_fatal_e; + + if( first_time ) { + // TODO: Program to set option in library via command-line and/or environment. + // Library listens to program, not to the environment. + openlog(ident, option, facility); + first_time = false; + } + if( ec != ec_none_e ) { - auto p = std::find_if( __gg__exception_table, __gg__exception_table_end, + auto pec = std::find_if( __gg__exception_table, __gg__exception_table_end, [ec](const ec_descr_t& descr) { return descr.type == ec; } ); - if( p == __gg__exception_table_end ) { - err(EXIT_FAILURE, - "logic error: %s:%zu: %s unknown exception %x", - ec_status.source_file, - ec_status.lineno, - ec_status.statement, - ec ); + if( pec != __gg__exception_table_end ) { + disposition = pec->disposition; + } else { + warnx("logic error: unknown exception %x", ec ); + } + /* + * An enabled, unhandled fatal EC normally results in termination. But + * EC-I-O is a special case: + * OPEN and CLOSE never result in termination. + * A SELECT statement with FILE STATUS indicates the user will handle the error. + * Only I/O statements are considered. + * Declaratives are handled first. We are in the default handler here, + * which is reached only if no Declarative was matched. + */ + auto file = ec_status.file_status(); + const char *filename = nullptr; + + if( file.ifile ) { + filename = file.filename; + switch( last_exception_file_operation ) { + case file_op_none: // not an I/O statement + assert(false); + abort(); + case file_op_open: + case file_op_close: // No OPEN/CLOSE results in a fatal error. + disposition = ec_category_none_e; + break; + default: + if( file.user_status ) { + // Not fatal if FILE STATUS is part of the file's SELECT statement. + disposition = ec_category_none_e; + } + break; + } + } else { + assert( ec_status.is_enabled() ); + assert( ec_status.is_enabled(ec) ); } - const char *disposition = NULL; - - switch( p->disposition ) { - case ec_category_fatal_e: - warnx("fatal exception at %s:%zu:%s %s (%s)", - ec_status.source_file, - ec_status.lineno, - ec_status.statement, - p->name, - p->description ); - abort(); - break; + switch( disposition ) { case ec_category_none_e: - disposition = "category none?"; - break; - case ec_category_nonfatal_e: - disposition = "nonfatal"; - break; - case ec_category_implementor_e: - disposition = "implementor"; - break; case uc_category_none_e: - disposition = "uc_category_none_e"; break; + case ec_category_fatal_e: case uc_category_fatal_e: - disposition = "uc_category_fatal_e"; + if( filename ) { + syslog(priority, "fatal exception: %s:%d: %s %s: %s (%s)", + program_name, + ec_status.lineno, + ec_status.statement, + filename, // show affected file before EC name + pec->name, + pec->description); + } else { + syslog(priority, "fatal exception: %s:%d: %s: %s (%s)", + program_name, + ec_status.lineno, + ec_status.statement, + pec->name, + pec->description); + } + abort(); break; + case ec_category_nonfatal_e: case uc_category_nonfatal_e: - disposition = "uc_category_nonfatal_e"; + syslog(priority, "%s:%d: %s: %s (%s)", + program_name, + ec_status.lineno, + ec_status.statement, + pec->name, + pec->description); break; + case ec_category_implementor_e: case uc_category_implementor_e: - disposition = "uc_category_implementor_e"; break; } - // If the EC was handled by a declarative, keep mum. - if( ec == ec_raised_and_handled ) { - ec_raised_and_handled = ec_none_e; - return; - } - - warnx("%s exception at %s:%zu:%s %s (%s)", - disposition, - ec_status.source_file, - ec_status.lineno, - ec_status.statement, - p->name, - p->description ); + ec_status.clear(); } } +/* + * To reach the default handler, an EC must have effect and not have been + * handled by program logic. To have effect, it must have been enabled + * explictly, or be of type EC-I-O. An EC may be handled by the statement or + * by a Declarative. + * + * Any EC handled by statement's conditional clause (e.g. ON SIZE ERROR) + * prevents an EC from being raised. Because it is not raised, it is handled + * neither by a Declarative, nor by the the default handler. + * + * A nonfatal EC matched to a Declarative is considered handled. A fatal EC is + * considered handled if the Declarative uses RESUME. For any EC that is + * handled (with RESUME for fatal), program control passes to the next + * statement. Else control passes here first. + * + * Any EC explicitly enabled (with >>TURN) must be explicitly handled. Only + * explicitly enabled ECs appear in enabled_ECs. when EC-I-O is raised as a + * byproduct of error status on a file operation, we say it is "implicitly + * enabled". It need not be explicitly handled. + * + * Implicit EC-I-O not handled by the statement or a Declarative is considered + * handled if the statement includes the FILE STATUS phrase. OPEN and CLOSE + * never cause program termination with EC-I-O; for those two statements the + * fatal status is ignored. These conditions are screened out by + * __gg__check_fatal_exception(), so that the default handler is not called. + * + * An unhandled EC reaches the default handler for any of 3 reasons: + * 1. It is EC-I-O (enabled does not matter). + * 2. It is enabled. + * 3. It is fatal and was matched to a Declarative that did not use RESUME. + * The default handler, default_exception_handler(), logs the EC. For a fatal + * EC, the process terminated with abort(3). + * + * Except for OPEN and CLOSE, I/O statements that raise an unhandled fatal EC + * cause program termination, consistent with IBM documentation. See + * Enterprise COBOL for z/OS: Enterprise COBOL for z/OS 6.4 Programming Guide, + * page 244, "Handling errors in input and output operations". + */ extern "C" void __gg__check_fatal_exception() { - if( ec_raised_and_handled == ec_none_e ) return; - /* - * "... if checking for EC-I-O exception conditions is not enabled, - * there is no link between EC-I-O exception conditions and I-O - * status values." - */ - if( ec_cmp(ec_raised_and_handled, ec_io_e) ) return; - - default_exception_handler(ec_raised_and_handled); - ec_raised_and_handled = ec_none_e; + if( MATCH_DECLARATIVE ) + warnx("%s: ec_status is %s", __func__, ec_status.unset()? "unset" : "set"); + + if( ec_status.copy_environment().unset() ) + { + ec_status.update(); // __gg__match_exception was not called first + // This is a good time to set the exception code back to zero + __gg__exception_code = 0; + } + + if( ec_status.done() ) { // false for part-handled fatal + if( MATCH_DECLARATIVE ) + warnx("%s: clearing ec_status", __func__); + ec_status.clear(); + return; // already handled + } + + auto ec = ec_status.unhandled(); + + if( MATCH_DECLARATIVE ) + warnx("%s: %s was not handled %s enabled", __func__, + local_ec_type_str(ec), ec_status.is_enabled(ec)? "is" : "is not"); + + // Look for ways I/O statement might have dealt with EC. + auto file = ec_status.file_status(); + if( file.ifile && ec_cmp(ec, ec_io_e) ) { + if( MATCH_DECLARATIVE ) + warnx("%s: %s with %sFILE STATUS", __func__, + file.op_str(), file.user_status? "" : "no "); + if( file.user_status ) { + ec_status.clear(); + return; // has FILE STATUS, ok + } + switch( file.operation ) { + case file_op_none: + assert(false); + abort(); + case file_op_open: // implicit, no Declarative, no FILE STATUS, but ok + case file_op_close: + ec_status.clear(); + return; + case file_op_start: + case file_op_read: + case file_op_write: + case file_op_rewrite: + case file_op_delete: + break; + } + } else { + if( ! ec_status.is_enabled() ) { + if( MATCH_DECLARATIVE ) + warnx("%s: %s is not enabled", __func__, local_ec_type_str(ec)); + ec_status.clear(); + return; + } + if( MATCH_DECLARATIVE ) + warnx("%s: %s is enabled", __func__, local_ec_type_str(ec)); + } + + if( MATCH_DECLARATIVE ) + warnx("%s: calling default_exception_handler(%s)", __func__, + local_ec_type_str(ec)); + + default_exception_handler(ec); } +/* + * Preserve the state of the raised EC during Declarative execution. + */ extern "C" void -__gg__clear_exception() +__gg__exception_push() { - ec_raised_and_handled = ec_none_e; + ec_stack.push(ec_status); + if( MATCH_DECLARATIVE ) + warnx("%s: %s: %u ECs, %u declaratives", __func__, + __gg__exception_statement, + static_cast<unsigned int>(enabled_ECs.size()), + static_cast<unsigned int>(declaratives.size())); } - -cbl_enabled_exceptions_array_t& -cbl_enabled_exceptions_array_t::operator=( const cbl_enabled_exceptions_array_t& input ) +/* + * Restore the state of the raised EC after Declarative execution. + */ +extern "C" +void +__gg__exception_pop() { - if( nec == input.nec ) { - if( nec == 0 || 0 == memcmp(ecs, input.ecs, nbytes()) ) return *this; - } - - if( nec < input.nec ) { - if( nec > 0 ) delete[] ecs; - ecs = new cbl_enabled_exception_t[1 + input.nec]; - } - if( input.nec > 0 ) { - auto pend = std::copy( input.ecs, input.ecs + input.nec, ecs ); - std::fill(pend, ecs + input.nec, cbl_enabled_exception_t()); - } - nec = input.nec; - return *this; + ec_status = ec_stack.top(); + ec_stack.pop(); + ec_status.reset_environment(); + if( MATCH_DECLARATIVE ) + warnx("%s: %s: %u ECs, %u declaratives", __func__, + __gg__exception_statement, + static_cast<unsigned int>(enabled_ECs.size()), + static_cast<unsigned int>(declaratives.size())); + __gg__check_fatal_exception(); } -// Update the list of compiler-maintained enabled exceptions. +// Called for RESUME in a Declarative to indicate a fatal EC was handled. extern "C" void -__gg__stash_exceptions( size_t nec, cbl_enabled_exception_t *ecs ) +__gg__clear_exception() { - enabled_ECs = cbl_enabled_exceptions_array_t(nec, ecs); - - if( false && getenv("match_declarative") ) - warnx("%s: %zu exceptions enabled", __func__, nec); + ec_stack.top().clear(); } +void +cbl_enabled_exception_t::dump( int i ) const { + warnx("cbl_enabled_exception_t: %2d {%s, %s, %u}", + i, + location? "location" : " none", + local_ec_type_str(ec), + static_cast<unsigned int>(file) ); +} /* - * Match the raised exception against a declarative handler + * Match the raised exception against a Declarative. * - * ECs unrelated to I/O are not matched to a Declarative unless - * enabled. Declaratives for I/O errors, on the other hand, match - * regardless of whether or not any EC is enabled. + * A Declarative that handles I/O errors with USE Format 1 doesn't name a + * specific EC. It's matched based on the file's status, irrespective of + * whether or not EC-I-O is enabled. USE Format 1 Declaratives are honored + * regardless of any >>TURN directive. * - * Declaratives handle I-O errors with USE Format 1. They don't name a - * specific EC. They're matched based on the file's status, - * irrespective of whether or not EC-I-O is enabled. If EC-I-O is - * enabled, and mentioned in a Declarative USE statement, then it is - * matched just like any other Format 3 USE statement. + * An EC is enabled by the >>TURN directive. The only ECs that can be disabled + * are those that were explicitly enabled. If EC-I-O is enabled, and mentioned + * in a Declarative with USE Format 3, then it is matched just like any other. */ extern "C" void -__gg__match_exception( cblc_field_t *index, - const cbl_declarative_t *dcls ) +__gg__match_exception( cblc_field_t *index ) { - static const cbl_declarative_t no_declaratives[1] = {}; - - size_t ifile = __gg__exception_file_number; - // The exception file number is assumed to always be zero, unless it's - // been set to a non-zero value. Having picked up that value it is our job - // to immediately set it back to zero: - __gg__exception_file_number = 0; - - int handled = __gg__exception_handled; - cblc_file_t *stashed = __gg__file_stashed(); + size_t isection = 0; - if( dcls == NULL ) dcls = no_declaratives; - size_t ndcl = dcls[0].section; - auto eodcls = dcls + 1 + ndcl, p = eodcls; + if( MATCH_DECLARATIVE ) enabled_ECs.dump("match_exception begin"); auto ec = ec_status.update().unhandled(); - // We need to set exception handled back to 0. We do it here because - // ec_status.update() looks at it - __gg__exception_handled = 0; + if( ec != ec_none_e ) { + /* + * An EC was raised and was not handled by the statement. + * We know the EC and, for I/O, the current file and its mode. + * Scan declaratives for a match: + * - EC is enabled or program has a Format 1 Declarative + * - EC matches the Declarative's USE statement + * Format 1 declaratives apply only to EC-I-O, whether or not enabled. + * Format 1 may be restricted to a particular mode (for all files). + * Format 1 and 3 may be restricted to a set of files. + */ - if(__gg__exception_code != ec_none_e) // cleared by ec_status_t::update - { - __gg__abort("__gg__match_exception(): __gg__exception_code should be ec_none_e"); - } - if( ec == ec_none_e ) { - if( ifile == 0) goto set_exception_section; + // This is a good time to set the actual exception code back to zero. + __gg__exception_code = 0; - if( stashed == nullptr ) - { - __gg__abort("__gg__match_exception(): stashed is null"); - } - ec = local_ec_type_of( stashed->io_status ); - } + auto f = ec_status.file_status(); + cbl_exception_t raised = { /*0,*/ f.ifile, ec, f.mode }; + bool enabled = enabled_ECs.match(ec); - if( ifile > 0 ) { // an I/O exception is raised - if( stashed == nullptr ) - { - __gg__abort("__gg__match_exception(): stashed is null (2)"); - } - auto mode = cbl_file_mode_t(stashed->mode_char); - cbl_exception_t oops = {0, ifile, ec, mode }; - p = std::find_if( dcls + 1, eodcls, - match_file_declarative(oops, file_status_t(handled)) ); + if( MATCH_DECLARATIVE ) enabled_ECs.dump("match_exception enabled"); - } else { // non-I/O exception - auto enabled = enabled_ECs.match(ec); - if( enabled ) { - p = std::find_if( dcls + 1, eodcls, [ec] (const cbl_declarative_t& dcl) { - if( ! enabled_ECs.match(dcl.type) ) return false; - if( ! ec_cmp(ec, dcl.type) ) return false; + auto p = std::find_if( declaratives.begin(), declaratives.end(), + [enabled, raised]( const cbl_declarative_t& dcl ) { + return match_declarative(enabled, raised, dcl); + } ); - if( getenv("match_declarative") ) { - warnx("__gg__match_exception:%d: matched " - "%s against mask %s for section #%zu", - __LINE__, - local_ec_type_str(ec), local_ec_type_str(dcl.type), - dcl.section); - } - return true; - } ); - if( p == eodcls ) { - default_exception_handler(ec); - } - } else { // not enabled - if( getenv("match_declarative") ) { + if( p == declaratives.end() ) { + if( MATCH_DECLARATIVE ) { warnx("__gg__match_exception:%d: raised exception " - "%s is disabled (%zu enabled)", __LINE__, - local_ec_type_str(ec), enabled_ECs.nec); + "%s not matched (%u enabled)", __LINE__, + local_ec_type_str(ec), + static_cast<unsigned int>(enabled_ECs.size())); } - } - } + } else { + isection = p->section; + ec_status.handled_by(isection); - set_exception_section: - size_t retval = p == eodcls? 0 : p->section; - ec_raised_and_handled = retval? ec : ec_none_e; + if( MATCH_DECLARATIVE ) { + warnx("__gg__match_exception:%d: matched " + "%s against mask %s for section #%u", + __LINE__, + local_ec_type_str(ec), + local_ec_type_str(p->type), + static_cast<unsigned int>(p->section)); + } + } + assert(ec != ec_none_e); + } // end EC match logic // If a declarative matches the raised exception, return its // symbol_table index. __gg__int128_to_field(index, - (__int128)retval, + (__int128)isection, 0, truncation_e, NULL); @@ -11306,21 +11663,24 @@ __gg__pseudo_return_flush() } extern "C" -_Float128 -__gg__float128_from_location(cblc_field_t *var, unsigned char *location) +GCOB_FP128 +__gg__float128_from_location( const cblc_field_t *var, + const unsigned char *location) { - _Float128 retval = 0; + GCOB_FP128 retval = 0; switch( var->capacity ) { case 4: { - retval = *(_Float32 *)location; + retval = *reinterpret_cast<_Float32 *>( + const_cast<unsigned char *>(location)); break; } case 8: { - retval = *(_Float64 *)location; + retval = *reinterpret_cast<_Float64 *>( + const_cast<unsigned char *>(location)); break; } @@ -11336,11 +11696,11 @@ __gg__float128_from_location(cblc_field_t *var, unsigned char *location) extern "C" __int128 -__gg__integer_from_float128(cblc_field_t *field) +__gg__integer_from_float128(const cblc_field_t *field) { - _Float128 fvalue = __gg__float128_from_location(field, field->data); + GCOB_FP128 fvalue = __gg__float128_from_location(field, field->data); // we round() to take care of the possible 2.99999999999... problem. - fvalue = roundf128(fvalue); + fvalue = FP128_FUNC(round)(fvalue); return (__int128)fvalue; } @@ -11367,41 +11727,41 @@ void __gg__func_exception_location(cblc_field_t *dest) { char ach[512] = " "; - if( stashed_exception_code ) + if( last_exception_code ) { ach[0] = '\0'; - if( stashed_exception_program_id ) + if( last_exception_program_id ) { - strcat(ach, stashed_exception_program_id); + strcat(ach, last_exception_program_id); strcat(ach, "; "); } - if( stashed_exception_paragraph ) + if( last_exception_paragraph ) { - strcat(ach, stashed_exception_paragraph ); - if( stashed_exception_section ) + strcat(ach, last_exception_paragraph ); + if( last_exception_section ) { strcat(ach, " OF "); - strcat(ach, stashed_exception_section); + strcat(ach, last_exception_section); } } else { - if( stashed_exception_section ) + if( last_exception_section ) { - strcat(ach, stashed_exception_section); + strcat(ach, last_exception_section); } } strcat(ach, "; "); - if( stashed_exception_source_file ) + if( last_exception_source_file ) { char achSource[128] = ""; snprintf( achSource, sizeof(achSource), "%s:%d ", - stashed_exception_source_file, - stashed_exception_line_number); + last_exception_source_file, + last_exception_line_number); strcat(ach, achSource); } else @@ -11418,9 +11778,9 @@ void __gg__func_exception_statement(cblc_field_t *dest) { char ach[128] = " "; - if(stashed_exception_statement) + if(last_exception_statement) { - snprintf(ach, sizeof(ach), "%s", stashed_exception_statement); + snprintf(ach, sizeof(ach), "%s", last_exception_statement); ach[sizeof(ach)-1] = '\0'; } __gg__adjust_dest_size(dest, strlen(ach)); @@ -11432,12 +11792,12 @@ void __gg__func_exception_status(cblc_field_t *dest) { char ach[128] = "<not in table?>"; - if(stashed_exception_code) + if(last_exception_code) { ec_descr_t *p = __gg__exception_table; while(p < __gg__exception_table_end ) { - if( p->type == (ec_type_t)stashed_exception_code ) + if( p->type == (ec_type_t)last_exception_code ) { snprintf(ach, sizeof(ach), "%s", p->name); break; @@ -11453,47 +11813,52 @@ __gg__func_exception_status(cblc_field_t *dest) memcpy(dest->data, ach, strlen(ach)); } -static cblc_file_t *recent_file = NULL; - extern "C" void -__gg__set_exception_file(cblc_file_t *file) +__gg__set_exception_file(const cblc_file_t *file) { - if( getenv("match_declarative") ) - { - warnx("%s: %s", __func__, file->name); - } - recent_file = file; ec_type_t ec = local_ec_type_of( file->io_status ); if( ec ) { - exception_raise(ec); + // During SORT operations, which routinely read files until they end, we + // need to suppress them. + if( ec != ec_io_at_end_e || !sv_suppress_eof_ec ) + { + last_exception_file_operation = file->prior_op; + last_exception_file_status = file->io_status; + last_exception_file_name = file->name; + exception_raise(ec); + } } } - extern "C" void -__gg__func_exception_file(cblc_field_t *dest, cblc_file_t *file) +__gg__func_exception_file(cblc_field_t *dest, + const cblc_file_t *file) { char ach[128]; if( !file ) { // This is where we process FUNCTION EXCEPTION-FILE <no parameter> - if( !(stashed_exception_code & ec_io_e) || !recent_file) + if( !(last_exception_code & ec_io_e) ) { - // There is no EC-I-O exception code, so we return two spaces + // There is no EC-I-O exception code, so we return two alphanumeric zeros. strcpy(ach, "00"); } else { + // The last exception code is an EC-I-O if( sv_from_raise_statement ) { strcpy(ach, " "); } else { - snprintf(ach, sizeof(ach), "%2.2d%s", recent_file->io_status, recent_file->name); + snprintf( ach, + sizeof(ach), "%2.2d%s", + last_exception_file_status, + last_exception_file_name); } } } @@ -11519,40 +11884,50 @@ extern "C" void __gg__set_exception_code(ec_type_t ec, int from_raise_statement) { - if( getenv("match_declarative") ) + if( MATCH_DECLARATIVE ) { - warnx("%s: raised %02x", __func__, ec); + warnx("%s: %s:%u: %s: %s", + __func__, + __gg__exception_source_file, + __gg__exception_line_number, + __gg__exception_statement, + local_ec_type_str(ec)); } sv_from_raise_statement = from_raise_statement; __gg__exception_code = ec; if( ec == ec_none_e) { - stashed_exception_code = 0 ; - stashed_exception_handled = 0 ; - stashed_exception_file_number = 0 ; - stashed_exception_file_status = 0 ; - stashed_exception_file_name = NULL ; - stashed_exception_program_id = NULL ; - stashed_exception_section = NULL ; - stashed_exception_paragraph = NULL ; - stashed_exception_source_file = NULL ; - stashed_exception_line_number = 0 ; - stashed_exception_statement = NULL ; + last_exception_code = 0 ; + last_exception_program_id = NULL ; + last_exception_section = NULL ; + last_exception_paragraph = NULL ; + last_exception_source_file = NULL ; + last_exception_line_number = 0 ; + last_exception_statement = NULL ; + last_exception_file_operation = file_op_none ; + last_exception_file_status = FsSuccess ; + last_exception_file_name = NULL ; } else { - stashed_exception_code = __gg__exception_code ; - stashed_exception_handled = __gg__exception_handled ; - stashed_exception_file_number = __gg__exception_file_number ; - stashed_exception_file_status = __gg__exception_file_status ; - stashed_exception_file_name = __gg__exception_file_name ; - stashed_exception_program_id = __gg__exception_program_id ; - stashed_exception_section = __gg__exception_section ; - stashed_exception_paragraph = __gg__exception_paragraph ; - stashed_exception_source_file = __gg__exception_source_file ; - stashed_exception_line_number = __gg__exception_line_number ; - stashed_exception_statement = __gg__exception_statement ; + last_exception_code = __gg__exception_code ; + last_exception_program_id = __gg__exception_program_id ; + last_exception_section = __gg__exception_section ; + last_exception_paragraph = __gg__exception_paragraph ; + last_exception_source_file = __gg__exception_source_file ; + last_exception_line_number = __gg__exception_line_number ; + last_exception_statement = __gg__exception_statement ; + + // These are set in __gg__set_exception_file just before this routine is + // called. In cases where the ec is not a file-i-o operation, we clear + // them here: + if( !(ec & ec_io_e) ) + { + last_exception_file_operation = file_op_none ; + last_exception_file_status = FsSuccess ; + last_exception_file_name = NULL ; + } } } @@ -11566,13 +11941,13 @@ __gg__float32_from_int128(cblc_field_t *destination, int *size_error) { int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); value /= __gg__power_of_ten(rdigits); - if( fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { if(size_error) { @@ -11607,7 +11982,7 @@ __gg__float64_from_int128(cblc_field_t *destination, *size_error = 0; } int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); @@ -11630,7 +12005,7 @@ __gg__float128_from_int128(cblc_field_t *destination, { if(size_error) *size_error = 0; int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); @@ -11644,20 +12019,20 @@ __gg__float128_from_int128(cblc_field_t *destination, extern "C" int -__gg__is_float_infinite(cblc_field_t *source, size_t offset) +__gg__is_float_infinite(const cblc_field_t *source, size_t offset) { int retval = 0; switch(source->capacity) { case 4: - retval = fpclassify( *(_Float32*)(source->data+offset)) == FP_INFINITE; + retval = fpclassify( *reinterpret_cast<_Float32*>(source->data+offset)) == FP_INFINITE; break; case 8: - retval = fpclassify( *(_Float64*)(source->data+offset)) == FP_INFINITE; + retval = fpclassify( *reinterpret_cast<_Float64*>(source->data+offset)) == FP_INFINITE; break; case 16: // retval = *(_Float128*)(source->data+offset) == INFINITY; - _Float128 t; + GCOB_FP128 t; memcpy(&t, source->data+offset, 16); retval = t == INFINITY; break; @@ -11667,64 +12042,64 @@ __gg__is_float_infinite(cblc_field_t *source, size_t offset) extern "C" int -__gg__float32_from_128( cblc_field_t *dest, - size_t dest_offset, - cblc_field_t *source, - size_t source_offset) +__gg__float32_from_128( const cblc_field_t *dest, + size_t dest_offset, + const cblc_field_t *source, + size_t source_offset) { int retval = 0; //_Float128 value = *(_Float128*)(source->data+source_offset); - _Float128 value; + GCOB_FP128 value; memcpy(&value, source->data+source_offset, 16); - if( fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { retval = 1; } else { - *(_Float32 *)(dest->data+dest_offset) = (_Float32)value; + *reinterpret_cast<_Float32 *>(dest->data+dest_offset) = (_Float32)value; } return retval; } extern "C" int -__gg__float32_from_64( cblc_field_t *dest, - size_t dest_offset, - cblc_field_t *source, - size_t source_offset) +__gg__float32_from_64( const cblc_field_t *dest, + size_t dest_offset, + const cblc_field_t *source, + size_t source_offset) { int retval = 0; - _Float64 value = *(_Float64*)(source->data+source_offset); - if( fabsf128(value) > 3.4028235E38Q ) + _Float64 value = *reinterpret_cast<_Float64*>(source->data+source_offset); + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { retval = 1; } else { - *(_Float32 *)(dest->data+dest_offset) = (_Float32)value; + *reinterpret_cast<_Float32 *>(dest->data+dest_offset) = (_Float32)value; } return retval; } extern "C" int -__gg__float64_from_128( cblc_field_t *dest, - size_t dest_offset, - cblc_field_t *source, - size_t source_offset) +__gg__float64_from_128( const cblc_field_t *dest, + size_t dest_offset, + const cblc_field_t *source, + size_t source_offset) { int retval = 0; // _Float128 value = *(_Float128*)(source->data+source_offset); - _Float128 value; + GCOB_FP128 value; memcpy(&value, source->data+source_offset, 16); - if( fabsf128(value) > 1.7976931348623157E308 ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL(1.7976931348623157E308) ) { retval = 1; } else { - *(_Float64 *)(dest->data+dest_offset) = (_Float64)value; + *reinterpret_cast<_Float64 *>(dest->data+dest_offset) = (_Float64)value; } return retval; } @@ -11796,7 +12171,8 @@ __gg__pop_local_variables() extern "C" void -__gg__copy_as_big_endian(unsigned char *dest, unsigned char *source) +__gg__copy_as_big_endian( unsigned char *dest, + const unsigned char *source) { // copy eight bytes of source to dest, flipping the endianness for(size_t i=0; i<8; i++) @@ -11819,7 +12195,7 @@ __gg__codeset_figurative_constants() extern "C" unsigned char * -__gg__get_figconst_data(cblc_field_t *field) +__gg__get_figconst_data(const cblc_field_t *field) { unsigned char *retval = NULL; cbl_figconst_t figconst = (cbl_figconst_t)(size_t)(field->initial); @@ -11904,7 +12280,7 @@ find_in_dirs(const char *dirs, char *unmangled_name, char *mangled_name) { while( !retval ) { - dirent *entry = readdir(dir); + const dirent *entry = readdir(dir); if( !entry ) { break; @@ -11960,7 +12336,7 @@ __gg__function_handle_from_cobpath( char *unmangled_name, char *mangled_name) { handle_executable = dlopen(NULL, RTLD_LAZY); } - if( !retval ) + //if( !retval ) { retval = dlsym(handle_executable, unmangled_name); } @@ -11970,7 +12346,7 @@ __gg__function_handle_from_cobpath( char *unmangled_name, char *mangled_name) } if( !retval ) { - const char *COBPATH = getenv("COBPATH"); + const char *COBPATH = getenv("GCOBOL_LIBRARY_PATH"); retval = find_in_dirs(COBPATH, unmangled_name, mangled_name); } if( !retval ) @@ -11984,14 +12360,17 @@ __gg__function_handle_from_cobpath( char *unmangled_name, char *mangled_name) extern "C" void -__gg__just_mangle_name( cblc_field_t *field, - char **mangled_name +__gg__just_mangle_name( const cblc_field_t *field, + char **mangled_name ) { static char ach_name[1024]; static char ach_unmangled[1024]; static char ach_mangled[1024]; + assert(field); + assert(field->data); + size_t length; length = field->capacity; memcpy(ach_name, field->data, length); @@ -12005,7 +12384,7 @@ __gg__just_mangle_name( cblc_field_t *field, bool is_pointer = false; - if( (field && field->type == FldPointer) ) + if( field->type == FldPointer ) { is_pointer = true; } @@ -12029,8 +12408,8 @@ __gg__just_mangle_name( cblc_field_t *field, extern "C" void * -__gg__function_handle_from_literal(int program_id, - char *literal) +__gg__function_handle_from_literal(int program_id, + const char *literal) { void *retval = NULL; static char ach_unmangled[1024]; @@ -12058,7 +12437,7 @@ __gg__function_handle_from_literal(int program_id, } PFUNC **pointers_p = it->second; PFUNC *pointers = *pointers_p; - retval = (void *)pointers[function_index]; + retval = reinterpret_cast<void *>(pointers[function_index]); } else { @@ -12070,10 +12449,10 @@ __gg__function_handle_from_literal(int program_id, extern "C" void * -__gg__function_handle_from_name(int program_id, - cblc_field_t *field, - size_t offset, - size_t length ) +__gg__function_handle_from_name(int program_id, + const cblc_field_t *field, + size_t offset, + size_t length ) { void *retval = NULL; static char ach_name[1024]; @@ -12111,7 +12490,7 @@ __gg__function_handle_from_name(int program_id, } PFUNC **pointers_p = it->second; PFUNC *pointers = *pointers_p; - retval = (void *)pointers[function_index]; + retval = reinterpret_cast<void *>(pointers[function_index]); } else { @@ -12147,10 +12526,10 @@ __gg__mirror_range( size_t nrows, cblc_field_t *src, // The row size_t src_o, size_t nspans, // The number of spans - size_t *spans, + const size_t *spans, size_t table, size_t ntbl, - size_t *tbls) + const size_t *tbls) { static std::unordered_map<size_t, size_t> rows_in_table; static std::unordered_map<size_t, size_t> widths_of_table; @@ -12171,7 +12550,7 @@ __gg__mirror_range( size_t nrows, // We need to know the width of one row of this table, which is different // depending on type of src: - cblc_field_t *parent = src; + const cblc_field_t *parent = src; while( parent ) { if( parent->occurs_upper ) @@ -12293,7 +12672,7 @@ __gg__mirror_range( size_t nrows, std::vector<size_t> subtable_spans = spans_in_table [subtable_index]; - unsigned char *subtable_source = source + subtable_offset; + const unsigned char *subtable_source = source + subtable_offset; if( subtable_spans.size() == 0 ) { @@ -12378,15 +12757,17 @@ __gg__deallocate( cblc_field_t *target, { // Target is a pointer. Free the data location int rdigits; - void *ptr = (void *)get_binary_value_local(&rdigits, + size_t addrv = get_binary_value_local(&rdigits, target, target->data + offset, sizeof(void *)); + void *ptr = reinterpret_cast<void *>(addrv); if( ptr ) { free(ptr); // And set the data location to zero - *(char **)(target->data + offset) = NULL; + *static_cast<char **>(static_cast<void *>(target->data + offset)) + = NULL; } } } @@ -12428,17 +12809,18 @@ get_the_byte(cblc_field_t *field) extern "C" void -__gg__allocate( cblc_field_t *first, - size_t first_offset, - int initialized, - int default_byte, - cblc_field_t *f_working_byte, - cblc_field_t *f_local_byte, - cblc_field_t *returning, - size_t returning_offset) +__gg__allocate( cblc_field_t *first, + size_t first_offset, + int initialized, + int default_byte, + cblc_field_t *f_working_byte, + cblc_field_t *f_local_byte, + const cblc_field_t *returning, + size_t returning_offset) { int working_byte = get_the_byte(f_working_byte); int local_byte = get_the_byte(f_local_byte); + int fill_char; unsigned char *retval = NULL; if( first->attr & based_e ) @@ -12446,12 +12828,12 @@ __gg__allocate( cblc_field_t *first, // first is the BASED variable we are allocating memory for if( first->capacity ) { - retval = (unsigned char *)malloc(first->capacity); + retval = static_cast<unsigned char *>(malloc(first->capacity)); + fill_char = 0; if( initialized ) { // This is ISO 2023 ALLOCATE rule 7 (ALL TO VALUE) - int fill_char = 0; if( default_byte >= 0 ) { fill_char = default_byte; @@ -12461,7 +12843,6 @@ __gg__allocate( cblc_field_t *first, else { // This is ISO 2023 ALLOCATE rule 9 (pointers NULL, otherwise OPT_INIT) - int fill_char = 0; if( default_byte >= 0 ) { fill_char = default_byte; @@ -12505,9 +12886,13 @@ __gg__allocate( cblc_field_t *first, tsize /= pof10; if( tsize ) { - retval = (unsigned char *)malloc(tsize); + retval = static_cast<unsigned char *>(malloc(tsize)); + if(!retval) + { + abort(); + } - int fill_char = 0; + fill_char = 0; if( initialized ) { // This is ISO 2023 rule 6 (defaultbyte if specified, else zero) @@ -12546,7 +12931,7 @@ __gg__allocate( cblc_field_t *first, if( returning ) { // 'returning' has to be a FldPointer variable; assign the retval to it. - *(unsigned char **)(returning->data + returning_offset) = retval; + *reinterpret_cast<unsigned char **>(returning->data + returning_offset) = retval; } } @@ -12575,7 +12960,8 @@ void __gg__module_name(cblc_field_t *dest, module_type_t type) { static size_t result_size = 64; - static char *result = (char *)malloc(result_size); + static char *result = static_cast<char *>(malloc(result_size)); + massert(result); strcpy(result, ""); @@ -12664,7 +13050,7 @@ __gg__module_name(cblc_field_t *dest, module_type_t type) if( strlen(result) + module_name_stack[i].substr(1).length() + 4 > result_size) { result_size *= 2; - result = (char *)realloc(result, result_size); + result = static_cast<char *>(realloc(result, result_size)); } strcat(result, module_name_stack[i].substr(1).c_str()); strcat(result, ";"); @@ -12690,3 +13076,197 @@ __gg__module_name(cblc_field_t *dest, module_type_t type) memcpy(dest->data, result, strlen(result)+1); } +/* + * Runtime functions defined for cbl_enabled_exceptions_t + */ +cbl_enabled_exceptions_t& +cbl_enabled_exceptions_t::decode( const std::vector<uint64_t>& encoded ) { + auto p = encoded.begin(); + while( p != encoded.end() ) { + auto location = static_cast<bool>(*p++); + auto ec = static_cast<ec_type_t>(*p++); + auto file = *p++; + cbl_enabled_exception_t enabled(location, ec, file); + insert(enabled); + } + return *this; +} +const cbl_enabled_exception_t * +cbl_enabled_exceptions_t::match( ec_type_t type, size_t file ) const { + auto output = enabled_exception_match( begin(), end(), type, file ); + + if( output != end() ) { + if( MATCH_DECLARATIVE ) + warnx(" enabled_exception_match found %x in input\n", type); + return &*output; + } + return nullptr; +} + +void +cbl_enabled_exceptions_t::dump( const char tag[] ) const { + if( empty() ) { + warnx("%s: no enabled exceptions", tag ); + return; + } + int i = 1; + for( auto& elem : *this ) { + warnx("%s: %2d {%s, %04x %s, %u}", tag, + i++, + elem.location? "with location" : " no location", + elem.ec, + local_ec_type_str(elem.ec), + static_cast<unsigned int>(elem.file) ); + } +} + + +static std::vector<cbl_declarative_t>& +decode( std::vector<cbl_declarative_t>& dcls, + const std::vector<uint64_t>& encoded ) { + auto p = encoded.begin(); + while( p != encoded.end() ) { + auto section = static_cast<size_t>(*p++); + auto global = static_cast<bool>(*p++); + auto type = static_cast<ec_type_t>(*p++); + auto nfile = static_cast<uint32_t>(*p++); + std::list<size_t> files; + assert(nfile <= cbl_declarative_t::files_max); + auto pend = p + nfile; + std::copy(p, pend, std::back_inserter(files)); + p += cbl_declarative_t::files_max; + auto mode = cbl_file_mode_t(*p++); + cbl_declarative_t dcl( section, type, files, mode, global ); + dcls.push_back(dcl); + } + return dcls; +} + +static std::vector<cbl_declarative_t>& +operator<<( std::vector<cbl_declarative_t>& dcls, + const std::vector<uint64_t>& encoded ) { + return decode( dcls, encoded ); +} + +// The first element of each array is the number of elements that follow +extern "C" +void +__gg__set_exception_environment( uint64_t *ecs, uint64_t *dcls ) + { + static struct prior_t { + uint64_t *ecs = nullptr, *dcls = nullptr; + } prior; + + if( MATCH_DECLARATIVE ) + if( prior.ecs != ecs || prior.dcls != dcls ) + warnx("set_exception_environment: %s: %p, %p", + __gg__exception_statement, ecs, dcls); + + if( ecs ) { + if( prior.ecs != ecs ) { + uint64_t *ecs_begin = ecs + 1, *ecs_end = ecs_begin + ecs[0]; + if( MATCH_DECLARATIVE ) { + warnx("%u elements implies %u ECs", + static_cast<unsigned int>(ecs[0]), + static_cast<unsigned int>(ecs[0] / 3)); + } + cbl_enabled_exceptions_t enabled; + enabled_ECs = enabled.decode( std::vector<uint64_t>(ecs_begin, ecs_end) ); + if( MATCH_DECLARATIVE ) enabled_ECs.dump("set_exception_environment"); + } + } else { + enabled_ECs.clear(); + } + + if( dcls ) { + if( prior.dcls != dcls ) { + uint64_t *dcls_begin = dcls + 1, *dcls_end = dcls_begin + dcls[0]; + if( MATCH_DECLARATIVE ) { + warnx("%u elements implies %u declaratives", + static_cast<unsigned int>(dcls[0]), + static_cast<unsigned int>(dcls[0] / 21)); + } + declaratives.clear(); + declaratives << std::vector<uint64_t>( dcls_begin, dcls_end ); + } + } else { + declaratives.clear(); + } + + __gg__exception_code = ec_none_e; + + prior.ecs = ecs; + prior.dcls = dcls; + } + +static char *sv_envname = NULL; + +extern "C" +void +__gg__set_env_name( const cblc_field_t *var, + size_t offset, + size_t length ) + { + free(sv_envname); + sv_envname = static_cast<char *>(malloc(length+1)); + massert(sv_envname); + memcpy(sv_envname, var->data+offset, length); + sv_envname[length] = '\0'; + } + +extern "C" +void +__gg__set_env_value(const cblc_field_t *value, + size_t offset, + size_t length ) + { + size_t name_length = strlen(sv_envname); + size_t value_length = length; + + static size_t env_length = 16; + static char *env = static_cast<char *>(malloc(env_length+1)); + static size_t val_length = 16; + static char *val = static_cast<char *>(malloc(val_length+1)); + if( env_length < name_length+1 ) + { + env_length = name_length+1; + env = static_cast<char *>(realloc(env, env_length)); + } + if( val_length < value_length+1 ) + { + val_length = value_length+1; + val = static_cast<char *>(realloc(val, val_length)); + } + massert(env); + massert(val); + + // The name and the value arrive in the internal codeset: + memcpy(env, sv_envname, name_length); + env[name_length] = '\0'; + memcpy(val, value->data+offset, value_length); + val[value_length] = '\0'; + + // Get rid of leading and trailing internal_space characters + char *trimmed_env = brute_force_trim(env); + char *trimmed_val = brute_force_trim(val); + + // Conver them to the console codeset + __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env)); + __gg__internal_to_console_in_place(trimmed_val, strlen(trimmed_val)); + + // And now, anticlimactically, set the variable: + setenv(trimmed_env, trimmed_val, 1); + } + +extern "C" +void +__gg__fprintf_stderr(const char *format_string, ...) + { + /* This routine allows the compiler to send stuff to stderr in a way + that is straightforward to use.. */ + va_list ap; + va_start(ap, format_string); + vfprintf(stderr, format_string, ap); + va_end(ap); + } + diff --git a/libgcobol/libgcobol.h b/libgcobol/libgcobol.h index 246ef51..2e338c2 100644 --- a/libgcobol/libgcobol.h +++ b/libgcobol/libgcobol.h @@ -39,6 +39,21 @@ Some are also called between source code modules in libgcobol, hence the need here for declarations. */ +extern void __gg__mabort(); + + +// The unnecessary abort() that follows is necessary to make cppcheck be +// aware that massert() actually terminates processing after a failed +// malloc(). +#define massert(p) if(!p){__gg__mabort();abort();} + +// This was part of an exercise to make cppcheck shut up about invalid +// pointer type conversions. +// It was also to avoid having reinterpret_cast<> all over the place. +// So, instead of reinterpret_cast<char *>(VALUE) +// I sometimes use PTRCAST(char, VALUE) +#define PTRCAST(TYPE, VALUE) static_cast<TYPE *>(static_cast<void *>(VALUE)) + extern "C" __int128 __gg__power_of_ten(int n); extern "C" __int128 __gg__dirty_to_binary_source( const char *dirty, @@ -67,7 +82,7 @@ extern "C" void __gg__int128_to_field(cblc_field_t *tgt, enum cbl_round_t rounded, int *compute_error); extern "C" void __gg__float128_to_field(cblc_field_t *tgt, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error); extern "C" void __gg__int128_to_qualified_field(cblc_field_t *tgt, @@ -79,10 +94,9 @@ extern "C" void __gg__int128_to_qualified_field(cblc_field_t *tgt, int *compute_error); extern "C" void __gg__float128_to_qualified_field(cblc_field_t *tgt, size_t tgt_offset, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error); - extern "C" void __gg__double_to_target( cblc_field_t *tgt, double tgt_value, cbl_round_t rounded); @@ -90,21 +104,31 @@ extern "C" char __gg__get_decimal_separator(); extern "C" char __gg__get_decimal_point(); extern "C" char * __gg__get_default_currency_string(); -extern "C" void __gg__clock_gettime(clockid_t clk_id, struct timespec *tp); -extern "C" _Float128 __gg__float128_from_location(cblc_field_t *var, - unsigned char *location); +struct cbl_timespec + { + /* You keep using that word "portability". I do not think it means what + you think it means. */ + time_t tv_sec; // Seconds. + long tv_nsec; // Nanoseconds. + } ; + +extern "C" void __gg__clock_gettime(struct cbl_timespec *tp); + +extern "C" GCOB_FP128 __gg__float128_from_location( + const cblc_field_t *var, + const unsigned char *location); extern "C" void __gg__adjust_dest_size(cblc_field_t *dest, size_t ncount); extern "C" void __gg__realloc_if_necessary( char **dest, size_t *dest_size, size_t new_size); -extern "C" void __gg__set_exception_file(cblc_file_t *file); +extern "C" void __gg__set_exception_file(const cblc_file_t *file); extern "C" void __gg__internal_to_console_in_place(char *loc, size_t length); -extern "C" __int128 __gg__binary_value_from_qualified_field(int *rdigits, - cblc_field_t *var, +extern "C" __int128 __gg__binary_value_from_qualified_field(int *rdigits, + const cblc_field_t *var, size_t offset, size_t size); -extern "C" _Float128 __gg__float128_from_qualified_field(cblc_field_t *field, +extern "C" GCOB_FP128 __gg__float128_from_qualified_field(const cblc_field_t *field, size_t offset, size_t size); extern "C" __int128 __gg__integer_from_qualified_field(cblc_field_t *var, diff --git a/libgcobol/libgcobol.spec.in b/libgcobol/libgcobol.spec.in index e8ccc0d..461587d 100644 --- a/libgcobol/libgcobol.spec.in +++ b/libgcobol/libgcobol.spec.in @@ -5,4 +5,4 @@ # %rename lib liborig -*lib: @LIBM@ %(liborig) +*lib: @LIBQUADSPEC@ @LIBM@ %(liborig) diff --git a/libgcobol/valconv.cc b/libgcobol/valconv.cc index 33d9a0d..aaa89f5 100644 --- a/libgcobol/valconv.cc +++ b/libgcobol/valconv.cc @@ -29,11 +29,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <ctype.h> -#include <stdio.h> -#include <string.h> +#include <cctype> +#include <cstdio> +#include <cstring> + #include <algorithm> #include <unordered_map> +#include <vector> #include "ec.h" #include "common-defs.h" @@ -67,9 +69,9 @@ __gg__realloc_if_necessary(char **dest, size_t *dest_size, size_t new_size) new_size |= new_size>>4; new_size |= new_size>>8; new_size |= new_size>>16; - new_size |= new_size>>32; + new_size |= (new_size>>16)>>16; *dest_size = new_size + 1; - *dest = (char *)realloc(*dest, *dest_size); + *dest = static_cast<char *>(realloc(*dest, *dest_size)); } } @@ -77,7 +79,7 @@ extern "C" void __gg__alphabet_create( cbl_encoding_t encoding, size_t alphabet_index, - unsigned char *alphabet, + const unsigned char *alphabet, int low_char, int high_char ) { @@ -220,7 +222,7 @@ Rindex(const char *dest, int length, char ch) extern "C" bool __gg__string_to_numeric_edited( char * const dest, - char *source, // In source characters + const char *source, // In source characters int rdigits, int is_negative, const char *picture) @@ -853,14 +855,14 @@ got_float: } else { - const char *decimal_location = index(dest, __gg__decimal_point); + const char *decimal_location = strchr(dest, __gg__decimal_point); if( !decimal_location ) { - decimal_location = index(dest, ascii_v); + decimal_location = strchr(dest, ascii_v); } if( !decimal_location ) { - decimal_location = index(dest, ascii_V); + decimal_location = strchr(dest, ascii_V); } if( !decimal_location ) { @@ -1220,9 +1222,9 @@ got_float: extern "C" void __gg__string_to_alpha_edited( char *dest, - char *source, + const char *source, int slength, - char *picture) + const char *picture) { // Put the PICTURE into the data area. If the caller didn't leave enough // room, well, poo on them. Said another way; if they specify disaster, diff --git a/libgcobol/valconv.h b/libgcobol/valconv.h index d907e6f..1efb2b9 100644 --- a/libgcobol/valconv.h +++ b/libgcobol/valconv.h @@ -60,18 +60,18 @@ extern "C" void __gg__realloc_if_necessary(char **dest, size_t *dest_size, size_t new_size); void __gg__alphabet_create(cbl_encoding_t encoding, size_t alphabet_index, - unsigned char *alphabet, + const unsigned char *alphabet, int low_char, int high_char ); bool __gg__string_to_numeric_edited(char * const dest, - char *source, // ASCII + const char *source, // ASCII int rdigits, int is_negative, const char *picture); void __gg__string_to_alpha_edited(char *dest, - char *source, + const char *source, int slength, - char *picture); + const char *picture); void __gg__currency_sign_init(); void __gg__currency_sign(int symbol, const char *sign); void __gg__remove_trailing_zeroes(char *p); |