Paul Eggert did:
> (set_tz, revert_tz): Declare, as they’re now extern.

This causes link errors on NetBSD 10 (caught by the CI):

gcc  -Wno-error -g -O2  -L/home/bruno/lib -L/usr/pkg/lib -o test-c-nstrftime 
test-c-nstrftime.o libtests.a ../gllib/libgnu.a libtests.a ../gllib/libgnu.a 
libtests.a   -lexecinfo -lm -lm -lm -lm -lm -lm  -lm -lm -lm -lm -lm
ld: ../gllib/libgnu.a(c-nstrftime.o): in function `__strftime_internal':
/home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1352: undefined 
reference to `revert_tz'
ld: /home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1340: undefined 
reference to `set_tz'
*** Error code 1 (continuing)

gcc  -Wno-error -g -O2  -L/home/bruno/lib -L/usr/pkg/lib -o test-nstrftime 
test-nstrftime.o libtests.a ../gllib/libgnu.a libtests.a ../gllib/libgnu.a 
libtests.a   -lexecinfo -lm -lm -lm -lm -lm -lm  -lm -lm -lm -lm -lm
ld: ../gllib/libgnu.a(nstrftime.o): in function `__strftime_internal':
/home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1340: undefined 
reference to `set_tz'
ld: /home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1352: undefined 
reference to `revert_tz'
*** Error code 1 (continuing)

