aboutsummaryrefslogtreecommitdiffstats
path: root/src/editfns.c
diff options
context:
space:
mode:
authorPaul Eggert2012-05-25 11:19:24 -0700
committerPaul Eggert2012-05-25 11:19:24 -0700
commit42b2a986d9d4b7040fb20c90ec0efeffb78e761a (patch)
treed38e7bf5307837f2f38982757f088100de18a64e /src/editfns.c
parente4d81efc58695c19154d5f6733d91172b4c3e5b7 (diff)
parenta8d3cbf75d219d7a249fc0623219511179e959da (diff)
downloademacs-42b2a986d9d4b7040fb20c90ec0efeffb78e761a.tar.gz
emacs-42b2a986d9d4b7040fb20c90ec0efeffb78e761a.zip
Merge from trunk.
Diffstat (limited to 'src/editfns.c')
-rw-r--r--src/editfns.c168
1 files changed, 90 insertions, 78 deletions
diff --git a/src/editfns.c b/src/editfns.c
index 7e7f82c5992..6d59b89513c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -59,10 +59,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
59#include "window.h" 59#include "window.h"
60#include "blockinput.h" 60#include "blockinput.h"
61 61
62#ifndef NULL
63#define NULL 0
64#endif
65
66#ifndef USER_FULL_NAME 62#ifndef USER_FULL_NAME
67#define USER_FULL_NAME pw->pw_gecos 63#define USER_FULL_NAME pw->pw_gecos
68#endif 64#endif
@@ -73,20 +69,13 @@ extern char **environ;
73 69
74#define TM_YEAR_BASE 1900 70#define TM_YEAR_BASE 1900
75 71
76/* Nonzero if TM_YEAR is a struct tm's tm_year value that causes
77 asctime to have well-defined behavior. */
78#ifndef TM_YEAR_IN_ASCTIME_RANGE
79# define TM_YEAR_IN_ASCTIME_RANGE(tm_year) \
80 (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE)
81#endif
82
83#ifdef WINDOWSNT 72#ifdef WINDOWSNT
84extern Lisp_Object w32_get_internal_run_time (void); 73extern Lisp_Object w32_get_internal_run_time (void);
85#endif 74#endif
86 75
87static void time_overflow (void) NO_RETURN; 76static void time_overflow (void) NO_RETURN;
88static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object, 77static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object,
89 int, time_t *, struct tm **); 78 int, time_t *, struct tm *);
90static int tm_diff (struct tm *, struct tm *); 79static int tm_diff (struct tm *, struct tm *);
91static void update_buffer_properties (ptrdiff_t, ptrdiff_t); 80static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
92 81
@@ -1691,7 +1680,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
1691 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) 1680 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
1692{ 1681{
1693 time_t t; 1682 time_t t;
1694 struct tm *tm; 1683 struct tm tm;
1695 1684
1696 CHECK_STRING (format_string); 1685 CHECK_STRING (format_string);
1697 format_string = code_convert_string_norecord (format_string, 1686 format_string = code_convert_string_norecord (format_string,
@@ -1702,53 +1691,54 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
1702 1691
1703static Lisp_Object 1692static Lisp_Object
1704format_time_string (char const *format, ptrdiff_t formatlen, 1693format_time_string (char const *format, ptrdiff_t formatlen,
1705 Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp) 1694 Lisp_Object timeval, int ut, time_t *tval, struct tm *tmp)
1706{ 1695{
1707 ptrdiff_t size; 1696 char buffer[4000];
1697 char *buf = buffer;
1698 size_t size = sizeof buffer;
1699 size_t len;
1700 Lisp_Object bufstring;
1708 int usec; 1701 int usec;
1709 int ns; 1702 int ns;
1710 struct tm *tm; 1703 struct tm *tm;
1704 USE_SAFE_ALLOCA;
1711 1705
1712 if (! lisp_time_argument (timeval, tval, &usec)) 1706 if (! lisp_time_argument (timeval, tval, &usec))
1713 error ("Invalid time specification"); 1707 error ("Invalid time specification");
1714 ns = usec * 1000; 1708 ns = usec * 1000;
1715 1709
1716 /* This is probably enough. */
1717 size = formatlen;
1718 if (size <= (STRING_BYTES_BOUND - 50) / 6)
1719 size = size * 6 + 50;
1720
1721 BLOCK_INPUT;
1722 tm = ut ? gmtime (tval) : localtime (tval);
1723 UNBLOCK_INPUT;
1724 if (! tm)
1725 time_overflow ();
1726 *tmp = tm;
1727
1728 synchronize_system_time_locale ();
1729
1730 while (1) 1710 while (1)
1731 { 1711 {
1732 char *buf = (char *) alloca (size + 1); 1712 BLOCK_INPUT;
1733 size_t result; 1713
1714 synchronize_system_time_locale ();
1715
1716 tm = ut ? gmtime (tval) : localtime (tval);
1717 if (! tm)
1718 {
1719 UNBLOCK_INPUT;
1720 time_overflow ();
1721 }
1722 *tmp = *tm;
1734 1723
1735 buf[0] = '\1'; 1724 buf[0] = '\1';
1736 BLOCK_INPUT; 1725 len = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns);
1737 result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns); 1726 if ((0 < len && len < size) || (len == 0 && buf[0] == '\0'))
1738 UNBLOCK_INPUT; 1727 break;
1739 if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
1740 return code_convert_string_norecord (make_unibyte_string (buf, result),
1741 Vlocale_coding_system, 0);
1742 1728
1743 /* If buffer was too small, make it bigger and try again. */ 1729 /* Buffer was too small, so make it bigger and try again. */
1744 BLOCK_INPUT; 1730 len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tm, ut, ns);
1745 result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen,
1746 tm, ut, ns);
1747 UNBLOCK_INPUT; 1731 UNBLOCK_INPUT;
1748 if (STRING_BYTES_BOUND <= result) 1732 if (STRING_BYTES_BOUND <= len)
1749 string_overflow (); 1733 string_overflow ();
1750 size = result + 1; 1734 size = len + 1;
1735 SAFE_ALLOCA (buf, char *, size);
1751 } 1736 }
1737
1738 UNBLOCK_INPUT;
1739 bufstring = make_unibyte_string (buf, len);
1740 SAFE_FREE ();
1741 return code_convert_string_norecord (bufstring, Vlocale_coding_system, 0);
1752} 1742}
1753 1743
1754DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0, 1744DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
@@ -1778,31 +1768,32 @@ DOW and ZONE.) */)
1778 1768
1779 BLOCK_INPUT; 1769 BLOCK_INPUT;
1780 decoded_time = localtime (&time_spec); 1770 decoded_time = localtime (&time_spec);
1771 /* Make a copy, in case a signal handler modifies TZ or the struct. */
1772 if (decoded_time)
1773 save_tm = *decoded_time;
1781 UNBLOCK_INPUT; 1774 UNBLOCK_INPUT;
1782 if (! (decoded_time 1775 if (! (decoded_time
1783 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= decoded_time->tm_year 1776 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= save_tm.tm_year
1784 && decoded_time->tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)) 1777 && save_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE))
1785 time_overflow (); 1778 time_overflow ();
1786 XSETFASTINT (list_args[0], decoded_time->tm_sec); 1779 XSETFASTINT (list_args[0], save_tm.tm_sec);
1787 XSETFASTINT (list_args[1], decoded_time->tm_min); 1780 XSETFASTINT (list_args[1], save_tm.tm_min);
1788 XSETFASTINT (list_args[2], decoded_time->tm_hour); 1781 XSETFASTINT (list_args[2], save_tm.tm_hour);
1789 XSETFASTINT (list_args[3], decoded_time->tm_mday); 1782 XSETFASTINT (list_args[3], save_tm.tm_mday);
1790 XSETFASTINT (list_args[4], decoded_time->tm_mon + 1); 1783 XSETFASTINT (list_args[4], save_tm.tm_mon + 1);
1791 /* On 64-bit machines an int is narrower than EMACS_INT, thus the 1784 /* On 64-bit machines an int is narrower than EMACS_INT, thus the
1792 cast below avoids overflow in int arithmetics. */ 1785 cast below avoids overflow in int arithmetics. */
1793 XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year); 1786 XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) save_tm.tm_year);
1794 XSETFASTINT (list_args[6], decoded_time->tm_wday); 1787 XSETFASTINT (list_args[6], save_tm.tm_wday);
1795 list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil; 1788 list_args[7] = save_tm.tm_isdst ? Qt : Qnil;
1796 1789
1797 /* Make a copy, in case gmtime modifies the struct. */
1798 save_tm = *decoded_time;
1799 BLOCK_INPUT; 1790 BLOCK_INPUT;
1800 decoded_time = gmtime (&time_spec); 1791 decoded_time = gmtime (&time_spec);
1801 UNBLOCK_INPUT;
1802 if (decoded_time == 0) 1792 if (decoded_time == 0)
1803 list_args[8] = Qnil; 1793 list_args[8] = Qnil;
1804 else 1794 else
1805 XSETINT (list_args[8], tm_diff (&save_tm, decoded_time)); 1795 XSETINT (list_args[8], tm_diff (&save_tm, decoded_time));
1796 UNBLOCK_INPUT;
1806 return Flist (9, list_args); 1797 return Flist (9, list_args);
1807} 1798}
1808 1799
@@ -1887,21 +1878,23 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1887 else 1878 else
1888 error ("Invalid time zone specification"); 1879 error ("Invalid time zone specification");
1889 1880
1881 BLOCK_INPUT;
1882
1890 /* Set TZ before calling mktime; merely adjusting mktime's returned 1883 /* Set TZ before calling mktime; merely adjusting mktime's returned
1891 value doesn't suffice, since that would mishandle leap seconds. */ 1884 value doesn't suffice, since that would mishandle leap seconds. */
1892 set_time_zone_rule (tzstring); 1885 set_time_zone_rule (tzstring);
1893 1886
1894 BLOCK_INPUT;
1895 value = mktime (&tm); 1887 value = mktime (&tm);
1896 UNBLOCK_INPUT;
1897 1888
1898 /* Restore TZ to previous value. */ 1889 /* Restore TZ to previous value. */
1899 newenv = environ; 1890 newenv = environ;
1900 environ = oldenv; 1891 environ = oldenv;
1901 xfree (newenv);
1902#ifdef LOCALTIME_CACHE 1892#ifdef LOCALTIME_CACHE
1903 tzset (); 1893 tzset ();
1904#endif 1894#endif
1895 UNBLOCK_INPUT;
1896
1897 xfree (newenv);
1905 } 1898 }
1906 1899
1907 if (value == (time_t) -1) 1900 if (value == (time_t) -1)
@@ -1928,24 +1921,37 @@ but this is considered obsolete. */)
1928{ 1921{
1929 time_t value; 1922 time_t value;
1930 struct tm *tm; 1923 struct tm *tm;
1931 register char *tem; 1924 char buf[sizeof "Mon Apr 30 12:49:17 " + INT_STRLEN_BOUND (int) + 1];
1925 int len IF_LINT (= 0);
1932 1926
1933 if (! lisp_time_argument (specified_time, &value, NULL)) 1927 if (! lisp_time_argument (specified_time, &value, NULL))
1934 error ("Invalid time specification"); 1928 error ("Invalid time specification");
1935 1929
1936 /* Convert to a string, checking for out-of-range time stamps. 1930 /* Convert to a string in ctime format, except without the trailing
1937 Don't use 'ctime', as that might dump core if VALUE is out of 1931 newline, and without the 4-digit year limit. Don't use asctime
1938 range. */ 1932 or ctime, as they might dump core if the year is outside the
1933 range -999 .. 9999. */
1939 BLOCK_INPUT; 1934 BLOCK_INPUT;
1940 tm = localtime (&value); 1935 tm = localtime (&value);
1936 if (tm)
1937 {
1938 static char const wday_name[][4] =
1939 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
1940 static char const mon_name[][4] =
1941 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1942 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1943 printmax_t year_base = TM_YEAR_BASE;
1944
1945 len = sprintf (buf, "%s %s%3d %02d:%02d:%02d %"pMd,
1946 wday_name[tm->tm_wday], mon_name[tm->tm_mon], tm->tm_mday,
1947 tm->tm_hour, tm->tm_min, tm->tm_sec,
1948 tm->tm_year + year_base);
1949 }
1941 UNBLOCK_INPUT; 1950 UNBLOCK_INPUT;
1942 if (! (tm && TM_YEAR_IN_ASCTIME_RANGE (tm->tm_year) && (tem = asctime (tm)))) 1951 if (! tm)
1943 time_overflow (); 1952 time_overflow ();
1944 1953
1945 /* Remove the trailing newline. */ 1954 return make_unibyte_string (buf, len);
1946 tem[strlen (tem) - 1] = '\0';
1947
1948 return build_string (tem);
1949} 1955}
1950 1956
1951/* Yield A - B, measured in seconds. 1957/* Yield A - B, measured in seconds.
@@ -1989,22 +1995,22 @@ the data it can't find. */)
1989 (Lisp_Object specified_time) 1995 (Lisp_Object specified_time)
1990{ 1996{
1991 time_t value; 1997 time_t value;
1998 int offset;
1992 struct tm *t; 1999 struct tm *t;
1993 struct tm localtm; 2000 struct tm localtm;
1994 struct tm *localt;
1995 Lisp_Object zone_offset, zone_name; 2001 Lisp_Object zone_offset, zone_name;
1996 2002
1997 zone_offset = Qnil; 2003 zone_offset = Qnil;
1998 zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time, 2004 zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time,
1999 0, &value, &localt); 2005 0, &value, &localtm);
2000 localtm = *localt;
2001 BLOCK_INPUT; 2006 BLOCK_INPUT;
2002 t = gmtime (&value); 2007 t = gmtime (&value);
2008 if (t)
2009 offset = tm_diff (&localtm, t);
2003 UNBLOCK_INPUT; 2010 UNBLOCK_INPUT;
2004 2011
2005 if (t) 2012 if (t)
2006 { 2013 {
2007 int offset = tm_diff (&localtm, t);
2008 zone_offset = make_number (offset); 2014 zone_offset = make_number (offset);
2009 if (SCHARS (zone_name) == 0) 2015 if (SCHARS (zone_name) == 0)
2010 { 2016 {
@@ -2042,9 +2048,16 @@ only the former. */)
2042 (Lisp_Object tz) 2048 (Lisp_Object tz)
2043{ 2049{
2044 const char *tzstring; 2050 const char *tzstring;
2051 char **old_environbuf;
2052
2053 if (! (NILP (tz) || EQ (tz, Qt)))
2054 CHECK_STRING (tz);
2055
2056 BLOCK_INPUT;
2045 2057
2046 /* When called for the first time, save the original TZ. */ 2058 /* When called for the first time, save the original TZ. */
2047 if (!environbuf) 2059 old_environbuf = environbuf;
2060 if (!old_environbuf)
2048 initial_tz = (char *) getenv ("TZ"); 2061 initial_tz = (char *) getenv ("TZ");
2049 2062
2050 if (NILP (tz)) 2063 if (NILP (tz))
@@ -2052,15 +2065,14 @@ only the former. */)
2052 else if (EQ (tz, Qt)) 2065 else if (EQ (tz, Qt))
2053 tzstring = "UTC0"; 2066 tzstring = "UTC0";
2054 else 2067 else
2055 { 2068 tzstring = SSDATA (tz);
2056 CHECK_STRING (tz);
2057 tzstring = SSDATA (tz);
2058 }
2059 2069
2060 set_time_zone_rule (tzstring); 2070 set_time_zone_rule (tzstring);
2061 xfree (environbuf);
2062 environbuf = environ; 2071 environbuf = environ;
2063 2072
2073 UNBLOCK_INPUT;
2074
2075 xfree (old_environbuf);
2064 return Qnil; 2076 return Qnil;
2065} 2077}
2066 2078