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)

Reply via email to