From: Robert Dubner mailto:[email protected]
Date: Fri, 10 Jul 2026 14:47:11 -0400
Subject: [PATCH] cobol: Address endian issues.
There are on the order of four ways that endianness impacts the COBOL
front end
and the libgcobol.so library.
1) The COBOL BINARY data type is always big-endian; the COMP-5 data type
takes
on the endianness of the target architecture.
2) The options -fexec-charset and -fexec-national-charset specify the
character
sets used for DISPLAY and NATIONAL variables. Those can independently be
multi-byte little-endian or big-endian, and they are independent of the
endianness of the target architecture.
3) The host machine can be either big-e or little-e.
4) The target machine likewise.
We got this far with the compiler because I assumed -- without even
knowing I
was assuming -- the machine architectures were little-endian. So, when
tested
with single-byte-coded ASCII or EBCDIC, or with little-endian UTF-16LE and
UTF-32LE, I could get things working without too much trouble.
I am not going to attempt to detail the myriad ways my code didn't work
when
I specified "-fexec-charset=utf-16be". Nor am I going to describe what
happened when I first tried to create GCOBOL on a big-endian IBM System Z.
But that explains the size of this patch. With these changes, GCOBOL is
able
to handle "-fexec-charset=utf-16be" on the x86_64. With these changes
GCOBOL
is beginning to be able to handle single-byte-encoded ASCII or EBCDIC on
the
System Z.
gcc/cobol/ChangeLog:
* Make-lang.in: Copy charmaps.cc and valconv.cc without using SED
to
alter their contents.
* cbldiag.h (struct cbl_loc_t): Mollify cppcheck.
* compare.cc (alpha_compare_figconst): Endianness.
(alpha_compare): Endianness.
* genapi.cc (get_class_condition_string): Endianness.
(parser_statement_end): Fix initialization.
(initialize_variable_internal): Likewise.
(leave_section_internal): Likewise.
(parser_init_list): Likewise.
(parser_alphabet): Pass "cbl_alphabet_t *" instead of
"cbl_alphabet_t &"
(parser_alphabet_use): Likewise.
(program_end_stuff): Endianness.
(establish_using): Endianness; use out-of-band metadata to handle
passing intermediate_e variables BY VALUE.
(parser_trim): Endianness.
(parser_sort): Change call to parser_alphabet_use().
(parser_file_sort): Likewise.
(parser_file_merge): Likewise.
(create_and_call): Change handling of BY VALUE; handle RETURN-CODE
properly for dialects IBM, MF, and GNU.
(actually_create_the_static_field): Endianness.
(parser_symbol_add): Endianness.
* genapi.h (parser_alphabet): Change declaration.
(parser_alphabet_use): Likewise.
(parser_file_merge): Make a couple of formal parameters "const".
* genmath.cc: Incorporate cobol-endian.h.
* genutil.cc (binary_from_numdisp): Endianness.
(get_binary_value): Endianness.
(safe_cast): Prevent aliasing.
(safe_assign): New routine that extracts the binary value from a
numeric source, and assigns it to the target, converting as
necessary based on the target's TREE_TYPE.
* genutil.h (safe_assign): New declaration.
* messages.cc: Incorporate cobol-endian.h.
* move.cc (mh_source_is_literalN): Use streamlined, endian-safe
routines.
* parse.y: Incorporate cobol-endian.h; set big_endian_e for
FldNumericBin5 when the target machine is big-endian.
* parse_ante.h (mode_syntax_only): Formatting.
(struct prototype_type_t): Likewise.
(is_allowed_name): Likewise.
(prototype_args): Likewise.
(verify_args): Likewise.
(valid_pointer_relop): Likewise.
(blankit): Eliminate.
(cbl_field_t::blank_initial): Handle multi-byte characters.
(cbl_field_t::set_initial): Formatting.
(data_division_ready): Likewise.
(field_binary_usage): Likewise.
(ast_end_program): Likewise.
* parse_util.h (intrinsic_invalid_parameter): Eliminate FldIndex
as
an invalid parameter type.
* symbols.cc (symbols_alphabet_set): Remove FldIndex from list of
invalid types.
(cbl_alphabet_t::reencode): Handle big-endian multi-byte charsets.
(iconv_cd): Use helpful_iconv_open().
(symbol_label_add): Eliminate overwritten assignment.
* util.cc (cbl_field_t::encode_numeric): Handle big-endian
numeric-display values.
libgcobol/ChangeLog:
* charmaps.cc (defined): Use conditional compilation to locate .h
files; incorporate cobol-endian.h.
(__gg__iconverter): Conditional use of malloc/xmalloc.
(fixcode): Convert utf16 and utf32 to utf-16le/be and
utf-32le/based
on target endianness. Convert utf16le/be and utf32le/be to
utf-16le/be and utf-32le/be to accommodate FreeBSD, which has only
the hyphenated versions.
(helpful_iconv_open): Use fixcode();
(char_from_figconst): New routine.
* charmaps.h (CHARMAPS_H): Format comment.
(ascii_cr): New definition.
(ascii_lbrace): Likewise.
(ascii_rbrace): Likewise.
(ascii_newline): Likewise.
(ebcdic_return): Likewise.
(ebcdic_newline): Likewise.
(helpful_iconv_open): New declaration.
(DEFAULT_32_ENCODING): Change to...
(HOST_32_ENCODING): New constant, based on host endianness.
(error_msg_direct): Eliminate debugging comment.
(charmap_as_unsigned_chars): New utility.
(charmap_load_unaligned): Likewise.
(charmap_store_unaligned): Likewise.
(store_uint16): Likewise.
(store_uint32): Likewise.
(class cbl_iconv_t): Use helpful_iconv_open().
(class charmap_t): Endianness.
(char_from_figconst): New declaration.
* gfileio.cc (relative_file_delete): Endianness.
(relative_file_start): Endianness.
(relative_file_rewrite): Endianness.
(relative_file_write): Endianness.
(write_a_char): Endianness.
(sequential_file_write): Endianness.
(relative_file_read): Endianness.
* gmath.cc (__gg__pow): Formatting.
(uint128_lo64): Endianness.
(uint128_hi64): Endianness.
(uint128_from_limbs): Endianness.
(int256_get_u128): Endianness.
(int256_set_u128): Endianness.
(int256_is_negative): Endianness.
(int128_abs_as_uint128): Endianness.
(add_int256_to_int256): Endianness.
(negate_int256): Endianness.
(divide_int256_by_int64): Endianness.
(squeeze_int256): Endianness.
(get_int256_from_qualified_field): Endianness.
(__gg__add_fixed_phase1): Endianness.
(__gg__addf1_fixed_phase2): Endianness.
(__gg__fixed_phase2_assign_to_c): Endianness.
(__gg__add_float_phase1): Endianness.
(__gg__addf1_float_phase2): Endianness.
(__gg__addf3): Endianness.
(__gg__subtractf1_fixed_phase2): Endianness.
(__gg__subtractf2_fixed_phase1): Endianness.
(__gg__subtractf1_float_phase2): Endianness.
(__gg__subtractf2_float_phase1): Endianness.
(__gg__subtractf3): Endianness.
(__gg__multiplyf1_phase1): Endianness.
(multiply_int128_by_int128): Endianness.
(__gg__multiplyf1_phase2): Endianness.
(__gg__multiplyf2): Endianness.
(shift_in_place128): Endianness.
(int256_as_decimal): Endianness.
(clz_uint64): Endianness.
(defined): Endianness.
(shift_left_int256): Endianness.
(divide_int128_by_int128): Endianness.
(__gg__dividef1_phase2): Endianness.
(__gg__dividef23): Endianness.
(__gg__dividef45): Endianness.
* inspect.cc (as_chars): Endianness.
(funky_find): Endianness.
(funky_find_wide): Endianness.
(funky_find_wide_backward): Endianness.
(append_normalized_character): Endianness.
(normalize_id): Endianness.
(normalize_id_sbc): Endianness.
(the_alpha_and_omega): Endianness.
(the_alpha_and_omega_sbc): Endianness.
(the_alpha_and_omega_backward): Endianness.
(inspect_backward_format_1): Endianness.
(__gg__inspect_format_1): Endianness.
(inspect_backward_format_2): Endianness.
(__gg__inspect_format_2): Endianness.
(normalize_for_inspect_format_4): Endianness.
(__gg__inspect_format_4): Endianness.
* intrinsic.cc (as_chars): Endianness.
(xrealloc): Compile for both cobol1 and libgcobol.so.
(mconvert_to_c_string): Endianness.
(ensure_char_capacity): Endianness.
(struct input_state): Allocate buffers using the proper sizes.
(get_all_time): Endianness.
(__gg__char): Endianness.
(__gg__formatted_current_date): Endianness.
(__gg__formatted_date): Endianness.
(__gg__formatted_datetime): Endianness.
(__gg__formatted_time): Endianness.
(change_case): Endianness.
(__gg__median): Endianness.
(numval): Endianness.
(numval_c): Endianness.
(__gg__ord): Endianness.
(__gg__trim_a): Endianness.
(__gg__numval_f): Endianness.
(__gg__test_numval_f): Endianness.
(ismatch): Endianness.
(iscasematch): Endianness.
(strstr): Endianness.
(strcasestr): Endianness.
(strlaststr): Endianness.
(strcaselaststr): Endianness.
(__gg__substitute): Endianness.
(__gg__locale_date): Endianness.
(__gg__locale_time): Endianness.
* io.cc (__compat_file_status_word): Endianness.
* libgcobol.cc (as_chars): Endianness.
(as_unsigned_chars): Endianness.
(load_unaligned): Endianness.
(store_unaligned): Endianness.
(signed_int128_max): Endianness.
(checked_realloc): Endianness.
(collated): Endianness.
(edited_to_binary): Endianness.
(native_to_binary_signed): Endianness.
(native_to_binary_unsigned): Endianness.
(digit_rt): Endianness.
(num_disp_dive_rt): Endianness.
(numeric_display_to_binary): Endianness.
(get_binary_value_local): Endianness.
(__gg__power_of_ten): Endianness.
(value_is_too_big): Endianness.
(binary_to_big_endian): Endianness.
(binary_to_native_binary): Endianness.
(int128_to_field): Endianness.
(__gg__field_from_string): Endianness.
(field_from_ascii): Endianness.
(uber_compare): Endianness.
(__gg__dirty_to_binary): Endianness.
(get_scaled_rdigits): Endianness.
(format_for_display_internal): Endianness.
(compare_88): Endianness.
(get_float128): Endianness.
(__gg__compare_field_class): Endianness.
(compare_strings): Endianness.
(__gg__compare_2): Endianness.
(__gg__double_to_target): Endianness.
(__gg__sort_table): Endianness.
(init_var_both): Endianness.
(alpha_to_alpha_move_from_location): Endianness.
(alpha_to_alpha_move): Endianness.
(__gg__move): Endianness.
(__gg__move_literala): Endianness.
(__gg__sort_workfile): Endianness.
(__gg__merge_files): Endianness.
(move_string): Endianness.
(normalize_for_inspect_format_4): Endianness.
(__gg__string): Endianness.
(display_both): Endianness.
(__gg__float128_from_qualified_field): Endianness.
(float128_to_int128): Endianness.
(float128_to_location): Endianness.
(__gg__onetime_initialization): Endianness.
(is_numeric_display_numeric): Endianness.
(classify_alphabetic_type): Endianness.
(accept_envar): Endianness.
(__gg__set_envar): Endianness.
(command_line_plan_b): Endianness.
(__gg__get_command_line): Endianness.
(__gg__set_pointer): Endianness.
(__gg__alphabet_use): Formatting.
(__gg__fetch_call_by_value_value): Eliminate.
(__gg__unstring): Endianness.
(match_declarative): Formatting.
(default_exception_handler): Formatting.
(__gg__check_fatal_exception): Endianness.
(__gg__float128_from_location): Endianness.
(__gg__adjust_encoding): Endianness.
(__gg__func_exception_file): Endianness.
(__gg__is_float_infinite): Formatting.
(__gg__float32_from_128): Endianness.
(__gg__float32_from_64): Endianness.
(__gg__float64_from_128): Endianness.
(__gg__just_mangle_name): Endianness.
(__gg__function_handle_from_name): Proper initialization.
(__gg__variables_to_init): Likewise.
(__gg__mirror_range): Formatting.
(__gg__allocate): Formatting.
(__gg__module_name): Formatting.
(__gg__set_exception_environment): Formatting.
(__gg__set_env_name): Endianness.
(__gg__set_env_value): Endianness.
(__gg__refer_from_string): Endianness.
(__gg__refer_from_psz): Endianness.
(__gg__compare_string_all): Endianness.
(__gg__compare_string_1): Endianness.
(__gg__compare_string_1a): Endianness.
(__gg__compare_string_2): Endianness.
(__gg__compare_string_2a): Endianness.
(__gg__compare_string_4): Endianness.
(__gg__compare_string_4a): Endianness.
(__gg_compare_string_different): Endianness.
(__gg__compare_numeric_all): Endianness.
(__gg__compare_binary_to_string): Endianness.
* libgcobol.h (defined): Endianness.
(COBOL_BIG_ENDIAN): Endianness.
(COBOL_LITTLE_ENDIAN): Endianness.
* stringbin.cc (__gg__binary_to_string_encoded): Endianness.
(digit_rt): Support for num_disp_dive_rt().
(num_disp_dive_rt): Recurse conversion of numeric-display to
binary.
(__gg__numeric_display_to_binary): Use num_disp_dive_rt().
* stringbin.h (__gg__numeric_display_to_binary): Remove
declaration.
* valconv.cc (defined): Use IN_GCC_FRONTEND to find .h files;
incorporate cobol-endian.h.
(TOUPPER): Simple toupper() routine.
(__gg__string_to_numeric_edited): Use TOUPPER.
* cobol-endian.h: New file. Provides access to big-e versus
little-e variables and preprocessor definitions.
gcc/testsuite/ChangeLog:
* cobol.dg/group2/Assorted_SPECIAL-NAMES_CLASS.cob: Modified for
endian neutrality.
* cobol.dg/group2/Non-numeric_data_in_numeric_items__2_.out:
Likewise.
* cobol.dg/group2/FUNCTION_TRIM_with_NATIONAL_characters.cob:
Likewise.
* cobol.dg/group2/Hexadecimal_literal.cob: Likewise.
* cobol.dg/group2/PACKED-DECIMAL_basic_comp-3_comp-6__2_.cob:
Likewise.
* cobol.dg/group2/PACKED-DECIMAL_basic_comp-3_comp-6__2_.out:
Likewise.
* cobol.dg/group2/compare_national_to_display.cob: Likewise.
* cobol.dg/group2/Complex_HEX__VALUE_and_MOVE_-_UTF-16.cob:
Removed.
* cobol.dg/group2/Complex_HEX__VALUE_and_MOVE_-_UTF-16.out:
Removed.
* cobol.dg/group2/DISPLAY__Sign_ASCII.out: Removed.
* cobol.dg/group2/Non-numeric_data_in_numeric_items__2_.cob:
Removed.
* cobol.dg/group2/DISPLAY__Sign_ASCII.cob: Removed.
* cobol.dg/group2/BINARY_and_COMP-5__little-endian_.cob: New test.
* cobol.dg/group2/BINARY_and_COMP-5__little-endian_.out: New test.
* cobol.dg/group2/Checking_IS_NUMERIC.cob: New test.
* cobol.dg/group2/Checking_IS_NUMERIC.out: New test.
* cobol.dg/group2/Non-numeric_data_in_numeric-display__1_.cob: New
test.
* cobol.dg/group2/Non-numeric_data_in_packed_decimal.cob: New
test.
* cobol.dg/group2/Non-numeric_data_in_packed_decimal.out: New
test.
* cobol.dg/group2/Numeric-display_sign_encoding__2_.cob: New test.
* cobol.dg/group2/Numeric-display_sign_encoding__2_.out: New test.
* cobol.dg/group2/Numeric-display_sign_encoding_sanity_check.cob:
New test.
* cobol.dg/group2/Numeric-display_sign_encoding_sanity_check.out:
New test.
---
gcc/cobol/Make-lang.in | 4 +-
gcc/cobol/cbldiag.h | 3 +-
gcc/cobol/compare.cc | 30 +-
gcc/cobol/genapi.cc | 375 ++-
gcc/cobol/genapi.h | 8 +-
gcc/cobol/genmath.cc | 2 +
gcc/cobol/genutil.cc | 51 +-
gcc/cobol/genutil.h | 5 +
gcc/cobol/messages.cc | 2 +
gcc/cobol/move.cc | 58 +-
gcc/cobol/parse.y | 10 +
gcc/cobol/parse_ante.h | 90 +-
gcc/cobol/parse_util.h | 1 -
gcc/cobol/symbols.cc | 41 +-
gcc/cobol/util.cc | 76 +-
.../group2/Assorted_SPECIAL-NAMES_CLASS.cob | 2 +-
.../BINARY_and_COMP-5__little-endian_.cob | 158 ++
.../BINARY_and_COMP-5__little-endian_.out | 35 +
.../cobol.dg/group2/Checking_IS_NUMERIC.cob | 56 +
.../cobol.dg/group2/Checking_IS_NUMERIC.out | 7 +
.../Complex_HEX__VALUE_and_MOVE_-_UTF-16.cob | 93 -
.../Complex_HEX__VALUE_and_MOVE_-_UTF-16.out | 7 -
.../cobol.dg/group2/DISPLAY__Sign_ASCII.out | 12 -
...FUNCTION_TRIM_with_NATIONAL_characters.cob | 4 +-
.../cobol.dg/group2/Hexadecimal_literal.cob | 5 +-
...on-numeric_data_in_numeric-display__1_.cob | 27 +
...n-numeric_data_in_numeric-display__1_.out} | 0
.../Non-numeric_data_in_numeric_items__2_.cob | 23 -
.../Non-numeric_data_in_packed_decimal.cob | 22 +
.../Non-numeric_data_in_packed_decimal.out | 3 +
... => Numeric-display_sign_encoding__2_.cob} | 21 +-
.../Numeric-display_sign_encoding__2_.out | 17 +
...ric-display_sign_encoding_sanity_check.cob | 23 +
...ric-display_sign_encoding_sanity_check.out | 10 +
...PACKED-DECIMAL_basic_comp-3_comp-6__2_.cob | 46 +-
...PACKED-DECIMAL_basic_comp-3_comp-6__2_.out | 16 +-
...9_RT3586_-_Code_format_heuristic_fails.cob | 7 +
.../group2/RT3609_Unexpected_PROCESS.cob | 9 +
.../group2/compare_national_to_display.cob | 2 +-
libgcobol/charmaps.cc | 148 ++
libgcobol/charmaps.h | 494 ++--
libgcobol/cobol-endian.h | 89 +
libgcobol/gfileio.cc | 154 +-
libgcobol/gmath.cc | 812 +++----
libgcobol/inspect.cc | 477 ++--
libgcobol/intrinsic.cc | 401 ++--
libgcobol/io.cc | 50 +-
libgcobol/libgcobol.cc | 2034 ++++++++++++-----
libgcobol/libgcobol.h | 22 -
libgcobol/stringbin.cc | 99 +-
libgcobol/stringbin.h | 6 -
libgcobol/valconv.cc | 36 +-
52 files changed, 3917 insertions(+), 2266 deletions(-)
create mode 100644
gcc/testsuite/cobol.dg/group2/BINARY_and_COMP-5__little-endian_.cob
create mode 100644
gcc/testsuite/cobol.dg/group2/BINARY_and_COMP-5__little-endian_.out
create mode 100644 gcc/testsuite/cobol.dg/group2/Checking_IS_NUMERIC.cob
create mode 100644 gcc/testsuite/cobol.dg/group2/Checking_IS_NUMERIC.out
delete mode 100644
gcc/testsuite/cobol.dg/group2/Complex_HEX__VALUE_and_MOVE_-_UTF-16.cob
delete mode 100644
gcc/testsuite/cobol.dg/group2/Complex_HEX__VALUE_and_MOVE_-_UTF-16.out
delete mode 100644 gcc/testsuite/cobol.dg/group2/DISPLAY__Sign_ASCII.out
create mode 100644
gcc/testsuite/cobol.dg/group2/Non-numeric_data_in_numeric-display__1_.cob
rename
gcc/testsuite/cobol.dg/group2/{Non-numeric_data_in_numeric_items__2_.out
=> Non-numeric_data_in_numeric-display__1_.out} (100%)
delete mode 100644
gcc/testsuite/cobol.dg/group2/Non-numeric_data_in_numeric_items__2_.cob
create mode 100644
gcc/testsuite/cobol.dg/group2/Non-numeric_data_in_packed_decimal.cob
create mode 100644
gcc/testsuite/cobol.dg/group2/Non-numeric_data_in_packed_decimal.out
rename gcc/testsuite/cobol.dg/group2/{DISPLAY__Sign_ASCII.cob =>
Numeric-display_sign_encoding__2_.cob} (78%)
create mode 100644
gcc/testsuite/cobol.dg/group2/Numeric-display_sign_encoding__2_.out
create mode 100644
gcc/testsuite/cobol.dg/group2/Numeric-display_sign_encoding_sanity_check.c
ob
create mode 100644
gcc/testsuite/cobol.dg/group2/Numeric-display_sign_encoding_sanity_check.o
ut
create mode 100644
gcc/testsuite/cobol.dg/group2/PR59_RT3586_-_Code_format_heuristic_fails.co
b
create mode 100644
gcc/testsuite/cobol.dg/group2/RT3609_Unexpected_PROCESS.cob
create mode 100644 libgcobol/cobol-endian.h