]> git.eshelyaron.com Git - emacs.git/commitdiff
Time zone name fixes for non-ASCII locales (Bug#641, Bug#9794)
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Oct 2011 06:52:55 +0000 (23:52 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Oct 2011 06:52:55 +0000 (23:52 -0700)
* configure.in (AC_STRUCT_TM, AC_STRUCT_TIMEZONE, HAVE_TM_GMTOFF):
Remove; no longer needed, now that we defer to strftime for time
zone names.
* src/editfns.c: Rewrite current-time-zone so that it invokes
the equivalent of (format-time-string "%Z") to get the time zone name.
This fixes a bug when the time zone name contains characters that
need converting from the system time locale to Emacs internal format.
This fixes a shortcoming that I introduced in my 1999-10-19 patch:
that patch fixed format-time-string to do the conversion, but
I forgot to fix current-time-zone.
(format_time_string): New function, containing most of
what Fformat_time_string used to contain.
(Fformat_time_string): Rewrite in terms of format_time_string.
This doesn't change this function's behavior.
(current-time-zone): Rewrite to use format_time_string.
This fixes the bug reported by Michael Schierl in
<http://lists.gnu.org/archive/html/emacs-devel/2007-06/msg00334.html>.
Jason Rumney's 2007-06-07 change worked around this bug, but
didn't fix it.
* src/systime.h (tzname, timezone): Remove no-longer-used declarations.

ChangeLog
configure.in
src/ChangeLog
src/editfns.c
src/systime.h

index 6147b1131fe2296230473f89dcc79d58c4766f74..9b9a7176b05d2015e8340c69a1ff90d2b7f44831 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-20  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Time zone name fixes for non-ASCII locales (Bug#641, Bug#9794)
+       * configure.in (AC_STRUCT_TM, AC_STRUCT_TIMEZONE, HAVE_TM_GMTOFF):
+       Remove; no longer needed, now that we defer to strftime for time
+       zone names.
+
 2011-10-18  Jan Djärv  <jan.h.d@swipnet.se>
 
        * configure.in (GLIB_REQUIRED, GTK_REQUIRED): Set to 2.10 (Bug#9786).
index 4a5788600c8ab282c665bb919e2f4f6ec4586e67..5b32e10853f3161f217f06965e36df708dee8ad8 100644 (file)
@@ -1315,12 +1315,6 @@ AC_CHECK_HEADERS(net/if_dl.h, , , [AC_INCLUDES_DEFAULT
 AC_CHECK_FUNCS(getifaddrs freeifaddrs)
 
 dnl checks for structure members
-AC_STRUCT_TM
-AC_STRUCT_TIMEZONE
-AC_CHECK_MEMBER(struct tm.tm_gmtoff,
-               [AC_DEFINE(HAVE_TM_GMTOFF, 1,
-                          [Define to 1 if `tm_gmtoff' is member of `struct tm'.])],,
-               [#include <time.h>])
 AC_CHECK_MEMBERS([struct ifreq.ifr_flags, struct ifreq.ifr_hwaddr,
                  struct ifreq.ifr_netmask, struct ifreq.ifr_broadaddr,
                  struct ifreq.ifr_addr,
index c6a23a773de77e9502be60ad35679448c0d1027d..36b205a120d4505d08551263050919183d8f09c8 100644 (file)
@@ -1,3 +1,24 @@
+2011-10-20  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Time zone name fixes for non-ASCII locales (Bug#641, Bug#9794)
+       * editfns.c: Rewrite current-time-zone so that it invokes
+       the equivalent of (format-time-string "%Z") to get the time zone name.
+       This fixes a bug when the time zone name contains characters that
+       need converting from the system time locale to Emacs internal format.
+       This fixes a shortcoming that I introduced in my 1999-10-19 patch:
+       that patch fixed format-time-string to do the conversion, but
+       I forgot to fix current-time-zone.
+       (format_time_string): New function, containing most of
+       what Fformat_time_string used to contain.
+       (Fformat_time_string): Rewrite in terms of format_time_string.
+       This doesn't change this function's behavior.
+       (current-time-zone): Rewrite to use format_time_string.
+       This fixes the bug reported by Michael Schierl in
+       <http://lists.gnu.org/archive/html/emacs-devel/2007-06/msg00334.html>.
+       Jason Rumney's 2007-06-07 change worked around this bug, but
+       didn't fix it.
+       * systime.h (tzname, timezone): Remove no-longer-used declarations.
+
 2011-10-19  Eli Zaretskii  <eliz@gnu.org>
 
        * xdisp.c (start_display): If the character at POS is displayed
index 5f89391ce2286e6a9cf369fd0cd4939971fdbbd4..83cd4bd55359358fad7339a93d873bff68ded493 100644 (file)
@@ -85,6 +85,8 @@ extern Lisp_Object w32_get_internal_run_time (void);
 #endif
 
 static void time_overflow (void) NO_RETURN;
+static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object,
+                                      int, time_t *, struct tm **);
 static int tm_diff (struct tm *, struct tm *);
 static void update_buffer_properties (EMACS_INT, EMACS_INT);
 
@@ -1700,33 +1702,41 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".
 usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
   (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
 {
-  time_t value;
+  time_t t;
+  struct tm *tm;
+
+  CHECK_STRING (format_string);
+  format_string = code_convert_string_norecord (format_string,
+                                               Vlocale_coding_system, 1);
+  return format_time_string (SSDATA (format_string), SBYTES (format_string),
+                            timeval, ! NILP (universal), &t, &tm);
+}
+
+static Lisp_Object
+format_time_string (char const *format, ptrdiff_t formatlen,
+                   Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp)
+{
   ptrdiff_t size;
   int usec;
   int ns;
   struct tm *tm;
-  int ut = ! NILP (universal);
-
-  CHECK_STRING (format_string);
 
-  if (! (lisp_time_argument (timeval, &value, &usec)
+  if (! (lisp_time_argument (timeval, tval, &usec)
         && 0 <= usec && usec < 1000000))
     error ("Invalid time specification");
   ns = usec * 1000;
 
-  format_string = code_convert_string_norecord (format_string,
-                                               Vlocale_coding_system, 1);
-
   /* This is probably enough.  */
-  size = SBYTES (format_string);
+  size = formatlen;
   if (size <= (STRING_BYTES_BOUND - 50) / 6)
     size = size * 6 + 50;
 
   BLOCK_INPUT;
-  tm = ut ? gmtime (&value) : localtime (&value);
+  tm = ut ? gmtime (tval) : localtime (tval);
   UNBLOCK_INPUT;
   if (! tm)
     time_overflow ();
+  *tmp = tm;
 
   synchronize_system_time_locale ();
 
@@ -1737,9 +1747,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
 
       buf[0] = '\1';
       BLOCK_INPUT;
-      result = emacs_nmemftime (buf, size, SSDATA (format_string),
-                               SBYTES (format_string),
-                               tm, ut, ns);
+      result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns);
       UNBLOCK_INPUT;
       if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
        return code_convert_string_norecord (make_unibyte_string (buf, result),
@@ -1747,9 +1755,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
 
       /* If buffer was too small, make it bigger and try again.  */
       BLOCK_INPUT;
-      result = emacs_nmemftime (NULL, (size_t) -1,
-                               SSDATA (format_string),
-                               SBYTES (format_string),
+      result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen,
                                tm, ut, ns);
       UNBLOCK_INPUT;
       if (STRING_BYTES_BOUND <= result)
@@ -1994,51 +2000,34 @@ the data it can't find.  */)
 {
   time_t value;
   struct tm *t;
-  struct tm gmt;
-
-  if (!lisp_time_argument (specified_time, &value, NULL))
-    t = NULL;
-  else
-    {
-      BLOCK_INPUT;
-      t = gmtime (&value);
-      if (t)
-       {
-         gmt = *t;
-         t = localtime (&value);
-       }
-      UNBLOCK_INPUT;
-    }
+  struct tm localtm;
+  struct tm *localt;
+  Lisp_Object zone_offset, zone_name;
+
+  zone_offset = Qnil;
+  zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time,
+                                 0, &value, &localt);
+  localtm = *localt;
+  BLOCK_INPUT;
+  t = gmtime (&value);
+  UNBLOCK_INPUT;
 
   if (t)
     {
-      int offset = tm_diff (t, &gmt);
-      char *s = 0;
-      char buf[sizeof "+00" + INT_STRLEN_BOUND (int)];
-
-#ifdef HAVE_TM_ZONE
-      if (t->tm_zone)
-       s = (char *)t->tm_zone;
-#else /* not HAVE_TM_ZONE */
-#ifdef HAVE_TZNAME
-      if (t->tm_isdst == 0 || t->tm_isdst == 1)
-       s = tzname[t->tm_isdst];
-#endif
-#endif /* not HAVE_TM_ZONE */
-
-      if (!s)
+      int offset = tm_diff (&localtm, t);
+      zone_offset = make_number (offset);
+      if (SCHARS (zone_name) == 0)
        {
          /* No local time zone name is available; use "+-NNNN" instead.  */
          int m = offset / 60;
          int am = offset < 0 ? - m : m;
+         char buf[sizeof "+00" + INT_STRLEN_BOUND (int)];
          sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
-         s = buf;
+         zone_name = build_string (buf);
        }
-
-      return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
     }
-  else
-    return Fmake_list (make_number (2), Qnil);
+
+  return list2 (zone_offset, zone_name);
 }
 
 /* This holds the value of `environ' produced by the previous
index bed9ed4aa7178374d74d575864d9e37b2af9cc91..b90372dbe2043031d238d918a98d35aba42cafea 100644 (file)
@@ -38,17 +38,6 @@ typedef unsigned long Time;
 # endif
 #endif
 
-#ifdef HAVE_TZNAME
-#ifndef tzname         /* For SGI.  */
-extern char *tzname[]; /* RS6000 and others want it this way.  */
-#endif
-#endif
-
-/* SVr4 doesn't actually declare this in its #include files.  */
-#ifdef USG5_4
-extern time_t timezone;
-#endif
-
 /* On some configurations (hpux8.0, X11R4), sys/time.h and X11/Xos.h
    disagree about the name of the guard symbol.  */
 #ifdef HPUX