Hello! I'm planning to use Gnulib's `strftime' module on `master' to fix portability problems related to `strftime', aka. #24130 (https://savannah.gnu.org/bugs/?24130). The good thing is that `strftime' will now work the same regardless of the underlying libc.
The source modification is attached. For a discussion of `nstrftime ()', see http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/14380 . Please let me know if you think of a good reason to not do this, otherwise I'll commit it within a week or so. Thanks, Ludo'.
>From 69f23174d313650ca8fb0f69ede45c48d7a26b05 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Ludovic=20Court=C3=A8s?= <[EMAIL PROTECTED]> Date: Tue, 2 Sep 2008 21:24:53 +0200 Subject: [PATCH] Use Gnulib's `strftime' to address bug #24130. * libguile/stime.c (scm_strftime): Use `nstrftime ()' from Gnulib. This provides the same semantics on all platforms, thereby fixing bug #24130. * doc/ref/posix.texi (Time): Remove note about non-portable `%Z' behavior. Describe the new, portable behavior. * test-suite/tests/time.test ("strftime")["strftime %Z doesn't return garbage"]: Reinstate. ["C99 %z format"](have-strftime-%z): Remove. ("GMT", "EST+5"): Don't use `have-strftime-%z'. --- doc/ref/posix.texi | 25 +++---------------------- libguile/stime.c | 8 ++++---- test-suite/tests/time.test | 40 +++++++--------------------------------- 3 files changed, 14 insertions(+), 59 deletions(-) diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi index 34194fb..a91bdb9 100644 --- a/doc/ref/posix.texi +++ b/doc/ref/posix.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. [EMAIL PROTECTED] Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007 [EMAIL PROTECTED] Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -1264,27 +1264,8 @@ formatting. If @code{setlocale} has been called (@pxref{Locales}), month and day names are from the current locale and in the locale character set. -Note that @samp{%Z} might print the @code{tm:zone} in @var{tm} or it -might print just the current zone (@code{tzset} above). A GNU system -prints @code{tm:zone}, a strict C99 system like NetBSD prints the -current zone. Perhaps in the future Guile will try to get [EMAIL PROTECTED]:zone} used always. [EMAIL PROTECTED] [EMAIL PROTECTED] The issue in the above is not just whether tm_zone exists in [EMAIL PROTECTED] struct tm, but whether libc feels it should read it. Being a [EMAIL PROTECTED] non-C99 field, a strict C99 program won't know to set it, quite [EMAIL PROTECTED] likely leaving garbage there. NetBSD, which has the field, [EMAIL PROTECTED] therefore takes the view that it mustn't read it. See the PR [EMAIL PROTECTED] about this at [EMAIL PROTECTED] [EMAIL PROTECTED] http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=21722 [EMAIL PROTECTED] [EMAIL PROTECTED] Uniformly making tm:zone used on all systems (all those which have [EMAIL PROTECTED] %Z at all of course) might be nice (either mung TZ and tzset, or [EMAIL PROTECTED] mung tzname[]). On the other hand it would make us do more than [EMAIL PROTECTED] C99 says, and we really don't want to get intimate with the gory [EMAIL PROTECTED] details of libc time funcs, no more than can be helped. [EMAIL PROTECTED] +Note that @samp{%Z} always ignores the @code{tm:zone} in @var{tm}; +instead it prints just the current zone (@code{tzset} above). @end deffn @deffn {Scheme Procedure} strptime format string diff --git a/libguile/stime.c b/libguile/stime.c index fa8b585..be5bf65 100644 --- a/libguile/stime.c +++ b/libguile/stime.c @@ -44,6 +44,7 @@ #include <stdio.h> #include <errno.h> +#include <strftime.h> #include "libguile/_scm.h" #include "libguile/async.h" @@ -689,10 +690,9 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0, tzset (); #endif - /* POSIX says strftime returns 0 on buffer overrun, but old - systems (i.e. libc 4 on GNU/Linux) might return `size' in that - case. */ - while ((len = strftime (tbuf, size, myfmt, &t)) == 0 || len == size) + /* Use `nstrftime ()' from Gnulib, which supports all GNU extensions + supported by glibc. */ + while ((len = nstrftime (tbuf, size, myfmt, &t, 0, 0)) == 0) { free (tbuf); size *= 2; diff --git a/test-suite/tests/time.test b/test-suite/tests/time.test index ebc4499..d5639eb 100644 --- a/test-suite/tests/time.test +++ b/test-suite/tests/time.test @@ -1,7 +1,7 @@ ;;;; time.test --- test suite for Guile's time functions -*- scheme -*- ;;;; Jim Blandy <[EMAIL PROTECTED]> --- June 1999, 2004 ;;;; -;;;; Copyright (C) 1999, 2004, 2006, 2007 Free Software Foundation, Inc. +;;;; Copyright (C) 1999, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. ;;;; ;;;; This program is free software; you can redistribute it and/or modify ;;;; it under the terms of the GNU General Public License as published by @@ -196,44 +196,19 @@ (with-test-prefix "strftime" - ;; Note we must force isdst to get the ZOW zone name out of %Z on HP-UX. - ;; If localtime is in daylight savings then it will decide there's no - ;; daylight savings zone name for the fake ZOW, and come back empty. - ;; - ;; This test is disabled because on NetBSD %Z doesn't look at the tm_zone - ;; field in struct tm passed by guile. That behaviour is reasonable - ;; enough since that field is not in C99 so a C99 program won't know it - ;; has to be set. For the details on that see - ;; - ;; http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=21722 - ;; - ;; Not sure what to do about this in guile, it'd be nice for %Z to look at - ;; tm:zone everywhere. - ;; - ;; - ;; (pass-if "strftime %Z doesn't return garbage" - ;; (let ((t (localtime (current-time)))) - ;; (set-tm:zone t "ZOW") - ;; (set-tm:isdst t 0) - ;; (string=? (strftime "%Z" t) - ;; "ZOW"))) + (pass-if "strftime %Z doesn't return garbage" + (let ((t (localtime (current-time)))) + (set-tm:zone t "ZOW") + (set-tm:isdst t 0) + (string=? (strftime "%Z" t) + "ZOW"))) (with-test-prefix "C99 %z format" - ;; C99 spec is empty string if no zone determinable - ;; - ;; on pre-C99 systems not sure what to expect if %z unsupported, probably - ;; "%z" unchanged in C99 if timezone - ;; - (define have-strftime-%z - (not (member (strftime "%z" (gmtime 0)) - '("" "%z")))) - ;; %z here is quite possibly affected by the same tm:gmtoff vs current ;; zone as %Z above is, so in the following tests we make them the same. (pass-if "GMT" - (or have-strftime-%z (throw 'unsupported)) (putenv "TZ=GMT+0") (tzset) (let ((tm (localtime 86400))) @@ -243,7 +218,6 @@ ;; because we didn't adjust for tm:gmtoff being west of Greenwich versus ;; tm_gmtoff being east of Greenwich (pass-if "EST+5" - (or have-strftime-%z (throw 'unsupported)) (putenv "TZ=EST+5") (tzset) (let ((tm (localtime 86400))) -- 1.6.0