gcc  -Wno-error -g -O2  -L/home/bruno/lib -L/usr/pkg/lib -o test-parse-datetime 
test-parse-datetime.o libtests.a ../gllib/libgnu.a libtests.a ../gllib/libgnu.a 
libtests.a    -lexecinfo -lm -lm -lm -lm -lm -lm  -lm -lm -lm -lm -lm
ld: ../gllib/libgnu.a(nstrftime.o): in function `__strftime_internal':
/home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1340: undefined 
reference to `set_tz'
ld: /home/bruno/testdir-all/build/gllib/../../gllib/strftime.c:1352: undefined 
reference to `revert_tz'
*** Error code 1 (continuing)

The cause is that
  - NetBSD 10 has timezone_t, therefore HAVE_TIMEZONE_T is 1,
  - therefore time_rz.c is not getting compiled,
  - part of time_rz.c is not needed to compile (tzalloc, tzfree, etc.),
    but other parts of time_rz.c (set_tz, revert_tz) *do* need to be
    compiled.

This patch fixes it.


2024-06-17  Bruno Haible  <br...@clisp.org>

        time_rz: Fix link errors on NetBSD (regression yesterday).
        * lib/time-internal.c: New file, extracted from lib/time_rz.c.
        (tzgetname): New function.
        * lib/time_rz.c (getenv_TZ, setenv_TZ, change_env, set_tz, revert_tz):
        Moved to lib/time-internal.c.
        * modules/time_rz (Files): Add lib/time-internal.c.
        (Depends-on): Update.
        (Makefile.am): Arrange to compile time-internal.c on all platforms.

diff --git a/lib/time-internal.c b/lib/time-internal.c
new file mode 100644
index 0000000000..dab67c762f
--- /dev/null
+++ b/lib/time-internal.c
@@ -0,0 +1,116 @@
+/* Time zone internal functions
+
+   Copyright 2015-2024 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   This file 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "flexmember.h"
+#include "time-internal.h"
+
+/* Get and set the TZ environment variable.  These functions can be
+   overridden by programs like Emacs that manage their own environment.  */
+
+#ifndef getenv_TZ
+static char *
+getenv_TZ (void)
+{
+  return getenv ("TZ");
+}
+#endif
+
+#ifndef setenv_TZ
+static int
+setenv_TZ (char const *tz)
+{
+  return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ");
+}
+#endif
+
+#if !HAVE_TIMEZONE_T
+static const char *
+tzgetname (timezone_t tz, int isdst)
+{
+  return tz->tz_is_set ? tz->abbrs : NULL;
+}
+#endif
+
+/* Change the environment to match the specified timezone_t value.
+   Return true if successful, false (setting errno) otherwise.  */
+static bool
+change_env (timezone_t tz)
+{
+  if (setenv_TZ (tzgetname (tz, 0)) != 0)
+    return false;
+  tzset ();
+  return true;
+}
+
+/* Temporarily set the time zone to TZ, which must not be null.
+   Return LOCAL_TZ if the time zone setting is already correct.
+   Otherwise return a newly allocated time zone representing the old
+   setting, or NULL (setting errno) on failure.  */
+timezone_t
+set_tz (timezone_t tz)
+{
+  char *env_tz = getenv_TZ ();
+  const char *tz_name = tzgetname (tz, 0);
+  if (env_tz
+      ? tz_name != NULL && strcmp (tz_name, env_tz) == 0
+      : tz_name == NULL)
+    return local_tz;
+  else
+    {
+      timezone_t old_tz = tzalloc (env_tz);
+      if (!old_tz)
+        return old_tz;
+      if (! change_env (tz))
+        {
+          int saved_errno = errno;
+          tzfree (old_tz);
+          errno = saved_errno;
+          return NULL;
+        }
+      return old_tz;
+    }
+}
+
+/* Restore an old setting returned by set_tz.  It must not be null.
+   Return true (preserving errno) if successful, false (setting errno)
+   otherwise.  */
+bool
+revert_tz (timezone_t tz)
+{
+  if (tz == local_tz)
+    return true;
+  else
+    {
+      int saved_errno = errno;
+      bool ok = change_env (tz);
+      if (!ok)
+        saved_errno = errno;
+      tzfree (tz);
+      errno = saved_errno;
+      return ok;
+    }
+}
diff --git a/lib/time_rz.c b/lib/time_rz.c
index a6523e1285..ab4ba61e28 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -138,84 +138,6 @@ tzfree (timezone_t tz)
       }
 }
 
-/* Get and set the TZ environment variable.  These functions can be
-   overridden by programs like Emacs that manage their own environment.  */
-
-#ifndef getenv_TZ
-static char *
-getenv_TZ (void)
-{
-  return getenv ("TZ");
-}
-#endif
-
-#ifndef setenv_TZ
-static int
-setenv_TZ (char const *tz)
-{
-  return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ");
-}
-#endif
-
-/* Change the environment to match the specified timezone_t value.
-   Return true if successful, false (setting errno) otherwise.  */
-static bool
-change_env (timezone_t tz)
-{
-  if (setenv_TZ (tz->tz_is_set ? tz->abbrs : NULL) != 0)
-    return false;
-  tzset ();
-  return true;
-}
-
-/* Temporarily set the time zone to TZ, which must not be null.
-   Return LOCAL_TZ if the time zone setting is already correct.
-   Otherwise return a newly allocated time zone representing the old
-   setting, or NULL (setting errno) on failure.  */
-timezone_t
-set_tz (timezone_t tz)
-{
-  char *env_tz = getenv_TZ ();
-  if (env_tz
-      ? tz->tz_is_set && strcmp (tz->abbrs, env_tz) == 0
-      : !tz->tz_is_set)
-    return local_tz;
-  else
-    {
-      timezone_t old_tz = tzalloc (env_tz);
-      if (!old_tz)
-        return old_tz;
-      if (! change_env (tz))
-        {
-          int saved_errno = errno;
-          tzfree (old_tz);
-          errno = saved_errno;
-          return NULL;
-        }
-      return old_tz;
-    }
-}
-
-/* Restore an old setting returned by set_tz.  It must not be null.
-   Return true (preserving errno) if successful, false (setting errno)
-   otherwise.  */
-bool
-revert_tz (timezone_t tz)
-{
-  if (tz == local_tz)
-    return true;
-  else
-    {
-      int saved_errno = errno;
-      bool ok = change_env (tz);
-      if (!ok)
-        saved_errno = errno;
-      tzfree (tz);
-      errno = saved_errno;
-      return ok;
-    }
-}
-
 /* Use time zone TZ to compute localtime_r (T, TM).  */
 struct tm *
 localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
diff --git a/modules/time_rz b/modules/time_rz
index f487e24c6b..aafc6fafe9 100644
--- a/modules/time_rz
+++ b/modules/time_rz
@@ -3,6 +3,7 @@ Reentrant time zone functions: localtime_rz, mktime_z, etc.
 
 Files:
 lib/time-internal.h
+lib/time-internal.c
 lib/time_rz.c
 m4/time_rz.m4
 
@@ -10,14 +11,14 @@ Depends-on:
 c99
 extensions
 time-h
-flexmember     [test $HAVE_TIMEZONE_T = 0]
+flexmember
+setenv
+stdbool
+tzset
+unsetenv
 idx            [test $HAVE_TIMEZONE_T = 0]
-setenv         [test $HAVE_TIMEZONE_T = 0]
-stdbool        [test $HAVE_TIMEZONE_T = 0]
 time_r         [test $HAVE_TIMEZONE_T = 0]
 timegm         [test $HAVE_TIMEZONE_T = 0]
-tzset          [test $HAVE_TIMEZONE_T = 0]
-unsetenv       [test $HAVE_TIMEZONE_T = 0]
 
 configure.ac:
 gl_TIME_RZ
@@ -25,6 +26,7 @@ gl_CONDITIONAL([GL_COND_OBJ_TIME_RZ], [test $HAVE_TIMEZONE_T 
= 0])
 gl_TIME_MODULE_INDICATOR([time_rz])
 
 Makefile.am:
+lib_SOURCES += time-internal.c
 if GL_COND_OBJ_TIME_RZ
 lib_SOURCES += time_rz.c
 endif




Reply via email to