diff options
| author | Paul Eggert | 2011-10-22 23:38:24 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-10-22 23:38:24 -0700 |
| commit | cfc09582247ffef6a46b6249e2fba9136a62d21e (patch) | |
| tree | 50e102f64a2b88c692d9110990abd416c78c32f0 /src/editfns.c | |
| parent | 92c938895c639463681ae1c58a944cae62b70b87 (diff) | |
| parent | 86c606818495d9411fd5d6b1477f9a097eb18020 (diff) | |
| download | emacs-cfc09582247ffef6a46b6249e2fba9136a62d21e.tar.gz emacs-cfc09582247ffef6a46b6249e2fba9136a62d21e.zip | |
Merge from trunk.
Diffstat (limited to 'src/editfns.c')
| -rw-r--r-- | src/editfns.c | 91 |
1 files changed, 40 insertions, 51 deletions
diff --git a/src/editfns.c b/src/editfns.c index b376c3a7c51..16e552afe1d 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -85,6 +85,8 @@ extern Lisp_Object w32_get_internal_run_time (void); | |||
| 85 | #endif | 85 | #endif |
| 86 | 86 | ||
| 87 | static void time_overflow (void) NO_RETURN; | 87 | static void time_overflow (void) NO_RETURN; |
| 88 | static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object, | ||
| 89 | int, time_t *, struct tm **); | ||
| 88 | static int tm_diff (struct tm *, struct tm *); | 90 | static int tm_diff (struct tm *, struct tm *); |
| 89 | static void update_buffer_properties (ptrdiff_t, ptrdiff_t); | 91 | static void update_buffer_properties (ptrdiff_t, ptrdiff_t); |
| 90 | 92 | ||
| @@ -1687,32 +1689,40 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". | |||
| 1687 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | 1689 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) |
| 1688 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) | 1690 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) |
| 1689 | { | 1691 | { |
| 1690 | time_t value; | 1692 | time_t t; |
| 1693 | struct tm *tm; | ||
| 1694 | |||
| 1695 | CHECK_STRING (format_string); | ||
| 1696 | format_string = code_convert_string_norecord (format_string, | ||
| 1697 | Vlocale_coding_system, 1); | ||
| 1698 | return format_time_string (SSDATA (format_string), SBYTES (format_string), | ||
| 1699 | timeval, ! NILP (universal), &t, &tm); | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | static Lisp_Object | ||
| 1703 | format_time_string (char const *format, ptrdiff_t formatlen, | ||
| 1704 | Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp) | ||
| 1705 | { | ||
| 1691 | ptrdiff_t size; | 1706 | ptrdiff_t size; |
| 1692 | int usec; | 1707 | int usec; |
| 1693 | int ns; | 1708 | int ns; |
| 1694 | struct tm *tm; | 1709 | struct tm *tm; |
| 1695 | int ut = ! NILP (universal); | ||
| 1696 | |||
| 1697 | CHECK_STRING (format_string); | ||
| 1698 | 1710 | ||
| 1699 | if (! lisp_time_argument (timeval, &value, &usec)) | 1711 | if (! lisp_time_argument (timeval, tval, &usec)) |
| 1700 | error ("Invalid time specification"); | 1712 | error ("Invalid time specification"); |
| 1701 | ns = usec * 1000; | 1713 | ns = usec * 1000; |
| 1702 | 1714 | ||
| 1703 | format_string = code_convert_string_norecord (format_string, | ||
| 1704 | Vlocale_coding_system, 1); | ||
| 1705 | |||
| 1706 | /* This is probably enough. */ | 1715 | /* This is probably enough. */ |
| 1707 | size = SBYTES (format_string); | 1716 | size = formatlen; |
| 1708 | if (size <= (STRING_BYTES_BOUND - 50) / 6) | 1717 | if (size <= (STRING_BYTES_BOUND - 50) / 6) |
| 1709 | size = size * 6 + 50; | 1718 | size = size * 6 + 50; |
| 1710 | 1719 | ||
| 1711 | BLOCK_INPUT; | 1720 | BLOCK_INPUT; |
| 1712 | tm = ut ? gmtime (&value) : localtime (&value); | 1721 | tm = ut ? gmtime (tval) : localtime (tval); |
| 1713 | UNBLOCK_INPUT; | 1722 | UNBLOCK_INPUT; |
| 1714 | if (! tm) | 1723 | if (! tm) |
| 1715 | time_overflow (); | 1724 | time_overflow (); |
| 1725 | *tmp = tm; | ||
| 1716 | 1726 | ||
| 1717 | synchronize_system_time_locale (); | 1727 | synchronize_system_time_locale (); |
| 1718 | 1728 | ||
| @@ -1723,9 +1733,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | |||
| 1723 | 1733 | ||
| 1724 | buf[0] = '\1'; | 1734 | buf[0] = '\1'; |
| 1725 | BLOCK_INPUT; | 1735 | BLOCK_INPUT; |
| 1726 | result = emacs_nmemftime (buf, size, SSDATA (format_string), | 1736 | result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns); |
| 1727 | SBYTES (format_string), | ||
| 1728 | tm, ut, ns); | ||
| 1729 | UNBLOCK_INPUT; | 1737 | UNBLOCK_INPUT; |
| 1730 | if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) | 1738 | if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) |
| 1731 | return code_convert_string_norecord (make_unibyte_string (buf, result), | 1739 | return code_convert_string_norecord (make_unibyte_string (buf, result), |
| @@ -1733,9 +1741,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | |||
| 1733 | 1741 | ||
| 1734 | /* If buffer was too small, make it bigger and try again. */ | 1742 | /* If buffer was too small, make it bigger and try again. */ |
| 1735 | BLOCK_INPUT; | 1743 | BLOCK_INPUT; |
| 1736 | result = emacs_nmemftime (NULL, (size_t) -1, | 1744 | result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen, |
| 1737 | SSDATA (format_string), | ||
| 1738 | SBYTES (format_string), | ||
| 1739 | tm, ut, ns); | 1745 | tm, ut, ns); |
| 1740 | UNBLOCK_INPUT; | 1746 | UNBLOCK_INPUT; |
| 1741 | if (STRING_BYTES_BOUND <= result) | 1747 | if (STRING_BYTES_BOUND <= result) |
| @@ -1983,51 +1989,34 @@ the data it can't find. */) | |||
| 1983 | { | 1989 | { |
| 1984 | time_t value; | 1990 | time_t value; |
| 1985 | struct tm *t; | 1991 | struct tm *t; |
| 1986 | struct tm gmt; | 1992 | struct tm localtm; |
| 1987 | 1993 | struct tm *localt; | |
| 1988 | if (!lisp_time_argument (specified_time, &value, NULL)) | 1994 | Lisp_Object zone_offset, zone_name; |
| 1989 | t = NULL; | 1995 | |
| 1990 | else | 1996 | zone_offset = Qnil; |
| 1991 | { | 1997 | zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time, |
| 1992 | BLOCK_INPUT; | 1998 | 0, &value, &localt); |
| 1993 | t = gmtime (&value); | 1999 | localtm = *localt; |
| 1994 | if (t) | 2000 | BLOCK_INPUT; |
| 1995 | { | 2001 | t = gmtime (&value); |
| 1996 | gmt = *t; | 2002 | UNBLOCK_INPUT; |
| 1997 | t = localtime (&value); | ||
| 1998 | } | ||
| 1999 | UNBLOCK_INPUT; | ||
| 2000 | } | ||
| 2001 | 2003 | ||
| 2002 | if (t) | 2004 | if (t) |
| 2003 | { | 2005 | { |
| 2004 | int offset = tm_diff (t, &gmt); | 2006 | int offset = tm_diff (&localtm, t); |
| 2005 | char *s = 0; | 2007 | zone_offset = make_number (offset); |
| 2006 | char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; | 2008 | if (SCHARS (zone_name) == 0) |
| 2007 | |||
| 2008 | #ifdef HAVE_TM_ZONE | ||
| 2009 | if (t->tm_zone) | ||
| 2010 | s = (char *)t->tm_zone; | ||
| 2011 | #else /* not HAVE_TM_ZONE */ | ||
| 2012 | #ifdef HAVE_TZNAME | ||
| 2013 | if (t->tm_isdst == 0 || t->tm_isdst == 1) | ||
| 2014 | s = tzname[t->tm_isdst]; | ||
| 2015 | #endif | ||
| 2016 | #endif /* not HAVE_TM_ZONE */ | ||
| 2017 | |||
| 2018 | if (!s) | ||
| 2019 | { | 2009 | { |
| 2020 | /* No local time zone name is available; use "+-NNNN" instead. */ | 2010 | /* No local time zone name is available; use "+-NNNN" instead. */ |
| 2021 | int m = offset / 60; | 2011 | int m = offset / 60; |
| 2022 | int am = offset < 0 ? - m : m; | 2012 | int am = offset < 0 ? - m : m; |
| 2013 | char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; | ||
| 2023 | sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); | 2014 | sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); |
| 2024 | s = buf; | 2015 | zone_name = build_string (buf); |
| 2025 | } | 2016 | } |
| 2026 | |||
| 2027 | return Fcons (make_number (offset), Fcons (build_string (s), Qnil)); | ||
| 2028 | } | 2017 | } |
| 2029 | else | 2018 | |
| 2030 | return Fmake_list (make_number (2), Qnil); | 2019 | return list2 (zone_offset, zone_name); |
| 2031 | } | 2020 | } |
| 2032 | 2021 | ||
| 2033 | /* This holds the value of `environ' produced by the previous | 2022 | /* This holds the value of `environ' produced by the previous |