Tested on x86_64 and aarch64 Linux and x86_64 darwin, OK for trunk? thanks Iain
This applies on top of https://gcc.gnu.org/pipermail/gcc-patches/2025-March/678927.html --- 8< --- We do not have a replacement at the moment, so fall back to using regular random and friends. PR cobol/119295 libgcobol/ChangeLog: * config.h.in: Regenerate. * configure: Regenerate. * configure.ac: Configure random_r and friends * intrinsic.cc (__gg__random): Use random_r when available. (__gg__random_next): Likewise. Signed-off-by: Iain Sandoe <i...@sandoe.co.uk> --- libgcobol/config.h.in | 12 +++++ libgcobol/configure | 105 ++++++++++++++++++++++++++++++++++++++++- libgcobol/configure.ac | 3 ++ libgcobol/intrinsic.cc | 25 ++++++++-- 4 files changed, 138 insertions(+), 7 deletions(-) diff --git a/libgcobol/config.h.in b/libgcobol/config.h.in index 14ebaeb2b26..e7e1492b579 100644 --- a/libgcobol/config.h.in +++ b/libgcobol/config.h.in @@ -9,6 +9,9 @@ /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV +/* Define to 1 if you have the `initstate_r' function. */ +#undef HAVE_INITSTATE_R + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H @@ -18,6 +21,15 @@ /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `random_r' function. */ +#undef HAVE_RANDOM_R + +/* Define to 1 if you have the `setstate_r' function. */ +#undef HAVE_SETSTATE_R + +/* Define to 1 if you have the `srandom_r' function. */ +#undef HAVE_SRANDOM_R + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H diff --git a/libgcobol/configure b/libgcobol/configure index ffbfebd96bf..0a6bafe265b 100755 --- a/libgcobol/configure +++ b/libgcobol/configure @@ -629,6 +629,7 @@ ac_includes_default="\ # include <unistd.h> #endif" +ac_func_list= ac_unique_file="Makefile.am" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE @@ -2337,6 +2338,76 @@ rm -f conftest.val as_fn_set_status $ac_retval } # ac_fn_cxx_compute_int + +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + 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 + 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. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext 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_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -2621,6 +2692,10 @@ $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi +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" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -11546,7 +11621,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11549 "configure" +#line 11624 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11652,7 +11727,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11655 "configure" +#line 11730 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17598,6 +17673,32 @@ case $host in esac +# These are GLIBC + + + + 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 + + + + + + + + + + + if test "${multilib}" = "yes"; then multilib_arg="--enable-multilib" else diff --git a/libgcobol/configure.ac b/libgcobol/configure.ac index 5ca7b12776d..7396a2e3527 100644 --- a/libgcobol/configure.ac +++ b/libgcobol/configure.ac @@ -195,6 +195,9 @@ case $host in esac AC_SUBST(extra_ldflags_libgcobol) +# These are GLIBC +AC_CHECK_FUNCS_ONCE(random_r srandom_r initstate_r setstate_r) + if test "${multilib}" = "yes"; then multilib_arg="--enable-multilib" else diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc index e3d255a29d6..b7e94f3b0d6 100644 --- a/libgcobol/intrinsic.cc +++ b/libgcobol/intrinsic.cc @@ -3408,9 +3408,13 @@ __gg__trim( cblc_field_t *dest, } } +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R static struct random_data *buf = NULL; static char *state = NULL; static const size_t state_len = 256; +#else +static unsigned seed = 0; +#endif extern "C" void @@ -3419,6 +3423,9 @@ __gg__random( cblc_field_t *dest, size_t input_offset, size_t input_size) { + int32_t retval_31; + int rdigits; +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R // This creates a thread-safe pseudo-random number generator // using input as the seed @@ -3435,16 +3442,21 @@ __gg__random( cblc_field_t *dest, __gg__clock_gettime(CLOCK_REALTIME, &ts); initstate_r( ts.tv_nsec, state, state_len, buf); } - - int rdigits; int seed = (int)__gg__binary_value_from_qualified_field(&rdigits, input, input_offset, input_size); srandom_r(seed, buf); - int32_t retval_31; random_r(buf, &retval_31); +#else + seed = (unsigned)__gg__binary_value_from_qualified_field(&rdigits, + input, + input_offset, + input_size); + srandom (seed); + retval_31 = random (); +#endif // We are going to convert this to a value between zero and not quite one: double retval = double(retval_31) / double(0x80000000UL); __gg__double_to_target( dest, @@ -3456,6 +3468,8 @@ extern "C" void __gg__random_next(cblc_field_t *dest) { + int32_t retval_31; +#if HAVE_INITSTATE_R && HAVE_SRANDOM_R && HAVE_RANDOM_R // The return value is between zero and not quite one if( !buf ) @@ -3468,9 +3482,10 @@ __gg__random_next(cblc_field_t *dest) __gg__clock_gettime(CLOCK_REALTIME, &ts); initstate_r( ts.tv_nsec, state, state_len, buf); } - int32_t retval_31; random_r(buf, &retval_31); - +#else + retval_31 = random (); +#endif // We are going to convert this to a value between zero and not quite one: double retval = double(retval_31) / double(0x80000000UL); __gg__double_to_target( dest, -- 2.39.2 (Apple Git-143)