diff options
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 5f89391ce22..83cd4bd5535 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 (EMACS_INT, EMACS_INT); | 91 | static void update_buffer_properties (EMACS_INT, EMACS_INT); |
| 90 | 92 | ||
| @@ -1700,33 +1702,41 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". | |||
| 1700 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | 1702 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) |
| 1701 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) | 1703 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) |
| 1702 | { | 1704 | { |
| 1703 | time_t value; | 1705 | time_t t; |
| 1706 | struct tm *tm; | ||
| 1707 | |||
| 1708 | CHECK_STRING (format_string); | ||
| 1709 | format_string = code_convert_string_norecord (format_string, | ||
| 1710 | Vlocale_coding_system, 1); | ||
| 1711 | return format_time_string (SSDATA (format_string), SBYTES (format_string), | ||
| 1712 | timeval, ! NILP (universal), &t, &tm); | ||
| 1713 | } | ||
| 1714 | |||
| 1715 | static Lisp_Object | ||
| 1716 | format_time_string (char const *format, ptrdiff_t formatlen, | ||
| 1717 | Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp) | ||
| 1718 | { | ||
| 1704 | ptrdiff_t size; | 1719 | ptrdiff_t size; |
| 1705 | int usec; | 1720 | int usec; |
| 1706 | int ns; | 1721 | int ns; |
| 1707 | struct tm *tm; | 1722 | struct tm *tm; |
| 1708 | int ut = ! NILP (universal); | ||
| 1709 | |||
| 1710 | CHECK_STRING (format_string); | ||
| 1711 | 1723 | ||
| 1712 | if (! (lisp_time_argument (timeval, &value, &usec) | 1724 | if (! (lisp_time_argument (timeval, tval, &usec) |
| 1713 | && 0 <= usec && usec < 1000000)) | 1725 | && 0 <= usec && usec < 1000000)) |
| 1714 | error ("Invalid time specification"); | 1726 | error ("Invalid time specification"); |
| 1715 | ns = usec * 1000; | 1727 | ns = usec * 1000; |
| 1716 | 1728 | ||
| 1717 | format_string = code_convert_string_norecord (format_string, | ||
| 1718 | Vlocale_coding_system, 1); | ||
| 1719 | |||
| 1720 | /* This is probably enough. */ | 1729 | /* This is probably enough. */ |
| 1721 | size = SBYTES (format_string); | 1730 | size = formatlen; |
| 1722 | if (size <= (STRING_BYTES_BOUND - 50) / 6) | 1731 | if (size <= (STRING_BYTES_BOUND - 50) / 6) |
| 1723 | size = size * 6 + 50; | 1732 | size = size * 6 + 50; |
| 1724 | 1733 | ||
| 1725 | BLOCK_INPUT; | 1734 | BLOCK_INPUT; |
| 1726 | tm = ut ? gmtime (&value) : localtime (&value); | 1735 | tm = ut ? gmtime (tval) : localtime (tval); |
| 1727 | UNBLOCK_INPUT; | 1736 | UNBLOCK_INPUT; |
| 1728 | if (! tm) | 1737 | if (! tm) |
| 1729 | time_overflow (); | 1738 | time_overflow (); |
| 1739 | *tmp = tm; | ||
| 1730 | 1740 | ||
| 1731 | synchronize_system_time_locale (); | 1741 | synchronize_system_time_locale (); |
| 1732 | 1742 | ||
| @@ -1737,9 +1747,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | |||
| 1737 | 1747 | ||
| 1738 | buf[0] = '\1'; | 1748 | buf[0] = '\1'; |
| 1739 | BLOCK_INPUT; | 1749 | BLOCK_INPUT; |
| 1740 | result = emacs_nmemftime (buf, size, SSDATA (format_string), | 1750 | result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns); |
| 1741 | SBYTES (format_string), | ||
| 1742 | tm, ut, ns); | ||
| 1743 | UNBLOCK_INPUT; | 1751 | UNBLOCK_INPUT; |
| 1744 | if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) | 1752 | if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) |
| 1745 | return code_convert_string_norecord (make_unibyte_string (buf, result), | 1753 | return code_convert_string_norecord (make_unibyte_string (buf, result), |
| @@ -1747,9 +1755,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | |||
| 1747 | 1755 | ||
| 1748 | /* If buffer was too small, make it bigger and try again. */ | 1756 | /* If buffer was too small, make it bigger and try again. */ |
| 1749 | BLOCK_INPUT; | 1757 | BLOCK_INPUT; |
| 1750 | result = emacs_nmemftime (NULL, (size_t) -1, | 1758 | result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen, |
| 1751 | SSDATA (format_string), | ||
| 1752 | SBYTES (format_string), | ||
| 1753 | tm, ut, ns); | 1759 | tm, ut, ns); |
| 1754 | UNBLOCK_INPUT; | 1760 | UNBLOCK_INPUT; |
| 1755 | if (STRING_BYTES_BOUND <= result) | 1761 | if (STRING_BYTES_BOUND <= result) |
| @@ -1994,51 +2000,34 @@ the data it can't find. */) | |||
| 1994 | { | 2000 | { |
| 1995 | time_t value; | 2001 | time_t value; |
| 1996 | struct tm *t; | 2002 | struct tm *t; |
| 1997 | struct tm gmt; | 2003 | struct tm localtm; |
| 1998 | 2004 | struct tm *localt; | |
| 1999 | if (!lisp_time_argument (specified_time, &value, NULL)) | 2005 | Lisp_Object zone_offset, zone_name; |
| 2000 | t = NULL; | 2006 | |
| 2001 | else | 2007 | zone_offset = Qnil; |
| 2002 | { | 2008 | zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time, |
| 2003 | BLOCK_INPUT; | 2009 | 0, &value, &localt); |
| 2004 | t = gmtime (&value); | 2010 | localtm = *localt; |
| 2005 | if (t) | 2011 | BLOCK_INPUT; |
| 2006 | { | 2012 | t = gmtime (&value); |
| 2007 | gmt = *t; | 2013 | UNBLOCK_INPUT; |
| 2008 | t = localtime (&value); | ||
| 2009 | } | ||
| 2010 | UNBLOCK_INPUT; | ||
| 2011 | } | ||
| 2012 | 2014 | ||
| 2013 | if (t) | 2015 | if (t) |
| 2014 | { | 2016 | { |
| 2015 | int offset = tm_diff (t, &gmt); | 2017 | int offset = tm_diff (&localtm, t); |
| 2016 | char *s = 0; | 2018 | zone_offset = make_number (offset); |
| 2017 | char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; | 2019 | if (SCHARS (zone_name) == 0) |
| 2018 | |||
| 2019 | #ifdef HAVE_TM_ZONE | ||
| 2020 | if (t->tm_zone) | ||
| 2021 | s = (char *)t->tm_zone; | ||
| 2022 | #else /* not HAVE_TM_ZONE */ | ||
| 2023 | #ifdef HAVE_TZNAME | ||
| 2024 | if (t->tm_isdst == 0 || t->tm_isdst == 1) | ||
| 2025 | s = tzname[t->tm_isdst]; | ||
| 2026 | #endif | ||
| 2027 | #endif /* not HAVE_TM_ZONE */ | ||
| 2028 | |||
| 2029 | if (!s) | ||
| 2030 | { | 2020 | { |
| 2031 | /* No local time zone name is available; use "+-NNNN" instead. */ | 2021 | /* No local time zone name is available; use "+-NNNN" instead. */ |
| 2032 | int m = offset / 60; | 2022 | int m = offset / 60; |
| 2033 | int am = offset < 0 ? - m : m; | 2023 | int am = offset < 0 ? - m : m; |
| 2024 | char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; | ||
| 2034 | sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); | 2025 | sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); |
| 2035 | s = buf; | 2026 | zone_name = build_string (buf); |
| 2036 | } | 2027 | } |
| 2037 | |||
| 2038 | return Fcons (make_number (offset), Fcons (build_string (s), Qnil)); | ||
| 2039 | } | 2028 | } |
| 2040 | else | 2029 | |
| 2041 | return Fmake_list (make_number (2), Qnil); | 2030 | return list2 (zone_offset, zone_name); |
| 2042 | } | 2031 | } |
| 2043 | 2032 | ||
| 2044 | /* This holds the value of `environ' produced by the previous | 2033 | /* This holds the value of `environ' produced by the previous |