diff options
64 files changed, 1938 insertions, 532 deletions
diff --git a/.gitignore b/.gitignore index 1abefeb4326..46ed4a137de 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ makefile lib/gnulib.mk src/config.h src/epaths.h +src/emacs-module.h # C-level sources built by 'make'. lib/alloca.h diff --git a/ChangeLog.3 b/ChangeLog.3 index 60bedb6db1a..9f43511991c 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -3989,8 +3989,6 @@ 2016-09-30 Paul Rankin <hello@paulwrankin.com> - outline-invisible-p): Only return `t' for the 'outline property - * lisp/outline.el (outline-invisible-p): Only return `t' for the 'outline property. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index e5fb0f59fb3..d4bbf17cb3d 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -30,12 +30,12 @@ GNULIB_MODULES=' careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 - dtoastr dtotimespec dup2 environ execinfo faccessat + diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat - manywarnings memrchr mkostemp mktime + manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat diff --git a/autogen.sh b/autogen.sh index 0153f896a17..76fde9e18d2 100755 --- a/autogen.sh +++ b/autogen.sh @@ -45,8 +45,8 @@ autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac` ## Also note that we do not handle micro versions. get_version () { - ## Remove eg "./autogen.sh: line 50: autoconf: command not found". - $1 --version 2>&1 | sed -e '/not found/d' -e 's/.* //' -n -e '1 s/\([0-9][0-9\.]*\).*/\1/p' + vers=`($1 --version) 2> /dev/null` && expr "$vers" : '[^ +]* \([0-9][0-9.]*\).*' } ## $1 = version string, eg "2.59" @@ -82,9 +82,8 @@ check_version () printf '%s' "(using $uprog0=$uprog) " fi - have_version=`get_version $uprog` - - [ x"$have_version" = x ] && return 1 + command -v $uprog > /dev/null || return 1 + have_version=`get_version $uprog` || return 4 have_maj=`major_version $have_version` need_maj=`major_version $2` @@ -158,6 +157,7 @@ if $do_autoconf; then 0) stat="ok" ;; 1) stat="missing" ;; 2) stat="too old" ;; + 4) stat="broken?" ;; *) stat="unable to check" ;; esac diff --git a/configure.ac b/configure.ac index 3fdcff5e7ea..65c5f9268ad 100644 --- a/configure.ac +++ b/configure.ac @@ -891,6 +891,7 @@ AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang], [emacs_cv_clang=yes], [emacs_cv_clang=no])]) +WERROR_CFLAGS= # When compiling with GCC, prefer -isystem to -I when including system # include files, to avoid generating useless diagnostics for the files. AS_IF([test $gl_gcc_warnings = no], @@ -900,7 +901,6 @@ AS_IF([test $gl_gcc_warnings = no], [ # Turn off some warnings if supported. gl_WARN_ADD([-Wno-switch]) - gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) gl_WARN_ADD([-Wno-pointer-sign]) gl_WARN_ADD([-Wno-string-plus-int]) gl_WARN_ADD([-Wno-unknown-attributes]) @@ -918,8 +918,7 @@ AS_IF([test $gl_gcc_warnings = no], ;; esac AS_IF([test $gl_gcc_warnings = yes], - [gl_WARN_ADD([-Werror], [WERROR_CFLAGS])]) - AC_SUBST([WERROR_CFLAGS]) + [WERROR_CFLAGS=-Werror]) nw="$nw -Wduplicated-branches" # Too many false alarms nw="$nw -Wformat-overflow=2" # False alarms due to GCC bug 80776 @@ -961,7 +960,7 @@ AS_IF([test $gl_gcc_warnings = no], nw="$nw -Wtype-limits" nw="$nw -Wunused-parameter" - if test $emacs_cv_clang = yes; then + if test "$emacs_cv_clang" = yes; then nw="$nw -Wcast-align" nw="$nw -Wdouble-promotion" nw="$nw -Wmissing-braces" @@ -984,11 +983,9 @@ AS_IF([test $gl_gcc_warnings = no], gl_WARN_ADD([-Wno-unused-parameter]) # Too many warnings for now gl_WARN_ADD([-Wno-format-nonliteral]) - # More things that clang is unduly picky about. - if test $emacs_cv_clang = yes; then + # clang is unduly picky about braces. + if test "$emacs_cv_clang" = yes; then gl_WARN_ADD([-Wno-missing-braces]) - gl_WARN_ADD([-Wno-tautological-compare]) - gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) fi # This causes too much noise in the MinGW build @@ -1006,15 +1003,22 @@ AS_IF([test $gl_gcc_warnings = no], # define _FORTIFY_SOURCE 2 #endif ]) + ]) - # We use a slightly smaller set of warning options for lib/. - # Remove the following and save the result in GNULIB_WARN_CFLAGS. - nw= - nw="$nw -Wunused-macros" +# clang is unduly picky about these regardless of whether +# --enable-gcc-warnings is specified. +if test "$emacs_cv_clang" = yes; then + gl_WARN_ADD([-Wno-tautological-compare]) + gl_WARN_ADD([-Wno-tautological-constant-out-of-range-compare]) +fi - gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw]) - AC_SUBST([GNULIB_WARN_CFLAGS]) - ]) +# Use a slightly smaller set of warning options for lib/. +nw= +nw="$nw -Wunused-macros" +gl_MANYWARN_COMPLEMENT([GNULIB_WARN_CFLAGS], [$WARN_CFLAGS], [$nw]) + +AC_SUBST([WERROR_CFLAGS]) +AC_SUBST([GNULIB_WARN_CFLAGS]) edit_cflags=" s,///*,/,g @@ -1033,7 +1037,7 @@ AC_ARG_ENABLE(link-time-optimization, recommended for typical use.])], if test "${enableval}" != "no"; then ac_lto_supported=no - if test $emacs_cv_clang = yes; then + if test "$emacs_cv_clang" = yes; then AC_MSG_CHECKING([whether link-time optimization is supported by clang]) GOLD_PLUGIN=`$CC -print-file-name=LLVMgold.so 2>/dev/null` if test -x "$GOLD_PLUGIN"; then @@ -1062,7 +1066,7 @@ if test "${enableval}" != "no"; then AC_MSG_RESULT([$ac_lto_supported]) if test "$ac_lto_supported" = "yes"; then CFLAGS="$CFLAGS $LTO" - if test x$emacs_cv_clang = xyes; then + if test "$emacs_cv_clang" = yes; then AC_MSG_WARN([Please read INSTALL before using link-time optimization with clang]) # WARNING: 'ar --plugin ...' doesn't work without # command, so plugin name is appended to ARFLAGS. @@ -2501,19 +2505,31 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" ## 6.8.2 makes Emacs crash; see Bug#13867. IMAGEMAGICK_MODULE="Wand >= 6.3.5 Wand != 6.8.2" EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE]) - AC_SUBST(IMAGEMAGICK_CFLAGS) - AC_SUBST(IMAGEMAGICK_LIBS) if test $HAVE_IMAGEMAGICK = yes; then - AC_DEFINE(HAVE_IMAGEMAGICK, 1, [Define to 1 if using imagemagick.]) OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS="$CFLAGS $IMAGEMAGICK_CFLAGS" LIBS="$IMAGEMAGICK_LIBS $LIBS" - AC_CHECK_FUNCS(MagickExportImagePixels MagickMergeImageLayers MagickAutoOrientImage) + AC_CHECK_FUNCS([MagickRelinquishMemory MagickExportImagePixels \ + MagickMergeImageLayers MagickAutoOrientImage]) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS + # Check that ImageMagick links. It does not link on Fedora 25 + # with './configure CC=clang', as pkg-config outputs flags like + # -lomp that work for GCC but not Clang. + if test "$ac_cv_func_MagickRelinquishMemory" != yes; then + HAVE_IMAGEMAGICK=no + fi fi + if test $HAVE_IMAGEMAGICK = yes; then + AC_DEFINE([HAVE_IMAGEMAGICK], 1, [Define to 1 if using ImageMagick.]) + else + IMAGEMAGICK_CFLAGS= + IMAGEMAGICK_LIBS= + fi + AC_SUBST([IMAGEMAGICK_CFLAGS]) + AC_SUBST([IMAGEMAGICK_LIBS]) fi fi @@ -3502,6 +3518,12 @@ AC_SUBST(LIBMODULES) AC_SUBST(HAVE_MODULES) AC_SUBST(MODULES_SUFFIX) +AC_CONFIG_FILES([src/emacs-module.h]) +AC_SUBST_FILE([module_env_snippet_25]) +AC_SUBST_FILE([module_env_snippet_26]) +module_env_snippet_25="$srcdir/src/module-env-25.h" +module_env_snippet_26="$srcdir/src/module-env-26.h" + ### Use -lpng if available, unless '--with-png=no'. HAVE_PNG=no LIBPNG= diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index 91e20fa7247..f9ba5cc3921 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -812,6 +812,10 @@ often (in seconds) progress messages are to be displayed. @cindex comments (insertion of) @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +When the commands in this section add comment delimiters, they use +either line comments or block comments depending on the setting of the +comment style (@pxref{Minor Modes}). + @table @asis @item @kbd{C-c C-c} (@code{comment-region}) @kindex C-c C-c @@ -1133,6 +1137,9 @@ line break. find useful while writing new code or editing old code: @table @asis +@item comment style +This specifies whether comment commands (such as @kbd{M-;}) insert +block comments or line comments. @item electric mode When this is enabled, certain visible characters cause reformatting as they are typed. This is normally helpful, but can be a nuisance when @@ -1168,20 +1175,32 @@ and @ref{Indentation Engine Basics}. You can toggle each of these minor modes on and off, and you can configure @ccmode{} so that it starts up with your favorite combination of them (@pxref{Sample Init File}). By default, when -you initialize a buffer, electric mode and syntactic-indentation mode -are enabled but the other three modes are disabled. - -@ccmode{} displays the current state of the first four of these minor -modes on the modeline by appending letters to the major mode's name, -one letter for each enabled minor mode: @samp{l} for electric mode, -@samp{a} for auto-newline mode, @samp{h} for hungry delete mode, and -@samp{w} for subword mode. If all these modes were enabled, you'd see -@samp{C/lahw}@footnote{The @samp{C} would be replaced with the name of -the language in question for the other languages @ccmode{} supports.}. +you initialize a buffer, the comment style is set to the default for +the major mode, electric mode and syntactic-indentation mode are +enabled, but the other three modes are disabled. + +@ccmode{} displays the current state of the first five of these minor +modes on the mode line by appending characters to the major mode's +name: @samp{/} or @samp{*} to indicate the comment style (respectively +line or block), and one letter for each of the other minor modes which +is enabled - @samp{l} for electric mode, @samp{a} for auto-newline +mode, @samp{h} for hungry delete mode, and @samp{w} for subword mode. +If the comment style was block and all the other modes were enabled, +you'd see @samp{C/*lahw}@footnote{The @samp{C} would be replaced with +the name of the language in question for the other languages @ccmode{} +supports.}. Here are the commands to toggle these modes: @table @asis +@item @kbd{C-c C-k} (@code{c-toggle-comment-style}) +@kindex C-c C-k +@findex c-toggle-comment-style +@findex toggle-comment-style (c-) +Toggle the comment style between line style and block style. In modes +(such as AWK Mode) which only have one of these styles, this function +does nothing. + @item @kbd{C-c C-l} (@code{c-toggle-electric-state}) @kindex C-c C-l @findex c-toggle-electric-state @@ -1218,10 +1237,12 @@ Toggle syntactic-indentation mode. @end table Common to all the toggle functions above is that if they are called -programmatically, they take an optional numerical argument. A -positive value will turn on the minor mode (or both of them in the -case of @code{c-toggle-auto-hungry-state}) and a negative value will -turn it (or them) off. +programmatically, they take an optional numerical argument. For +@code{c-toggle-comment style}, a positive value will select block +comments, a negative value will select line comments. For the other +functions, a positive value will turn on the minor mode (or both of +them in the case of @code{c-toggle-auto-hungry-state}) and a negative +value will turn it (or them) off. @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -7232,6 +7253,22 @@ too, add this to your @code{c-initialization-hook}: @xref{Getting Started}. This was a very common question. @item +@emph{How do I get block comments in my C++ files?} + +Interactively, change the comment style with @kbd{C-c C-k}. +@xref{Minor Modes}. + +To configure this setting, say, for files within the gdb project, you +could amend your C++ Mode hook like this: + +@example +(defun my-c++-mode-hook () + (if (string-match "/gdb/" (buffer-file-name)) + (c-toggle-comment-style 1))) +(add-hook 'c++-mode-hook 'my-c++-mode-hook) +@end example + +@item @emph{How do I stop my C++ lambda expressions being indented way over to the right?} @@ -462,6 +462,12 @@ Negative prefix arg flips the direction of selection. Also, defun are selected unless they are separated from the defun by a blank line. +** New command 'replace-buffer-contents'. +This command replaces the contents of the accessible portion of the +current buffer with the contents of the accessible portion of a +different buffer while keeping point, mark, markers, and text +properties as intact as possible. + * Changes in Specialized Modes and Packages in Emacs 26.1 @@ -749,6 +755,9 @@ header's value. where the GnuPG home directory (used for signature verification) is located and whether GnuPG's option "--homedir" is used or not. +--- +*** Deleting a package no longer respects 'delete-by-moving-to-trash'. + ** Tramp +++ @@ -932,6 +941,7 @@ of not providing replacement pairs via the history. *** make-variable-frame-local. Variables cannot be frame-local any more. *** From subr.el: window-dot, set-window-dot, read-input, show-buffer, eval-current-buffer, string-to-int +*** icomplete-prospects-length. *** All the default-FOO variables that hold the default value of the FOO variable. Use 'default-value' and 'setq-default' to access and change FOO, respectively. The exhaustive list of removed variables is: diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 85bcc8bc89c..9470bd635f5 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -224,11 +224,7 @@ put_filename (char *filename) for (tmp = filename; *tmp; tmp++) { - /* Use separate variable to silence a Clang warning on macOS. - Clang takes offence of the additional set of parantheses - generated by the macro. */ - bool is_sep = IS_DIRECTORY_SEP (*tmp); - if (is_sep) + if (IS_DIRECTORY_SEP (*tmp)) filename = tmp + 1; } diff --git a/lib/diffseq.h b/lib/diffseq.h new file mode 100644 index 00000000000..a3cf140990b --- /dev/null +++ b/lib/diffseq.h @@ -0,0 +1,529 @@ +/* Analyze differences between two vectors. + + Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2017 Free Software + Foundation, Inc. + + This program 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. + + This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* The basic idea is to consider two vectors as similar if, when + transforming the first vector into the second vector through a + sequence of edits (inserts and deletes of one element each), + this sequence is short - or equivalently, if the ordered list + of elements that are untouched by these edits is long. For a + good introduction to the subject, read about the "Levenshtein + distance" in Wikipedia. + + The basic algorithm is described in: + "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + Algorithmica Vol. 1, 1986, pp. 251-266, + <http://dx.doi.org/10.1007/BF01840446>. + See especially section 4.2, which describes the variation used below. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", Esko Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118, + <http://dx.doi.org/10.1016/S0019-9958(85)80046-2>. + + Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE + heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) + at the price of producing suboptimal output for large inputs with + many differences. */ + +/* Before including this file, you need to define: + ELEMENT The element type of the vectors being compared. + EQUAL A two-argument macro that tests two elements for + equality. + OFFSET A signed integer type sufficient to hold the + difference between two indices. Usually + something like ptrdiff_t. + EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. + NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. + NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. + EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an + early abort of the computation. + USE_HEURISTIC (Optional) Define if you want to support the + heuristic for large vectors. + It is also possible to use this file with abstract arrays. In this case, + xvec and yvec are not represented in memory. They only exist conceptually. + In this case, the list of defines above is amended as follows: + ELEMENT Undefined. + EQUAL Undefined. + XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) + A three-argument macro: References xvec[xoff] and + yvec[yoff] and tests these elements for equality. + Before including this file, you also need to include: + #include <limits.h> + #include <stdbool.h> + #include "minmax.h" + */ + +/* Maximum value of type OFFSET. */ +#define OFFSET_MAX \ + ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) + +/* Default to no early abort. */ +#ifndef EARLY_ABORT +# define EARLY_ABORT(ctxt) false +#endif + +/* Use this to suppress gcc's "...may be used before initialized" warnings. + Beware: The Code argument must not contain commas. */ +#ifndef IF_LINT +# if defined GCC_LINT || defined lint +# define IF_LINT(Code) Code +# else +# define IF_LINT(Code) /* empty */ +# endif +#endif + +/* As above, but when Code must contain one comma. */ +#ifndef IF_LINT2 +# if defined GCC_LINT || defined lint +# define IF_LINT2(Code1, Code2) Code1, Code2 +# else +# define IF_LINT2(Code1, Code2) /* empty */ +# endif +#endif + +/* + * Context of comparison operation. + */ +struct context +{ + #ifdef ELEMENT + /* Vectors being compared. */ + ELEMENT const *xvec; + ELEMENT const *yvec; + #endif + + /* Extra fields. */ + EXTRA_CONTEXT_FIELDS + + /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point + furthest along the given diagonal in the forward search of the edit + matrix. */ + OFFSET *fdiag; + + /* Vector, indexed by diagonal, containing the X coordinate of the point + furthest along the given diagonal in the backward search of the edit + matrix. */ + OFFSET *bdiag; + + #ifdef USE_HEURISTIC + /* This corresponds to the diff --speed-large-files flag. With this + heuristic, for vectors with a constant small density of changes, + the algorithm is linear in the vector size. */ + bool heuristic; + #endif + + /* Edit scripts longer than this are too expensive to compute. */ + OFFSET too_expensive; + + /* Snakes bigger than this are considered "big". */ + #define SNAKE_LIMIT 20 +}; + +struct partition +{ + /* Midpoints of this partition. */ + OFFSET xmid; + OFFSET ymid; + + /* True if low half will be analyzed minimally. */ + bool lo_minimal; + + /* Likewise for high half. */ + bool hi_minimal; +}; + + +/* Find the midpoint of the shortest edit script for a specified portion + of the two vectors. + + Scan from the beginnings of the vectors, and simultaneously from the ends, + doing a breadth-first search through the space of edit-sequence. + When the two searches meet, we have found the midpoint of the shortest + edit sequence. + + If FIND_MINIMAL is true, find the minimal edit script regardless of + expense. Otherwise, if the search is too expensive, use heuristics to + stop the search and report a suboptimal answer. + + Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted elements minus the number + of deleted elements (counting only elements before the midpoint). + + Set PART->lo_minimal to true iff the minimal edit script for the + left half of the partition is known; similarly for PART->hi_minimal. + + This function assumes that the first elements of the specified portions + of the two vectors do not match, and likewise that the last elements do not + match. The caller must trim matching elements from the beginning and end + of the portions it is going to specify. + + If we return the "wrong" partitions, the worst this can do is cause + suboptimal diff output. It cannot cause incorrect diff output. */ + +static void +diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal, + struct partition *part, struct context *ctxt) +{ + OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */ + OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */ +#ifdef ELEMENT + ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */ + ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */ + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */ + const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */ + const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */ + const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ + OFFSET fmin = fmid; + OFFSET fmax = fmid; /* Limits of top-down search. */ + OFFSET bmin = bmid; + OFFSET bmax = bmid; /* Limits of bottom-up search. */ + OFFSET c; /* Cost. */ + bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd + diagonal with respect to the northwest. */ + + fd[fmid] = xoff; + bd[bmid] = xlim; + + for (c = 1;; ++c) + { + OFFSET d; /* Active diagonal. */ + bool big_snake = false; + + /* Extend the top-down search by an edit step in each diagonal. */ + if (fmin > dmin) + fd[--fmin - 1] = -1; + else + ++fmin; + if (fmax < dmax) + fd[++fmax + 1] = -1; + else + --fmax; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = fd[d - 1]; + OFFSET thi = fd[d + 1]; + OFFSET x0 = tlo < thi ? thi : tlo + 1; + + for (x = x0, y = x0 - d; + x < xlim && y < ylim && XREF_YREF_EQUAL (x, y); + x++, y++) + continue; + if (x - x0 > SNAKE_LIMIT) + big_snake = true; + fd[d] = x; + if (odd && bmin <= d && d <= bmax && bd[d] <= x) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + /* Similarly extend the bottom-up search. */ + if (bmin > dmin) + bd[--bmin - 1] = OFFSET_MAX; + else + ++bmin; + if (bmax < dmax) + bd[++bmax + 1] = OFFSET_MAX; + else + --bmax; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = bd[d - 1]; + OFFSET thi = bd[d + 1]; + OFFSET x0 = tlo < thi ? tlo : thi - 1; + + for (x = x0, y = x0 - d; + xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1); + x--, y--) + continue; + if (x0 - x > SNAKE_LIMIT) + big_snake = true; + bd[d] = x; + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + if (find_minimal) + continue; + +#ifdef USE_HEURISTIC + bool heuristic = ctxt->heuristic; +#else + bool heuristic = false; +#endif + + /* Heuristic: check occasionally for a diagonal that has made lots + of progress compared with the edit distance. If we have any + such, find the one that has made the most progress and return it + as if it had succeeded. + + With this heuristic, for vectors with a constant small density + of changes, the algorithm is linear in the vector size. */ + + if (200 < c && big_snake && heuristic) + { + { + OFFSET best = 0; + + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET dd = d - fmid; + OFFSET x = fd[d]; + OFFSET y = x - d; + OFFSET v = (x - xoff) * 2 - dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = true; + part->hi_minimal = false; + return; + } + } + + { + OFFSET best = 0; + + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET dd = d - bmid; + OFFSET x = bd[d]; + OFFSET y = x - d; + OFFSET v = (xlim - x) * 2 + dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = false; + part->hi_minimal = true; + return; + } + } + } + + /* Heuristic: if we've gone well beyond the call of duty, give up + and report halfway between our best results so far. */ + if (c >= ctxt->too_expensive) + { + OFFSET fxybest; + OFFSET fxbest IF_LINT (= 0); + OFFSET bxybest; + OFFSET bxbest IF_LINT (= 0); + + /* Find forward diagonal that maximizes X + Y. */ + fxybest = -1; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x = MIN (fd[d], xlim); + OFFSET y = x - d; + if (ylim < y) + { + x = ylim + d; + y = ylim; + } + if (fxybest < x + y) + { + fxybest = x + y; + fxbest = x; + } + } + + /* Find backward diagonal that minimizes X + Y. */ + bxybest = OFFSET_MAX; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x = MAX (xoff, bd[d]); + OFFSET y = x - d; + if (y < yoff) + { + x = yoff + d; + y = yoff; + } + if (x + y < bxybest) + { + bxybest = x + y; + bxbest = x; + } + } + + /* Use the better of the two diagonals. */ + if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) + { + part->xmid = fxbest; + part->ymid = fxybest - fxbest; + part->lo_minimal = true; + part->hi_minimal = false; + } + else + { + part->xmid = bxbest; + part->ymid = bxybest - bxbest; + part->lo_minimal = false; + part->hi_minimal = true; + } + return; + } + } + #undef XREF_YREF_EQUAL +} + + +/* Compare in detail contiguous subsequences of the two vectors + which are known, as a whole, to match each other. + + The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1. + + Note that XLIM, YLIM are exclusive bounds. All indices into the vectors + are origin-0. + + If FIND_MINIMAL, find a minimal difference no matter how + expensive it is. + + The results are recorded by invoking NOTE_DELETE and NOTE_INSERT. + + Return false if terminated normally, or true if terminated through early + abort. */ + +static bool +compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, + bool find_minimal, struct context *ctxt) +{ +#ifdef ELEMENT + ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */ + ELEMENT const *yv = ctxt->yvec; + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + { + xoff++; + yoff++; + } + + /* Slide up the top initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) + { + xlim--; + ylim--; + } + + /* Handle simple cases. */ + if (xoff == xlim) + while (yoff < ylim) + { + NOTE_INSERT (ctxt, yoff); + if (EARLY_ABORT (ctxt)) + return true; + yoff++; + } + else if (yoff == ylim) + while (xoff < xlim) + { + NOTE_DELETE (ctxt, xoff); + if (EARLY_ABORT (ctxt)) + return true; + xoff++; + } + else + { + struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 }); + + /* Find a point of correspondence in the middle of the vectors. */ + diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt); + + /* Use the partitions to split this problem into subproblems. */ + if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt)) + return true; + if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt)) + return true; + } + + return false; + #undef XREF_YREF_EQUAL +} + +#undef ELEMENT +#undef EQUAL +#undef OFFSET +#undef EXTRA_CONTEXT_FIELDS +#undef NOTE_DELETE +#undef NOTE_INSERT +#undef EARLY_ABORT +#undef USE_HEURISTIC +#undef XVECREF_YVECREF_EQUAL +#undef OFFSET_MAX diff --git a/lib/gettext.h b/lib/gettext.h index e7520af252f..742ce37e6ce 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -185,7 +185,8 @@ npgettext_aux (const char *domain, #include <string.h> #if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ - /* || __STDC_VERSION__ >= 199901L */ ) + /* || __STDC_VERSION__ == 199901L + || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ) # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 #else # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 73d304307d4..509089e6391 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings +# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stat --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=tzset --avoid=unsetenv --avoid=utime --avoid=utime-h --gnu-make --makefile-name=gnulib.mk.in --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-leading-zeros count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 diffseq dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode filevercmp flexmember fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ignore-value intprops largefile lstat manywarnings memrchr minmax mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time std-gnu11 stdalign stddef stdio stpcpy strftime strtoimax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub update-copyright utimens vla warnings MOSTLYCLEANFILES += core *.stackdump @@ -1167,6 +1167,14 @@ EXTRA_DIST += gl_openssl.h sha512.h endif ## end gnulib module crypto/sha512 +## begin gnulib module diffseq +ifeq (,$(OMIT_GNULIB_MODULE_diffseq)) + +libgnu_a_SOURCES += diffseq.h + +endif +## end gnulib module diffseq + ## begin gnulib module dirent ifeq (,$(OMIT_GNULIB_MODULE_dirent)) @@ -1747,6 +1755,14 @@ EXTRA_libgnu_a_SOURCES += memrchr.c endif ## end gnulib module memrchr +## begin gnulib module minmax +ifeq (,$(OMIT_GNULIB_MODULE_minmax)) + +libgnu_a_SOURCES += minmax.h + +endif +## end gnulib module minmax + ## begin gnulib module mkostemp ifeq (,$(OMIT_GNULIB_MODULE_mkostemp)) diff --git a/lib/minmax.h b/lib/minmax.h new file mode 100644 index 00000000000..6b602a94fdb --- /dev/null +++ b/lib/minmax.h @@ -0,0 +1,60 @@ +/* MIN, MAX macros. + Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2017 Free Software + Foundation, Inc. + + This program 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, or (at your option) + any later version. + + This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* Note: MIN, MAX are also defined in <sys/param.h> on some systems + (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about + MIN, MAX macro redefinitions on some systems; the workaround is to + #include this file as the last one among the #include list. */ + +/* Before we define the following symbols we get the <limits.h> file + since otherwise we get redefinitions on some systems if <limits.h> is + included after this file. Likewise for <sys/param.h>. + If more than one of these system headers define MIN and MAX, pick just + one of the headers (because the definitions most likely are the same). */ +#if HAVE_MINMAX_IN_LIMITS_H +# include <limits.h> +#elif HAVE_MINMAX_IN_SYS_PARAM_H +# include <sys/param.h> +#endif + +/* Note: MIN and MAX should be used with two arguments of the + same type. They might not return the minimum and maximum of their two + arguments, if the arguments have different types or have unusual + floating-point values. For example, on a typical host with 32-bit 'int', + 64-bit 'long long', and 64-bit IEEE 754 'double' types: + + MAX (-1, 2147483648) returns 4294967295. + MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0. + MAX (NaN, 0.0) returns 0.0. + MAX (+0.0, -0.0) returns -0.0. + + and in each case the answer is in some sense bogus. */ + +/* MAX(a,b) returns the maximum of A and B. */ +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* MIN(a,b) returns the minimum of A and B. */ +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#endif /* _MINMAX_H */ diff --git a/lib/strftime.c b/lib/strftime.c index 18c899d2117..99bee4ef978 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -1123,23 +1123,18 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) if (modifier == L_('E')) goto bad_format; - { - /* Use a new variable here instead of reusing number_value - because Clang complains about the self-assignment - generated by DO_NUMBER. */ - ptrdiff_t n = ns; - if (width == -1) - width = 9; - else - { - /* Take an explicit width less than 9 as a precision. */ - int j; - for (j = width; j < 9; j++) - n /= 10; - } + number_value = ns; + if (width == -1) + width = 9; + else + { + /* Take an explicit width less than 9 as a precision. */ + int j; + for (j = width; j < 9; j++) + number_value /= 10; + } - DO_NUMBER (width, n); - } + DO_NUMBER (width, number_value); #endif case L_('n'): diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index ca6b8a38d99..6dbb45ec6b9 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -2518,7 +2518,10 @@ try matching its doc string against `custom-guess-doc-alist'." (copy-sequence type) (list type)))) (when options - (widget-put tmp :options options)) + ;; This used to use widget-put, but with strict plists that + ;; fails when type is an even-length list, eg (repeat character). + ;; Passing our result through widget-convert makes it a valid widget. + (setcdr tmp (append (list :options options) (cdr tmp)))) tmp)) (defun custom-variable-value-create (widget) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index bebfd18d7a6..4245294457f 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2127,7 +2127,7 @@ If NOSAVE is non-nil, the package is not removed from (package-desc-name pkg-used-elsewhere-by))) (t (add-hook 'post-command-hook #'package-menu--post-refresh) - (delete-directory dir t t) + (delete-directory dir t) ;; Remove NAME-VERSION.signed and NAME-readme.txt files. (dolist (suffix '(".signed" "readme.txt")) (let* ((version (package-version-join (package-desc-version pkg-desc))) diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el index c570d7cca89..47c2cb4dab1 100644 --- a/lisp/eshell/em-basic.el +++ b/lisp/eshell/em-basic.el @@ -50,12 +50,6 @@ ;; ;; The umask command changes the default file permissions for newly ;; created files. It uses the same syntax as bash. -;; -;;;_* `version' -;; -;; This command reports the version number for Eshell and all its -;; dependent module, including the date when those modules were last -;; modified. ;;; Code: diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index fe1f1188c88..cdd05bd7e9a 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -563,6 +563,8 @@ For example, to retrieve the second element of a user's record in (defun eshell-index-value (value index) "Reference VALUE using the given INDEX." + (when (and (stringp index) (get-text-property 0 'number index)) + (setq index (string-to-number index))) (if (stringp index) (cdr (assoc index value)) (cond diff --git a/lisp/files.el b/lisp/files.el index 8ac1993754e..06f49bba23c 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -591,13 +591,14 @@ settings being applied, but still respect file-local ones.") ;; ignore. So AFAICS the only reason this variable exists is for a ;; minor convenience feature for handling of an obsolete Rmail file format. (defvar local-enable-local-variables t - "Like `enable-local-variables' but meant for buffer-local bindings. + "Like `enable-local-variables', except for major mode in a -*- line. The meaningful values are nil and non-nil. The default is non-nil. -If a major mode sets this to nil, buffer-locally, then any local -variables list in a file visited in that mode will be ignored. +It should be set in a buffer-local fashion. -This variable does not affect the use of major modes specified -in a -*- line.") +Setting this to nil has the same effect as setting `enable-local-variables' +to nil, except that it does not ignore any mode: setting in a -*- line. +Unless this difference matters to you, you should set `enable-local-variables' +instead of this variable.") (defcustom enable-local-eval 'maybe "Control processing of the \"variable\" `eval' in a file's local variables. @@ -6076,16 +6077,18 @@ specifies the list of buffers to kill, asking for approval for each one." (kill-buffer-ask buffer))) (setq list (cdr list)))) -(defun kill-matching-buffers (regexp &optional internal-too) +(defun kill-matching-buffers (regexp &optional internal-too no-ask) "Kill buffers whose name matches the specified REGEXP. -The optional second argument indicates whether to kill internal buffers too." +Ignores buffers whose name starts with a space, unless optional +prefix argument INTERNAL-TOO is non-nil. Asks before killing +each buffer, unless NO-ASK is non-nil." (interactive "sKill buffers matching this regular expression: \nP") (dolist (buffer (buffer-list)) (let ((name (buffer-name buffer))) (when (and name (not (string-equal name "")) (or internal-too (/= (aref name 0) ?\s)) (string-match regexp name)) - (kill-buffer-ask buffer))))) + (funcall (if no-ask 'kill-buffer 'kill-buffer-ask) buffer))))) (defun rename-auto-save-file () diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 66c9fbea871..3f384c65ece 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -3430,13 +3430,20 @@ possible values." (progn (goto-char date-position) (setq date (get-text-property (point) 'original-date)) + (beginning-of-line) (when (looking-at "[^:]+:[\t ]*") (setq bface (get-text-property (match-beginning 0) 'face) eface (get-text-property (match-end 0) 'face))) - (delete-region (point) - (progn - (gnus-article-forward-header) - (point))) + (goto-char date-position) + (delete-region + (or (and (bolp) date-position) + ;; There might be space(s) added for line unfolding. + (and (get-text-property date-position 'gnus-date-type) + (< (skip-chars-backward "\t ") 0) + (text-property-any (point) date-position + 'gnus-date-type nil)) + date-position) + (progn (gnus-article-forward-header) (point))) (article-transform-date date type bface eface)) (save-restriction (widen) @@ -3455,9 +3462,14 @@ possible values." (when (looking-at "[^:]+:[\t ]*") (setq bface (get-text-property (match-beginning 0) 'face) eface (get-text-property (match-end 0) 'face))) - (delete-region pos (or (text-property-any pos (point-max) - 'gnus-date-type nil) - (point-max)))) + ;; Note: a feature like `gnus-treat-unfold-headers' breaks + ;; the continuity of text props of a multi-line Date header, + ;; that a user-defined date format might create, by adding + ;; spaces. So, don't rely on gnus-date-type or original-date + ;; text prop in case of searching for the header boundary. + (delete-region pos (progn + (gnus-article-forward-header) + (point)))) (unless date ;; the 1st time (goto-char (point-min)) (while (re-search-forward "^Date:[\t ]*" nil t) @@ -3477,32 +3489,48 @@ possible values." (widen))))))) (defun article-transform-date (date type bface eface) - (dolist (this-type (cond - ((null type) - (list 'ut)) - ((atom type) - (list type)) - (t - type))) - (goto-char - (prog1 - (point) - (add-text-properties - (point) - (progn - (insert (article-make-date-line date (or this-type 'ut)) "\n") - (point)) - (list 'original-date date 'gnus-date-type this-type)))) - ;; Do highlighting. - (when (looking-at - "\\([^:]+:\\)[\t ]*\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?") - (put-text-property (match-beginning 1) (match-end 1) 'face bface) + (let (begin date-line) + (dolist (this-type (cond ((null type) + (list 'ut)) + ((atom type) + (list type)) + (t + type))) + (setq begin (point) + date-line (article-make-date-line date (or this-type 'ut))) + (if (and (eq this-type 'user-defined) (bolp) + ;; Test if this is not a continuation. + (not (get-text-property + (prog2 (end-of-line 0) (point) (goto-char begin)) + 'gnus-date-type))) + (progn + (string-match "\\`\\([^\t\n :]+:\\)?[\t ]*" date-line) + (if (match-beginning 1) + (insert date-line "\n") + ;; This user-defined date seems to intend to be a continuation + ;; line of a multi-line Date header like this: + ;; Date: Thu, Jan 1 00:00:00 1970 +0000 + ;; (47 years, 5 months, 20 days ago) + (insert "Date: " (substring date-line (match-end 0)) "\n"))) + (insert date-line "\n")) + (add-text-properties begin (point) (list 'original-date date + 'gnus-date-type this-type)) + (goto-char begin) + ;; Do highlighting. + (beginning-of-line) + (looking-at + "\\([^\n:]+:\\)?[\t ]*\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?") + (when (and bface (match-beginning 1)) + (put-text-property (match-beginning 1) (match-end 1) 'face bface)) (when (match-beginning 2) - (put-text-property (match-beginning 2) (match-end 2) 'face eface)) - (while (and (zerop (forward-line 1)) - (looking-at "[\t ]+\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?")) - (when (match-beginning 1) - (put-text-property (match-beginning 1) (match-end 1) 'face eface)))))) + (when eface + (put-text-property (match-beginning 2) (match-end 2) 'face eface)) + (while (and (zerop (forward-line 1)) + (looking-at + "[\t ]+\\(\\(?:[^\t\n ]+[\t ]+\\)*[^\t\n ]+\\)?")) + (when (and eface (match-beginning 1)) + (put-text-property (match-beginning 1) (match-end 1) + 'face eface))))))) (defun article-make-date-line (date type) "Return a DATE line of TYPE." @@ -3735,7 +3763,7 @@ is to run." "Convert the current article date to the user-defined format. This format is defined by the `gnus-article-time-format' variable." (interactive (list t)) - (article-date-ut 'user highlight)) + (article-date-ut 'user-defined highlight)) (defun article-date-iso8601 (&optional highlight) "Convert the current article date to ISO8601." diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el index dd64bfed60a..9ff581da996 100644 --- a/lisp/gnus/mm-view.el +++ b/lisp/gnus/mm-view.el @@ -475,12 +475,12 @@ If MODE is not set, try to find mode automatically." (require 'font-lock) ;; I find font-lock a bit too verbose. (let ((font-lock-verbose nil) - (font-lock-support-mode nil)) + (font-lock-support-mode nil) + (enable-local-variables nil)) ;; Disable support modes, e.g., jit-lock, lazy-lock, etc. ;; Note: XEmacs people use `font-lock-mode-hook' to run those modes. (set (make-local-variable 'font-lock-mode-hook) nil) (setq buffer-file-name (mm-handle-filename handle)) - (set (make-local-variable 'enable-local-variables) nil) (with-demoted-errors (if mode (save-window-excursion diff --git a/lisp/icomplete.el b/lisp/icomplete.el index cd352de65b4..a4153e806df 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -56,10 +56,6 @@ :link '(info-link "(emacs)Icomplete") :group 'minibuffer) -(defvar icomplete-prospects-length 80) -(make-obsolete-variable - 'icomplete-prospects-length 'icomplete-prospects-height "23.1") - (defcustom icomplete-separator " | " "String used by Icomplete to separate alternatives in the minibuffer." :type 'string @@ -91,13 +87,14 @@ Otherwise this should be a list of the completion tables (e.g., :version "24.4") ;;;_* User Customization variables -(defcustom icomplete-prospects-height - ;; 20 is an estimated common size for the prompt + minibuffer content, to - ;; try to guess the number of lines used up by icomplete-prospects-length. - (+ 1 (/ (+ icomplete-prospects-length 20) (window-width))) +(defcustom icomplete-prospects-height 2 + ;; We used to compute how many lines 100 characters would take in + ;; the current window width, but the return value of `window-width' + ;; is unreliable on startup (e.g., if we're in daemon mode), so now + ;; we simply base the default value on an 80 column window. "Maximum number of lines to use in the minibuffer." :type 'integer - :version "23.1") + :version "26.1") (defcustom icomplete-compute-delay .3 "Completions-computation stall, used only with large-number completions. diff --git a/lisp/international/characters.el b/lisp/international/characters.el index 3eb287fd963..33cb3d85223 100644 --- a/lisp/international/characters.el +++ b/lisp/international/characters.el @@ -881,9 +881,9 @@ with L, LRE, or LRO Unicode bidi character type.") (#x05C1 . #x05C2) (#x05C4 . #x05C5) (#x05C7 . #x05C7) - (#x0600 . #x0603) - (#x0610 . #x0615) - (#x064B . #x065E) + (#x0600 . #x0605) + (#x0610 . #x061C) + (#x064B . #x065F) (#x0670 . #x0670) (#x06D6 . #x06E4) (#x06E7 . #x06E8) @@ -893,11 +893,15 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0730 . #x074A) (#x07A6 . #x07B0) (#x07EB . #x07F3) - (#x0901 . #x0902) + (#x0816 . #x0823) + (#x0825 . #x082D) + (#x0859 . #x085B) + (#x08D4 . #x0902) + (#x093A . #x093A) (#x093C . #x093C) (#x0941 . #x0948) (#x094D . #x094D) - (#x0951 . #x0954) + (#x0951 . #x0957) (#x0962 . #x0963) (#x0981 . #x0981) (#x09BC . #x09BC) @@ -907,7 +911,12 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0A01 . #x0A02) (#x0A3C . #x0A3C) (#x0A41 . #x0A4D) + (#x0A41 . #x0A42) + (#x0A47 . #x0A48) + (#x0A4B . #x0A4D) + (#x0A51 . #x0A51) (#x0A70 . #x0A71) + (#x0A75 . #x0A75) (#x0A81 . #x0A82) (#x0ABC . #x0ABC) (#x0AC1 . #x0AC8) @@ -916,20 +925,24 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0B01 . #x0B01) (#x0B3C . #x0B3C) (#x0B3F . #x0B3F) - (#x0B41 . #x0B43) + (#x0B41 . #x0B44) (#x0B4D . #x0B56) + (#x0B62 . #x0B63) (#x0B82 . #x0B82) (#x0BC0 . #x0BC0) (#x0BCD . #x0BCD) + (#x0C00 . #x0C00) (#x0C3E . #x0C40) (#x0C46 . #x0C56) + (#x0C62 . #x0C63) + (#x0C81 . #x0C81) (#x0CBC . #x0CBC) - (#x0CBF . #x0CBF) - (#x0CC6 . #x0CC6) (#x0CCC . #x0CCD) (#x0CE2 . #x0CE3) - (#x0D41 . #x0D43) + (#x0D01 . #x0D01) + (#x0D41 . #x0D44) (#x0D4D . #x0D4D) + (#x0D62 . #x0D63) (#x0DCA . #x0DCA) (#x0DD2 . #x0DD6) (#x0E31 . #x0E31) @@ -945,14 +958,20 @@ with L, LRE, or LRO Unicode bidi character type.") (#x0F71 . #x0F7E) (#x0F80 . #x0F84) (#x0F86 . #x0F87) - (#x0F90 . #x0FBC) + (#x0F8D . #x0FBC) (#x0FC6 . #x0FC6) (#x102D . #x1030) (#x1032 . #x1037) - (#x1039 . #x1039) + (#x1039 . #x103A) + (#x103D . #x103E) (#x1058 . #x1059) - (#x1160 . #x11FF) - (#x135F . #x135F) + (#x105E . #x1160) + (#x1171 . #x1074) + (#x1082 . #x1082) + (#x1085 . #x1086) + (#x108D . #x108D) + (#x109D . #x109D) + (#x135D . #x135F) (#x1712 . #x1714) (#x1732 . #x1734) (#x1752 . #x1753) @@ -962,84 +981,214 @@ with L, LRE, or LRO Unicode bidi character type.") (#x17C6 . #x17C6) (#x17C9 . #x17D3) (#x17DD . #x17DD) - (#x180B . #x180D) + (#x180B . #x180E) + (#x18A9 . #x18A9) + (#x1885 . #x1886) (#x18A9 . #x18A9) (#x1920 . #x1922) (#x1927 . #x1928) (#x1932 . #x1932) (#x1939 . #x193B) (#x1A17 . #x1A18) + (#x1A1B . #x1A1B) + (#x1A56 . #x1A56) + (#x1A58 . #x1A5E) + (#x1A60 . #x1A60) + (#x1A62 . #x1A62) + (#x1A65 . #x1A6C) + (#x1A73 . #x1A7C) + (#x1A7F . #x1A7F) + (#x1AB0 . #x1ABE) (#x1B00 . #x1B03) (#x1B34 . #x1B34) (#x1B36 . #x1B3A) (#x1B3C . #x1B3C) (#x1B42 . #x1B42) (#x1B6B . #x1B73) + (#x1B80 . #x1B81) + (#x1BA2 . #x1BA5) + (#x1BA8 . #x1BA9) + (#x1BAB . #x1BAD) + (#x1BE6 . #x1BE6) + (#x1BE8 . #x1BE9) + (#x1BED . #x1BED) + (#x1BEF . #x1BF1) + (#x1C2C . #x1C33) + (#x1C36 . #x1C37) + (#x1CD0 . #x1CD2) + (#x1CD4 . #x1CE0) + (#x1CE2 . #x1CE8) + (#x1CED . #x1CED) + (#x1CF4 . #x1CF4) + (#x1CF8 . #x1CF9) (#x1DC0 . #x1DFF) (#x200B . #x200F) (#x202A . #x202E) (#x2060 . #x206F) - (#x20D0 . #x20EF) - (#x302A . #x302F) - (#x3099 . #x309A) + (#x20D0 . #x20F0) + (#x2CEF . #x2CF1) + (#x2D7F . #x2D7F) + (#x2DE0 . #x2DFF) + (#xA66F . #xA672) + (#xA674 . #xA69F) + (#xA6F0 . #xA6F1) + (#xA802 . #xA802) (#xA806 . #xA806) (#xA80B . #xA80B) (#xA825 . #xA826) + (#xA8C4 . #xA8C5) + (#xA8E0 . #xA8F1) + (#xA926 . #xA92D) + (#xA947 . #xA951) + (#xA980 . #xA9B3) + (#xA9B6 . #xA9B9) + (#xA9BC . #xA9BC) + (#xA9E5 . #xA9E5) + (#xAA29 . #xAA2E) + (#xAA31 . #xAA32) + (#xAA35 . #xAA36) + (#xAA43 . #xAA43) + (#xAA4C . #xAA4C) + (#xAA7C . #xAA7C) + (#xAAB0 . #xAAB0) + (#xAAB2 . #xAAB4) + (#xAAB7 . #xAAB8) + (#xAABE . #xAABF) + (#xAAC1 . #xAAC1) + (#xAAEC . #xAAED) + (#xAAF6 . #xAAF6) + (#xABE5 . #xABE5) + (#xABE8 . #xABE8) + (#xABED . #xABED) (#xFB1E . #xFB1E) (#xFE00 . #xFE0F) - (#xFE20 . #xFE23) + (#xFE20 . #xFE2F) (#xFEFF . #xFEFF) (#xFFF9 . #xFFFB) + (#x101FD . #x101FD) + (#x102E0 . #x102E0) + (#x10376 . #x1037A) (#x10A01 . #x10A0F) (#x10A38 . #x10A3F) + (#x10AE5 . #x10AE6) + (#x11001 . #x11001) + (#x11038 . #x11046) + (#x1107F . #x11081) + (#x110B3 . #x110B6) + (#x110B9 . #x110BA) + (#x110BD . #x110BD) + (#x11100 . #x11102) + (#x11127 . #x1112B) + (#x1112D . #x11134) + (#x11173 . #x11173) + (#x11180 . #x11181) + (#x111B6 . #x111BE) + (#x111CA . #x111CC) + (#x1122F . #x11231) + (#x11234 . #x11234) + (#x11236 . #x11237) + (#x1123E . #x1123E) + (#x112DF . #x112DF) + (#x112E3 . #x112EA) + (#x11300 . #x11301) + (#x1133C . #x1133C) + (#x11340 . #x11340) + (#x11366 . #x1136C) + (#x11370 . #x11374) + (#x11438 . #x1143F) + (#x11442 . #x11444) + (#x11446 . #x11446) + (#x114B3 . #x114B8) + (#x114BA . #x114C0) + (#x114C2 . #x114C3) + (#x115B2 . #x115B5) + (#x115BC . #x115BD) + (#x115BF . #x115C0) + (#x115DC . #x115DD) + (#x11633 . #x1163A) + (#x1163D . #x1163D) + (#x1163F . #x11640) + (#x116AB . #x116AB) + (#x116AD . #x116AD) + (#x116B0 . #x116B5) + (#x116B7 . #x116B7) + (#x1171D . #x1171F) + (#x11722 . #x11725) + (#x11727 . #x1172B) + (#x11C30 . #x11C36) + (#x11C38 . #x11C3D) + (#x11C92 . #x11CA7) + (#x11CAA . #x11CB0) + (#x11CB2 . #x11CB3) + (#x11CB5 . #x11CB6) + (#x16AF0 . #x16AF4) + (#x16B30 . #x16B36) + (#x16F8F . #x16F92) + (#x1BC9D . #x1BC9E) + (#x1BCA0 . #x1BCA3) (#x1D167 . #x1D169) (#x1D173 . #x1D182) (#x1D185 . #x1D18B) (#x1D1AA . #x1D1AD) (#x1D242 . #x1D244) + (#x1DA00 . #x1DA36) + (#x1DA3B . #x1DA6C) + (#x1DA75 . #x1DA75) + (#x1DA84 . #x1DA84) + (#x1DA9B . #x1DA9F) + (#x1DAA1 . #x1DAAF) + (#x1E000 . #x1E006) + (#x1E008 . #x1E018) + (#x1E01B . #x1E021) + (#x1E023 . #x1E024) + (#x1E026 . #x1E02A) + (#x1E8D0 . #x1E8D6) + (#x1E944 . #x1E94A) (#xE0001 . #xE01EF)))) (dolist (elt l) (set-char-table-range char-width-table elt 0))) ;; 2: East Asian Wide and Full-width characters. (let ((l '((#x1100 . #x115F) - (#x231A . #x231B) + (#x231A . #x231B) (#x2329 . #x232A) - (#x23E9 . #x23EC) - (#x23F0 . #x23F0) - (#x23F3 . #x23F3) - (#x25FD . #x25FE) - (#x2614 . #x2615) - (#x2648 . #x2653) - (#x267F . #x267F) - (#x2693 . #x2693) - (#x26A1 . #x26A1) - (#x26AA . #x26AB) - (#x26BD . #x26BE) - (#x26C4 . #x26C5) - (#x26CE . #x26CE) - (#x26D4 . #x26D4) - (#x26EA . #x26EA) - (#x26F2 . #x26F3) - (#x26F5 . #x26F5) - (#x26FA . #x26FA) - (#x26FD . #x26FD) - (#x2705 . #x2705) - (#x270A . #x270B) - (#x2728 . #x2728) - (#x274C . #x274C) - (#x274E . #x274E) - (#x2753 . #x2755) - (#x2757 . #x2757) - (#x2795 . #x2797) - (#x27B0 . #x27B0) - (#x27BF . #x27BF) - (#x2B1B . #x2B1C) - (#x2B50 . #x2B50) - (#x2B55 . #x2B55) + (#x23E9 . #x23EC) + (#x23F0 . #x23F0) + (#x23F3 . #x23F3) + (#x25FD . #x25FE) + (#x2614 . #x2615) + (#x2648 . #x2653) + (#x267F . #x267F) + (#x2693 . #x2693) + (#x26A1 . #x26A1) + (#x26AA . #x26AB) + (#x26BD . #x26BE) + (#x26C4 . #x26C5) + (#x26CE . #x26CE) + (#x26D4 . #x26D4) + (#x26EA . #x26EA) + (#x26F2 . #x26F3) + (#x26F5 . #x26F5) + (#x26FA . #x26FA) + (#x26FD . #x26FD) + (#x2705 . #x2705) + (#x270A . #x270B) + (#x2728 . #x2728) + (#x274C . #x274C) + (#x274E . #x274E) + (#x2753 . #x2755) + (#x2757 . #x2757) + (#x2795 . #x2797) + (#x27B0 . #x27B0) + (#x27BF . #x27BF) + (#x2B1B . #x2B1C) + (#x2B50 . #x2B50) + (#x2B55 . #x2B55) (#x2E80 . #x303E) - (#x3040 . #x4DBF) + (#x3040 . #x3247) + (#x3250 . #x4DBF) (#x4E00 . #xA4CF) + (#xA490 . #xA4C6) (#xA960 . #xA97F) (#xAC00 . #xD7A3) (#xF900 . #xFAFF) @@ -1047,28 +1196,48 @@ with L, LRE, or LRO Unicode bidi character type.") (#xFE30 . #xFE6F) (#xFF01 . #xFF60) (#xFFE0 . #xFFE6) - (#x16FE0 . #x16FE0) - (#x17000 . #x187EC) - (#x18800 . #x18AF2) - (#x1B000 . #x1B001) - (#x1F18E . #x1F18E) - (#x1F191 . #x1F19A) - (#x1F200 . #x1F2FF) - (#x1F300 . #x1F5FF) - (#x1F600 . #x1F64F) - (#x1F680 . #x1F6C5) - (#x1F6CC . #x1F6CC) - (#x1F6D0 . #x1F6D2) - (#x1F6EB . #x1F6EC) - (#x1F6F4 . #x1F6F6) - (#x1F910 . #x1F91E) - (#x1F920 . #x1F927) - (#x1F930 . #x1F930) - (#x1F933 . #x1F93E) - (#x1F940 . #x1F94B) - (#x1F950 . #x1F95E) - (#x1F980 . #x1F991) - (#x1F9C0 . #x1F9C0) + (#x16FE0 . #x16FE0) + (#x17000 . #x187EC) + (#x18800 . #x18AF2) + (#x1B000 . #x1B001) + (#x1F004 . #x1F004) + (#x1F0CF . #x1F0CF) + (#x1F18E . #x1F18E) + (#x1F191 . #x1F19A) + (#x1F200 . #x1F320) + (#x1F32D . #x1F335) + (#x1F337 . #x1F37C) + (#x1F37E . #x1F393) + (#x1F3A0 . #x1F3CA) + (#x1F3CF . #x1F3D3) + (#x1F3E0 . #x1F3F0) + (#x1F3F4 . #x1F3F4) + (#x1F3F8 . #x1F3FA) + (#x1F3FB . #x1F3FF) + (#x1F400 . #x1F43E) + (#x1F440 . #x1F440) + (#x1F442 . #x1F4FC) + (#x1F4FF . #x1F53D) + (#x1F54B . #x1F54E) + (#x1F550 . #x1F567) + (#x1F57A . #x1F57A) + (#x1F595 . #x1F596) + (#x1F5A4 . #x1F5A4) + (#x1F5FB . #x1F5FF) + (#x1F600 . #x1F64F) + (#x1F680 . #x1F6C5) + (#x1F6CC . #x1F6CC) + (#x1F6D0 . #x1F6D2) + (#x1F6EB . #x1F6EC) + (#x1F6F4 . #x1F6F6) + (#x1F910 . #x1F91E) + (#x1F920 . #x1F927) + (#x1F930 . #x1F930) + (#x1F933 . #x1F93E) + (#x1F940 . #x1F94B) + (#x1F950 . #x1F95E) + (#x1F980 . #x1F991) + (#x1F9C0 . #x1F9C0) (#x20000 . #x2FFFF) (#x30000 . #x3FFFF)))) (dolist (elt l) diff --git a/lisp/international/mule.el b/lisp/international/mule.el index fa3ad80e2f7..6cfb7e6d457 100644 --- a/lisp/international/mule.el +++ b/lisp/international/mule.el @@ -1970,7 +1970,7 @@ use \"coding: 'raw-text\" instead." (goto-char tail-start) (re-search-forward "[\r\n]\^L" tail-end t) (if (re-search-forward - "[\r\n]\\([^[\r\n]*\\)[ \t]*Local Variables:[ \t]*\\([^\r\n]*\\)[\r\n]" + "[\r\n]\\([^\r\n]*\\)[ \t]*Local Variables:[ \t]*\\([^\r\n]*\\)[\r\n]" tail-end t) ;; The prefix is what comes before "local variables:" in its ;; line. The suffix is what comes after "local variables:" diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 0377cd549a2..c3480cd6c64 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3006,7 +3006,7 @@ PATTERN is as returned by `completion-pcm--string->pattern'." (let ((poss ())) (dolist (c compl) (when (string-match-p regex c) (push c poss))) - poss))))) + (nreverse poss)))))) (defun completion-pcm--hilit-commonality (pattern completions) (when completions @@ -3258,7 +3258,7 @@ the same set of elements." "\\)\\'"))) (dolist (f all) (unless (string-match-p re f) (push f try))) - (or try all)))) + (or (nreverse try) all)))) (defun completion-pcm--merge-try (pattern all prefix suffix) diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 415cde2fc8a..ac5a9c45bbd 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -429,14 +429,16 @@ for all methods. Resulting data are derived from connection history." tramp-cache-data) res)) +;; When "emacs -Q" has been called, both variables are nil. We do not +;; load the persistency file then, in order to have a clean test environment. +;;;###tramp-autoload +(defvar tramp-cache-read-persistent-data (or init-file-user site-run-file) + "Whether to read persistent data at startup time.") + ;; Read persistent connection history. (when (and (stringp tramp-persistency-file-name) (zerop (hash-table-count tramp-cache-data)) - ;; When "emacs -Q" has been called, both variables are nil. - ;; We do not load the persistency file then, in order to - ;; have a clean test environment. - (or init-file-user - site-run-file)) + tramp-cache-read-persistent-data) (condition-case err (with-temp-buffer (insert-file-contents tramp-persistency-file-name) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 859809c00a8..4c750df3c40 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1669,10 +1669,10 @@ connection if a previous connection has died for some reason." (format "Opening connection for %s@%s using %s" user host method)) ;; Enable `auth-source'. - (tramp-set-connection-property vec "first-password-request" t) + (tramp-set-connection-property + vec "first-password-request" tramp-cache-read-persistent-data) - ;; There will be a callback of "askPassword" when a password is - ;; needed. + ;; There will be a callback of "askPassword" when a password is needed. (dbus-register-method :session dbus-service-emacs object-path tramp-gvfs-interface-mountoperation "askPassword" @@ -1693,7 +1693,7 @@ connection if a previous connection has died for some reason." 'tramp-gvfs-handler-askquestion) ;; The call must be asynchronously, because of the "askPassword" - ;; or "askQuestion"callbacks. + ;; or "askQuestion" callbacks. (if (string-match "(so)$" tramp-gvfs-mountlocation-signature) (with-tramp-dbus-call-method vec nil :session tramp-gvfs-service-daemon tramp-gvfs-path-mounttracker diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 5bedc383d86..8d81ac64aa2 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2075,7 +2075,7 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;; are already loaded. This results in ;; recursive loading. Therefore, we load the ;; Tramp packages locally. - (when (and (listp sf) (eq (car sf) 'autoload)) + (when (autoloadp sf) (let ((default-directory (tramp-compat-temporary-file-directory))) (load (cadr sf) 'noerror 'nomessage))) @@ -2210,6 +2210,31 @@ Falls back to normal file name handler if no Tramp file name handler exists." ;;;###autoload (tramp-register-autoload-file-name-handlers) +(defun tramp-use-absolute-autoload-file-names () + "Change Tramp autoload objects to use absolute file names. +This avoids problems during autoload, when `load-path' contains +remote file names." + ;; We expect all other Tramp files in the same directory as tramp.el. + (let* ((dir (expand-file-name (file-name-directory (locate-library "tramp")))) + (files-regexp + (format + "^%s$" + (regexp-opt + (mapcar + 'file-name-sans-extension + (directory-files dir nil "^tramp.+\\.elc?$")) + 'paren)))) + (mapatoms + (lambda (atom) + (when (and (functionp atom) + (autoloadp (symbol-function atom)) + (string-match files-regexp (cadr (symbol-function atom)))) + (ignore-errors + (setf (cadr (symbol-function atom)) + (expand-file-name (cadr (symbol-function atom)) dir)))))))) + +(eval-after-load 'tramp (tramp-use-absolute-autoload-file-names)) + (defun tramp-register-file-name-handlers () "Add Tramp file name handlers to `file-name-handler-alist'." ;; Remove autoloaded handlers from file name handler alist. Useful, @@ -2876,11 +2901,10 @@ User is always nil." (tramp-get-method-parameter v 'tramp-case-insensitive) ;; There isn't. So we must check, in case there's a connection already. - (and (tramp-connectable-p filename) + (and (file-remote-p filename nil 'connected) (with-tramp-connection-property v "case-insensitive" (ignore-errors (with-tramp-progress-reporter v 5 "Checking case-insensitive" - (tramp-backtrace v) ;; The idea is to compare a file with lower case ;; letters with the same file with upper case letters. (let ((candidate @@ -3551,14 +3575,14 @@ The terminal type can be configured with `tramp-terminal-type'." PROC and VEC indicate the remote connection to be used. POS, if set, is the starting point of the region to be deleted in the connection buffer." - ;; Enable `auth-source'. We must use `tramp-current-*' variables in - ;; case we have several hops. + ;; Enable `auth-source', unless "emacs -Q" has been called. We must + ;; use `tramp-current-*' variables in case we have several hops. (tramp-set-connection-property (make-tramp-file-name :method tramp-current-method :user tramp-current-user :domain tramp-current-domain :host tramp-current-host :port tramp-current-port) - "first-password-request" t) + "first-password-request" tramp-cache-read-persistent-data) (save-restriction (with-tramp-progress-reporter proc 3 "Waiting for prompts from remote shell" diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index 9c0798e7529..c05200b3898 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -251,8 +251,14 @@ With universal argument, inserts the analysis as a comment on that line." ;; Minor mode functions. +;; `c-block-comment-flag' gets initialized to the current mode's default in +;; c-basic-common-init. +(defvar c-block-comment-flag nil) +(make-variable-buffer-local 'c-block-comment-flag) + (defun c-update-modeline () - (let ((fmt (format "/%s%s%s%s" + (let ((fmt (format "/%s%s%s%s%s" + (if c-block-comment-flag "*" "/") (if c-electric-flag "l" "") (if (and c-electric-flag c-auto-newline) "a" "") @@ -270,9 +276,6 @@ With universal argument, inserts the analysis as a comment on that line." (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name) (match-string 1 mode-name) mode-name))) -;; (setq c-submode-indicators -;; (if (> (length fmt) 1) -;; fmt)) (setq mode-name (if (> (length fmt) 1) (concat bare-mode-name fmt) @@ -362,6 +365,32 @@ left out." (electric-indent-local-mode (if c-electric-flag 1 0))) (c-keep-region-active)) +(defun c-toggle-comment-style (&optional arg) + "Toggle the comment style between block and line comments. +Optional numeric ARG, if supplied, switches to block comment +style when positive, to line comment style when negative, and +just toggles it when zero or left out. + +This action does nothing when the mode only has one comment style." + (interactive "P") + (setq c-block-comment-flag + (cond + ((and c-line-comment-starter c-block-comment-starter) + (c-calculate-state arg c-block-comment-flag)) + (c-line-comment-starter nil) + (t t))) + (setq comment-start + (concat (if c-block-comment-flag + c-block-comment-starter + c-line-comment-starter) + " ")) + (setq comment-end + (if c-block-comment-flag + (concat " " c-block-comment-ender) + "")) + (c-update-modeline) + (c-keep-region-active)) + ;; Electric keys diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 9773b1ca85b..aa84ade083c 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -8100,7 +8100,7 @@ comment at the start of cc-engine.el for more info." (and (setq found (c-syntactic-re-search-forward - "[;:,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" + "[;:,]\\|\\s)\\|\\(=\\|\\s(\\)" limit t t)) (eq (char-before) ?:) (if (looking-at c-:-op-cont-regexp) @@ -8118,8 +8118,8 @@ comment at the start of cc-engine.el for more info." (eq (char-before) ?\[) (c-go-up-list-forward)) (setq brackets-after-id t)) - (backward-char) - found)) + (when found (backward-char)) + t)) (list id-start id-end brackets-after-id (match-beginning 1) decorated) (goto-char here) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index adb1f1a4937..9bae7d9aa2f 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1214,6 +1214,12 @@ casts and declarations are fontified. Used on level 2 and higher." (and (zerop (c-backward-token-2 2)) (looking-at c-arithmetic-op-regexp)))) (cons nil nil)) + ;; In a C++ member initialization list. + ((and (eq (char-before match-pos) ?,) + (c-major-mode-is 'c++-mode) + (save-excursion (c-back-over-member-initializers))) + (c-put-char-property (1- match-pos) 'c-type 'c-not-decl) + (cons 'not-decl nil)) ;; At start of a declaration inside a declaration paren. ((save-excursion (and (memq (char-before match-pos) '(?\( ?\,)) @@ -1235,6 +1241,85 @@ casts and declarations are fontified. Used on level 2 and higher." (cons 'decl nil)) (t (cons 'arglist t))))) +(defun c-font-lock-single-decl (limit decl-or-cast match-pos context toplev) + ;; Try to fontify a single declaration, together with all its declarators. + ;; Return nil if we're successful, non-nil if we fail. POINT should be + ;; positioned at the start of the putative declaration before calling. + ;; POINT is left undefined by this function. + ;; + ;; LIMIT sets a maximum position we'll fontify out to. + ;; DECL-OR-CAST has the form of a result from `c-forward-decl-or-cast-1', + ;; and must indicate a declaration (i.e. not be nil or 'cast). + ;; MATCH-POS is the position after the last symbol before the decl. + ;; CONTEXT is the context of the current decl., as determined by + ;; c-get-fontification-context. + ;; TOPLEV is non-nil if the decl. is at the top level (i.e. outside any + ;; braces, or directly inside a class, namespace, etc.) + + ;; Do we have an expression as the second or third clause of + ;; a "for" paren expression? + (if (save-excursion + (and + (car (cddr decl-or-cast)) ; maybe-expression flag. + (c-go-up-list-backward) + (eq (char-after) ?\() + (progn (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (looking-at c-paren-stmt-key) + (progn (goto-char match-pos) + (while (and (eq (char-before) ?\)) + (c-go-list-backward)) + (c-backward-syntactic-ws)) + (eq (char-before) ?\;)))) + ;; We've got an expression in "for" parens. Remove the + ;; "type" that would spuriously get fontified. + (let ((elt (and (consp c-record-type-identifiers) + (assq (cadr (cddr decl-or-cast)) + c-record-type-identifiers)))) + (when elt + (setq c-record-type-identifiers + (c-delq-from-dotted-list + elt c-record-type-identifiers))) + t) + ;; Back up to the type to fontify the declarator(s). + (goto-char (car decl-or-cast)) + + (let ((decl-list + (if (not (memq context '(nil top))) + ;; Should normally not fontify a list of + ;; declarators inside an arglist, but the first + ;; argument in the ';' separated list of a "for" + ;; statement is an exception. + (when (eq (char-before match-pos) ?\() + (save-excursion + (goto-char (1- match-pos)) + (c-backward-syntactic-ws) + (and (c-simple-skip-symbol-backward) + (looking-at c-paren-stmt-key)))) + t))) + + ;; Fix the `c-decl-id-start' or `c-decl-type-start' property + ;; before the first declarator if it's a list. + ;; `c-font-lock-declarators' handles the rest. + (when decl-list + (save-excursion + (c-backward-syntactic-ws) + (unless (bobp) + (c-put-char-property (1- (point)) 'c-type + (if (cadr decl-or-cast) + 'c-decl-type-start + 'c-decl-id-start))))) + + (c-font-lock-declarators + (min limit (point-max)) decl-list + (cadr decl-or-cast) (not toplev))) + + ;; A declaration has been successfully identified, so do all the + ;; fontification of types and refs that've been recorded. + (c-fontify-recorded-types-and-refs) + nil)) + + (defun c-font-lock-declarations (limit) ;; Fontify all the declarations, casts and labels from the point to LIMIT. ;; Assumes that strings and comments have been fontified already. @@ -1436,70 +1521,9 @@ casts and declarations are fontified. Used on level 2 and higher." (setq max-type-decl-end-before-token (point))) (when (> (point) max-type-decl-end) (setq max-type-decl-end (point)))) - - ;; Do we have an expression as the second or third clause of - ;; a "for" paren expression? - (if (save-excursion - (and - (car (cddr decl-or-cast)) ; maybe-expression flag. - (goto-char start-pos) - (c-go-up-list-backward) - (eq (char-after) ?\() - (progn (c-backward-syntactic-ws) - (c-simple-skip-symbol-backward)) - (looking-at c-paren-stmt-key) - (progn (goto-char match-pos) - (while (and (eq (char-before) ?\)) - (c-go-list-backward)) - (c-backward-syntactic-ws)) - (eq (char-before) ?\;)))) - ;; We've got an expression in "for" parens. Remove the - ;; "type" that would spuriously get fontified. - (let ((elt (and (consp c-record-type-identifiers) - (assq (cadr (cddr decl-or-cast)) - c-record-type-identifiers)))) - (when elt - (setq c-record-type-identifiers - (c-delq-from-dotted-list - elt c-record-type-identifiers))) - t) - ;; Back up to the type to fontify the declarator(s). - (goto-char (car decl-or-cast)) - - (let ((decl-list - (if (not (memq context '(nil top))) - ;; Should normally not fontify a list of - ;; declarators inside an arglist, but the first - ;; argument in the ';' separated list of a "for" - ;; statement is an exception. - (when (eq (char-before match-pos) ?\() - (save-excursion - (goto-char (1- match-pos)) - (c-backward-syntactic-ws) - (and (c-simple-skip-symbol-backward) - (looking-at c-paren-stmt-key)))) - t))) - - ;; Fix the `c-decl-id-start' or `c-decl-type-start' property - ;; before the first declarator if it's a list. - ;; `c-font-lock-declarators' handles the rest. - (when decl-list - (save-excursion - (c-backward-syntactic-ws) - (unless (bobp) - (c-put-char-property (1- (point)) 'c-type - (if (cadr decl-or-cast) - 'c-decl-type-start - 'c-decl-id-start))))) - - (c-font-lock-declarators - (min limit (point-max)) decl-list - (cadr decl-or-cast) (not toplev))) - - ;; A declaration has been successfully identified, so do all the - ;; fontification of types and refs that've been recorded. - (c-fontify-recorded-types-and-refs) - nil)) + (goto-char start-pos) + (c-font-lock-single-decl limit decl-or-cast match-pos + context toplev)) (t t)))) @@ -1584,8 +1608,8 @@ casts and declarations are fontified. Used on level 2 and higher." ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; fontification". (let ((decl-search-lim (c-determine-limit 1000)) - paren-state bod-res is-typedef encl-pos - (here (point)) + paren-state encl-pos token-end context decl-or-cast + start-pos top-level c-restricted-<>-arglists c-recognize-knr-p) ; Strictly speaking, bogus, but it ; speeds up lisp.h tremendously. (save-excursion @@ -1599,22 +1623,27 @@ casts and declarations are fontified. Used on level 2 and higher." (c-syntactic-skip-backward "^;{}" decl-search-lim t)) (when (or (bobp) (memq (char-before) '(?\; ?{ ?}))) + (setq token-end (point)) (c-forward-syntactic-ws) ;; We're now putatively at the declaration. + (setq start-pos (point)) (setq paren-state (c-parse-state)) ;; At top level or inside a "{"? (if (or (not (setq encl-pos (c-most-enclosing-brace paren-state))) (eq (char-after encl-pos) ?\{)) (progn - (when (looking-at c-typedef-key) ; "typedef" - (setq is-typedef t) - (goto-char (match-end 0)) - (c-forward-syntactic-ws)) - ;; At a real declaration? - (if (memq (c-forward-type t) '(t known found decltype)) - (c-font-lock-declarators - limit t is-typedef (not (c-bs-at-toplevel-p here))))))))) + (setq top-level (c-at-toplevel-p)) + (let ((got-context (c-get-fontification-context + token-end nil top-level))) + (setq context (car got-context) + c-restricted-<>-arglists (cdr got-context))) + (setq decl-or-cast + (c-forward-decl-or-cast-1 token-end context nil)) + (when (consp decl-or-cast) + (goto-char start-pos) + (c-font-lock-single-decl limit decl-or-cast token-end + context top-level))))))) nil)) (defun c-font-lock-enclosing-decls (limit) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 84d4eab75af..a9d5ac34ad4 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1449,6 +1449,7 @@ comment style. Other stuff like the syntax table must also be set up properly." t "/*" awk nil) +(c-lang-defvar c-block-comment-starter (c-lang-const c-block-comment-starter)) (c-lang-defconst c-block-comment-ender "String that ends block comments, or nil if such don't exist. @@ -1458,6 +1459,7 @@ comment style. Other stuff like the syntax table must also be set up properly." t "*/" awk nil) +(c-lang-defvar c-block-comment-ender (c-lang-const c-block-comment-ender)) (c-lang-defconst c-block-comment-ender-regexp ;; Regexp which matches the end of a block comment (if such exists in the @@ -1515,27 +1517,30 @@ properly." (c-lang-defvar c-doc-comment-start-regexp (c-lang-const c-doc-comment-start-regexp)) +(c-lang-defconst c-block-comment-is-default + "Non-nil when the default comment style is block comment." + ;; Note to maintainers of derived modes: You are responsible for ensuring + ;; the pertinent `c-block-comment-{starter,ender}' or + ;; `c-line-comment-{starter,ender}' are non-nil. + t nil + c t) +(c-lang-defvar c-block-comment-is-default + (c-lang-const c-block-comment-is-default)) + (c-lang-defconst comment-start "String that starts comments inserted with M-; etc. `comment-start' is initialized from this." - ;; Default: Prefer line comments to block comments, and pad with a space. - t (concat (or (c-lang-const c-line-comment-starter) - (c-lang-const c-block-comment-starter)) - " ") - ;; In C we still default to the block comment style since line - ;; comments aren't entirely portable. - c "/* ") + t (concat + (if (c-lang-const c-block-comment-is-default) + (c-lang-const c-block-comment-starter) + (c-lang-const c-line-comment-starter)) + " ")) (c-lang-setvar comment-start (c-lang-const comment-start)) (c-lang-defconst comment-end "String that ends comments inserted with M-; etc. `comment-end' is initialized from this." - ;; Default: Use block comment style if comment-start uses block - ;; comments, and pad with a space in that case. - t (if (string-match (concat "\\`\\(" - (c-lang-const c-block-comment-start-regexp) - "\\)") - (c-lang-const comment-start)) + t (if (c-lang-const c-block-comment-is-default) (concat " " (c-lang-const c-block-comment-ender)) "")) (c-lang-setvar comment-end (c-lang-const comment-end)) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 20c63d4dbe2..a501ebba256 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -398,7 +398,7 @@ control). See \"cc-mode.el\" for more info." ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode) - ) + (define-key c-mode-base-map "\C-c\C-k" 'c-toggle-comment-style)) ;; We don't require the outline package, but we configure it a bit anyway. (cc-bytecomp-defvar outline-level) @@ -547,7 +547,7 @@ that requires a literal mode spec at compile time." (setq yank-handled-properties (remq yank-cat-handler yank-handled-properties))))) - ;; For the benefit of adaptive file, which otherwise mis-fills. + ;; For the benefit of adaptive fill, which otherwise mis-fills. (setq fill-paragraph-handle-comment nil) ;; Install `c-fill-paragraph' on `fill-paragraph-function' so that a @@ -623,6 +623,8 @@ that requires a literal mode spec at compile time." ;; setup the comment indent variable in a Emacs version portable way (set (make-local-variable 'comment-indent-function) 'c-comment-indent) + ;; What sort of comments are default for M-;? + (setq c-block-comment-flag c-block-comment-is-default) ;; In Emacs 24.4 onwards, prevent Emacs's built in electric indentation from ;; messing up CC Mode's, and set `c-electric-flag' if `electric-indent-mode' @@ -1621,10 +1623,10 @@ This function is called from `c-common-init', once per mode initialization." (defvar c-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for C. - (define-key map "\C-c\C-e" 'c-macro-expand) map) "Keymap used in c-mode buffers.") +;; Add bindings which are only useful for C. +(define-key c-mode-map "\C-c\C-e" 'c-macro-expand) (easy-menu-define c-c-menu c-mode-map "C Mode Commands" @@ -1737,13 +1739,13 @@ the code is C or C++ and based on that chooses whether to enable (defvar c++-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for C++. - (define-key map "\C-c\C-e" 'c-macro-expand) - (define-key map "\C-c:" 'c-scope-operator) - (define-key map "<" 'c-electric-lt-gt) - (define-key map ">" 'c-electric-lt-gt) map) "Keymap used in c++-mode buffers.") +;; Add bindings which are only useful for C++. +(define-key c++-mode-map "\C-c\C-e" 'c-macro-expand) +(define-key c++-mode-map "\C-c:" 'c-scope-operator) +(define-key c++-mode-map "<" 'c-electric-lt-gt) +(define-key c++-mode-map ">" 'c-electric-lt-gt) (easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" (cons "C++" (c-lang-const c-mode-menu c++))) @@ -1789,10 +1791,10 @@ Key bindings: (defvar objc-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for Objective-C. - (define-key map "\C-c\C-e" 'c-macro-expand) map) "Keymap used in objc-mode buffers.") +;; Add bindings which are only useful for Objective-C. +(define-key objc-mode-map "\C-c\C-e" 'c-macro-expand) (easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" (cons "ObjC" (c-lang-const c-mode-menu objc))) @@ -1842,9 +1844,9 @@ Key bindings: (defvar java-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for Java. map) "Keymap used in java-mode buffers.") +;; Add bindings which are only useful for Java. ;; Regexp trying to describe the beginning of a Java top-level ;; definition. This is not used by CC Mode, nor is it maintained @@ -1895,9 +1897,9 @@ Key bindings: (defvar idl-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for IDL. map) "Keymap used in idl-mode buffers.") +;; Add bindings which are only useful for IDL. (easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" (cons "IDL" (c-lang-const c-mode-menu idl))) @@ -1942,10 +1944,10 @@ Key bindings: (defvar pike-mode-map (let ((map (c-make-inherited-keymap))) - ;; Additional bindings. - (define-key map "\C-c\C-e" 'c-macro-expand) map) "Keymap used in pike-mode buffers.") +;; Additional bindings. +(define-key pike-mode-map "\C-c\C-e" 'c-macro-expand) (easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands" (cons "Pike" (c-lang-const c-mode-menu pike))) @@ -1994,19 +1996,19 @@ Key bindings: (defvar awk-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for awk. - (define-key map "#" 'self-insert-command);Overrides electric parent binding. - (define-key map "/" 'self-insert-command);Overrides electric parent binding. - (define-key map "*" 'self-insert-command);Overrides electric parent binding. - (define-key map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. - (define-key map "\C-c\C-p" 'undefined) - (define-key map "\C-c\C-u" 'undefined) - (define-key map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 - (define-key map "\M-e" 'c-end-of-statement) ; 2003/10/7 - (define-key map "\C-\M-a" 'c-awk-beginning-of-defun) - (define-key map "\C-\M-e" 'c-awk-end-of-defun) map) "Keymap used in awk-mode buffers.") +;; Add bindings which are only useful for awk. +(define-key awk-mode-map "#" 'self-insert-command);Overrides electric parent binding. +(define-key awk-mode-map "/" 'self-insert-command);Overrides electric parent binding. +(define-key awk-mode-map "*" 'self-insert-command);Overrides electric parent binding. +(define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. +(define-key awk-mode-map "\C-c\C-p" 'undefined) +(define-key awk-mode-map "\C-c\C-u" 'undefined) +(define-key awk-mode-map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 +(define-key awk-mode-map "\M-e" 'c-end-of-statement) ; 2003/10/7 +(define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun) +(define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun) (easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" (cons "AWK" (c-lang-const c-mode-menu awk))) diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el index c234cca3ff9..f2b487dd3bb 100644 --- a/lisp/progmodes/prolog.el +++ b/lisp/progmodes/prolog.el @@ -358,13 +358,15 @@ The version numbers are of the format (Major . Minor)." (defcustom prolog-indent-width 4 "The indentation width used by the editing buffer." :group 'prolog-indentation - :type 'integer) + :type 'integer + :safe 'integerp) (defcustom prolog-left-indent-regexp "\\(;\\|\\*?->\\)" "Regexp for `prolog-electric-if-then-else-flag'." :version "24.1" :group 'prolog-indentation - :type 'regexp) + :type 'regexp + :safe 'stringp) (defcustom prolog-paren-indent-p nil "If non-nil, increase indentation for parenthesis expressions. @@ -374,14 +376,16 @@ right (if this variable is non-nil) or in the same way as for compound terms (if this variable is nil, default)." :version "24.1" :group 'prolog-indentation - :type 'boolean) + :type 'boolean + :safe 'booleanp) (defcustom prolog-paren-indent 4 "The indentation increase for parenthesis expressions. Only used in ( If -> Then ; Else) and ( Disj1 ; Disj2 ) style expressions." :version "24.1" :group 'prolog-indentation - :type 'integer) + :type 'integer + :safe 'integerp) (defcustom prolog-parse-mode 'beg-of-clause "The parse mode used (decides from which point parsing is done). diff --git a/lisp/simple.el b/lisp/simple.el index df664fc0503..a5565ab6e73 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2589,8 +2589,12 @@ Return what remains of the list." (goto-char pos)) ;; Adjust the valid marker adjustments (dolist (adj valid-marker-adjustments) - (set-marker (car adj) - (- (car adj) (cdr adj)))))) + ;; Insert might have invalidated some of the markers + ;; via modification hooks. Update only the currently + ;; valid ones (bug#25599). + (if (marker-buffer (car adj)) + (set-marker (car adj) + (- (car adj) (cdr adj))))))) ;; (MARKER . OFFSET) means a marker MARKER was adjusted by OFFSET. (`(,(and marker (pred markerp)) . ,(and offset (pred integerp))) (warn "Encountered %S entry in undo list with no matching (TEXT . POS) entry" diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 0beaaaa32f1..b37e6dce1af 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -764,7 +764,6 @@ cannot be completed sensibly: `custom-ident', "Self inserting keys which should trigger re-indentation." :version "22.2" :type '(repeat character) - :options '((?\} ?\;)) :group 'css) (defvar css-mode-syntax-table @@ -1289,10 +1288,11 @@ the string PROPERTY." (let ((property (save-excursion (re-search-backward ":[^/]" (line-beginning-position) t) - (let ((property-end (point))) - (skip-chars-backward "-[:alnum:]") - (let ((property (buffer-substring (point) property-end))) - (car (member property css-property-ids))))))) + (when (eq (char-after) ?:) + (let ((property-end (point))) + (skip-chars-backward "-[:alnum:]") + (let ((prop (buffer-substring (point) property-end))) + (car (member prop css-property-ids)))))))) (when property (let ((end (point))) (save-excursion diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index 25e01df70ee..7c3d73e52b7 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el @@ -380,7 +380,9 @@ the bounds of a possible ill-formed URI (one lacking a scheme)." (save-restriction (narrow-to-region (1- url-beg) (min end (point-max))) (setq paren-end (ignore-errors - (scan-lists (1- url-beg) 1 0)))) + ;; Make the scan work inside comments. + (let ((parse-sexp-ignore-comments nil)) + (scan-lists (1- url-beg) 1 0))))) (not (blink-matching-check-mismatch (1- url-beg) paren-end)) (setq end (1- paren-end))) ;; Ensure PT is actually within BOUNDARY. Check the following diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el index 9897dea9c7f..a3c9655ebdd 100644 --- a/lisp/url/url-util.el +++ b/lisp/url/url-util.el @@ -565,7 +565,7 @@ Has a preference for looking backward when not directly on a symbol." (skip-chars-forward url-get-url-filename-chars)) (setq start (point))) (setq url (buffer-substring-no-properties start (point)))) - (if (and url (string-match "^(.*)\\.?$" url)) + (if (and url (string-match "^(\\(.*\\))\\.?$" url)) (setq url (match-string 1 url))) (if (and url (string-match "^URL:" url)) (setq url (substring url 4 nil))) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 8f53a990e34..1ac58e871cc 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -61,6 +61,7 @@ AC_DEFUN([gl_EARLY], # Code from module crypto/sha1: # Code from module crypto/sha256: # Code from module crypto/sha512: + # Code from module diffseq: # Code from module dirent: # Code from module dirfd: # Code from module dosname: @@ -105,6 +106,7 @@ AC_DEFUN([gl_EARLY], # Code from module lstat: # Code from module manywarnings: # Code from module memrchr: + # Code from module minmax: # Code from module mkostemp: # Code from module mktime: # Code from module mktime-internal: @@ -289,6 +291,7 @@ AC_DEFUN([gl_INIT], gl_PREREQ_MEMRCHR fi gl_STRING_MODULE_INDICATOR([memrchr]) + gl_MINMAX gl_FUNC_MKOSTEMP if test $HAVE_MKOSTEMP = 0; then AC_LIBOBJ([mkostemp]) @@ -821,6 +824,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/count-one-bits.h lib/count-trailing-zeros.c lib/count-trailing-zeros.h + lib/diffseq.h lib/dirent.in.h lib/dirfd.c lib/dosname.h @@ -875,6 +879,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/md5.c lib/md5.h lib/memrchr.c + lib/minmax.h lib/mkostemp.c lib/mktime-internal.h lib/mktime.c @@ -991,6 +996,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/manywarnings.m4 m4/md5.m4 m4/memrchr.m4 + m4/minmax.m4 m4/mkostemp.m4 m4/mktime.m4 m4/multiarch.m4 diff --git a/m4/minmax.m4 b/m4/minmax.m4 new file mode 100644 index 00000000000..6845fce89c4 --- /dev/null +++ b/m4/minmax.m4 @@ -0,0 +1,44 @@ +# minmax.m4 serial 4 +dnl Copyright (C) 2005, 2009-2017 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_PREREQ([2.53]) + +AC_DEFUN([gl_MINMAX], +[ + AC_REQUIRE([gl_PREREQ_MINMAX]) +]) + +# Prerequisites of lib/minmax.h. +AC_DEFUN([gl_PREREQ_MINMAX], +[ + gl_MINMAX_IN_HEADER([limits.h]) + gl_MINMAX_IN_HEADER([sys/param.h]) +]) + +dnl gl_MINMAX_IN_HEADER(HEADER) +dnl The parameter has to be a literal header name; it cannot be macro, +dnl nor a shell variable. (Because autoheader collects only AC_DEFINE +dnl invocations with a literal macro name.) +AC_DEFUN([gl_MINMAX_IN_HEADER], +[ + m4_pushdef([header], AS_TR_SH([$1])) + m4_pushdef([HEADER], AS_TR_CPP([$1])) + AC_CACHE_CHECK([whether <$1> defines MIN and MAX], + [gl_cv_minmax_in_]header, + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <$1> + int x = MIN (42, 17);]], + [[]])], + [gl_cv_minmax_in_]header[=yes], + [gl_cv_minmax_in_]header[=no])]) + if test $gl_cv_minmax_in_[]header = yes; then + AC_DEFINE([HAVE_MINMAX_IN_]HEADER, 1, + [Define to 1 if <$1> defines the MIN and MAX macros.]) + fi + m4_popdef([HEADER]) + m4_popdef([header]) +]) diff --git a/src/Makefile.in b/src/Makefile.in index 2be24ac192a..57969d5fc58 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -639,13 +639,13 @@ mostlyclean: rm -f globals.h gl-stamp rm -f *.res *.tmp clean: mostlyclean - rm -f emacs-*.*.*$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/* + rm -f emacs-*.*.*[0-9]$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/* ## bootstrap-clean is used to clean up just before a bootstrap. ## It should remove all files generated during a compilation/bootstrap, ## but not things like config.status or TAGS. bootstrap-clean: clean - rm -f epaths.h config.h config.stamp + rm -f emacs-module.h epaths.h config.h config.stamp if test -f ./.gdbinit; then \ mv ./.gdbinit ./.gdbinit.save; \ if test -f "$(srcdir)/.gdbinit"; then rm -f ./.gdbinit.save; \ diff --git a/src/bidi.c b/src/bidi.c index dce0bf695f6..e34da778ba0 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -565,9 +565,7 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) 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 +verify (BIDI_CACHE_CHUNK < BIDI_CACHE_MAX_ELTS_PER_SLOT); 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; @@ -2468,9 +2466,11 @@ typedef struct bpa_stack_entry { unsigned flags : 2; } bpa_stack_entry; -/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the +/* Allow for the two struct bidi_it objects too, since they can be big. + With MAX_ALLOCA of 16 KiB, this should allow at least 900 slots in the BPA stack, which should be more than enough for actual bidi text. */ -#define MAX_BPA_STACK ((int)max (MAX_ALLOCA / sizeof (bpa_stack_entry), 1)) +enum { MAX_BPA_STACK = max (1, ((MAX_ALLOCA - 2 * sizeof (struct bidi_it)) + / sizeof (bpa_stack_entry))) }; /* UAX#9 says to match opening brackets with the matching closing brackets or their canonical equivalents. As of Unicode 8.0, there @@ -2517,7 +2517,7 @@ typedef struct bpa_stack_entry { #define PUSH_BPA_STACK \ do { \ int ch; \ - if (bpa_sp < MAX_BPA_STACK - 1) \ + if (bpa_sp < MAX_BPA_STACK - 1 && bidi_cache_last_idx <= INT_MAX) \ { \ bpa_sp++; \ ch = CANONICAL_EQU (bidi_it->ch); \ @@ -2563,7 +2563,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) ptrdiff_t pairing_pos; int idx_at_entry = bidi_cache_idx; - eassert (MAX_BPA_STACK >= 100); + verify (MAX_BPA_STACK >= 100); bidi_copy_it (&saved_it, bidi_it); /* bidi_cache_iterator_state refuses to cache on backward scans, and bidi_cache_fetch_state doesn't bring scan_dir from the diff --git a/src/buffer.h b/src/buffer.h index a2bdc4e7294..be270fe4823 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -412,6 +412,15 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ : BUF_FETCH_BYTE ((buf), (pos))) +/* Return character at byte position POS in buffer BUF. If BUF is + unibyte and the character is not ASCII, make the returning + character multibyte. */ + +#define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \ + (! NILP (BVAR ((buf), enable_multibyte_characters)) \ + ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ + : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos)))) + /* Return the byte at byte position N in buffer BUF. */ #define BUF_FETCH_BYTE(buf, n) \ diff --git a/src/conf_post.h b/src/conf_post.h index 18b096e2cf6..e1d6a9397d3 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -57,10 +57,13 @@ typedef bool bool_bf; #endif /* Simulate __has_attribute on compilers that lack it. It is used only - on arguments like alloc_size that are handled in this simulation. */ + on arguments like alloc_size that are handled in this simulation. + __has_attribute should be used only in #if expressions, as Oracle + Studio 12.5's __has_attribute does not work in plain code. */ #ifndef __has_attribute # define __has_attribute(a) __has_attribute_##a # define __has_attribute_alloc_size GNUC_PREREQ (4, 3, 0) +# define __has_attribute_cleanup GNUC_PREREQ (3, 4, 0) # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) # define __has_attribute_no_address_safety_analysis false # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) diff --git a/src/editfns.c b/src/editfns.c index 43b17f9f116..da99c055b54 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3105,6 +3105,207 @@ determines whether case is significant or ignored. */) /* Same length too => they are equal. */ return make_number (0); } + + +/* Set up necessary definitions for diffseq.h; see comments in + diffseq.h for explanation. */ + +#undef ELEMENT +#undef EQUAL + +#define XVECREF_YVECREF_EQUAL(ctx, xoff, yoff) \ + buffer_chars_equal ((ctx), (xoff), (yoff)) + +#define OFFSET ptrdiff_t + +#define EXTRA_CONTEXT_FIELDS \ + /* Buffers to compare. */ \ + struct buffer *buffer_a; \ + struct buffer *buffer_b; \ + /* Bit vectors recording for each character whether it was deleted + or inserted. */ \ + unsigned char *deletions; \ + unsigned char *insertions; + +#define NOTE_DELETE(ctx, xoff) set_bit ((ctx)->deletions, (xoff)) +#define NOTE_INSERT(ctx, yoff) set_bit ((ctx)->insertions, (yoff)) + +struct context; +static void set_bit (unsigned char *, OFFSET); +static bool bit_is_set (const unsigned char *, OFFSET); +static bool buffer_chars_equal (struct context *, OFFSET, OFFSET); + +#include "minmax.h" +#include "diffseq.h" + +DEFUN ("replace-buffer-contents", Freplace_buffer_contents, + Sreplace_buffer_contents, 1, 1, "bSource buffer: ", + doc: /* Replace accessible portion of current buffer with that of SOURCE. +SOURCE can be a buffer or a string that names a buffer. +Interactively, prompt for SOURCE. +As far as possible the replacement is non-destructive, i.e. existing +buffer contents, markers, properties, and overlays in the current +buffer stay intact. */) + (Lisp_Object source) +{ + struct buffer *a = current_buffer; + Lisp_Object source_buffer = Fget_buffer (source); + if (NILP (source_buffer)) + nsberror (source); + struct buffer *b = XBUFFER (source_buffer); + if (! BUFFER_LIVE_P (b)) + error ("Selecting deleted buffer"); + if (a == b) + error ("Cannot replace a buffer with itself"); + + ptrdiff_t min_a = BEGV; + ptrdiff_t min_b = BUF_BEGV (b); + ptrdiff_t size_a = ZV - min_a; + ptrdiff_t size_b = BUF_ZV (b) - min_b; + eassume (size_a >= 0); + eassume (size_b >= 0); + bool a_empty = size_a == 0; + bool b_empty = size_b == 0; + + /* Handle trivial cases where at least one accessible portion is + empty. */ + + if (a_empty && b_empty) + return Qnil; + + if (a_empty) + return Finsert_buffer_substring (source, Qnil, Qnil); + + if (b_empty) + { + del_range_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, true); + return Qnil; + } + + /* FIXME: It is not documented how to initialize the contents of the + context structure. This code cargo-cults from the existing + caller in src/analyze.c of GNU Diffutils, which appears to + work. */ + + ptrdiff_t diags = size_a + size_b + 3; + ptrdiff_t *buffer; + USE_SAFE_ALLOCA; + SAFE_NALLOCA (buffer, 2, diags); + /* Micro-optimization: Casting to size_t generates much better + code. */ + ptrdiff_t del_bytes = (size_t) size_a / CHAR_BIT + 1; + ptrdiff_t ins_bytes = (size_t) size_b / CHAR_BIT + 1; + struct context ctx = { + .buffer_a = a, + .buffer_b = b, + .deletions = SAFE_ALLOCA (del_bytes), + .insertions = SAFE_ALLOCA (ins_bytes), + .fdiag = buffer + size_b + 1, + .bdiag = buffer + diags + size_b + 1, + /* FIXME: Find a good number for .too_expensive. */ + .too_expensive = 1000000, + }; + memclear (ctx.deletions, del_bytes); + memclear (ctx.insertions, ins_bytes); + /* compareseq requires indices to be zero-based. We add BEGV back + later. */ + bool early_abort = compareseq (0, size_a, 0, size_b, false, &ctx); + /* Since we didn’t define EARLY_ABORT, we should never abort + early. */ + eassert (! early_abort); + SAFE_FREE (); + + Fundo_boundary (); + ptrdiff_t count = SPECPDL_INDEX (); + record_unwind_protect (save_excursion_restore, save_excursion_save ()); + + ptrdiff_t i = size_a; + ptrdiff_t j = size_b; + /* Walk backwards through the lists of changes. This was also + cargo-culted from src/analyze.c in GNU Diffutils. Because we + walk backwards, we don’t have to keep the positions in sync. */ + while (i >= 0 || j >= 0) + { + /* Check whether there is a change (insertion or deletion) + before the current position. */ + if ((i > 0 && bit_is_set (ctx.deletions, i - 1)) || + (j > 0 && bit_is_set (ctx.insertions, j - 1))) + { + ptrdiff_t end_a = min_a + i; + ptrdiff_t end_b = min_b + j; + /* Find the beginning of the current change run. */ + while (i > 0 && bit_is_set (ctx.deletions, i - 1)) + --i; + while (j > 0 && bit_is_set (ctx.insertions, j - 1)) + --j; + ptrdiff_t beg_a = min_a + i; + ptrdiff_t beg_b = min_b + j; + eassert (beg_a >= BEGV); + eassert (beg_b >= BUF_BEGV (b)); + eassert (beg_a <= end_a); + eassert (beg_b <= end_b); + eassert (end_a <= ZV); + eassert (end_b <= BUF_ZV (b)); + eassert (beg_a < end_a || beg_b < end_b); + if (beg_a < end_a) + del_range (beg_a, end_a); + if (beg_b < end_b) + { + SET_PT (beg_a); + Finsert_buffer_substring (source, make_natnum (beg_b), + make_natnum (end_b)); + } + } + --i; + --j; + } + + return unbind_to (count, Qnil); +} + +static void +set_bit (unsigned char *a, ptrdiff_t i) +{ + eassert (i >= 0); + /* Micro-optimization: Casting to size_t generates much better + code. */ + size_t j = i; + a[j / CHAR_BIT] |= (1 << (j % CHAR_BIT)); +} + +static bool +bit_is_set (const unsigned char *a, ptrdiff_t i) +{ + eassert (i >= 0); + /* Micro-optimization: Casting to size_t generates much better + code. */ + size_t j = i; + return a[j / CHAR_BIT] & (1 << (j % CHAR_BIT)); +} + +/* Return true if the characters at position POS_A of buffer + CTX->buffer_a and at position POS_B of buffer CTX->buffer_b are + equal. POS_A and POS_B are zero-based. Text properties are + ignored. */ + +static bool +buffer_chars_equal (struct context *ctx, + ptrdiff_t pos_a, ptrdiff_t pos_b) +{ + eassert (pos_a >= 0); + pos_a += BUF_BEGV (ctx->buffer_a); + eassert (pos_a >= BUF_BEGV (ctx->buffer_a)); + eassert (pos_a < BUF_ZV (ctx->buffer_a)); + + eassert (pos_b >= 0); + pos_b += BUF_BEGV (ctx->buffer_b); + eassert (pos_b >= BUF_BEGV (ctx->buffer_b)); + eassert (pos_b < BUF_ZV (ctx->buffer_b)); + + return BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_a, pos_a) + == BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_b, pos_b); +} + static void subst_char_in_region_unwind (Lisp_Object arg) @@ -3978,6 +4179,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) bool maybe_combine_byte; bool arg_intervals = false; USE_SAFE_ALLOCA; + sa_avail -= sizeof initial_buffer; /* Information recorded for each format spec. */ struct info @@ -5315,6 +5517,7 @@ functions if all the text being accessed has this property. */); defsubr (&Sinsert_buffer_substring); defsubr (&Scompare_buffer_substrings); + defsubr (&Sreplace_buffer_contents); defsubr (&Ssubst_char_in_region); defsubr (&Stranslate_region_internal); defsubr (&Sdelete_region); diff --git a/src/emacs-module.c b/src/emacs-module.c index de62329b3b8..2693a4529d6 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -170,6 +170,10 @@ static struct emacs_env_private global_env_private; internal_handler_##handlertype, \ internal_cleanup_##handlertype) +#if !__has_attribute (cleanup) + #error "__attribute__ ((cleanup)) not supported by this compiler; try GCC" +#endif + /* It is very important that pushing the handler doesn't itself raise a signal. Install the cleanup only after the handler has been pushed. Use __attribute__ ((cleanup)) to avoid @@ -764,6 +768,9 @@ funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist) USE_SAFE_ALLOCA; ATTRIBUTE_MAY_ALIAS emacs_value *args; if (plain_values && ! module_assertions) + /* FIXME: The cast below is incorrect because the argument array + is not declared as const, so module functions can modify it. + Either declare it as const, or remove this branch. */ args = (emacs_value *) arglist; else { diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in new file mode 100644 index 00000000000..339234fdb51 --- /dev/null +++ b/src/emacs-module.h.in @@ -0,0 +1,106 @@ +/* emacs-module.h - GNU Emacs module API. + +Copyright (C) 2015-2017 Free Software Foundation, Inc. + +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 <http://www.gnu.org/licenses/>. */ + +#ifndef EMACS_MODULE_H +#define EMACS_MODULE_H + +#include <stdint.h> +#include <stddef.h> + +#ifndef __cplusplus +#include <stdbool.h> +#endif + +#if defined __cplusplus && __cplusplus >= 201103L +# define EMACS_NOEXCEPT noexcept +#else +# define EMACS_NOEXCEPT +#endif + +#ifdef __has_attribute +#if __has_attribute(__nonnull__) +# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#endif +#endif +#ifndef EMACS_ATTRIBUTE_NONNULL +# define EMACS_ATTRIBUTE_NONNULL(...) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Current environment. */ +typedef struct emacs_env_26 emacs_env; + +/* Opaque pointer representing an Emacs Lisp value. + BEWARE: Do not assume NULL is a valid value! */ +typedef struct emacs_value_tag *emacs_value; + +enum { emacs_variadic_function = -2 }; + +/* Struct passed to a module init function (emacs_module_init). */ +struct emacs_runtime +{ + /* Structure size (for version checking). */ + ptrdiff_t size; + + /* Private data; users should not touch this. */ + struct emacs_runtime_private *private_members; + + /* Return an environment pointer. */ + emacs_env *(*get_environment) (struct emacs_runtime *ert) + EMACS_ATTRIBUTE_NONNULL(1); +}; + + +/* Possible Emacs function call outcomes. */ +enum emacs_funcall_exit +{ + /* Function has returned normally. */ + emacs_funcall_exit_return = 0, + + /* Function has signaled an error using `signal'. */ + emacs_funcall_exit_signal = 1, + + /* Function has exit using `throw'. */ + emacs_funcall_exit_throw = 2, +}; + +struct emacs_env_25 +{ +@module_env_snippet_25@ +}; + +struct emacs_env_26 +{ +@module_env_snippet_25@ + +@module_env_snippet_26@ +}; + +/* Every module should define a function as follows. */ +extern int emacs_module_init (struct emacs_runtime *ert) + EMACS_ATTRIBUTE_NONNULL(1); + +#ifdef __cplusplus +} +#endif + +#endif /* EMACS_MODULE_H */ diff --git a/src/emacs.c b/src/emacs.c index b0892c7ebb8..da8df1bf1c7 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -223,8 +223,12 @@ Initialization options:\n\ --fg-daemon[=NAME] start a (named) server in the foreground\n\ --debug-init enable Emacs Lisp debugger for init file\n\ --display, -d DISPLAY use X server DISPLAY\n\ +", +#ifdef HAVE_MODULES + "\ --module-assertions assert behavior of dynamic modules\n\ ", +#endif "\ --no-build-details do not add build details such as time stamps\n\ --no-desktop do not load a saved desktop\n\ @@ -1733,7 +1737,9 @@ static const struct standard_args standard_args[] = { "-nl", "--no-loadup", 70, 0 }, { "-nsl", "--no-site-lisp", 65, 0 }, { "-no-build-details", "--no-build-details", 63, 0 }, +#ifdef HAVE_MODULES { "-module-assertions", "--module-assertions", 62, 0 }, +#endif /* -d must come last before the options handled in startup.el. */ { "-d", "--display", 60, 1 }, { "-display", 0, 60, 1 }, diff --git a/src/fileio.c b/src/fileio.c index c21056ee6f2..cb070029a9b 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3306,11 +3306,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) ? Qt : Qnil); } -#ifndef READ_BUF_SIZE -#define READ_BUF_SIZE (64 << 10) -#endif -/* Some buffer offsets are stored in 'int' variables. */ -verify (READ_BUF_SIZE <= INT_MAX); +enum { READ_BUF_SIZE = MAX_ALLOCA }; /* This function is called after Lisp functions to decide a coding system are called, or when they cause an error. Before they are diff --git a/src/gmalloc.c b/src/gmalloc.c index 49f1fafccc0..baaff58050f 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -77,11 +77,6 @@ extern void *(*__morecore) (ptrdiff_t); #ifdef HYBRID_MALLOC # include "sheap.h" # define DUMPED bss_sbrk_did_unexec -static bool -ALLOCATED_BEFORE_DUMPING (char *p) -{ - return bss_sbrk_buffer <= p && p < bss_sbrk_buffer + STATIC_HEAP_SIZE; -} #endif #ifdef __cplusplus @@ -133,8 +128,13 @@ typedef union /* Heap information for a busy block. */ struct { - /* Zero for a large (multiblock) object, or positive giving the - logarithm to the base two of the fragment size. */ + /* Zero for a block that is not one of ours (typically, + allocated by system malloc), positive for the log base 2 of + the fragment size of a fragmented block, -1 for the first + block of a multiblock object, and unspecified for later + blocks of that object. Type-0 blocks can be present + because the system malloc can be invoked by library + functions in an undumped Emacs. */ int type; union { @@ -144,8 +144,7 @@ typedef union size_t first; /* First free fragment of the block. */ } frag; /* For a large object, in its first block, this has the number - of blocks in the object. In the other blocks, this has a - negative number which says how far back the first block is. */ + of blocks in the object. */ ptrdiff_t size; } info; } busy; @@ -166,7 +165,7 @@ extern char *_heapbase; extern malloc_info *_heapinfo; /* Address to block number and vice versa. */ -#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define BLOCK(A) ((size_t) ((char *) (A) - _heapbase) / BLOCKSIZE + 1) #define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + _heapbase)) /* Current search index for the heap table. */ @@ -491,11 +490,8 @@ register_heapinfo (void) ++_chunks_used; /* Describe the heapinfo block itself in the heapinfo. */ - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = blocks; - /* Leave back-pointers for malloc_find_address. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; } #ifdef USE_PTHREAD @@ -608,7 +604,7 @@ morecore_nolock (size_t size) PROTECT_MALLOC_STATE (0); /* Check if we need to grow the info table. */ - if ((size_t) BLOCK ((char *) result + size) > heapsize) + if (heapsize < BLOCK ((char *) result + size)) { /* Calculate the new _heapinfo table size. We do not account for the added blocks in the table itself, as we hope to place them in @@ -617,7 +613,7 @@ morecore_nolock (size_t size) newsize = heapsize; do newsize *= 2; - while ((size_t) BLOCK ((char *) result + size) > newsize); + while (newsize < BLOCK ((char *) result + size)); /* We must not reuse existing core for the new info table when called from realloc in the case of growing a large block, because the @@ -665,8 +661,7 @@ morecore_nolock (size_t size) /* Is it big enough to record status for its own space? If so, we win. */ - if ((size_t) BLOCK ((char *) newinfo - + newsize * sizeof (malloc_info)) + if (BLOCK ((char *) newinfo + newsize * sizeof (malloc_info)) < newsize) break; @@ -883,17 +878,11 @@ _malloc_internal_nolock (size_t size) --_chunks_free; } - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = blocks; ++_chunks_used; _bytes_used += blocks * BLOCKSIZE; _bytes_free -= blocks * BLOCKSIZE; - - /* Mark all the blocks of the object just allocated except for the - first with a negative number so you can find the first block by - adding that adjustment. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; } PROTECT_MALLOC_STATE (1); @@ -1026,7 +1015,7 @@ _free_internal_nolock (void *ptr) type = _heapinfo[block].busy.type; switch (type) { - case 0: + case -1: /* Get as many statistics as early as we can. */ --_chunks_used; _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; @@ -1187,7 +1176,7 @@ _free_internal_nolock (void *ptr) prev->prev->next = next; if (next != NULL) next->prev = prev->prev; - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = 1; /* Keep the statistics accurate. */ @@ -1326,7 +1315,7 @@ _realloc_internal_nolock (void *ptr, size_t size) type = _heapinfo[block].busy.type; switch (type) { - case 0: + case -1: /* Maybe reallocate a large block to a small fragment. */ if (size <= BLOCKSIZE / 2) { @@ -1346,7 +1335,7 @@ _realloc_internal_nolock (void *ptr, size_t size) { /* The new size is smaller; return excess memory to the free list. */ - _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.type = -1; _heapinfo[block + blocks].busy.info.size = _heapinfo[block].busy.info.size - blocks; _heapinfo[block].busy.info.size = blocks; @@ -1721,6 +1710,20 @@ extern void *aligned_alloc (size_t alignment, size_t size); extern int posix_memalign (void **memptr, size_t alignment, size_t size); #endif +/* Assuming PTR was allocated via the hybrid malloc, return true if + PTR was allocated via gmalloc, not the system malloc. Also, return + true if _heaplimit is zero; this can happen temporarily when + gmalloc calls itself for internal use, and in that case PTR is + already known to be allocated via gmalloc. */ + +static bool +allocated_via_gmalloc (void *ptr) +{ + size_t block = BLOCK (ptr); + size_t blockmax = _heaplimit - 1; + return block <= blockmax && _heapinfo[block].busy.type != 0; +} + /* See the comments near the beginning of this file for explanations of the following functions. */ @@ -1743,13 +1746,10 @@ hybrid_calloc (size_t nmemb, size_t size) void hybrid_free (void *ptr) { - if (!DUMPED) + if (allocated_via_gmalloc (ptr)) gfree (ptr); - else if (!ALLOCATED_BEFORE_DUMPING (ptr)) + else free (ptr); - /* Otherwise the dumped emacs is trying to free something allocated - before dumping; do nothing. */ - return; } #if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN @@ -1775,19 +1775,20 @@ hybrid_realloc (void *ptr, size_t size) int type; size_t block, oldsize; + if (!ptr) + return hybrid_malloc (size); + if (!allocated_via_gmalloc (ptr)) + return realloc (ptr, size); if (!DUMPED) return grealloc (ptr, size); - if (!ALLOCATED_BEFORE_DUMPING (ptr)) - return realloc (ptr, size); /* The dumped emacs is trying to realloc storage allocated before - dumping. We just malloc new space and copy the data. */ - if (size == 0 || ptr == NULL) - return malloc (size); - block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1; + dumping via gmalloc. Allocate new space and copy the data. Do + not bother with gfree (ptr), as that would just waste time. */ + block = BLOCK (ptr); type = _heapinfo[block].busy.type; oldsize = - type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE + type < 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE : (size_t) 1 << type; result = malloc (size); if (result) diff --git a/src/image.c b/src/image.c index 429777ce511..aedec7954ee 100644 --- a/src/image.c +++ b/src/image.c @@ -2041,10 +2041,20 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, (*ximg)->info.bmiColors[0].rgbGreen = 0; (*ximg)->info.bmiColors[0].rgbRed = 0; (*ximg)->info.bmiColors[0].rgbReserved = 0; + /* bmiColors is a variable-length array declared by w32api + headers as bmiColors[1], which triggers a warning under + -Warray-bounds; shut that up. */ +# if GNUC_PREREQ (4, 4, 0) +# pragma GCC push_options +# pragma GCC diagnostic ignored "-Warray-bounds" +# endif (*ximg)->info.bmiColors[1].rgbBlue = 255; (*ximg)->info.bmiColors[1].rgbGreen = 255; (*ximg)->info.bmiColors[1].rgbRed = 255; (*ximg)->info.bmiColors[1].rgbReserved = 0; +# if GNUC_PREREQ (4, 4, 0) +# pragma GCC pop_options +# endif } hdc = get_frame_dc (f); diff --git a/src/lread.c b/src/lread.c index 3004e2b1915..b01cbd5c072 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4863,11 +4863,12 @@ The remaining ENTRIES in the alist element describe the functions and variables defined in that file, the features provided, and the features required. Each entry has the form `(provide . FEATURE)', `(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', -`(defface . SYMBOL)', or `(t . SYMBOL)'. Entries like `(t . SYMBOL)' -may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an -autoload before this file redefined it as a function. In addition, -entries may also be single symbols, which means that SYMBOL was -defined by `defvar' or `defconst'. +`(defface . SYMBOL)', `(define-type . SYMBOL)', +`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. +Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry, +and means that SYMBOL was an autoload before this file redefined it +as a function. In addition, entries may also be single symbols, +which means that symbol was defined by `defvar' or `defconst'. During preloading, the file name recorded is relative to the main Lisp directory. These file names are converted to absolute at startup. */); diff --git a/src/emacs-module.h b/src/module-env-25.h index ad102e6d843..17e67004b24 100644 --- a/src/emacs-module.h +++ b/src/module-env-25.h @@ -1,95 +1,3 @@ -/* emacs-module.h - GNU Emacs module API. - -Copyright (C) 2015-2017 Free Software Foundation, Inc. - -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 <http://www.gnu.org/licenses/>. */ - -#ifndef EMACS_MODULE_H -#define EMACS_MODULE_H - -#if ! (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \ - && ! (defined __cplusplus && __cplusplus >= 199711L) -# error "This file requires at least C99 or C++98" -#endif - -#include <stdint.h> -#include <stddef.h> - -#ifndef __cplusplus -#include <stdbool.h> -#endif - -#if defined __cplusplus && __cplusplus >= 201103L -# define EMACS_NOEXCEPT noexcept -#else -# define EMACS_NOEXCEPT -#endif - -#ifdef __has_attribute -#if __has_attribute(__nonnull__) -# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#endif -#endif -#ifndef EMACS_ATTRIBUTE_NONNULL -# define EMACS_ATTRIBUTE_NONNULL(...) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Current environment. */ -typedef struct emacs_env_25 emacs_env; - -/* Opaque pointer representing an Emacs Lisp value. - BEWARE: Do not assume NULL is a valid value! */ -typedef struct emacs_value_tag *emacs_value; - -enum { emacs_variadic_function = -2 }; - -/* Struct passed to a module init function (emacs_module_init). */ -struct emacs_runtime -{ - /* Structure size (for version checking). */ - ptrdiff_t size; - - /* Private data; users should not touch this. */ - struct emacs_runtime_private *private_members; - - /* Return an environment pointer. */ - emacs_env *(*get_environment) (struct emacs_runtime *ert) - EMACS_ATTRIBUTE_NONNULL(1); -}; - - -/* Possible Emacs function call outcomes. */ -enum emacs_funcall_exit -{ - /* Function has returned normally. */ - emacs_funcall_exit_return = 0, - - /* Function has signaled an error using `signal'. */ - emacs_funcall_exit_signal = 1, - - /* Function has exit using `throw'. */ - emacs_funcall_exit_throw = 2, -}; - -struct emacs_env_25 -{ /* Structure size (for version checking). */ ptrdiff_t size; @@ -230,18 +138,3 @@ struct emacs_env_25 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec) EMACS_ATTRIBUTE_NONNULL(1); - - /* Returns whether a quit is pending. */ - bool (*should_quit) (emacs_env *env) - EMACS_ATTRIBUTE_NONNULL(1); -}; - -/* Every module should define a function as follows. */ -extern int emacs_module_init (struct emacs_runtime *ert) - EMACS_ATTRIBUTE_NONNULL(1); - -#ifdef __cplusplus -} -#endif - -#endif /* EMACS_MODULE_H */ diff --git a/src/module-env-26.h b/src/module-env-26.h new file mode 100644 index 00000000000..1ab12d45c84 --- /dev/null +++ b/src/module-env-26.h @@ -0,0 +1,3 @@ + /* Returns whether a quit is pending. */ + bool (*should_quit) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL(1); diff --git a/src/unexelf.c b/src/unexelf.c index 7fad64fab17..5129784ade2 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -576,7 +576,17 @@ unexec (const char *new_name, const char *old_name) } /* This loop seeks out relocation sections for the data section, so - that it can undo relocations performed by the runtime loader. */ + that it can undo relocations performed by the runtime loader. + + The following approach does not work on x86 platforms that use + the GNU Gold linker, which can generate .rel.dyn relocation + sections containing R_386_32 entries that the following code does + not grok. Emacs works around this problem by avoiding C + constructs that generate such entries, which is horrible hack. + + FIXME: Presumably more problems like this will crop up as linkers + get fancier. We really need to stop assuming that Emacs can grok + arbitrary linker output. See Bug#27248. */ for (n = new_file_h->e_shnum; 0 < --n; ) { ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n); diff --git a/src/widget.c b/src/widget.c index d7ec7028517..585039d58c6 100644 --- a/src/widget.c +++ b/src/widget.c @@ -108,7 +108,7 @@ emacsFrameTranslations [] = "\ static EmacsFrameClassRec emacsFrameClassRec = { { /* core fields */ - /* superclass */ &widgetClassRec, + /* superclass */ 0, /* filled in by emacsFrameClass */ /* class_name */ (char *) "EmacsFrame", /* widget_size */ sizeof (EmacsFrameRec), /* class_initialize */ 0, @@ -146,7 +146,16 @@ static EmacsFrameClassRec emacsFrameClassRec = { } }; -WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec; +WidgetClass +emacsFrameClass (void) +{ + /* Set the superclass here rather than relying on static + initialization, to work around an unexelf.c bug on x86 platforms + that use the GNU Gold linker (Bug#27248). */ + emacsFrameClassRec.core_class.superclass = &widgetClassRec; + + return (WidgetClass) &emacsFrameClassRec; +} static void get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height) diff --git a/src/widget.h b/src/widget.h index 2c5fb61df2f..97dd6ab61de 100644 --- a/src/widget.h +++ b/src/widget.h @@ -90,7 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ typedef struct _EmacsFrameRec *EmacsFrame; typedef struct _EmacsFrameClassRec *EmacsFrameClass; -extern WidgetClass emacsFrameClass; +extern WidgetClass emacsFrameClass (void); extern struct _DisplayContext *display_context; diff --git a/src/xfns.c b/src/xfns.c index e463391c74a..7be2253cc3b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2875,7 +2875,7 @@ x_window (struct frame *f, long window_prompting) XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; XtSetArg (al[ac], XtNborderWidth, 0); ac++; - frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget, + frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget, al, ac); f->output_data.x->edit_widget = frame_widget; diff --git a/test/Makefile.in b/test/Makefile.in index 9c1f2d2658f..414eca90564 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -97,11 +97,17 @@ TEST_LOCALE = C # this by default since it gives nicer stacktraces. TEST_LOAD_EL ?= yes +ifeq (@HAVE_MODULES@, yes) +MODULES_EMACSOPT := --module-assertions +else +MODULES_EMACSOPT := +endif + # The actual Emacs command run in the targets below. # Prevent any setting of EMACSLOADPATH in user environment causing problems. emacs = EMACSLOADPATH= LC_ALL=$(TEST_LOCALE) \ EMACS_TEST_DIRECTORY=$(abspath $(srcdir)) \ - $(GDB) "$(EMACS)" $(EMACSOPT) + $(GDB) "$(EMACS)" $(MODULES_EMACSOPT) $(EMACSOPT) test_module_dir := $(srcdir)/data/emacs-module @@ -138,10 +144,9 @@ else testloadfile = $* endif -## Ignore any test errors so we can continue to test other files. %.log: %.elc $(AM_V_at)${MKDIR_P} $(dir $@) - -$(AM_V_GEN)HOME=/nonexistent $(emacs) -l ert -l $(testloadfile) \ + $(AM_V_GEN)HOME=/nonexistent $(emacs) -l ert -l $(testloadfile) \ --eval "(ert-run-tests-batch-and-exit ${SELECTOR_ACTUAL})" ${WRITE_LOG} ifeq (@HAVE_MODULES@, yes) @@ -234,8 +239,11 @@ check-maybe: check-no-automated-subdir ## Run the tests. .PHONY: check-doit -check-doit: ${LOGFILES} - @$(emacs) -l ert -f ert-summarize-tests-batch-and-exit $^ +## We can't put LOGFILES as prerequisites, because that would stop the +## summarizing step from running when there is an error. +check-doit: + -@${MAKE} -k ${LOGFILES} + @$(emacs) -l ert -f ert-summarize-tests-batch-and-exit ${LOGFILES} .PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean diff --git a/test/lisp/international/mule-tests.el b/test/lisp/international/mule-tests.el new file mode 100644 index 00000000000..d7453332437 --- /dev/null +++ b/test/lisp/international/mule-tests.el @@ -0,0 +1,39 @@ +;;; mule-tests.el --- unit tests for mule.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Free Software Foundation, Inc. + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Unit tests for lisp/international/mule.el. + +;;; Code: + +(ert-deftest find-auto-coding--bug27391 () + "Check that Bug#27391 is fixed." + (with-temp-buffer + (insert "\n[comment]: # ( Local Variables: )\n" + "[comment]: # ( coding: utf-8 )\n" + "[comment]: # ( End: )\n") + (goto-char (point-min)) + (should (equal (let ((auto-coding-alist ()) + (auto-coding-regexp-alist ()) + (auto-coding-functions ())) + (find-auto-coding "" (buffer-size))) + '(utf-8 . :coding))))) + +;;; mule-tests.el ends here diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 28147c48d6c..a90e3fff355 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -75,6 +75,7 @@ (setq password-cache-expiry nil tramp-verbose 0 + tramp-cache-read-persistent-data t ;; For auth-sources. tramp-copy-size-limit nil tramp-message-show-message nil tramp-persistency-file-name nil) @@ -3761,7 +3762,29 @@ process sentinels. They shall not disturb each other." (mapconcat 'shell-quote-argument load-path " -L ") (shell-quote-argument code))))))) -(ert-deftest tramp-test38-unload () +(ert-deftest tramp-test38-remote-load-path () + "Check that Tramp autoloads its packages with remote `load-path'." + ;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el. + ;; It shall still work, when a remote file name is in the + ;; `load-path'. + (let ((code + "(let ((force-load-messages t)\ + (load-path (cons \"/foo:bar:\" load-path)))\ + (tramp-cleanup-all-connections))")) + (should + (string-match + (format + "Loading %s" + (expand-file-name + "tramp-cmds" (file-name-directory (locate-library "tramp")))) + (shell-command-to-string + (format + "%s -batch -Q -L %s -l tramp-sh --eval %s" + (expand-file-name invocation-name invocation-directory) + (mapconcat 'shell-quote-argument load-path " -L ") + (shell-quote-argument code))))))) + +(ert-deftest tramp-test39-unload () "Check that Tramp and its subpackages unload completely. Since it unloads Tramp, it shall be the last test to run." ;; Mark as failed until all symbols are unbound. diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el index b4666ae72d7..68946a01c06 100644 --- a/test/lisp/textmodes/css-mode-tests.el +++ b/test/lisp/textmodes/css-mode-tests.el @@ -159,7 +159,12 @@ (insert "body { f") (let ((completions (css-mode-tests--completions))) (should (member "filter" completions)) - (should-not (member "position" completions))))) + (should-not (member "position" completions)))) + ;; Bug#27392 + (with-temp-buffer + (css-mode) + (insert "html { grid") + (should (> (length (css-mode-tests--completions)) 0)))) (ert-deftest css-test-foreign-completions () (let ((other-buffer-1 (generate-new-buffer "1")) diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el index d4449eacbf9..128534264e5 100644 --- a/test/lisp/thingatpt-tests.el +++ b/test/lisp/thingatpt-tests.el @@ -120,4 +120,13 @@ position to retrieve THING.") (should (equal (list-at-point) (cdr str-res))))))) +(ert-deftest thing-at-point-url-in-comment () + (with-temp-buffer + (c-mode) + (insert "/* (http://foo/bar)\n(http://foo/bar(baz)) */\n") + (goto-char 6) + (should (equal (thing-at-point 'url) "http://foo/bar")) + (goto-char 23) + (should (equal (thing-at-point 'url) "http://foo/bar(baz)")))) + ;;; thingatpt.el ends here diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 3073e371933..a3ea8ab60b5 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -208,4 +208,35 @@ '(error "Invalid format operation %$"))) (should (equal (format "%1$c %1$s" ?±) "± 177"))) +(ert-deftest replace-buffer-contents-1 () + (with-temp-buffer + (insert #("source" 2 4 (prop 7))) + (let ((source (current-buffer))) + (with-temp-buffer + (insert "before dest after") + (let ((marker (set-marker (make-marker) 14))) + (save-restriction + (narrow-to-region 8 12) + (replace-buffer-contents source)) + (should (equal (marker-buffer marker) (current-buffer))) + (should (equal (marker-position marker) 16))) + (should (equal-including-properties + (buffer-string) + #("before source after" 9 11 (prop 7)))) + (should (equal (point) 9)))) + (should (equal-including-properties + (buffer-string) + #("source" 2 4 (prop 7)))))) + +(ert-deftest replace-buffer-contents-2 () + (with-temp-buffer + (insert "foo bar baz qux") + (let ((source (current-buffer))) + (with-temp-buffer + (insert "foo BAR baz qux") + (replace-buffer-contents source) + (should (equal-including-properties + (buffer-string) + "foo bar baz qux")))))) + ;;; editfns-tests.el ends here diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el index fbd3bf84a42..0cf7fc9f59c 100644 --- a/test/src/undo-tests.el +++ b/test/src/undo-tests.el @@ -444,5 +444,27 @@ Demonstrates bug 16818." (ert-run-tests-interactively "^undo-") (ert-run-tests-batch "^undo-"))) +(ert-deftest undo-test-skip-invalidated-markers () + "Test marker adjustment when the marker points nowhere. +Demonstrates bug 25599." + (with-temp-buffer + (buffer-enable-undo) + (insert ";; aaaaaaaaa +;; bbbbbbbb") + (let ((overlay-modified + (lambda (ov after-p _beg _end &optional length) + (unless after-p + (when (overlay-buffer ov) + (delete-overlay ov)))))) + (save-excursion + (goto-char (point-min)) + (let ((ov (make-overlay (line-beginning-position 2) + (line-end-position 2)))) + (overlay-put ov 'insert-in-front-hooks + (list overlay-modified))))) + (kill-region (point-min) (line-beginning-position 2)) + (undo-boundary) + (undo))) + (provide 'undo-tests) ;;; undo-tests.el ends here |