commit 964f16e1686899b7796045b10ffdb3c9b97a8153 (HEAD, refs/remotes/origin/master) Author: Stefan Monnier Date: Wed Dec 10 21:56:33 2014 -0500 * lisp/emacs-lisp/eldoc.el (eldoc-documentation-function): Change default. (eldoc-mode, eldoc-schedule-timer): Adjust to new default. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e65835c..2ed1f08 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2014-12-11 Stefan Monnier + + * emacs-lisp/eldoc.el (eldoc-documentation-function): Change default. + (eldoc-mode, eldoc-schedule-timer): Adjust to new default. + 2014-12-10 Artur Malabarba * let-alist.el: Add new package and macro. @@ -17,13 +22,12 @@ 2014-12-10 Andreas Schwab - * files.el (file-tree-walk): Use file-name-as-directory - unconditionally. + * files.el (file-tree-walk): Use file-name-as-directory unconditionally. 2014-12-10 Lars Magne Ingebrigtsen - * files.el (directory-files-recursively): Use - `file-name-all-completions' instead of `directory-files' for + * files.el (directory-files-recursively): + Use `file-name-all-completions' instead of `directory-files' for greater speed. * net/shr.el (shr-tag-object): Don't bug out on text elements in @@ -108,8 +112,8 @@ 2014-12-09 Fabián Ezequiel Gallina - * progmodes/python.el (inferior-python-mode): Set - `comint-prompt-read-only` to `t` only locally. + * progmodes/python.el (inferior-python-mode): + Set `comint-prompt-read-only` to `t` only locally. 2014-12-08 Lars Magne Ingebrigtsen diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 6dddf5b..2ee3d23 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -79,8 +79,8 @@ This has two preferred values: `upcase' or `downcase'. Actually, any name of a function which takes a string as an argument and returns another string is acceptable. -Note that if `eldoc-documentation-function' is non-nil, this variable -has no effect, unless the function handles it explicitly." +Note that this variable has no effect, unless +`eldoc-documentation-function' handles it explicitly." :type '(radio (function-item upcase) (function-item downcase) function) @@ -102,8 +102,8 @@ If value is nil, messages are always truncated to fit in a single line of display in the echo area. Function or variable symbol name may be truncated to make more of the arglist or documentation string visible. -Note that if `eldoc-documentation-function' is non-nil, this variable -has no effect, unless the function handles it explicitly." +Note that this variable has no effect, unless +`eldoc-documentation-function' handles it explicitly." :type '(radio (const :tag "Always" t) (const :tag "Never" nil) (const :tag "Yes, but truncate symbol names if it will\ @@ -186,7 +186,7 @@ expression point is on." :group 'eldoc :lighter eldoc-minor-mode-string (setq eldoc-last-message nil) (cond - ((not eldoc-documentation-function) + ((memq eldoc-documentation-function '(nil ignore)) (message "There is no ElDoc support in this buffer") (setq eldoc-mode nil)) (eldoc-mode @@ -225,7 +225,9 @@ expression point is on." eldoc-idle-delay t (lambda () (when (or eldoc-mode - (and global-eldoc-mode eldoc-documentation-function)) + (and global-eldoc-mode + (not (memq eldoc-documentation-function + '(nil ignore))))) (eldoc-print-current-symbol-info)))))) ;; If user has changed the idle delay, update the timer. @@ -321,7 +323,7 @@ Otherwise work like `message'." ;;;###autoload -(defvar eldoc-documentation-function nil +(defvar eldoc-documentation-function #'ignore "Function to call to return doc string. The function of no args should return a one-line string for displaying doc about a function etc. appropriate to the context around point. commit 7b244600872bda831a2d80c4797b8fb13b73197c Author: Glenn Morris Date: Wed Dec 10 16:18:46 2014 -0500 * lisp/let-alist.el: Cosmetic changes. diff --git a/lisp/let-alist.el b/lisp/let-alist.el index 1cf5c27..982dd2e 100644 --- a/lisp/let-alist.el +++ b/lisp/let-alist.el @@ -1,4 +1,4 @@ -;;; let-alist.el --- Easily let-bind values of an assoc-list by their names. +;;; let-alist.el --- Easily let-bind values of an assoc-list by their names ;; Copyright (C) 2014 Free Software Foundation, Inc. @@ -9,8 +9,23 @@ ;; Prefix: let-alist ;; Separator: - +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + ;;; Commentary: -;; + ;; This package offers a single macro, `let-alist'. This macro takes a ;; first argument (whose value must be an alist) and a body. ;; @@ -39,28 +54,11 @@ ;; invocations, the inner one can't access the variables of the outer ;; one. -;;; License: -;; -;; This file is part of GNU Emacs. -;; -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - ;;; Code: (defun let-alist--deep-dot-search (data) - "Return alist of symbols inside DATA which start with a `.'. + "Return alist of symbols inside DATA that start with a `.'. Perform a deep search and return an alist where each car is the symbol, and each cdr is the same symbol without the `.'." (cond @@ -77,9 +75,8 @@ symbol, and each cdr is the same symbol without the `.'." ;;;###autoload (defmacro let-alist (alist &rest body) "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. -Dotted symbol is any symbol starting with a `.'. Only those -present in BODY are let-bound and this search is done at compile -time. +Dotted symbol is any symbol starting with a `.'. Only those present +in BODY are let-bound and this search is done at compile time. For instance, the following code @@ -103,8 +100,4 @@ expands to (provide 'let-alist) -;; Local Variables: -;; sentence-end-double-space: t -;; End: - ;;; let-alist.el ends here commit 98582c0079ea51b7cbadbec9021a4d07f807faf0 Author: Glenn Morris Date: Wed Dec 10 16:17:44 2014 -0500 ChangeLog fixes diff --git a/ChangeLog b/ChangeLog index 88654dc..ee109f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,18 +1,14 @@ 2014-12-06 Stephen Leake - * CONTRIBUTE: improve; add explicit web references, move some info + * CONTRIBUTE: Improve; add explicit web references, move some info from admin/notes/* here. * INSTALL.REPO: You can't "just run make" after a clean checkout. - * admin/notes/commits: deleted; merged into ./CONTRIBUTE - - * admin/notes/repo: move commit, branch info into ./CONTRIBUTE - 2014-12-05 Stephen Leake - * etc/CONTRIBUTE: renamed to ./CONTRIBUTE, preparatory to further - changes/cleanup + * CONTRIBUTE: Move here from etc/, preparatory to further + changes/cleanup. 2014-12-05 Paul Eggert diff --git a/admin/ChangeLog b/admin/ChangeLog index 00279a4..360e2f1 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog @@ -1,3 +1,9 @@ +2014-12-06 Stephen Leake + + * notes/commits: Delete; merge into ./CONTRIBUTE. + + * notes/repo: Move commit, branch info into ./CONTRIBUTE. + 2014-12-01 Glenn Morris * update_autogen: Fix bogosity introduced in 2014-11-16 merge. diff --git a/etc/ChangeLog b/etc/ChangeLog index 9ac0d00..f56fb4e 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -6,6 +6,10 @@ * NEWS: Mention the new eww `S' command. +2014-12-05 Stephen Leake + + * CONTRIBUTE: Move to ../. + 2014-12-05 Lars Magne Ingebrigtsen * NEWS: Add some doc markers to the eww stuff. commit a5b477aa92e4b76896efa57f9bd62912bd92dd02 Author: Artur Malabarba Date: Wed Dec 10 10:15:22 2014 -0500 Add let-alist macro and package. * let-alist.el: Add new package and macro. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index d5f2254..e65835c 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,7 @@ +2014-12-10 Artur Malabarba + + * let-alist.el: Add new package and macro. + 2014-12-10 Eric S. Raymond * vc/vc-dispatcher.el, vc/vc-hooks.el, vc/vc-rcs.el, diff --git a/lisp/let-alist.el b/lisp/let-alist.el new file mode 100644 index 0000000..1cf5c27 --- /dev/null +++ b/lisp/let-alist.el @@ -0,0 +1,110 @@ +;;; let-alist.el --- Easily let-bind values of an assoc-list by their names. + +;; Copyright (C) 2014 Free Software Foundation, Inc. + +;; Author: Artur Malabarba +;; Maintainer: Artur Malabarba +;; Version: 1.0 +;; Keywords: extensions lisp +;; Prefix: let-alist +;; Separator: - + +;;; Commentary: +;; +;; This package offers a single macro, `let-alist'. This macro takes a +;; first argument (whose value must be an alist) and a body. +;; +;; The macro expands to a let form containing body, where each dotted +;; symbol inside body is let-bound to their cdrs in the alist. Dotted +;; symbol is any symbol starting with a `.'. Only those present in +;; the body are let-bound and this search is done at compile time. +;; +;; For instance, the following code +;; +;; (let-alist alist +;; (if (and .title .body) +;; .body +;; .site)) +;; +;; expands to +;; +;; (let ((.title (cdr (assq 'title alist))) +;; (.body (cdr (assq 'body alist))) +;; (.site (cdr (assq 'site alist)))) +;; (if (and .title .body) +;; .body +;; .site)) +;; +;; Note that only one level is supported. If you nest `let-alist' +;; invocations, the inner one can't access the variables of the outer +;; one. + +;;; License: +;; +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + + +(defun let-alist--deep-dot-search (data) + "Return alist of symbols inside DATA which start with a `.'. +Perform a deep search and return an alist where each car is the +symbol, and each cdr is the same symbol without the `.'." + (cond + ((symbolp data) + (let ((name (symbol-name data))) + (when (string-match "\\`\\." name) + ;; Return the cons cell inside a list, so it can be appended + ;; with other results in the clause below. + (list (cons data (intern (replace-match "" nil nil name))))))) + ((not (listp data)) nil) + (t (apply #'append + (remove nil (mapcar #'let-alist--deep-dot-search data)))))) + +;;;###autoload +(defmacro let-alist (alist &rest body) + "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. +Dotted symbol is any symbol starting with a `.'. Only those +present in BODY are let-bound and this search is done at compile +time. + +For instance, the following code + + (let-alist alist + (if (and .title .body) + .body + .site)) + +expands to + + (let ((.title (cdr (assq 'title alist))) + (.body (cdr (assq 'body alist))) + (.site (cdr (assq 'site alist)))) + (if (and .title .body) + .body + .site))" + (declare (indent 1) (debug t)) + `(let ,(mapcar (lambda (x) `(,(car x) (cdr (assq ',(cdr x) ,alist)))) + (delete-dups (let-alist--deep-dot-search body))) + ,@body)) + +(provide 'let-alist) + +;; Local Variables: +;; sentence-end-double-space: t +;; End: + +;;; let-alist.el ends here commit f3e16cbb5258fcbe2969eb48b332b2c629cfb2a6 Author: Eli Zaretskii Date: Wed Dec 10 19:39:37 2014 +0200 Fix out-of-memory condition in display of long bracketed lines (bug#19322) src/bidi.c (BIDI_CACHE_MAX_ELTS_PER_SLOT): New macro. (bidi_cache_max_elts): New global variable. (bidi_shelve_header_size): Add the sizeof bidi_cache_max_elts. (bidi_cache_shrink, bidi_initialize): Reset bidi_cache_max_elts to its initial value. (bidi_cache_search): Handle overflown cache. Improve commentary. (bidi_cache_ensure_space): Limit allocations to the current value of bidi_cache_max_elts. Force xpalloc not to over-allocate. If less than a full BIDI_CACHE_CHUNK is left to the limit, decrease the increment to not exceed the limit. (bidi_cache_iterator_state): Now returns non-zero if succeeded to cache, zero otherwise (meaning the cache overflowed). In the latter case, set bidi_cache_last_idx to -1. (bidi_peek_at_next_level): Handle overflown cache. (bidi_push_it): Increase the cache limit for iterating the new object. (bidi_pop_it): Decrease the cache limit back to previous value. (bidi_shelve_cache): Shelve the current value of the cache limit. (bidi_unshelve_cache): Restore the value of cache limit. (bidi_find_bracket_pairs): If the cache overflows while looking for the paired bracket, give up and let bidi_resolve_neutrals process the bracket as a simple neutral. (bidi_find_other_level_edge): If the cache overflows, fall back on Plan B, which effectively stops the reordering and restarts it on the next character (after resetting the cache). (bidi_move_to_visually_next): When the cache overflows, reset it after processing the last cached character. diff --git a/src/ChangeLog b/src/ChangeLog index 09268d1..2a6e237 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,33 @@ +2014-12-10 Eli Zaretskii + + * bidi.c (BIDI_CACHE_MAX_ELTS_PER_SLOT): New macro. + (bidi_cache_max_elts): New global variable. + (bidi_shelve_header_size): Add the sizeof bidi_cache_max_elts. + (bidi_cache_shrink, bidi_initialize): Reset bidi_cache_max_elts to + its initial value. + (bidi_cache_search): Handle overflown cache. Improve commentary. + (bidi_cache_ensure_space): Limit allocations to the current value + of bidi_cache_max_elts. Force xpalloc not to over-allocate. If + less than a full BIDI_CACHE_CHUNK is left to the limit, decrease + the increment to not exceed the limit. + (bidi_cache_iterator_state): Now returns non-zero if succeeded to + cache, zero otherwise (meaning the cache overflowed). In the + latter case, set bidi_cache_last_idx to -1. + (bidi_peek_at_next_level): Handle overflown cache. + (bidi_push_it): Increase the cache limit for iterating the new + object. + (bidi_pop_it): Decrease the cache limit back to previous value. + (bidi_shelve_cache): Shelve the current value of the cache limit. + (bidi_unshelve_cache): Restore the value of cache limit. + (bidi_find_bracket_pairs): If the cache overflows while looking + for the paired bracket, give up and let bidi_resolve_neutrals + process the bracket as a simple neutral. (Bug#19322) + (bidi_find_other_level_edge): If the cache overflows, fall back on + Plan B, which effectively stops the reordering and restarts it on + the next character (after resetting the cache). + (bidi_move_to_visually_next): When the cache overflows, reset it + after processing the last cached character. + 2014-12-10 Paul Eggert Fix glitches in gnutls.c, mostly memory-related diff --git a/src/bidi.c b/src/bidi.c index cc70d08..0d291fc 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -546,6 +546,30 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) characters). 200 was chosen as an upper limit for reasonably-long lines in a text file/buffer. */ #define BIDI_CACHE_CHUNK 200 +/* Maximum size we allow the cache to become, per iterator stack slot, + in units of struct bidi_it size. If we allow unlimited growth, we + could run out of memory for pathologically long bracketed text or + very long text lines that need to be reordered. This is aggravated + when word-wrap is in effect, since then functions display_line and + move_it_in_display_line_to need to keep up to 4 copies of the + cache. + + This limitation means there can be no more than that amount of + contiguous RTL text on any single physical line in a LTR paragraph, + and similarly with contiguous LTR + numeric text in a RTL + paragraph. (LTR text in a LTR paragraph and RTL text in a RTL + paragraph are not reordered, and so don't need the cache, and + cannot hit this limit.) More importantly, no single line can have + text longer than this inside paired brackets (because bracket pairs + resolution uses the cache). If the limit is exceeded, the fallback + code will produce visual order that will be incorrect if there are + RTL characters in the offending line of text. */ +/* Do we need to allow customization of this limit? */ +#define BIDI_CACHE_MAX_ELTS_PER_SLOT 50000 +#if BIDI_CACHE_CHUNK >= BIDI_CACHE_MAX_ELTS_PER_SLOT +# error BIDI_CACHE_CHUNK must be less than BIDI_CACHE_MAX_ELTS_PER_SLOT +#endif +static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; static struct bidi_it *bidi_cache; static ptrdiff_t bidi_cache_size = 0; enum { elsz = sizeof (struct bidi_it) }; @@ -566,7 +590,7 @@ enum bidi_shelve_header_size = (sizeof (bidi_cache_idx) + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start) - + sizeof (bidi_cache_last_idx)) + + sizeof (bidi_cache_last_idx) + sizeof (bidi_cache_max_elts)) }; /* Effectively remove the cached states beyond the Nth state from the @@ -604,6 +628,7 @@ bidi_cache_shrink (void) bidi_cache_size = BIDI_CACHE_CHUNK; } bidi_cache_reset (); + bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; } static void @@ -622,7 +647,9 @@ bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it) /* Find a cached state with a given CHARPOS and resolved embedding level less or equal to LEVEL. If LEVEL is -1, disregard the resolved levels in cached states. DIR, if non-zero, means search - in that direction from the last cache hit. */ + in that direction from the last cache hit. + + Value is the index of the cached state, or -1 if not found. */ static ptrdiff_t bidi_cache_search (ptrdiff_t charpos, int level, int dir) { @@ -696,7 +723,8 @@ bidi_cache_find_level_change (int level, int dir, bool before) ptrdiff_t i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1; int incr = before ? 1 : 0; - eassert (!dir || bidi_cache_last_idx >= 0); + if (i < 0) /* cache overflowed? */ + i = 0; if (!dir) dir = -1; @@ -734,23 +762,37 @@ bidi_cache_ensure_space (ptrdiff_t idx) /* Enlarge the cache as needed. */ if (idx >= bidi_cache_size) { - /* The bidi cache cannot be larger than the largest Lisp string - or buffer. */ - ptrdiff_t string_or_buffer_bound - = max (BUF_BYTES_MAX, STRING_BYTES_BOUND); + ptrdiff_t chunk_size = BIDI_CACHE_CHUNK; - /* Also, it cannot be larger than what C can represent. */ - ptrdiff_t c_bound - = (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz; + if (bidi_cache_size > bidi_cache_max_elts - chunk_size) + chunk_size = bidi_cache_max_elts - bidi_cache_size; - bidi_cache - = xpalloc (bidi_cache, &bidi_cache_size, - max (BIDI_CACHE_CHUNK, idx - bidi_cache_size + 1), - min (string_or_buffer_bound, c_bound), elsz); + if (max (idx + 1, + bidi_cache_size + chunk_size) <= bidi_cache_max_elts) + { + /* The bidi cache cannot be larger than the largest Lisp + string or buffer. */ + ptrdiff_t string_or_buffer_bound + = max (BUF_BYTES_MAX, STRING_BYTES_BOUND); + + /* Also, it cannot be larger than what C can represent. */ + ptrdiff_t c_bound + = (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz; + ptrdiff_t max_elts = bidi_cache_max_elts; + + max_elts = min (max_elts, min (string_or_buffer_bound, c_bound)); + + /* Force xpalloc not to over-allocate by passing it MAX_ELTS + as its 4th argument. */ + bidi_cache = xpalloc (bidi_cache, &bidi_cache_size, + max (chunk_size, idx - bidi_cache_size + 1), + max_elts, elsz); + eassert (bidi_cache_size > idx); + } } } -static void +static int bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, bool update_only) { @@ -762,7 +804,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, idx = bidi_cache_search (bidi_it->charpos, -1, 1); if (idx < 0 && update_only) - return; + return 0; if (idx < 0) { @@ -771,19 +813,23 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, /* Character positions should correspond to cache positions 1:1. If we are outside the range of cached positions, the cache is useless and must be reset. */ - if (idx > bidi_cache_start && - (bidi_it->charpos > (bidi_cache[idx - 1].charpos - + bidi_cache[idx - 1].nchars) - || bidi_it->charpos < bidi_cache[bidi_cache_start].charpos)) + if (bidi_cache_start < idx && idx < bidi_cache_size + && (bidi_it->charpos > (bidi_cache[idx - 1].charpos + + bidi_cache[idx - 1].nchars) + || bidi_it->charpos < bidi_cache[bidi_cache_start].charpos)) { bidi_cache_reset (); idx = bidi_cache_start; } if (bidi_it->nchars <= 0) emacs_abort (); - bidi_copy_it (&bidi_cache[idx], bidi_it); - if (!resolved) - bidi_cache[idx].resolved_level = -1; + /* Don't cache if no available space in the cache. */ + if (bidi_cache_size > idx) + { + bidi_copy_it (&bidi_cache[idx], bidi_it); + if (!resolved) + bidi_cache[idx].resolved_level = -1; + } } else { @@ -806,9 +852,19 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved, bidi_cache[idx].bracket_enclosed_type = bidi_it->bracket_enclosed_type; } - bidi_cache_last_idx = idx; - if (idx >= bidi_cache_idx) - bidi_cache_idx = idx + 1; + if (bidi_cache_size > idx) + { + bidi_cache_last_idx = idx; + if (idx >= bidi_cache_idx) + bidi_cache_idx = idx + 1; + return 1; + } + else + { + /* The cache overflowed. */ + bidi_cache_last_idx = -1; + return 0; + } } /* Look for a cached iterator state that corresponds to CHARPOS. If @@ -846,8 +902,13 @@ bidi_cache_find (ptrdiff_t charpos, bool resolved_only, struct bidi_it *bidi_it) static int bidi_peek_at_next_level (struct bidi_it *bidi_it) { - if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1) + if (bidi_cache_idx == bidi_cache_start) emacs_abort (); + /* If the cache overflowed, return the level of the last cached + character. */ + if (bidi_cache_last_idx == -1 + || (bidi_cache_last_idx >= bidi_cache_idx - 1 && bidi_it->scan_dir > 0)) + return bidi_cache[bidi_cache_idx - 1].resolved_level; return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level; } @@ -864,6 +925,8 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it) void bidi_push_it (struct bidi_it *bidi_it) { + /* Give this stack slot its cache room. */ + bidi_cache_max_elts += BIDI_CACHE_MAX_ELTS_PER_SLOT; /* Save the current iterator state in its entirety after the last used cache slot. */ bidi_cache_ensure_space (bidi_cache_idx); @@ -900,6 +963,9 @@ bidi_pop_it (struct bidi_it *bidi_it) /* Invalidate the last-used cache slot data. */ bidi_cache_last_idx = -1; + + bidi_cache_max_elts -= BIDI_CACHE_MAX_ELTS_PER_SLOT; + eassert (bidi_cache_max_elts > 0); } static ptrdiff_t bidi_cache_total_alloc; @@ -939,6 +1005,11 @@ bidi_shelve_cache (void) + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start), &bidi_cache_last_idx, sizeof (bidi_cache_last_idx)); + memcpy (databuf + sizeof (bidi_cache_idx) + + bidi_cache_idx * sizeof (struct bidi_it) + + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) + + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx), + &bidi_cache_max_elts, sizeof (bidi_cache_max_elts)); return databuf; } @@ -960,6 +1031,7 @@ bidi_unshelve_cache (void *databuf, bool just_free) /* A NULL pointer means an empty cache. */ bidi_cache_start = 0; bidi_cache_sp = 0; + bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; bidi_cache_reset (); } } @@ -999,6 +1071,12 @@ bidi_unshelve_cache (void *databuf, bool just_free) + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start), sizeof (bidi_cache_last_idx)); + memcpy (&bidi_cache_max_elts, + p + sizeof (bidi_cache_idx) + + bidi_cache_idx * sizeof (struct bidi_it) + + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) + + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx), + sizeof (bidi_cache_max_elts)); bidi_cache_total_alloc -= (bidi_shelve_header_size + bidi_cache_idx * sizeof (struct bidi_it)); @@ -1045,6 +1123,7 @@ bidi_initialize (void) bidi_cache_sp = 0; bidi_cache_total_alloc = 0; + bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; bidi_initialized = 1; } @@ -2459,6 +2538,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) struct bidi_it tem_it; bool l2r_seen = false, r2l_seen = false; ptrdiff_t pairing_pos; + int idx_at_entry = bidi_cache_idx; eassert (MAX_BPA_STACK >= 100); bidi_copy_it (&saved_it, bidi_it); @@ -2483,7 +2563,15 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) levels below). */ if (btype == BIDI_BRACKET_OPEN && bidi_it->bracket_pairing_pos == -1) bidi_it->bracket_pairing_pos = bidi_it->charpos; - bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + if (!bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0)) + { + /* No more space in cache -- give up and let the opening + bracket that started this be processed as a + NEUTRAL_ON. */ + bidi_cache_reset_to (idx_at_entry - bidi_cache_start); + bidi_copy_it (bidi_it, &saved_it); + goto give_up; + } if (btype == BIDI_BRACKET_OPEN) PUSH_BPA_STACK; else if (btype == BIDI_BRACKET_CLOSE) @@ -2572,7 +2660,16 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) { if (maxlevel < bidi_it->level_stack[bidi_it->stack_idx].level) maxlevel = bidi_it->level_stack[bidi_it->stack_idx].level; - bidi_cache_iterator_state (bidi_it, type == NEUTRAL_B, 0); + if (!bidi_cache_iterator_state (bidi_it, + type == NEUTRAL_B, 0)) + { + /* No more space in cache -- give up and let the + opening bracket that started this be + processed as any other NEUTRAL_ON. */ + bidi_cache_reset_to (idx_at_entry - bidi_cache_start); + bidi_copy_it (bidi_it, &saved_it); + goto give_up; + } type = bidi_resolve_weak (bidi_it); } } @@ -2648,6 +2745,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) } } + give_up: return retval; } @@ -3210,10 +3308,35 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) if (end_flag) emacs_abort (); - bidi_cache_iterator_state (bidi_it, 1, 0); + if (!bidi_cache_iterator_state (bidi_it, 1, 0)) + { + /* Can't happen: if the cache needs to grow, it means we + were at base embedding level, so the cache should have + been either empty or already large enough to cover this + character position. */ + emacs_abort (); + } do { new_level = bidi_level_of_next_char (bidi_it); - bidi_cache_iterator_state (bidi_it, 1, 0); + /* If the cache is full, perform an emergency return by + pretending that the level ended. */ + if (!bidi_cache_iterator_state (bidi_it, 1, 0)) + { + new_level = level - 1; + /* Since the cache should only grow when we are scanning + forward looking for the edge of the level that is one + above the base embedding level, we can only have this + contingency when LEVEL - 1 is the base embedding + level. */ + eassert (new_level == bidi_it->level_stack[0].level); + /* Plan B, for when the cache overflows: Back up to the + previous character by fetching the last cached state, + and force the resolved level of that character be the + base embedding level. */ + bidi_cache_fetch_state (bidi_cache_idx - 1, bidi_it); + bidi_it->resolved_level = new_level; + bidi_cache_iterator_state (bidi_it, 1, 1); + } } while (new_level >= level); } } @@ -3367,6 +3490,12 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) && bidi_it->charpos > (bidi_cache[bidi_cache_idx - 1].charpos + bidi_cache[bidi_cache_idx - 1].nchars - 1)) bidi_cache_reset (); + /* Also reset the cache if it overflowed and we have just + emergency-exited using Plan B. */ + else if (bidi_it->resolved_level == bidi_it->level_stack[0].level + && bidi_cache_idx >= bidi_cache_size + && bidi_it->charpos == bidi_cache[bidi_cache_idx - 1].charpos) + bidi_cache_reset (); /* But as long as we are caching during forward scan, we must cache each state, or else the cache integrity will be compromised: it assumes cached states correspond to buffer commit 8bc7ac5c25f42b745cc90131a9a456f763582dbf Author: Eric S. Raymond Date: Wed Dec 10 12:33:26 2014 -0500 Righteous featurectomy of vc-keep-workfiles - always do it. * vc/vc-dispatcher.el, vc/vc-hooks.el, vc/vc-rcs.el, vc/vc-sccs.el, vc/vc.el: Righteous featurectomy of vc-keep-workfiles, it's a shoot-self-in-foot archaism. Workfiles are always kept. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 53c03e0..d5f2254 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,10 @@ +2014-12-10 Eric S. Raymond + + * vc/vc-dispatcher.el, vc/vc-hooks.el, vc/vc-rcs.el, + vc/vc-sccs.el, vc/vc.el: Righteous featurectomy of + vc-keep-workfiles, it's a shoot-self-in-foot archaism. + Workfiles are always kept. + 2014-12-10 Rasmus Pank Roulund * net/ange-ftp.el (ange-ftp-switches-ok): Disallow flags causing diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index d2125d5..e1bf05c8 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -702,7 +702,7 @@ the buffer contents as a comment." ;; Now make sure we see the expanded headers (when log-fileset (mapc - (lambda (file) (vc-resynch-buffer file vc-keep-workfiles t)) + (lambda (file) (vc-resynch-buffer file t t)) log-fileset)) (when (vc-dispatcher-browsing) (vc-dir-move-to-goal-column)) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 9a4fe16..0ffca56 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -164,13 +164,6 @@ Otherwise, not displayed." :type 'boolean :group 'vc) -(defcustom vc-keep-workfiles t - "Whether to keep work files on disk after commits, on a locking VCS. -This variable has no effect on modern merging-based version -control systems." - :type 'boolean - :group 'vc) - ;;; This is handled specially now. ;; Tell Emacs about this new kind of minor mode ;; (add-to-list 'minor-mode-alist '(vc-mode vc-mode)) diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el index 20b292f..9bb9af1 100644 --- a/lisp/vc/vc-rcs.el +++ b/lisp/vc/vc-rcs.el @@ -226,12 +226,10 @@ When VERSION is given, perform check for that version." (defun vc-rcs-register (files &optional comment) "Register FILES into the RCS version-control system. +Automatically retrieve a read-only version of the file with keywords expanded. COMMENT can be used to provide an initial description for each FILES. Passes either `vc-rcs-register-switches' or `vc-register-switches' -to the RCS command. - -Automatically retrieve a read-only version of the file with keywords -expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile." +to the RCS command." (let (subdir name) (dolist (file files) (and (not (file-exists-p @@ -244,6 +242,7 @@ expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile." (apply #'vc-do-command "*vc*" 0 "ci" file ;; if available, use the secure registering option (and (vc-rcs-release-p "5.6.4") "-i") + "-u" (and comment (concat "-t-" comment)) (vc-switches 'RCS 'register)) ;; parse output to find master file name and workfile version @@ -328,7 +327,7 @@ whether to remove it." (apply #'vc-do-command "*vc*" 0 "ci" (vc-master-name file) ;; if available, use the secure check-in option (and (vc-rcs-release-p "5.6.4") "-j") - (concat (if vc-keep-workfiles "-u" "-r") rev) + (concat "-u" rev) (concat "-m" comment) switches) (vc-file-setprop file 'vc-working-revision nil) diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el index c7144c0..a8e122d 100644 --- a/lisp/vc/vc-sccs.el +++ b/lisp/vc/vc-sccs.el @@ -195,12 +195,10 @@ Optional string REV is a revision." (defun vc-sccs-register (files &optional comment) "Register FILES into the SCCS version-control system. +Automatically retrieve a read-only version of the files with keywords expanded. COMMENT can be used to provide an initial description of FILES. Passes either `vc-sccs-register-switches' or `vc-register-switches' -to the SCCS command. - -Automatically retrieve a read-only version of the files with keywords -expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile." +to the SCCS command." (dolist (file files) (let* ((dirname (or (file-name-directory file) "")) (basename (file-name-nondirectory file)) @@ -214,8 +212,7 @@ expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile." (and comment (concat "-y" comment)) (vc-switches 'SCCS 'register))) (delete-file file) - (if vc-keep-workfiles - (vc-sccs-do-command nil 0 "get" (vc-master-name file)))))) + (vc-sccs-do-command nil 0 "get" (vc-master-name file))))) (defun vc-sccs-responsible-p (file) "Return non-nil if SCCS thinks it would be responsible for registering FILE." @@ -230,8 +227,7 @@ expanded if `vc-keep-workfiles' is non-nil, otherwise, delete the workfile." (apply 'vc-sccs-do-command nil 0 "delta" (vc-master-name file) (concat "-y" comment) (vc-switches 'SCCS 'checkin)) - (if vc-keep-workfiles - (vc-sccs-do-command nil 0 "get" (vc-master-name file))))) + (vc-sccs-do-command nil 0 "get" (vc-master-name file)))) (defun vc-sccs-find-revision (file rev buffer) (apply 'vc-sccs-do-command diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 6e0e2c6..3ea4809 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1111,8 +1111,7 @@ For old-style locking-based version control systems, like RCS: If every file is registered and unlocked, check out (lock) the file(s) for editing. If every file is locked by you and has changes, pop up a - *vc-log* buffer to check in the changes. If the variable - `vc-keep-workfiles' is non-nil (the default), leave a + *vc-log* buffer to check in the changes. Leave a read-only copy of each changed file after checking in. If every file is locked by you and unchanged, unlock them. If every file is locked by someone else, offer to steal the lock." @@ -1353,7 +1352,7 @@ first backend that could register the file is used." ;; (make-local-variable 'backup-inhibited) ;; (setq backup-inhibited t)) - (vc-resynch-buffer file vc-keep-workfiles t)) + (vc-resynch-buffer file t t)) files) (when (derived-mode-p 'vc-dir-mode) (vc-dir-move-to-goal-column)) @@ -1516,9 +1515,6 @@ buffer is popped up to accept a comment. If INITIAL-CONTENTS is non-nil, then COMMENT is used as the initial contents of the log entry buffer. -If `vc-keep-workfiles' is nil, FILE is deleted afterwards, provided -that the version control system supports this mode of operation. - Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'." (when vc-before-checkin-hook (run-hooks 'vc-before-checkin-hook)) commit bdc373bf456de464b44836b11826705c0aef70b1 Author: Rasmus Pank Roulund Date: Wed Dec 10 17:47:53 2014 +0100 (ange-ftp-switches-ok): Disallow flags causing trouble with ls over ftp. Fixes: debbugs:19192 * net/ange-ftp.el (ange-ftp-switches-ok): Disallow flags causing trouble with ls over ftp. These flags result in ls returning no output, causing Tramp-breakage. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 454ee00..53c03e0 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,9 @@ +2014-12-10 Rasmus Pank Roulund + + * net/ange-ftp.el (ange-ftp-switches-ok): Disallow flags causing + trouble with ls over ftp. These flags result in ls returning no + output, causing Tramp-breakage. (bug#19192) + 2014-12-10 Andreas Schwab * files.el (file-tree-walk): Use file-name-as-directory diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index d7632ed..db79c0d 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -2831,16 +2831,24 @@ match subdirectories as well.") files ange-ftp-files-hashtable))) (defun ange-ftp-switches-ok (switches) - "Return SWITCHES (a string) if suitable for our use." + "Return SWITCHES (a string) if suitable for use with ls over ftp." (and (stringp switches) - ;; We allow the A switch, which lists all files except "." and - ;; "..". This is OK because we manually insert these entries - ;; in the hash table. + ;; We allow the --almost-all switch, which lists all files + ;; except "." and "..". This is OK because we manually + ;; insert these entries in the hash table. (string-match - "--\\(almost-\\)?all\\>\\|\\(\\`\\| \\)-[[:alpha:]]*[aA]" switches) + "--\\(almost-\\)?all\\>\\|\\(\\`\\| \\)-[[:alpha:]]*[aA]" + switches) + ;; Disallow other long flags except --(almost-)all. + (not (string-match "\\(\\`\\| \\)--\\w+" + (replace-regexp-in-string + "--\\(almost-\\)?all\\>" "" + switches))) + ;; Must include 'l'. (string-match "\\(\\`\\| \\)-[[:alpha:]]*l" switches) + ;; Disallow recursive flag. (not (string-match - "--recursive\\>\\|\\(\\`\\| \\)-[[:alpha:]]*R" switches)) + "\\(\\`\\| \\)-[[:alpha:]]*R" switches)) switches)) (defun ange-ftp-get-files (directory &optional no-error)