aboutsummaryrefslogtreecommitdiffstats
path: root/src/editfns.c
diff options
context:
space:
mode:
authorPaul Eggert2014-11-16 20:38:15 -0800
committerPaul Eggert2014-11-16 20:41:22 -0800
commit0921dbc3ab4dcc6b291ef45e46a24b322bbcb885 (patch)
tree0e320978c7d30af415bb7de6e0b8f6735a3ca3d1 /src/editfns.c
parent058f56d24f776bdc25bcac86fe1f8969a78374e9 (diff)
downloademacs-0921dbc3ab4dcc6b291ef45e46a24b322bbcb885.tar.gz
emacs-0921dbc3ab4dcc6b291ef45e46a24b322bbcb885.zip
Improve time stamp handling, and be more consistent about it.
This implements a suggestion made in: http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg00587.html Among other things, this means timer.el no longer needs to autoload the time-date module. * doc/lispref/os.texi (Time of Day, Time Conversion, Time Parsing) (Processor Run Time, Time Calculations): Document the new behavior, plus be clearer about the old behavior. (Idle Timers): Take advantage of new functionality. * etc/NEWS: Document the changes. * lisp/allout-widgets.el (allout-elapsed-time-seconds): Doc fix. * lisp/arc-mode.el (archive-ar-summarize): * lisp/calendar/time-date.el (seconds-to-time, days-to-time, time-since): * lisp/emacs-lisp/timer.el (timer-relative-time, timer-event-handler) (run-at-time, with-timeout-suspend, with-timeout-unsuspend): * lisp/net/tramp.el (tramp-time-less-p, tramp-time-subtract): * lisp/proced.el (proced-time-lessp): * lisp/timezone.el (timezone-time-from-absolute): * lisp/type-break.el (type-break-schedule, type-break-time-sum): Simplify by using new functionality. * lisp/calendar/cal-dst.el (calendar-next-time-zone-transition): Do not return time values in obsolete and undocumented (HI . LO) format; use (HI LO) instead. * lisp/calendar/time-date.el (with-decoded-time-value): Treat 'nil' as current time. This is mostly for XEmacs. (encode-time-value, with-decoded-time-value): Obsolete. (time-add, time-subtract, time-less-p): Use no-op autoloads, for XEmacs. Define only if XEmacs, as they're now C builtins in Emacs. * lisp/ldefs-boot.el: Update to match new time-date.el * lisp/proced.el: Do not require time-date. * src/editfns.c (invalid_time): New function. Use it instead of 'error ("Invalid time specification")'. (time_add, time_subtract, time_arith, Ftime_add, Ftime_less_p) (decode_float_time, lisp_to_timespec, lisp_time_struct): New functions. (make_time_tail, make_time): Remove. All uses changed to use new functions or plain list4i. (disassemble_lisp_time): Return effective length if successful. Check that LOW is an integer, if it's combined with other components. (decode_time_components): Decode into struct lisp_time, not struct timespec, so that we can support a wide set of times regardless of whether time_t is signed. Decode plain numbers as seconds since the Epoch, and nil as the current time. (lisp_time_argument, lisp_seconds_argument, Ffloat_time): Reimplement in terms of new functions. (Fencode_time): Just use list2i. (syms_of_editfns): Add time-add, time-subtract, time-less-p. * src/keyboard.c (decode_timer): Don't allow the new formats (floating point or nil) in timers. * src/systime.h (LO_TIME_BITS): New constant. Use it everywhere in place of the magic number '16'. (struct lisp_time): New type. (decode_time_components): Use it. (lisp_to_timespec): New decl.
Diffstat (limited to 'src/editfns.c')
-rw-r--r--src/editfns.c364
1 files changed, 269 insertions, 95 deletions
diff --git a/src/editfns.c b/src/editfns.c
index 376d8e3a0ea..0a07886934c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -64,6 +64,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
64extern Lisp_Object w32_get_internal_run_time (void); 64extern Lisp_Object w32_get_internal_run_time (void);
65#endif 65#endif
66 66
67static struct lisp_time lisp_time_struct (Lisp_Object, int *);
67static void set_time_zone_rule (char const *); 68static void set_time_zone_rule (char const *);
68static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec, 69static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
69 bool, struct tm *); 70 bool, struct tm *);
@@ -1392,6 +1393,12 @@ time_overflow (void)
1392 error ("Specified time is not representable"); 1393 error ("Specified time is not representable");
1393} 1394}
1394 1395
1396static void
1397invalid_time (void)
1398{
1399 error ("Invalid time specification");
1400}
1401
1395/* A substitute for mktime_z on platforms that lack it. It's not 1402/* A substitute for mktime_z on platforms that lack it. It's not
1396 thread-safe, but should be good enough for Emacs in typical use. */ 1403 thread-safe, but should be good enough for Emacs in typical use. */
1397#ifndef HAVE_TZALLOC 1404#ifndef HAVE_TZALLOC
@@ -1420,26 +1427,26 @@ mktime_z (timezone_t tz, struct tm *tm)
1420static EMACS_INT 1427static EMACS_INT
1421hi_time (time_t t) 1428hi_time (time_t t)
1422{ 1429{
1423 time_t hi = t >> 16; 1430 time_t hi = t >> LO_TIME_BITS;
1424 1431
1425 /* Check for overflow, helping the compiler for common cases where 1432 /* Check for overflow, helping the compiler for common cases where
1426 no runtime check is needed, and taking care not to convert 1433 no runtime check is needed, and taking care not to convert
1427 negative numbers to unsigned before comparing them. */ 1434 negative numbers to unsigned before comparing them. */
1428 if (! ((! TYPE_SIGNED (time_t) 1435 if (! ((! TYPE_SIGNED (time_t)
1429 || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16 1436 || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> LO_TIME_BITS
1430 || MOST_NEGATIVE_FIXNUM <= hi) 1437 || MOST_NEGATIVE_FIXNUM <= hi)
1431 && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM 1438 && (TIME_T_MAX >> LO_TIME_BITS <= MOST_POSITIVE_FIXNUM
1432 || hi <= MOST_POSITIVE_FIXNUM))) 1439 || hi <= MOST_POSITIVE_FIXNUM)))
1433 time_overflow (); 1440 time_overflow ();
1434 1441
1435 return hi; 1442 return hi;
1436} 1443}
1437 1444
1438/* Return the bottom 16 bits of the time T. */ 1445/* Return the bottom bits of the time T. */
1439static int 1446static int
1440lo_time (time_t t) 1447lo_time (time_t t)
1441{ 1448{
1442 return t & ((1 << 16) - 1); 1449 return t & ((1 << LO_TIME_BITS) - 1);
1443} 1450}
1444 1451
1445DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0, 1452DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
@@ -1453,6 +1460,96 @@ picosecond counts. */)
1453 return make_lisp_time (current_timespec ()); 1460 return make_lisp_time (current_timespec ());
1454} 1461}
1455 1462
1463static struct lisp_time
1464time_add (struct lisp_time ta, struct lisp_time tb)
1465{
1466 EMACS_INT hi = ta.hi + tb.hi;
1467 int lo = ta.lo + tb.lo;
1468 int us = ta.us + tb.us;
1469 int ps = ta.ps + tb.ps;
1470 us += (1000000 <= ps);
1471 ps -= (1000000 <= ps) * 1000000;
1472 lo += (1000000 <= us);
1473 us -= (1000000 <= us) * 1000000;
1474 hi += (1 << LO_TIME_BITS <= lo);
1475 lo -= (1 << LO_TIME_BITS <= lo) << LO_TIME_BITS;
1476 return (struct lisp_time) { hi, lo, us, ps };
1477}
1478
1479static struct lisp_time
1480time_subtract (struct lisp_time ta, struct lisp_time tb)
1481{
1482 EMACS_INT hi = ta.hi - tb.hi;
1483 int lo = ta.lo - tb.lo;
1484 int us = ta.us - tb.us;
1485 int ps = ta.ps - tb.ps;
1486 us -= (ps < 0);
1487 ps += (ps < 0) * 1000000;
1488 lo -= (us < 0);
1489 us += (us < 0) * 1000000;
1490 hi -= (lo < 0);
1491 lo += (lo < 0) << LO_TIME_BITS;
1492 return (struct lisp_time) { hi, lo, us, ps };
1493}
1494
1495static Lisp_Object
1496time_arith (Lisp_Object a, Lisp_Object b,
1497 struct lisp_time (*op) (struct lisp_time, struct lisp_time))
1498{
1499 int alen, blen;
1500 struct lisp_time ta = lisp_time_struct (a, &alen);
1501 struct lisp_time tb = lisp_time_struct (b, &blen);
1502 struct lisp_time t = op (ta, tb);
1503 if (! (MOST_NEGATIVE_FIXNUM <= t.hi && t.hi <= MOST_POSITIVE_FIXNUM))
1504 time_overflow ();
1505 Lisp_Object val = Qnil;
1506
1507 switch (max (alen, blen))
1508 {
1509 default:
1510 val = Fcons (make_number (t.ps), val);
1511 /* Fall through. */
1512 case 3:
1513 val = Fcons (make_number (t.us), val);
1514 /* Fall through. */
1515 case 2:
1516 val = Fcons (make_number (t.lo), val);
1517 val = Fcons (make_number (t.hi), val);
1518 break;
1519 }
1520
1521 return val;
1522}
1523
1524DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0,
1525 doc: /* Return the sum of two time values A and B, as a time value. */)
1526 (Lisp_Object a, Lisp_Object b)
1527{
1528 return time_arith (a, b, time_add);
1529}
1530
1531DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
1532 doc: /* Return the difference between two time values A and B, as a time value. */)
1533 (Lisp_Object a, Lisp_Object b)
1534{
1535 return time_arith (a, b, time_subtract);
1536}
1537
1538DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
1539 doc: /* Return non-nil if time value T1 is earlier than time value T2. */)
1540 (Lisp_Object t1, Lisp_Object t2)
1541{
1542 int t1len, t2len;
1543 struct lisp_time a = lisp_time_struct (t1, &t1len);
1544 struct lisp_time b = lisp_time_struct (t2, &t2len);
1545 return ((a.hi != b.hi ? a.hi < b.hi
1546 : a.lo != b.lo ? a.lo < b.lo
1547 : a.us != b.us ? a.us < b.us
1548 : a.ps < b.ps)
1549 ? Qt : Qnil);
1550}
1551
1552
1456DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time, 1553DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
1457 0, 0, 0, 1554 0, 0, 0,
1458 doc: /* Return the current run time used by Emacs. 1555 doc: /* Return the current run time used by Emacs.
@@ -1491,21 +1588,6 @@ does the same thing as `current-time'. */)
1491} 1588}
1492 1589
1493 1590
1494/* Make a Lisp list that represents the time T with fraction TAIL. */
1495static Lisp_Object
1496make_time_tail (time_t t, Lisp_Object tail)
1497{
1498 return Fcons (make_number (hi_time (t)),
1499 Fcons (make_number (lo_time (t)), tail));
1500}
1501
1502/* Make a Lisp list that represents the system time T. */
1503static Lisp_Object
1504make_time (time_t t)
1505{
1506 return make_time_tail (t, Qnil);
1507}
1508
1509/* Make a Lisp list that represents the Emacs time T. T may be an 1591/* Make a Lisp list that represents the Emacs time T. T may be an
1510 invalid time, with a slightly negative tv_nsec value such as 1592 invalid time, with a slightly negative tv_nsec value such as
1511 UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a 1593 UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a
@@ -1513,23 +1595,30 @@ make_time (time_t t)
1513Lisp_Object 1595Lisp_Object
1514make_lisp_time (struct timespec t) 1596make_lisp_time (struct timespec t)
1515{ 1597{
1598 time_t s = t.tv_sec;
1516 int ns = t.tv_nsec; 1599 int ns = t.tv_nsec;
1517 return make_time_tail (t.tv_sec, list2i (ns / 1000, ns % 1000 * 1000)); 1600 return list4i (hi_time (s), lo_time (s), ns / 1000, ns % 1000 * 1000);
1518} 1601}
1519 1602
1520/* Decode a Lisp list SPECIFIED_TIME that represents a time. 1603/* Decode a Lisp list SPECIFIED_TIME that represents a time.
1521 Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values. 1604 Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values.
1522 Return true if successful. */ 1605 Return 2, 3, or 4 to indicate the effective length of SPECIFIED_TIME
1523static bool 1606 if successful, 0 if unsuccessful. */
1607static int
1524disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, 1608disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
1525 Lisp_Object *plow, Lisp_Object *pusec, 1609 Lisp_Object *plow, Lisp_Object *pusec,
1526 Lisp_Object *ppsec) 1610 Lisp_Object *ppsec)
1527{ 1611{
1612 Lisp_Object high = make_number (0);
1613 Lisp_Object low = specified_time;
1614 Lisp_Object usec = make_number (0);
1615 Lisp_Object psec = make_number (0);
1616 int len = 4;
1617
1528 if (CONSP (specified_time)) 1618 if (CONSP (specified_time))
1529 { 1619 {
1530 Lisp_Object low = XCDR (specified_time); 1620 high = XCAR (specified_time);
1531 Lisp_Object usec = make_number (0); 1621 low = XCDR (specified_time);
1532 Lisp_Object psec = make_number (0);
1533 if (CONSP (low)) 1622 if (CONSP (low))
1534 { 1623 {
1535 Lisp_Object low_tail = XCDR (low); 1624 Lisp_Object low_tail = XCDR (low);
@@ -1540,40 +1629,119 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
1540 low_tail = XCDR (low_tail); 1629 low_tail = XCDR (low_tail);
1541 if (CONSP (low_tail)) 1630 if (CONSP (low_tail))
1542 psec = XCAR (low_tail); 1631 psec = XCAR (low_tail);
1632 else
1633 len = 3;
1543 } 1634 }
1544 else if (!NILP (low_tail)) 1635 else if (!NILP (low_tail))
1545 usec = low_tail; 1636 {
1637 usec = low_tail;
1638 len = 3;
1639 }
1640 else
1641 len = 2;
1546 } 1642 }
1643 else
1644 len = 2;
1547 1645
1548 *phigh = XCAR (specified_time); 1646 /* When combining components, require LOW to be an integer,
1549 *plow = low; 1647 as otherwise it would be a pain to add up times. */
1550 *pusec = usec; 1648 if (! INTEGERP (low))
1551 *ppsec = psec; 1649 return 0;
1552 return 1;
1553 } 1650 }
1651 else if (INTEGERP (specified_time))
1652 len = 2;
1653
1654 *phigh = high;
1655 *plow = low;
1656 *pusec = usec;
1657 *ppsec = psec;
1658 return len;
1659}
1554 1660
1555 return 0; 1661/* Convert T into an Emacs time *RESULT, truncating toward minus infinity.
1662 Return true if T is in range, false otherwise. */
1663static bool
1664decode_float_time (double t, struct lisp_time *result)
1665{
1666 double lo_multiplier = 1 << LO_TIME_BITS;
1667 double emacs_time_min = MOST_NEGATIVE_FIXNUM * lo_multiplier;
1668 if (! (emacs_time_min <= t && t < -emacs_time_min))
1669 return false;
1670
1671 double small_t = t / lo_multiplier;
1672 EMACS_INT hi = small_t;
1673 double t_sans_hi = t - hi * lo_multiplier;
1674 int lo = t_sans_hi;
1675 long double fracps = (t_sans_hi - lo) * 1e12L;
1676#ifdef INT_FAST64_MAX
1677 int_fast64_t ifracps = fracps;
1678 int us = ifracps / 1000000;
1679 int ps = ifracps % 1000000;
1680#else
1681 int us = fracps / 1e6L;
1682 int ps = fracps - us * 1e6L;
1683#endif
1684 us -= (ps < 0);
1685 ps += (ps < 0) * 1000000;
1686 lo -= (us < 0);
1687 us += (us < 0) * 1000000;
1688 hi -= (lo < 0);
1689 lo += (lo < 0) << LO_TIME_BITS;
1690 result->hi = hi;
1691 result->lo = lo;
1692 result->us = us;
1693 result->ps = ps;
1694 return true;
1556} 1695}
1557 1696
1558/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp 1697/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp
1559 list, generate the corresponding time value. 1698 list, generate the corresponding time value.
1699 If LOW is floating point, the other components should be zero.
1560 1700
1561 If RESULT is not null, store into *RESULT the converted time; 1701 If RESULT is not null, store into *RESULT the converted time.
1562 if the converted time does not fit into struct timespec,
1563 store an invalid timespec to indicate the overflow.
1564 If *DRESULT is not null, store into *DRESULT the number of 1702 If *DRESULT is not null, store into *DRESULT the number of
1565 seconds since the start of the POSIX Epoch. 1703 seconds since the start of the POSIX Epoch.
1566 1704
1567 Return true if successful. */ 1705 Return true if successful, false if the components are of the
1706 wrong type or represent a time out of range. */
1568bool 1707bool
1569decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, 1708decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
1570 Lisp_Object psec, 1709 Lisp_Object psec,
1571 struct timespec *result, double *dresult) 1710 struct lisp_time *result, double *dresult)
1572{ 1711{
1573 EMACS_INT hi, lo, us, ps; 1712 EMACS_INT hi, lo, us, ps;
1574 if (! (INTEGERP (high) && INTEGERP (low) 1713 if (! (INTEGERP (high)
1575 && INTEGERP (usec) && INTEGERP (psec))) 1714 && INTEGERP (usec) && INTEGERP (psec)))
1576 return false; 1715 return false;
1716 if (! INTEGERP (low))
1717 {
1718 if (FLOATP (low))
1719 {
1720 double t = XFLOAT_DATA (low);
1721 if (result && ! decode_float_time (t, result))
1722 return false;
1723 if (dresult)
1724 *dresult = t;
1725 return true;
1726 }
1727 else if (NILP (low))
1728 {
1729 struct timespec now = current_timespec ();
1730 if (result)
1731 {
1732 result->hi = hi_time (now.tv_sec);
1733 result->lo = lo_time (now.tv_sec);
1734 result->us = now.tv_nsec / 1000;
1735 result->ps = now.tv_nsec % 1000 * 1000;
1736 }
1737 if (dresult)
1738 *dresult = now.tv_sec + now.tv_nsec / 1e9;
1739 return true;
1740 }
1741 else
1742 return false;
1743 }
1744
1577 hi = XINT (high); 1745 hi = XINT (high);
1578 lo = XINT (low); 1746 lo = XINT (low);
1579 us = XINT (usec); 1747 us = XINT (usec);
@@ -1583,53 +1751,68 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
1583 each overflow into the next higher-order component. */ 1751 each overflow into the next higher-order component. */
1584 us += ps / 1000000 - (ps % 1000000 < 0); 1752 us += ps / 1000000 - (ps % 1000000 < 0);
1585 lo += us / 1000000 - (us % 1000000 < 0); 1753 lo += us / 1000000 - (us % 1000000 < 0);
1586 hi += lo >> 16; 1754 hi += lo >> LO_TIME_BITS;
1587 ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0); 1755 ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0);
1588 us = us % 1000000 + 1000000 * (us % 1000000 < 0); 1756 us = us % 1000000 + 1000000 * (us % 1000000 < 0);
1589 lo &= (1 << 16) - 1; 1757 lo &= (1 << LO_TIME_BITS) - 1;
1590 1758
1591 if (result) 1759 if (result)
1592 { 1760 {
1593 if ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi) 1761 if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM))
1594 && hi <= TIME_T_MAX >> 16) 1762 return false;
1595 { 1763 result->hi = hi;
1596 /* Return the greatest representable time that is not greater 1764 result->lo = lo;
1597 than the requested time. */ 1765 result->us = us;
1598 time_t sec = hi; 1766 result->ps = ps;
1599 *result = make_timespec ((sec << 16) + lo, us * 1000 + ps / 1000);
1600 }
1601 else
1602 *result = invalid_timespec ();
1603 } 1767 }
1604 1768
1605 if (dresult) 1769 if (dresult)
1606 *dresult = (us * 1e6 + ps) / 1e12 + lo + hi * 65536.0; 1770 {
1771 double dhi = hi;
1772 *dresult = (us * 1e6 + ps) / 1e12 + lo + dhi * (1 << LO_TIME_BITS);
1773 }
1607 1774
1608 return true; 1775 return true;
1609} 1776}
1610 1777
1778struct timespec
1779lisp_to_timespec (struct lisp_time t)
1780{
1781 if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
1782 && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
1783 return invalid_timespec ();
1784 time_t s = (t.hi << LO_TIME_BITS) + t.lo;
1785 int ns = t.us * 1000 + t.ps / 1000;
1786 return make_timespec (s, ns);
1787}
1788
1611/* Decode a Lisp list SPECIFIED_TIME that represents a time. 1789/* Decode a Lisp list SPECIFIED_TIME that represents a time.
1790 Store its effective length into *PLEN.
1612 If SPECIFIED_TIME is nil, use the current time. 1791 If SPECIFIED_TIME is nil, use the current time.
1792 Signal an error if SPECIFIED_TIME does not represent a time. */
1793static struct lisp_time
1794lisp_time_struct (Lisp_Object specified_time, int *plen)
1795{
1796 Lisp_Object high, low, usec, psec;
1797 struct lisp_time t;
1798 int len = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec);
1799 if (! (len && decode_time_components (high, low, usec, psec, &t, 0)))
1800 invalid_time ();
1801 *plen = len;
1802 return t;
1803}
1613 1804
1614 Round the time down to the nearest struct timespec value. 1805/* Like lisp_time_struct, except return a struct timespec.
1615 Return seconds since the Epoch. 1806 Discard any low-order digits. */
1616 Signal an error if unsuccessful. */
1617struct timespec 1807struct timespec
1618lisp_time_argument (Lisp_Object specified_time) 1808lisp_time_argument (Lisp_Object specified_time)
1619{ 1809{
1620 if (NILP (specified_time)) 1810 int len;
1621 return current_timespec (); 1811 struct lisp_time lt = lisp_time_struct (specified_time, &len);
1622 else 1812 struct timespec t = lisp_to_timespec (lt);
1623 { 1813 if (! timespec_valid_p (t))
1624 Lisp_Object high, low, usec, psec; 1814 time_overflow ();
1625 struct timespec t; 1815 return t;
1626 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1627 && decode_time_components (high, low, usec, psec, &t, 0)))
1628 error ("Invalid time specification");
1629 if (! timespec_valid_p (t))
1630 time_overflow ();
1631 return t;
1632 }
1633} 1816}
1634 1817
1635/* Like lisp_time_argument, except decode only the seconds part, 1818/* Like lisp_time_argument, except decode only the seconds part,
@@ -1637,20 +1820,16 @@ lisp_time_argument (Lisp_Object specified_time)
1637static time_t 1820static time_t
1638lisp_seconds_argument (Lisp_Object specified_time) 1821lisp_seconds_argument (Lisp_Object specified_time)
1639{ 1822{
1640 if (NILP (specified_time)) 1823 Lisp_Object high, low, usec, psec;
1641 return time (NULL); 1824 struct lisp_time t;
1642 else 1825 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1643 { 1826 && decode_time_components (high, low, make_number (0),
1644 Lisp_Object high, low, usec, psec; 1827 make_number (0), &t, 0)))
1645 struct timespec t; 1828 invalid_time ();
1646 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) 1829 if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
1647 && decode_time_components (high, low, make_number (0), 1830 && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
1648 make_number (0), &t, 0))) 1831 time_overflow ();
1649 error ("Invalid time specification"); 1832 return (t.hi << LO_TIME_BITS) + t.lo;
1650 if (! timespec_valid_p (t))
1651 time_overflow ();
1652 return t.tv_sec;
1653 }
1654} 1833}
1655 1834
1656DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0, 1835DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
@@ -1668,18 +1847,10 @@ or (if you need time as a string) `format-time-string'. */)
1668 (Lisp_Object specified_time) 1847 (Lisp_Object specified_time)
1669{ 1848{
1670 double t; 1849 double t;
1671 if (NILP (specified_time)) 1850 Lisp_Object high, low, usec, psec;
1672 { 1851 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1673 struct timespec now = current_timespec (); 1852 && decode_time_components (high, low, usec, psec, 0, &t)))
1674 t = now.tv_sec + now.tv_nsec / 1e9; 1853 invalid_time ();
1675 }
1676 else
1677 {
1678 Lisp_Object high, low, usec, psec;
1679 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1680 && decode_time_components (high, low, usec, psec, 0, &t)))
1681 error ("Invalid time specification");
1682 }
1683 return make_float (t); 1854 return make_float (t);
1684} 1855}
1685 1856
@@ -1969,7 +2140,7 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1969 if (value == (time_t) -1) 2140 if (value == (time_t) -1)
1970 time_overflow (); 2141 time_overflow ();
1971 2142
1972 return make_time (value); 2143 return list2i (hi_time (value), lo_time (value));
1973} 2144}
1974 2145
1975DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, 2146DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
@@ -4874,6 +5045,9 @@ functions if all the text being accessed has this property. */);
4874 defsubr (&Suser_full_name); 5045 defsubr (&Suser_full_name);
4875 defsubr (&Semacs_pid); 5046 defsubr (&Semacs_pid);
4876 defsubr (&Scurrent_time); 5047 defsubr (&Scurrent_time);
5048 defsubr (&Stime_add);
5049 defsubr (&Stime_subtract);
5050 defsubr (&Stime_less_p);
4877 defsubr (&Sget_internal_run_time); 5051 defsubr (&Sget_internal_run_time);
4878 defsubr (&Sformat_time_string); 5052 defsubr (&Sformat_time_string);
4879 defsubr (&Sfloat_time); 5053 defsubr (&Sfloat_time);