diff options
| author | Paul Eggert | 2013-07-09 23:26:23 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-07-09 23:26:23 -0700 |
| commit | 954b166e9037de5fdd43b4fbe7b8c73a36ac402e (patch) | |
| tree | 4a1aa065be1ec87b53fdaff13f1129863ba2ebb5 /src | |
| parent | 56973319b58a66e97ae45e050f9f943ff8f1439b (diff) | |
| download | emacs-954b166e9037de5fdd43b4fbe7b8c73a36ac402e.tar.gz emacs-954b166e9037de5fdd43b4fbe7b8c73a36ac402e.zip | |
Timestamp fixes for undo.
* doc/lispref/text.texi (Undo):
Document (t . 0) and (t . -1) in buffer-undo-list.
* etc/NEWS: Changes to visited-file-modtime, set-visited-file-modtime.
* lisp/files.el (clear-visited-file-modtime): Move here from fileio.c.
* src/atimer.c (schedule_atimer):
* src/fileio.c (Ffile_newer_than_file_p):
Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT.
* src/buffer.c (buffer-undo-list): Document (t . 0) and (t . -1).
* src/fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el.
(syms_of_fileio): Remove Sclear_visited_file_name.
(Fvisited_file_modtime): Return -1, not (-1 ...), when the visited
file doesn't exist; this avoids an ambiguity with negative timestamps.
(Fset_visited_file_modtime): Accept -1 and 0 as time-list arg.
* src/systime.h (make_emacs_time, invalid_emacs_time):
Don't assume struct timespec layout; POSIX doesn't guarantee it.
(EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove.
* src/undo.c (record_first_change): Push (visited-file-modtime) onto
undo list rather than reimplementing it by hand, incorrectly.
Fixes: debbugs:14824
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 18 | ||||
| -rw-r--r-- | src/atimer.c | 2 | ||||
| -rw-r--r-- | src/buffer.c | 5 | ||||
| -rw-r--r-- | src/fileio.c | 46 | ||||
| -rw-r--r-- | src/systime.h | 23 | ||||
| -rw-r--r-- | src/undo.c | 7 |
6 files changed, 52 insertions, 49 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a96f1153ef0..049c917eddd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2013-07-10 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Timestamp fixes for undo (Bug#14824). | ||
| 4 | * atimer.c (schedule_atimer): | ||
| 5 | * fileio.c (Ffile_newer_than_file_p): | ||
| 6 | Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT. | ||
| 7 | * buffer.c (buffer-undo-list): Document (t . 0) and (t . -1). | ||
| 8 | * fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el. | ||
| 9 | (syms_of_fileio): Remove Sclear_visited_file_name. | ||
| 10 | (Fvisited_file_modtime): Return -1, not (-1 ...), when the visited | ||
| 11 | file doesn't exist; this avoids an ambiguity with negative timestamps. | ||
| 12 | (Fset_visited_file_modtime): Accept -1 and 0 as time-list arg. | ||
| 13 | * systime.h (make_emacs_time, invalid_emacs_time): | ||
| 14 | Don't assume struct timespec layout; POSIX doesn't guarantee it. | ||
| 15 | (EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove. | ||
| 16 | * undo.c (record_first_change): Push (visited-file-modtime) onto | ||
| 17 | undo list rather than reimplementing it by hand, incorrectly. | ||
| 18 | |||
| 1 | 2013-07-09 Ken Brown <kbrown@cornell.edu> | 19 | 2013-07-09 Ken Brown <kbrown@cornell.edu> |
| 2 | 20 | ||
| 3 | * sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB. | 21 | * sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB. |
diff --git a/src/atimer.c b/src/atimer.c index 73c7aa5686b..bb5294670d3 100644 --- a/src/atimer.c +++ b/src/atimer.c | |||
| @@ -336,7 +336,7 @@ schedule_atimer (struct atimer *t) | |||
| 336 | struct atimer *a = atimers, *prev = NULL; | 336 | struct atimer *a = atimers, *prev = NULL; |
| 337 | 337 | ||
| 338 | /* Look for the first atimer that is ripe after T. */ | 338 | /* Look for the first atimer that is ripe after T. */ |
| 339 | while (a && EMACS_TIME_GT (t->expiration, a->expiration)) | 339 | while (a && EMACS_TIME_LT (a->expiration, t->expiration)) |
| 340 | prev = a, a = a->next; | 340 | prev = a, a = a->next; |
| 341 | 341 | ||
| 342 | /* Insert T in front of the atimer found, if any. */ | 342 | /* Insert T in front of the atimer found, if any. */ |
diff --git a/src/buffer.c b/src/buffer.c index 94104ef535c..81768849a4b 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -6095,6 +6095,11 @@ and is the visited file's modification time, as of that time. If the | |||
| 6095 | modification time of the most recent save is different, this entry is | 6095 | modification time of the most recent save is different, this entry is |
| 6096 | obsolete. | 6096 | obsolete. |
| 6097 | 6097 | ||
| 6098 | An entry (t . 0) means means the buffer was previously unmodified but | ||
| 6099 | its time stamp was unknown because it was not associated with a file. | ||
| 6100 | An entry (t . -1) is similar, except that it means the buffer's visited | ||
| 6101 | file did not exist. | ||
| 6102 | |||
| 6098 | An entry (nil PROPERTY VALUE BEG . END) indicates that a text property | 6103 | An entry (nil PROPERTY VALUE BEG . END) indicates that a text property |
| 6099 | was modified between BEG and END. PROPERTY is the property name, | 6104 | was modified between BEG and END. PROPERTY is the property name, |
| 6100 | and VALUE is the old value. | 6105 | and VALUE is the old value. |
diff --git a/src/fileio.c b/src/fileio.c index d030c78c422..cb863410ccf 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3345,7 +3345,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) | |||
| 3345 | if (stat (SSDATA (absname2), &st2) < 0) | 3345 | if (stat (SSDATA (absname2), &st2) < 0) |
| 3346 | return Qt; | 3346 | return Qt; |
| 3347 | 3347 | ||
| 3348 | return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2)) | 3348 | return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1)) |
| 3349 | ? Qt : Qnil); | 3349 | ? Qt : Qnil); |
| 3350 | } | 3350 | } |
| 3351 | 3351 | ||
| @@ -5375,36 +5375,19 @@ See Info node `(elisp)Modification Time' for more details. */) | |||
| 5375 | return Qnil; | 5375 | return Qnil; |
| 5376 | } | 5376 | } |
| 5377 | 5377 | ||
| 5378 | DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime, | ||
| 5379 | Sclear_visited_file_modtime, 0, 0, 0, | ||
| 5380 | doc: /* Clear out records of last mod time of visited file. | ||
| 5381 | Next attempt to save will certainly not complain of a discrepancy. */) | ||
| 5382 | (void) | ||
| 5383 | { | ||
| 5384 | current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS); | ||
| 5385 | current_buffer->modtime_size = -1; | ||
| 5386 | return Qnil; | ||
| 5387 | } | ||
| 5388 | |||
| 5389 | DEFUN ("visited-file-modtime", Fvisited_file_modtime, | 5378 | DEFUN ("visited-file-modtime", Fvisited_file_modtime, |
| 5390 | Svisited_file_modtime, 0, 0, 0, | 5379 | Svisited_file_modtime, 0, 0, 0, |
| 5391 | doc: /* Return the current buffer's recorded visited file modification time. | 5380 | doc: /* Return the current buffer's recorded visited file modification time. |
| 5392 | The value is a list of the form (HIGH LOW USEC PSEC), like the time values that | 5381 | The value is a list of the form (HIGH LOW USEC PSEC), like the time values that |
| 5393 | `file-attributes' returns. If the current buffer has no recorded file | 5382 | `file-attributes' returns. If the current buffer has no recorded file |
| 5394 | modification time, this function returns 0. If the visited file | 5383 | modification time, this function returns 0. If the visited file |
| 5395 | doesn't exist, HIGH will be -1. | 5384 | doesn't exist, return -1. |
| 5396 | See Info node `(elisp)Modification Time' for more details. */) | 5385 | See Info node `(elisp)Modification Time' for more details. */) |
| 5397 | (void) | 5386 | (void) |
| 5398 | { | 5387 | { |
| 5399 | if (EMACS_NSECS (current_buffer->modtime) < 0) | 5388 | int ns = EMACS_NSECS (current_buffer->modtime); |
| 5400 | { | 5389 | if (ns < 0) |
| 5401 | if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) | 5390 | return make_number (UNKNOWN_MODTIME_NSECS - ns); |
| 5402 | { | ||
| 5403 | /* make_lisp_time won't work here if time_t is unsigned. */ | ||
| 5404 | return list4i (-1, 65535, 0, 0); | ||
| 5405 | } | ||
| 5406 | return make_number (0); | ||
| 5407 | } | ||
| 5408 | return make_lisp_time (current_buffer->modtime); | 5391 | return make_lisp_time (current_buffer->modtime); |
| 5409 | } | 5392 | } |
| 5410 | 5393 | ||
| @@ -5415,12 +5398,22 @@ Useful if the buffer was not read from the file normally | |||
| 5415 | or if the file itself has been changed for some known benign reason. | 5398 | or if the file itself has been changed for some known benign reason. |
| 5416 | An argument specifies the modification time value to use | 5399 | An argument specifies the modification time value to use |
| 5417 | \(instead of that of the visited file), in the form of a list | 5400 | \(instead of that of the visited file), in the form of a list |
| 5418 | \(HIGH LOW USEC PSEC) as returned by `current-time'. */) | 5401 | \(HIGH LOW USEC PSEC) or an integer flag as returned by |
| 5419 | (Lisp_Object time_list) | 5402 | `visited-file-modtime'. */) |
| 5403 | (Lisp_Object time_flag) | ||
| 5420 | { | 5404 | { |
| 5421 | if (!NILP (time_list)) | 5405 | if (!NILP (time_flag)) |
| 5422 | { | 5406 | { |
| 5423 | current_buffer->modtime = lisp_time_argument (time_list); | 5407 | EMACS_TIME mtime; |
| 5408 | if (INTEGERP (time_flag)) | ||
| 5409 | { | ||
| 5410 | CHECK_RANGED_INTEGER (time_flag, -1, 0); | ||
| 5411 | mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag)); | ||
| 5412 | } | ||
| 5413 | else | ||
| 5414 | mtime = lisp_time_argument (time_flag); | ||
| 5415 | |||
| 5416 | current_buffer->modtime = mtime; | ||
| 5424 | current_buffer->modtime_size = -1; | 5417 | current_buffer->modtime_size = -1; |
| 5425 | } | 5418 | } |
| 5426 | else | 5419 | else |
| @@ -6121,7 +6114,6 @@ This includes interactive calls to `delete-file' and | |||
| 6121 | defsubr (&Swrite_region); | 6114 | defsubr (&Swrite_region); |
| 6122 | defsubr (&Scar_less_than_car); | 6115 | defsubr (&Scar_less_than_car); |
| 6123 | defsubr (&Sverify_visited_file_modtime); | 6116 | defsubr (&Sverify_visited_file_modtime); |
| 6124 | defsubr (&Sclear_visited_file_modtime); | ||
| 6125 | defsubr (&Svisited_file_modtime); | 6117 | defsubr (&Svisited_file_modtime); |
| 6126 | defsubr (&Sset_visited_file_modtime); | 6118 | defsubr (&Sset_visited_file_modtime); |
| 6127 | defsubr (&Sdo_auto_save); | 6119 | defsubr (&Sdo_auto_save); |
diff --git a/src/systime.h b/src/systime.h index c3bc00c1479..df733b290c3 100644 --- a/src/systime.h +++ b/src/systime.h | |||
| @@ -67,7 +67,9 @@ SYSTIME_INLINE time_t *emacs_secs_addr (EMACS_TIME *t) { return &t->tv_sec; } | |||
| 67 | SYSTIME_INLINE EMACS_TIME | 67 | SYSTIME_INLINE EMACS_TIME |
| 68 | make_emacs_time (time_t s, int ns) | 68 | make_emacs_time (time_t s, int ns) |
| 69 | { | 69 | { |
| 70 | EMACS_TIME r = { s, ns }; | 70 | EMACS_TIME r; |
| 71 | r.tv_sec = s; | ||
| 72 | r.tv_nsec = ns; | ||
| 71 | return r; | 73 | return r; |
| 72 | } | 74 | } |
| 73 | 75 | ||
| @@ -75,7 +77,9 @@ make_emacs_time (time_t s, int ns) | |||
| 75 | SYSTIME_INLINE EMACS_TIME | 77 | SYSTIME_INLINE EMACS_TIME |
| 76 | invalid_emacs_time (void) | 78 | invalid_emacs_time (void) |
| 77 | { | 79 | { |
| 78 | EMACS_TIME r = { 0, -1 }; | 80 | EMACS_TIME r; |
| 81 | r.tv_sec = 0; | ||
| 82 | r.tv_nsec = -1; | ||
| 79 | return r; | 83 | return r; |
| 80 | } | 84 | } |
| 81 | 85 | ||
| @@ -166,21 +170,6 @@ EMACS_TIME_EQ (EMACS_TIME t1, EMACS_TIME t2) | |||
| 166 | return timespec_cmp (t1, t2) == 0; | 170 | return timespec_cmp (t1, t2) == 0; |
| 167 | } | 171 | } |
| 168 | SYSTIME_INLINE int | 172 | SYSTIME_INLINE int |
| 169 | EMACS_TIME_NE (EMACS_TIME t1, EMACS_TIME t2) | ||
| 170 | { | ||
| 171 | return timespec_cmp (t1, t2) != 0; | ||
| 172 | } | ||
| 173 | SYSTIME_INLINE int | ||
| 174 | EMACS_TIME_GT (EMACS_TIME t1, EMACS_TIME t2) | ||
| 175 | { | ||
| 176 | return timespec_cmp (t1, t2) > 0; | ||
| 177 | } | ||
| 178 | SYSTIME_INLINE int | ||
| 179 | EMACS_TIME_GE (EMACS_TIME t1, EMACS_TIME t2) | ||
| 180 | { | ||
| 181 | return timespec_cmp (t1, t2) >= 0; | ||
| 182 | } | ||
| 183 | SYSTIME_INLINE int | ||
| 184 | EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2) | 173 | EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2) |
| 185 | { | 174 | { |
| 186 | return timespec_cmp (t1, t2) < 0; | 175 | return timespec_cmp (t1, t2) < 0; |
diff --git a/src/undo.c b/src/undo.c index d8711882fbf..234b8510f0a 100644 --- a/src/undo.c +++ b/src/undo.c | |||
| @@ -229,10 +229,9 @@ record_first_change (void) | |||
| 229 | if (base_buffer->base_buffer) | 229 | if (base_buffer->base_buffer) |
| 230 | base_buffer = base_buffer->base_buffer; | 230 | base_buffer = base_buffer->base_buffer; |
| 231 | 231 | ||
| 232 | bset_undo_list | 232 | bset_undo_list (current_buffer, |
| 233 | (current_buffer, | 233 | Fcons (Fcons (Qt, Fvisited_file_modtime ()), |
| 234 | Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)), | 234 | BVAR (current_buffer, undo_list))); |
| 235 | BVAR (current_buffer, undo_list))); | ||
| 236 | } | 235 | } |
| 237 | 236 | ||
| 238 | /* Record a change in property PROP (whose old value was VAL) | 237 | /* Record a change in property PROP (whose old value was VAL) |