Merge from origin/emacs-25
50fa7d6
;* src/w32heap.c: Fix typo and wording of the comments.6f1325e
electric-quote mode no longer worries about codingc2a1792
* src/regex.c (re_search_2): Make new code safe for -Wjump-mi...f6134bb
Port to GCC 6.2.1 + --enable-gcc-warningsb2ba630
Explain how to debug emacsclient lisp errors9da53e2
Let describe-function work for lambda again5c2da93
Fix kill-line's docstringad66b3f
Fix handling of allocation in regex matching5a26c9b
* lisp/electric.el (electric-quote-mode): Improve doc (Bug#24...3877c91
vc-region-history: Search just on lines intersecting the region8988327
Fix documentation of 'alist-get'b6998ea
* src/regex.h (re_match_object): Improve commentary. # Conflicts: # etc/NEWS # lisp/help-fns.el
This commit is contained in:
commit
394bdb8f23
12 changed files with 156 additions and 65 deletions
|
@ -422,9 +422,7 @@ portable; curved quotes are less ambiguous and typically look nicer.
|
|||
|
||||
Electric Quote mode makes it easier to type curved quotes. As you
|
||||
type characters it optionally converts @t{`} to @t{‘}, @t{'} to @t{’},
|
||||
@t{``} to @t{“}, and @t{''} to @t{”}. These conversions are
|
||||
suppressed in buffers whose coding systems cannot represent curved
|
||||
quote characters.
|
||||
@t{``} to @t{“}, and @t{''} to @t{”}.
|
||||
|
||||
@vindex electric-quote-paragraph
|
||||
@vindex electric-quote-comment
|
||||
|
|
|
@ -152,6 +152,13 @@ presence of @code{condition-case}. (To invoke the debugger, the error
|
|||
must still fulfill the criteria specified by @code{debug-on-error} and
|
||||
@code{debug-ignored-errors}.)
|
||||
|
||||
@cindex emacsclient, getting a backtrace
|
||||
@cindex backtrace from emacsclient's @option{--eval}
|
||||
For example, setting this variable is useful to get a backtrace from
|
||||
code evaluated by emacsclient's @option{--eval} option. If Lisp code
|
||||
evaluated by emacsclient signals an error while this variable is
|
||||
non-@code{nil}, the backtrace will popup in the running Emacs.
|
||||
|
||||
@strong{Warning:} Setting this variable to non-@code{nil} may have
|
||||
annoying effects. Various parts of Emacs catch errors in the normal
|
||||
course of affairs, and you may not even realize that errors happen
|
||||
|
|
|
@ -1556,15 +1556,15 @@ keys may not be symbols:
|
|||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun alist-get key value &optional default remove
|
||||
@defun alist-get key alist &optional default remove
|
||||
This function is like @code{assq}, but instead of returning the entire
|
||||
association for @var{key}, @code{(@var{key} . @var{value})}, it
|
||||
returns just the @var{value}. If @var{key} is not found in
|
||||
@var{alist} it returns @var{default}.
|
||||
association for @var{key} in @var{alist},
|
||||
@w{@code{(@var{key} . @var{value})}}, it returns just the @var{value}.
|
||||
If @var{key} is not found in @var{alist}, it returns @var{default}.
|
||||
|
||||
This is a generalized variable (@pxref{Generalized Variables}) that
|
||||
can be used to change a value with @code{setf}. When using it to set
|
||||
a value, optional argument @var{remove} non-nil means to remove
|
||||
a value, optional argument @var{remove} non-@code{nil} means to remove
|
||||
@var{key} from @var{alist} if the new value is @code{eql} to @var{default}.
|
||||
@end defun
|
||||
|
||||
|
|
|
@ -430,12 +430,6 @@ The variable `electric-layout-rules' says when and how to insert newlines."
|
|||
:version "25.1"
|
||||
:type 'boolean :safe 'booleanp :group 'electricity)
|
||||
|
||||
(defun electric--insertable-p (string)
|
||||
(or (not buffer-file-coding-system)
|
||||
(eq (coding-system-base buffer-file-coding-system) 'undecided)
|
||||
(not (unencodable-char-position nil nil buffer-file-coding-system
|
||||
nil string))))
|
||||
|
||||
(defun electric-quote-post-self-insert-function ()
|
||||
"Function that `electric-quote-mode' adds to `post-self-insert-hook'.
|
||||
This requotes when a quoting key is typed."
|
||||
|
@ -460,8 +454,7 @@ This requotes when a quoting key is typed."
|
|||
(when start
|
||||
(save-excursion
|
||||
(if (eq last-command-event ?\`)
|
||||
(cond ((and (electric--insertable-p "“")
|
||||
(search-backward "‘`" (- (point) 2) t))
|
||||
(cond ((search-backward "‘`" (- (point) 2) t)
|
||||
(replace-match "“")
|
||||
(when (and electric-pair-mode
|
||||
(eq (cdr-safe
|
||||
|
@ -469,16 +462,13 @@ This requotes when a quoting key is typed."
|
|||
(char-after)))
|
||||
(delete-char 1))
|
||||
(setq last-command-event ?“))
|
||||
((and (electric--insertable-p "‘")
|
||||
(search-backward "`" (1- (point)) t))
|
||||
((search-backward "`" (1- (point)) t)
|
||||
(replace-match "‘")
|
||||
(setq last-command-event ?‘)))
|
||||
(cond ((and (electric--insertable-p "”")
|
||||
(search-backward "’'" (- (point) 2) t))
|
||||
(cond ((search-backward "’'" (- (point) 2) t)
|
||||
(replace-match "”")
|
||||
(setq last-command-event ?”))
|
||||
((and (electric--insertable-p "’")
|
||||
(search-backward "'" (1- (point)) t))
|
||||
((search-backward "'" (1- (point)) t)
|
||||
(replace-match "’")
|
||||
(setq last-command-event ?’)))))))))
|
||||
|
||||
|
|
|
@ -106,23 +106,24 @@ to get buffer-local values.")
|
|||
|
||||
;;;###autoload
|
||||
(defun describe-function (function)
|
||||
"Display the full documentation of FUNCTION (a symbol)."
|
||||
"Display the full documentation of FUNCTION (a symbol).
|
||||
When called from lisp, FUNCTION may also be a function object."
|
||||
(interactive
|
||||
(let ((fn (function-called-at-point))
|
||||
(enable-recursive-minibuffers t)
|
||||
val)
|
||||
(setq val (completing-read (if fn
|
||||
(format "Describe function (default %s): " fn)
|
||||
"Describe function: ")
|
||||
#'help--symbol-completion-table
|
||||
#'fboundp
|
||||
t nil nil (and fn (symbol-name fn))))
|
||||
(list (if (equal val "")
|
||||
fn (intern val)))))
|
||||
(or (and function (symbolp function))
|
||||
(user-error "You didn't specify a function symbol"))
|
||||
(or (fboundp function)
|
||||
(user-error "Symbol's function definition is void: %s" function))
|
||||
(let* ((fn (function-called-at-point))
|
||||
(enable-recursive-minibuffers t)
|
||||
(val (completing-read
|
||||
(if fn
|
||||
(format "Describe function (default %s): " fn)
|
||||
"Describe function: ")
|
||||
#'help--symbol-completion-table #'fboundp t nil nil
|
||||
(and fn (symbol-name fn)))))
|
||||
(unless (equal val "")
|
||||
(setq fn (intern val)))
|
||||
(unless (and fn (symbolp fn))
|
||||
(user-error "You didn't specify a function symbol"))
|
||||
(unless (fboundp fn)
|
||||
(user-error "Symbol's function definition is void: %s" fn))
|
||||
(list fn)))
|
||||
|
||||
;; We save describe-function-orig-buffer on the help xref stack, so
|
||||
;; it is restored by the back/forward buttons. 'help-buffer'
|
||||
|
|
|
@ -4957,8 +4957,8 @@ To kill a whole line, when point is not at the beginning, type \
|
|||
\\[move-beginning-of-line] \\[kill-line] \\[kill-line].
|
||||
|
||||
If `show-trailing-whitespace' is non-nil, this command will just
|
||||
kill the rest of the current line, even if there are only
|
||||
nonblanks there.
|
||||
kill the rest of the current line, even if there are no nonblanks
|
||||
there.
|
||||
|
||||
If option `kill-whole-line' is non-nil, then this command kills the whole line
|
||||
including its terminating newline, when used at the beginning of a line
|
||||
|
|
|
@ -2393,7 +2393,7 @@ When called interactively with a prefix argument, prompt for REMOTE-LOCATION."
|
|||
"Show the history of the region FROM..TO."
|
||||
(interactive "r")
|
||||
(let* ((lfrom (line-number-at-pos from))
|
||||
(lto (line-number-at-pos to))
|
||||
(lto (line-number-at-pos (1- to)))
|
||||
(file buffer-file-name)
|
||||
(backend (vc-backend file))
|
||||
(buf (get-buffer-create "*VC-history*")))
|
||||
|
|
|
@ -253,9 +253,11 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
|
|||
QUIT;
|
||||
|
||||
bool wanted = (NILP (match)
|
||||
|| re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0);
|
||||
|| (re_match_object = name,
|
||||
re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0));
|
||||
|
||||
immediate_quit = 0;
|
||||
re_match_object = Qnil; /* Stop protecting name from GC. */
|
||||
|
||||
if (wanted)
|
||||
{
|
||||
|
|
79
src/regex.c
79
src/regex.c
|
@ -153,6 +153,8 @@
|
|||
|
||||
/* Converts the pointer to the char to BEG-based offset from the start. */
|
||||
# define PTR_TO_OFFSET(d) POS_AS_IN_BUFFER (POINTER_TO_OFFSET (d))
|
||||
/* Strings are 0-indexed, buffers are 1-indexed; we pun on the boolean
|
||||
result to get the right base index. */
|
||||
# define POS_AS_IN_BUFFER(p) ((p) + (NILP (re_match_object) || BUFFERP (re_match_object)))
|
||||
|
||||
# define RE_MULTIBYTE_P(bufp) ((bufp)->multibyte)
|
||||
|
@ -1363,11 +1365,62 @@ typedef struct
|
|||
#define NEXT_FAILURE_HANDLE(h) fail_stack.stack[(h) - 3].integer
|
||||
#define TOP_FAILURE_HANDLE() fail_stack.frame
|
||||
|
||||
#ifdef emacs
|
||||
# define STR_BASE_PTR(obj) \
|
||||
(NILP (obj) ? current_buffer->text->beg \
|
||||
: STRINGP (obj) ? SDATA (obj) \
|
||||
: NULL)
|
||||
#else
|
||||
# define STR_BASE_PTR(obj) NULL
|
||||
#endif
|
||||
|
||||
#define ENSURE_FAIL_STACK(space) \
|
||||
while (REMAINING_AVAIL_SLOTS <= space) { \
|
||||
re_char *orig_base = STR_BASE_PTR (re_match_object); \
|
||||
bool might_relocate = orig_base != NULL; \
|
||||
ptrdiff_t string1_off, end1_off, end_match_1_off; \
|
||||
ptrdiff_t string2_off, end2_off, end_match_2_off; \
|
||||
ptrdiff_t d_off, dend_off, dfail_off; \
|
||||
if (might_relocate) \
|
||||
{ \
|
||||
if (string1) \
|
||||
{ \
|
||||
string1_off = string1 - orig_base; \
|
||||
end1_off = end1 - orig_base; \
|
||||
end_match_1_off = end_match_1 - orig_base; \
|
||||
} \
|
||||
if (string2) \
|
||||
{ \
|
||||
string2_off = string2 - orig_base; \
|
||||
end2_off = end2 - orig_base; \
|
||||
end_match_2_off = end_match_2 - orig_base; \
|
||||
} \
|
||||
d_off = d - orig_base; \
|
||||
dend_off = dend - orig_base; \
|
||||
dfail_off = dfail - orig_base; \
|
||||
} \
|
||||
if (!GROW_FAIL_STACK (fail_stack)) \
|
||||
return -2; \
|
||||
/* In Emacs, GROW_FAIL_STACK might relocate string pointers. */ \
|
||||
if (might_relocate) \
|
||||
{ \
|
||||
re_char *new_base = STR_BASE_PTR (re_match_object); \
|
||||
if (string1) \
|
||||
{ \
|
||||
string1 = new_base + string1_off; \
|
||||
end1 = new_base + end1_off; \
|
||||
end_match_1 = new_base + end_match_1_off; \
|
||||
} \
|
||||
if (string2) \
|
||||
{ \
|
||||
string2 = new_base + string2_off; \
|
||||
end2 = new_base + end2_off; \
|
||||
end_match_2 = new_base + end_match_2_off; \
|
||||
} \
|
||||
d = new_base + d_off; \
|
||||
dend = new_base + dend_off; \
|
||||
dfail = new_base + dfail_off; \
|
||||
} \
|
||||
DEBUG_PRINT ("\n Doubled stack; size now: %zd\n", (fail_stack).size);\
|
||||
DEBUG_PRINT (" slots available: %zd\n", REMAINING_AVAIL_SLOTS);\
|
||||
}
|
||||
|
@ -4293,6 +4346,10 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1, size_t size1,
|
|||
/* Loop through the string, looking for a place to start matching. */
|
||||
for (;;)
|
||||
{
|
||||
ptrdiff_t offset1, offset2;
|
||||
re_char *orig_base;
|
||||
bool might_relocate;
|
||||
|
||||
/* If the pattern is anchored,
|
||||
skip quickly past places we cannot match.
|
||||
We don't bother to treat startpos == 0 specially
|
||||
|
@ -4409,6 +4466,17 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1, size_t size1,
|
|||
&& !bufp->can_be_null)
|
||||
return -1;
|
||||
|
||||
/* re_match_2_internal may allocate, relocating the Lisp text
|
||||
object that we're searching. */
|
||||
IF_LINT (offset2 = 0); /* Work around GCC bug 78081. */
|
||||
orig_base = STR_BASE_PTR (re_match_object);
|
||||
might_relocate = orig_base != NULL;
|
||||
if (might_relocate)
|
||||
{
|
||||
if (string1) offset1 = string1 - orig_base;
|
||||
if (string2) offset2 = string2 - orig_base;
|
||||
}
|
||||
|
||||
val = re_match_2_internal (bufp, string1, size1, string2, size2,
|
||||
startpos, regs, stop);
|
||||
|
||||
|
@ -4418,6 +4486,13 @@ re_search_2 (struct re_pattern_buffer *bufp, const char *str1, size_t size1,
|
|||
if (val == -2)
|
||||
return -2;
|
||||
|
||||
if (might_relocate)
|
||||
{
|
||||
re_char *new_base = STR_BASE_PTR (re_match_object);
|
||||
if (string1) string1 = offset1 + new_base;
|
||||
if (string2) string2 = offset2 + new_base;
|
||||
}
|
||||
|
||||
advance:
|
||||
if (!range)
|
||||
break;
|
||||
|
@ -4905,8 +4980,8 @@ WEAK_ALIAS (__re_match, re_match)
|
|||
#endif /* not emacs */
|
||||
|
||||
#ifdef emacs
|
||||
/* In Emacs, this is the string or buffer in which we
|
||||
are matching. It is used for looking up syntax properties. */
|
||||
/* In Emacs, this is the string or buffer in which we are matching.
|
||||
See the declaration in regex.h for details. */
|
||||
Lisp_Object re_match_object;
|
||||
#endif
|
||||
|
||||
|
|
10
src/regex.h
10
src/regex.h
|
@ -175,8 +175,14 @@ extern reg_syntax_t re_syntax_options;
|
|||
|
||||
#ifdef emacs
|
||||
# include "lisp.h"
|
||||
/* In Emacs, this is the string or buffer in which we
|
||||
are matching. It is used for looking up syntax properties. */
|
||||
/* In Emacs, this is the string or buffer in which we are matching.
|
||||
It is used for looking up syntax properties, and also to recompute
|
||||
pointers in case the object is relocated as a side effect of
|
||||
calling malloc (if it calls r_alloc_sbrk in ralloc.c).
|
||||
|
||||
If the value is a Lisp string object, we are matching text in that
|
||||
string; if it's nil, we are matching text in the current buffer; if
|
||||
it's t, we are matching text in a C string. */
|
||||
extern Lisp_Object re_match_object;
|
||||
#endif
|
||||
|
||||
|
|
36
src/search.c
36
src/search.c
|
@ -280,8 +280,10 @@ looking_at_1 (Lisp_Object string, bool posix)
|
|||
immediate_quit = 1;
|
||||
QUIT; /* Do a pending quit right away, to avoid paradoxical behavior */
|
||||
|
||||
/* Get pointers and sizes of the two strings
|
||||
that make up the visible portion of the buffer. */
|
||||
/* Get pointers and sizes of the two strings that make up the
|
||||
visible portion of the buffer. Note that we can use pointers
|
||||
here, unlike in search_buffer, because we only call re_match_2
|
||||
once, after which we never use the pointers again. */
|
||||
|
||||
p1 = BEGV_ADDR;
|
||||
s1 = GPT_BYTE - BEGV_BYTE;
|
||||
|
@ -400,6 +402,7 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start,
|
|||
(NILP (Vinhibit_changing_match_data)
|
||||
? &search_regs : NULL));
|
||||
immediate_quit = 0;
|
||||
re_match_object = Qnil; /* Stop protecting string from GC. */
|
||||
|
||||
/* Set last_thing_searched only when match data is changed. */
|
||||
if (NILP (Vinhibit_changing_match_data))
|
||||
|
@ -470,6 +473,7 @@ fast_string_match_internal (Lisp_Object regexp, Lisp_Object string,
|
|||
SBYTES (string), 0,
|
||||
SBYTES (string), 0);
|
||||
immediate_quit = 0;
|
||||
re_match_object = Qnil; /* Stop protecting string from GC. */
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -557,6 +561,7 @@ fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
|
|||
len = re_match_2 (buf, (char *) p1, s1, (char *) p2, s2,
|
||||
pos_byte, NULL, limit_byte);
|
||||
immediate_quit = 0;
|
||||
re_match_object = Qnil; /* Stop protecting string from GC. */
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -1171,8 +1176,8 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
|
|||
|
||||
if (RE && !(trivial_regexp_p (string) && NILP (Vsearch_spaces_regexp)))
|
||||
{
|
||||
unsigned char *p1, *p2;
|
||||
ptrdiff_t s1, s2;
|
||||
unsigned char *base;
|
||||
ptrdiff_t off1, off2, s1, s2;
|
||||
struct re_pattern_buffer *bufp;
|
||||
|
||||
bufp = compile_pattern (string,
|
||||
|
@ -1186,16 +1191,19 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
|
|||
can take too long. */
|
||||
QUIT; /* Do a pending quit right away,
|
||||
to avoid paradoxical behavior */
|
||||
/* Get pointers and sizes of the two strings
|
||||
that make up the visible portion of the buffer. */
|
||||
/* Get offsets and sizes of the two strings that make up the
|
||||
visible portion of the buffer. We compute offsets instead of
|
||||
pointers because re_search_2 may call malloc and therefore
|
||||
change the buffer text address. */
|
||||
|
||||
p1 = BEGV_ADDR;
|
||||
base = current_buffer->text->beg;
|
||||
off1 = BEGV_ADDR - base;
|
||||
s1 = GPT_BYTE - BEGV_BYTE;
|
||||
p2 = GAP_END_ADDR;
|
||||
off2 = GAP_END_ADDR - base;
|
||||
s2 = ZV_BYTE - GPT_BYTE;
|
||||
if (s1 < 0)
|
||||
{
|
||||
p2 = p1;
|
||||
off2 = off1;
|
||||
s2 = ZV_BYTE - BEGV_BYTE;
|
||||
s1 = 0;
|
||||
}
|
||||
|
@ -1210,7 +1218,9 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
|
|||
{
|
||||
ptrdiff_t val;
|
||||
|
||||
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
|
||||
val = re_search_2 (bufp,
|
||||
(char*) (base + off1), s1,
|
||||
(char*) (base + off2), s2,
|
||||
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
|
||||
(NILP (Vinhibit_changing_match_data)
|
||||
? &search_regs : &search_regs_1),
|
||||
|
@ -1255,8 +1265,10 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
|
|||
{
|
||||
ptrdiff_t val;
|
||||
|
||||
val = re_search_2 (bufp, (char *) p1, s1, (char *) p2, s2,
|
||||
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
|
||||
val = re_search_2 (bufp,
|
||||
(char*) (base + off1), s1,
|
||||
(char*) (base + off2), s2,
|
||||
pos_byte - BEGV_BYTE, lim_byte - pos_byte,
|
||||
(NILP (Vinhibit_changing_match_data)
|
||||
? &search_regs : &search_regs_1),
|
||||
lim_byte - BEGV_BYTE);
|
||||
|
|
|
@ -129,18 +129,18 @@ static DWORD_PTR committed = 0;
|
|||
/* The maximum block size that can be handled by a non-growable w32
|
||||
heap is limited by the MaxBlockSize value below.
|
||||
|
||||
This point deserves and explanation.
|
||||
This point deserves an explanation.
|
||||
|
||||
The W32 heap allocator can be used for a growable
|
||||
heap or a non-growable one.
|
||||
The W32 heap allocator can be used for a growable heap or a
|
||||
non-growable one.
|
||||
|
||||
A growable heap is not compatible with a fixed base address for the
|
||||
heap. Only a non-growable one is. One drawback of non-growable
|
||||
heaps is that they can hold only objects smaller than a certain
|
||||
size (the one defined below). Most of the largest blocks are GC'ed
|
||||
before dumping. In any case and to be safe, we implement a simple
|
||||
size (the one defined below). Most of the larger blocks are GC'ed
|
||||
before dumping. In any case, and to be safe, we implement a simple
|
||||
first-fit allocation algorithm starting at the end of the
|
||||
dumped_data[] array like depicted below:
|
||||
dumped_data[] array as depicted below:
|
||||
|
||||
----------------------------------------------
|
||||
| | | |
|
||||
|
@ -273,7 +273,7 @@ init_heap (void)
|
|||
else
|
||||
{
|
||||
/* Find the RtlCreateHeap function. Headers for this function
|
||||
are provided with the w32 ddk, but the function is available
|
||||
are provided with the w32 DDK, but the function is available
|
||||
in ntdll.dll since XP. */
|
||||
HMODULE hm_ntdll = LoadLibrary ("ntdll.dll");
|
||||
RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap
|
||||
|
|
Loading…
Add table
Reference in a new issue