diff options
| author | Paul Eggert | 2012-07-06 18:57:42 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-07-06 18:57:42 -0700 |
| commit | 31571fd712d8c1796f7d31739f1b48cf25948d64 (patch) | |
| tree | 36e8f03e132306f2824b8711827fcd8a6514279a /src | |
| parent | 4516fbef7207ca23ca72da28d060dad979319310 (diff) | |
| download | emacs-31571fd712d8c1796f7d31739f1b48cf25948d64.tar.gz emacs-31571fd712d8c1796f7d31739f1b48cf25948d64.zip | |
Do not require float-time's arg to fit in time_t (Bug#11825).
This works better on hosts where time_t is unsigned, and where
float-time is applied to the (negative) difference between two times.
* editfns.c (decode_time_components): Last arg is now double *,
not int *, and means to store all the result as a double, without
worrying about whether the seconds part fits in time_t.
All callers changed.
(lisp_time_argument): Remove last int * arg, as it's no longer needed.
All callers changed.
(Ffloat_time): Do not fail merely because the specified time falls
outside of time_t range.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/editfns.c | 79 | ||||
| -rw-r--r-- | src/fileio.c | 4 | ||||
| -rw-r--r-- | src/systime.h | 4 | ||||
| -rw-r--r-- | src/undo.c | 2 |
5 files changed, 71 insertions, 32 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 03c92804fb8..435c6d87050 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2012-07-07 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Do not require float-time's arg to fit in time_t (Bug#11825). | ||
| 4 | This works better on hosts where time_t is unsigned, and where | ||
| 5 | float-time is applied to the (negative) difference between two times. | ||
| 6 | * editfns.c (decode_time_components): Last arg is now double *, | ||
| 7 | not int *, and means to store all the result as a double, without | ||
| 8 | worrying about whether the seconds part fits in time_t. | ||
| 9 | All callers changed. | ||
| 10 | (lisp_time_argument): Remove last int * arg, as it's no longer needed. | ||
| 11 | All callers changed. | ||
| 12 | (Ffloat_time): Do not fail merely because the specified time falls | ||
| 13 | outside of time_t range. | ||
| 14 | |||
| 1 | 2012-07-07 Glenn Morris <rgm@gnu.org> | 15 | 2012-07-07 Glenn Morris <rgm@gnu.org> |
| 2 | 16 | ||
| 3 | * s/darwin.h (HAVE_RES_INIT, HAVE_LIBRESOLV): | 17 | * s/darwin.h (HAVE_RES_INIT, HAVE_LIBRESOLV): |
diff --git a/src/editfns.c b/src/editfns.c index e40bea44e9c..fe119490f3f 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -1521,16 +1521,20 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, | |||
| 1521 | } | 1521 | } |
| 1522 | 1522 | ||
| 1523 | /* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp | 1523 | /* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp |
| 1524 | list, generate the corresponding EMACS_TIME value *RESULT, and | 1524 | list, generate the corresponding time value. |
| 1525 | if RESULT_PSEC is not null store into *RESULT_PSEC the | 1525 | |
| 1526 | (nonnegative) difference in picoseconds between the input time and | 1526 | If RESULT is not null, store into *RESULT the converted time; |
| 1527 | the returned time. Return nonzero if successful. */ | 1527 | this can fail if the converted time does not fit into EMACS_TIME. |
| 1528 | If *DRESULT is not null, store into *DRESULT the number of | ||
| 1529 | seconds since the start of the POSIX Epoch. | ||
| 1530 | |||
| 1531 | Return nonzero if successful. */ | ||
| 1528 | int | 1532 | int |
| 1529 | decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, | 1533 | decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, |
| 1530 | Lisp_Object psec, EMACS_TIME *result, int *result_psec) | 1534 | Lisp_Object psec, |
| 1535 | EMACS_TIME *result, double *dresult) | ||
| 1531 | { | 1536 | { |
| 1532 | EMACS_INT hi, lo, us, ps; | 1537 | EMACS_INT hi, lo, us, ps; |
| 1533 | time_t sec; | ||
| 1534 | if (! (INTEGERP (high) && INTEGERP (low) | 1538 | if (! (INTEGERP (high) && INTEGERP (low) |
| 1535 | && INTEGERP (usec) && INTEGERP (psec))) | 1539 | && INTEGERP (usec) && INTEGERP (psec))) |
| 1536 | return 0; | 1540 | return 0; |
| @@ -1548,27 +1552,38 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, | |||
| 1548 | us = us % 1000000 + 1000000 * (us % 1000000 < 0); | 1552 | us = us % 1000000 + 1000000 * (us % 1000000 < 0); |
| 1549 | lo &= (1 << 16) - 1; | 1553 | lo &= (1 << 16) - 1; |
| 1550 | 1554 | ||
| 1551 | /* Check for overflow in the highest-order component. */ | 1555 | if (result) |
| 1552 | if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi) | 1556 | { |
| 1553 | && hi <= TIME_T_MAX >> 16)) | 1557 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi) |
| 1554 | return 0; | 1558 | && hi <= TIME_T_MAX >> 16) |
| 1559 | { | ||
| 1560 | /* Return the greatest representable time that is not greater | ||
| 1561 | than the requested time. */ | ||
| 1562 | time_t sec = hi; | ||
| 1563 | EMACS_SET_SECS_NSECS (*result, (sec << 16) + lo, | ||
| 1564 | us * 1000 + ps / 1000); | ||
| 1565 | } | ||
| 1566 | else | ||
| 1567 | { | ||
| 1568 | /* Overflow in the highest-order component. */ | ||
| 1569 | return 0; | ||
| 1570 | } | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | if (dresult) | ||
| 1574 | *dresult = (us * 1e6 + ps) / 1e12 + lo + hi * 65536.0; | ||
| 1555 | 1575 | ||
| 1556 | sec = hi; | ||
| 1557 | EMACS_SET_SECS_NSECS (*result, (sec << 16) + lo, us * 1000 + ps / 1000); | ||
| 1558 | if (result_psec) | ||
| 1559 | *result_psec = ps % 1000; | ||
| 1560 | return 1; | 1576 | return 1; |
| 1561 | } | 1577 | } |
| 1562 | 1578 | ||
| 1563 | /* Decode a Lisp list SPECIFIED_TIME that represents a time. | 1579 | /* Decode a Lisp list SPECIFIED_TIME that represents a time. |
| 1564 | If SPECIFIED_TIME is nil, use the current time. | 1580 | If SPECIFIED_TIME is nil, use the current time. |
| 1565 | Round the time down to the nearest EMACS_TIME value, and | 1581 | |
| 1566 | if PPSEC is not null store into *PPSEC the (nonnegative) difference in | 1582 | Round the time down to the nearest EMACS_TIME value. |
| 1567 | picoseconds between the input time and the returned time. | ||
| 1568 | Return seconds since the Epoch. | 1583 | Return seconds since the Epoch. |
| 1569 | Signal an error if unsuccessful. */ | 1584 | Signal an error if unsuccessful. */ |
| 1570 | EMACS_TIME | 1585 | EMACS_TIME |
| 1571 | lisp_time_argument (Lisp_Object specified_time, int *ppsec) | 1586 | lisp_time_argument (Lisp_Object specified_time) |
| 1572 | { | 1587 | { |
| 1573 | EMACS_TIME t; | 1588 | EMACS_TIME t; |
| 1574 | if (NILP (specified_time)) | 1589 | if (NILP (specified_time)) |
| @@ -1577,14 +1592,15 @@ lisp_time_argument (Lisp_Object specified_time, int *ppsec) | |||
| 1577 | { | 1592 | { |
| 1578 | Lisp_Object high, low, usec, psec; | 1593 | Lisp_Object high, low, usec, psec; |
| 1579 | if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) | 1594 | if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) |
| 1580 | && decode_time_components (high, low, usec, psec, &t, ppsec))) | 1595 | && decode_time_components (high, low, usec, psec, &t, 0))) |
| 1581 | error ("Invalid time specification"); | 1596 | error ("Invalid time specification"); |
| 1582 | } | 1597 | } |
| 1583 | return t; | 1598 | return t; |
| 1584 | } | 1599 | } |
| 1585 | 1600 | ||
| 1586 | /* Like lisp_time_argument, except decode only the seconds part, | 1601 | /* Like lisp_time_argument, except decode only the seconds part, |
| 1587 | and do not check the subseconds part, and always round down. */ | 1602 | do not allow out-of-range time stamps, do not check the subseconds part, |
| 1603 | and always round down. */ | ||
| 1588 | static time_t | 1604 | static time_t |
| 1589 | lisp_seconds_argument (Lisp_Object specified_time) | 1605 | lisp_seconds_argument (Lisp_Object specified_time) |
| 1590 | { | 1606 | { |
| @@ -1616,12 +1632,21 @@ If precise time stamps are required, use either `current-time', | |||
| 1616 | or (if you need time as a string) `format-time-string'. */) | 1632 | or (if you need time as a string) `format-time-string'. */) |
| 1617 | (Lisp_Object specified_time) | 1633 | (Lisp_Object specified_time) |
| 1618 | { | 1634 | { |
| 1619 | int psec; | 1635 | double t; |
| 1620 | EMACS_TIME t = lisp_time_argument (specified_time, &psec); | 1636 | if (NILP (specified_time)) |
| 1621 | double ps = (1000 * 1000 * 1000 <= INTMAX_MAX / 1000 | 1637 | { |
| 1622 | ? EMACS_NSECS (t) * (intmax_t) 1000 + psec | 1638 | EMACS_TIME now; |
| 1623 | : EMACS_NSECS (t) * 1e3 + psec); | 1639 | EMACS_GET_TIME (now); |
| 1624 | return make_float (EMACS_SECS (t) + ps / 1e12); | 1640 | t = EMACS_SECS (now) + EMACS_NSECS (now) / 1e9; |
| 1641 | } | ||
| 1642 | else | ||
| 1643 | { | ||
| 1644 | Lisp_Object high, low, usec, psec; | ||
| 1645 | if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) | ||
| 1646 | && decode_time_components (high, low, usec, psec, 0, &t))) | ||
| 1647 | error ("Invalid time specification"); | ||
| 1648 | } | ||
| 1649 | return make_float (t); | ||
| 1625 | } | 1650 | } |
| 1626 | 1651 | ||
| 1627 | /* Write information into buffer S of size MAXSIZE, according to the | 1652 | /* Write information into buffer S of size MAXSIZE, according to the |
| @@ -1730,7 +1755,7 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". | |||
| 1730 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) | 1755 | usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) |
| 1731 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) | 1756 | (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) |
| 1732 | { | 1757 | { |
| 1733 | EMACS_TIME t = lisp_time_argument (timeval, 0); | 1758 | EMACS_TIME t = lisp_time_argument (timeval); |
| 1734 | struct tm tm; | 1759 | struct tm tm; |
| 1735 | 1760 | ||
| 1736 | CHECK_STRING (format_string); | 1761 | CHECK_STRING (format_string); |
diff --git a/src/fileio.c b/src/fileio.c index 0f6a1d5f799..8f3b9e92257 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3031,7 +3031,7 @@ Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of | |||
| 3031 | { | 3031 | { |
| 3032 | Lisp_Object absname, encoded_absname; | 3032 | Lisp_Object absname, encoded_absname; |
| 3033 | Lisp_Object handler; | 3033 | Lisp_Object handler; |
| 3034 | EMACS_TIME t = lisp_time_argument (timestamp, 0); | 3034 | EMACS_TIME t = lisp_time_argument (timestamp); |
| 3035 | 3035 | ||
| 3036 | absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)); | 3036 | absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)); |
| 3037 | 3037 | ||
| @@ -5159,7 +5159,7 @@ An argument specifies the modification time value to use | |||
| 5159 | { | 5159 | { |
| 5160 | if (!NILP (time_list)) | 5160 | if (!NILP (time_list)) |
| 5161 | { | 5161 | { |
| 5162 | current_buffer->modtime = lisp_time_argument (time_list, 0); | 5162 | current_buffer->modtime = lisp_time_argument (time_list); |
| 5163 | current_buffer->modtime_size = -1; | 5163 | current_buffer->modtime_size = -1; |
| 5164 | } | 5164 | } |
| 5165 | else | 5165 | else |
diff --git a/src/systime.h b/src/systime.h index 0f91551239e..938083a5ffc 100644 --- a/src/systime.h +++ b/src/systime.h | |||
| @@ -112,8 +112,8 @@ extern void set_waiting_for_input (EMACS_TIME *); | |||
| 112 | /* defined in editfns.c */ | 112 | /* defined in editfns.c */ |
| 113 | extern Lisp_Object make_lisp_time (EMACS_TIME); | 113 | extern Lisp_Object make_lisp_time (EMACS_TIME); |
| 114 | extern int decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, | 114 | extern int decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, |
| 115 | Lisp_Object, EMACS_TIME *, int *); | 115 | Lisp_Object, EMACS_TIME *, double *); |
| 116 | extern EMACS_TIME lisp_time_argument (Lisp_Object, int *); | 116 | extern EMACS_TIME lisp_time_argument (Lisp_Object); |
| 117 | #endif | 117 | #endif |
| 118 | 118 | ||
| 119 | /* Compare times T1 and T2 for equality, inequality etc. */ | 119 | /* Compare times T1 and T2 for equality, inequality etc. */ |
diff --git a/src/undo.c b/src/undo.c index c4ef557a221..bada46563a0 100644 --- a/src/undo.c +++ b/src/undo.c | |||
| @@ -521,7 +521,7 @@ Return what remains of the list. */) | |||
| 521 | (mod_time, 0, | 521 | (mod_time, 0, |
| 522 | XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000); | 522 | XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000); |
| 523 | else | 523 | else |
| 524 | mod_time = lisp_time_argument (cdr, 0); | 524 | mod_time = lisp_time_argument (cdr); |
| 525 | 525 | ||
| 526 | if (current_buffer->base_buffer) | 526 | if (current_buffer->base_buffer) |
| 527 | base_buffer = current_buffer->base_buffer; | 527 | base_buffer = current_buffer->base_buffer; |