emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android a61c5fb9a21: Merge remote-tracking branch 'origin/master


From: Po Lu
Subject: feature/android a61c5fb9a21: Merge remote-tracking branch 'origin/master' into feature/android
Date: Wed, 21 Jun 2023 21:02:49 -0400 (EDT)

branch: feature/android
commit a61c5fb9a212ca0bcfcca5d1652bd9d7841d95bd
Merge: bdaeecd1759 72f1c12e58e
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/android
---
 configure.ac                           |   2 +-
 doc/lispref/searching.texi             |   6 +-
 doc/misc/cc-mode.texi                  |  10 +
 doc/misc/tramp.texi                    |  18 +-
 etc/NEWS                               |  13 +-
 lisp/emacs-lisp/byte-opt.el            |   8 +-
 lisp/emacs-lisp/subr-x.el              |   5 -
 lisp/kmacro.el                         |  13 +-
 lisp/net/tramp.el                      |  11 +-
 lisp/progmodes/cc-align.el             |  10 +
 lisp/progmodes/cc-defs.el              |  26 +-
 lisp/progmodes/cc-engine.el            | 378 ++++++++++---
 lisp/progmodes/cc-fonts.el             |   4 +-
 lisp/progmodes/cc-langs.el             |   4 +
 lisp/progmodes/cc-mode.el              |   7 +-
 lisp/progmodes/cc-vars.el              |   3 +-
 lisp/progmodes/elisp-mode.el           |   3 +
 lisp/startup.el                        |  28 +-
 src/nsterm.m                           |   2 +-
 src/pgtkfns.c                          |   7 +-
 src/regex-emacs.c                      |  15 +-
 test/lisp/emacs-lisp/bytecomp-tests.el |   4 +
 test/lisp/emacs-lisp/edebug-tests.el   |   1 +
 test/lisp/net/tramp-tests.el           | 990 +++++++++++++++++++--------------
 test/src/regex-emacs-tests.el          |  66 +++
 25 files changed, 1073 insertions(+), 561 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7454e201c3f..60d02963da8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1725,7 +1725,7 @@ AS_IF([test $gl_gcc_warnings = no],
 
   nw="$nw -Wcast-align=strict"      # Emacs is tricky with pointers.
   nw="$nw -Wduplicated-branches"    # Too many false alarms
-  nw="$nw -Wformat-overflow=2"      # False alarms due to GCC bug 80776
+  nw="$nw -Wformat-overflow=2"      # False alarms due to GCC bug 110333
   nw="$nw -Wsystem-headers"         # Don't let system headers trigger warnings
   nw="$nw -Woverlength-strings"     # Not a problem these days
   nw="$nw -Wvla"                    # Emacs uses <vla.h>.
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 28230cea643..7c9893054d9 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -546,15 +546,11 @@ example, the regular expression that matches the @samp{\} 
character is
 
 For historical compatibility, a repetition operator is treated as ordinary
 if it appears at the start of a regular expression
-or after @samp{^}, @samp{\(}, @samp{\(?:} or @samp{\|}.
+or after @samp{^}, @samp{\`}, @samp{\(}, @samp{\(?:} or @samp{\|}.
 For example, @samp{*foo} is treated as @samp{\*foo}, and
 @samp{two\|^\@{2\@}} is treated as @samp{two\|^@{2@}}.
 It is poor practice to depend on this behavior; use proper backslash
 escaping anyway, regardless of where the repetition operator appears.
-Also, a repetition operator should not immediately follow a backslash escape
-that matches only empty strings, as Emacs has bugs in this area.
-For example, it is unwise to use @samp{\b*}, which can be omitted
-without changing the documented meaning of the regular expression.
 
 As a @samp{\} is not special inside a bracket expression, it can
 never remove the special meaning of @samp{-}, @samp{^} or @samp{]}.
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 4ac9cc3ca2d..5f905be09d5 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -6252,6 +6252,16 @@ returned if there's no template argument on the first 
line.
 
 @comment ------------------------------------------------------------
 
+@defun c-lineup-template-args-indented-from-margin
+@findex lineup-template-args-indented-from-margin (c-)
+Indent a template argument line `c-basic-offset' from the left-hand
+margin of the line with the containing <.
+
+@workswith @code{template-args-cont}.
+@end defun
+
+@comment ------------------------------------------------------------
+
 @defun c-lineup-ObjC-method-call
 @findex lineup-ObjC-method-call @r{(c-)}
 For Objective-C code, line up selector args as Emacs Lisp mode does
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index a854c15f2b3..eb5c418728e 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3644,10 +3644,20 @@ Each involved method must be an inline method 
(@pxref{Inline methods}).
 @code{tramp-default-proxies-alist} and is available for re-use during
 that Emacs session.  Subsequent @value{tramp} connections to the same
 remote host can then use the shortcut form:
-@samp{@trampfn{ssh,you@@remotehost,/path}}.  Ad-hoc definitions are
-removed from @code{tramp-default-proxies-alist} via the command
-@kbd{M-x tramp-cleanup-all-connections @key{RET}} (@pxref{Cleanup
-remote connections}).
+@samp{@trampfn{ssh,you@@remotehost,/path}}.
+
+@defopt tramp-show-ad-hoc-proxies
+If this user option is non-@code{nil}, ad-hoc definitions are kept in
+remote file names instead of showing the shortcuts.
+
+@lisp
+(customize-set-variable 'tramp-show-ad-hoc-proxies t)
+@end lisp
+@end defopt
+
+Ad-hoc definitions are removed from @code{tramp-default-proxies-alist}
+via the command @kbd{M-x tramp-cleanup-all-connections @key{RET}}
+(@pxref{Cleanup remote connections}).
 
 @defopt tramp-save-ad-hoc-proxies
 For ad-hoc definitions to be saved automatically in
diff --git a/etc/NEWS b/etc/NEWS
index 9d0e63f24d2..08bf7599274 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -492,6 +492,14 @@ symbol, and either that symbol is ':eval' and the second 
element of
 the list evaluates to 'nil' or the symbol's value as a variable is
 'nil' or void.
 
++++
+** Regexp zero-width assertions followed by operators are better defined.
+Previously, regexps such as "xy\\B*" would have ill-defined behaviour.
+Now any operator following a zero-width assertion applies to that
+assertion only (which is useless).  For historical compatibility, an
+operator character following '^' or '\`' becomes literal, but we
+advise against relying on this.
+
 
 * Lisp Changes in Emacs 30.1
 
@@ -707,11 +715,6 @@ Since circular alias chains now cannot occur, 
'function-alias-p',
 'indirect-function' and 'indirect-variable' will never signal an error.
 Their 'noerror' arguments have no effect and are therefore obsolete.
 
----
-** New function 'eval-command-interactive-spec' in the subr-x library.
-This function evaluates a command's interactive form and returns the
-resultant list.
-
 
 * Changes in Emacs 30.1 on Non-Free Operating Systems
 
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index f64674d5a6c..307e3841e9b 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -873,7 +873,13 @@ for speeding up processing.")
   (cons accum args))
 
 (defun byte-optimize-plus (form)
-  (let ((args (remq 0 (byte-opt--arith-reduce #'+ 0 (cdr form)))))
+  (let* ((not-0 (remq 0 (byte-opt--arith-reduce #'+ 0 (cdr form))))
+         (args (if (and (= (length not-0) 1)
+                        (> (length form) 2))
+                   ;; We removed numbers and only one arg remains: add a 0
+                   ;; so that it isn't turned into (* X 1) later on.
+                   (append not-0 '(0))
+                 not-0)))
     (cond
      ;; (+) -> 0
      ((null args) 0)
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 38f85c242c7..9e906930b92 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -504,11 +504,6 @@ Used by `emacs-authors-mode' and `emacs-news-mode'."
                           (progn (forward-line -1) (point))
                         (point-max)))))
 
-(defun eval-command-interactive-spec (command)
-  "Evaluate COMMAND's interactive form and return resultant list.
-If COMMAND has no interactive form, return nil."
-  (advice-eval-interactive-spec (cadr (interactive-form command))))
-
 (provide 'subr-x)
 
 ;;; subr-x.el ends here
diff --git a/lisp/kmacro.el b/lisp/kmacro.el
index 64aa7a27bde..7489076ea2e 100644
--- a/lisp/kmacro.el
+++ b/lisp/kmacro.el
@@ -504,8 +504,9 @@ ARG is the number of times to execute the item.")
 
 
 (defun kmacro-call-ring-2nd (arg)
-  "Execute second keyboard macro in macro ring."
-  (interactive "P")
+  "Execute second keyboard macro in macro ring.
+With numeric argument ARG, execute the macro that many times."
+  (interactive "p")
   (unless (kmacro-ring-empty-p)
     (funcall (car kmacro-ring) arg)))
 
@@ -514,7 +515,7 @@ ARG is the number of times to execute the item.")
   "Execute second keyboard macro in macro ring.
 This is like `kmacro-call-ring-2nd', but allows repeating macro commands
 without repeating the prefix."
-  (interactive "P")
+  (interactive "p")
   (let ((keys (kmacro-get-repeat-prefix)))
     (kmacro-call-ring-2nd arg)
     (if (and kmacro-ring keys)
@@ -650,10 +651,10 @@ The macro is now available for use via 
\\[kmacro-call-macro],
 or it can be given a name with \\[kmacro-name-last-macro] and then invoked
 under that name.
 
-With numeric arg, repeat macro now that many times,
+With numeric ARG, repeat the macro that many times,
 counting the definition just completed as the first repetition.
 An argument of zero means repeat until error."
-  (interactive "P")
+  (interactive "p")
    ;; Isearch may push the kmacro-end-macro key sequence onto the macro.
    ;; Just ignore it when executing the macro.
   (unless executing-kbd-macro
@@ -787,7 +788,7 @@ Zero argument means repeat until there is an error.
 
 To give a macro a name, so you can call it even after defining other
 macros, use \\[kmacro-name-last-macro]."
-  (interactive "P")
+  (interactive "p")
   (if defining-kbd-macro
       (kmacro-end-macro nil))
   (kmacro-call-macro arg no-repeat))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 7849f81aebe..b98dff3b536 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -525,6 +525,11 @@ interpreted as a regular expression which always matches."
   :version "24.3"
   :type 'boolean)
 
+(defcustom tramp-show-ad-hoc-proxies nil
+  "Whether to show ad-hoc proxies in file names."
+  :version "29.2"
+  :type 'boolean)
+
 ;; For some obscure technical reasons, `system-name' on w32 returns
 ;; either lower case or upper case letters.  See
 ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=38079#20>.
@@ -1807,8 +1812,8 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME 
&optional HOP)."
       (when (cadr args)
        (setq localname (and (stringp (cadr args)) (cadr args))))
       (when hop
-       ;; Keep hop in file name for completion.
-       (unless minibuffer-completing-file-name
+       ;; Keep hop in file name for completion or when indicated.
+       (unless (or minibuffer-completing-file-name tramp-show-ad-hoc-proxies)
          (setq hop nil))
        ;; Assure that the hops are in `tramp-default-proxies-alist'.
        ;; In tramp-archive.el, the slot `hop' is used for the archive
@@ -1858,7 +1863,7 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME 
&optional HOP)."
     (replace-regexp-in-string
      (rx (regexp tramp-postfix-host-regexp) eos)
      tramp-postfix-hop-format
-     (tramp-make-tramp-file-name vec 'noloc)))))
+     (tramp-make-tramp-file-name (tramp-file-name-unify vec))))))
 
 (defun tramp-completion-make-tramp-file-name (method user host localname)
   "Construct a Tramp file name from METHOD, USER, HOST and LOCALNAME.
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 34ef0b9c1af..91a7665edbb 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -940,6 +940,16 @@ Works with: template-args-cont."
             (zerop (c-forward-token-2 1 nil (c-point 'eol))))
        (vector (current-column)))))
 
+(defun c-lineup-template-args-indented-from-margin (_langelem)
+  "Indent a template argument line `c-basic-offset' from the margin
+of the line with the containing <.
+
+Works with: template-args-cont."
+  (save-excursion
+    (goto-char (c-langelem-2nd-pos c-syntactic-element))
+    (back-to-indentation)
+    (vector (+ (current-column) c-basic-offset))))
+
 (defun c-lineup-ObjC-method-call (langelem)
   "Line up selector args as Emacs Lisp mode does with function args:
 Go to the position right after the message receiver, and if you are at
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 1d98b215525..f9b63cbeed6 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1284,6 +1284,29 @@ MODE is either a mode symbol or a list of mode symbols."
        pos)
       (most-positive-fixnum))))
 
+(defmacro c-put-char-properties (from to property value)
+  ;; FIXME!!!  Doc comment here!
+  (declare (debug t))
+  (setq property (eval property))
+  `(let ((-to- ,to) (-from- ,from))
+     ,(if c-use-extents
+         ;; XEmacs
+         `(progn
+            (map-extents (lambda (ext ignored)
+                           (delete-extent ext))
+                         nil -from- -to- nil nil ',property)
+            (set-extent-properties (make-extent -from- -to-)
+                                   (cons property
+                                         (cons ,value
+                                               '(start-open t
+                                                            end-open t)))))
+       ;; Emacs
+       `(progn
+          ,@(when (and (fboundp 'syntax-ppss)
+                       (eq `,property 'syntax-table))
+              `((setq c-syntax-table-hwm (min c-syntax-table-hwm -from-))))
+          (put-text-property -from- -to- ',property ,value)))))
+
 (defmacro c-clear-char-properties (from to property)
   ;; Remove all the occurrences of the given property in the given
   ;; region that has been put with `c-put-char-property'.  PROPERTY is
@@ -1379,7 +1402,8 @@ isn't found, return nil; point is then left undefined."
        value)
       (t (let ((place (c-next-single-property-change
                       (point) ,property nil -limit-)))
-          (when place
+          (when (and place
+                     (< place -limit-))
             (goto-char (1+ place))
             (c-get-char-property place ,property)))))))
 
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 66cfd3dee9e..0eadeafc836 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -2672,6 +2672,7 @@ comment at the start of cc-engine.el for more info."
          (progn (goto-char beg)
                 (c-skip-ws-forward end+1)
                 (eq (point) end+1))))))
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; We maintain a sopisticated cache of positions which are in a literal,
@@ -7039,8 +7040,8 @@ comment at the start of cc-engine.el for more info."
   ;; POS (default point) is at a < character.  If it is both marked
   ;; with open/close paren syntax-table property, and has a matching >
   ;; (also marked) which is after LIM, remove the property both from
-  ;; the current > and its partner.  Return t when this happens, nil
-  ;; when it doesn't.
+  ;; the current > and its partner.  Return the position after the >
+  ;; when this happens, nil when it doesn't.
   (save-excursion
     (if pos
        (goto-char pos)
@@ -7054,15 +7055,15 @@ comment at the start of cc-engine.el for more info."
                        c->-as-paren-syntax)) ; should always be true.
        (c-unmark-<->-as-paren (1- (point)))
        (c-unmark-<->-as-paren pos)
-       (c-truncate-lit-pos-cache pos))
-      t)))
+       (c-truncate-lit-pos-cache pos)
+      (point)))))
 
 (defun c-clear->-pair-props-if-match-before (lim &optional pos)
   ;; POS (default point) is at a > character.  If it is both marked
   ;; with open/close paren syntax-table property, and has a matching <
   ;; (also marked) which is before LIM, remove the property both from
-  ;; the current < and its partner.  Return t when this happens, nil
-  ;; when it doesn't.
+  ;; the current < and its partner.  Return the position of the < when
+  ;; this happens, nil when it doesn't.
   (save-excursion
     (if pos
        (goto-char pos)
@@ -7076,8 +7077,8 @@ comment at the start of cc-engine.el for more info."
                        c-<-as-paren-syntax)) ; should always be true.
        (c-unmark-<->-as-paren (point))
        (c-truncate-lit-pos-cache (point))
-       (c-unmark-<->-as-paren pos))
-      t)))
+       (c-unmark-<->-as-paren pos)
+       (point)))))
 
 ;; Set by c-common-init in cc-mode.el.
 (defvar c-new-BEG)
@@ -7085,7 +7086,48 @@ comment at the start of cc-engine.el for more info."
 ;; Set by c-before-change-check-raw-strings.
 (defvar c-old-END-literality)
 
-(defun c-before-change-check-<>-operators (beg end)
+(defun c-end-of-literal (pt-s pt-search)
+  ;; If a literal is open in the `c-semi-pp-to-literal' state PT-S, return the
+  ;; end point of this literal (or point-max) assuming PT-S is valid at
+  ;; PT-SEARCH.  Otherwise, return nil.
+  (when (car (cddr pt-s))              ; Literal start
+    (let ((lit-type (cadr pt-s))
+         (lit-beg (car (cddr pt-s)))
+         ml-end-re
+         )
+      (save-excursion
+       (cond
+        ((eq lit-type 'string)
+         (if (and c-ml-string-opener-re
+                  (c-ml-string-opener-at-or-around-point lit-beg))
+             (progn
+               (setq ml-end-re
+                     (funcall c-make-ml-string-closer-re-function
+                              (match-string 1)))
+               (goto-char (max (- pt-search (1- (length ml-end-re)))
+                               (point-min)))
+               (re-search-forward ml-end-re nil 'stay))
+           ;; For an ordinary string, we can't use `parse-partial-sexp' since
+           ;; not all syntax-table properties have yet been set.
+           (goto-char pt-search)
+           (re-search-forward
+              "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\"\n\\]\\)*[\"\n]" nil 'stay)))
+        ((memq lit-type '(c c++))
+         ;; To work around a bug in parse-partial-sexp, where effect is given
+         ;; to the syntax of a backslash, even the the scan starts with point
+         ;; just after it.
+         (if (and (eq (char-before pt-search) ?\\)
+                  (eq (char-after pt-search) ?\n))
+             (progn
+               (c-put-char-property (1- pt-search) 'syntax-table '(1))
+               (parse-partial-sexp pt-search (point-max) nil nil (car pt-s)
+                                   'syntax-table)
+               (c-clear-char-property (1- pt-search) 'syntax-table))
+         (parse-partial-sexp pt-search (point-max) nil nil (car pt-s)
+                             'syntax-table))))
+       (point)))))
+
+(defun c-unmark-<>-around-region (beg end &optional old-len)
   ;; Unmark certain pairs of "< .... >" which are currently marked as
   ;; template/generic delimiters.  (This marking is via syntax-table text
   ;; properties), and expand the (c-new-BEG c-new-END) region to include all
@@ -7099,66 +7141,201 @@ comment at the start of cc-engine.el for more info."
   ;; enclose a brace or semicolon, so we use these as bounds on the
   ;; region we must work on.
   ;;
+  ;; The buffer is widened, and point is undefined, both at entry and exit.
+  ;;
+  ;; FIXME!!!  This routine ignores the possibility of macros entirely.
+  ;; 2010-01-29.
+
+  (when (> end beg)
+    ;; Extend the region (BEG END) to deal with any complicating literals.
+    (let* ((lit-search-beg (if (memq (char-before beg) '(?/ ?*))
+                              (1- beg) beg))
+          (lit-search-end (if (memq (char-after end) '(?/ ?*))
+                              (1+ end) end))
+          ;; Note we can't use c-full-pp-to-literal here, since we haven't
+          ;; yet applied syntax-table properties to ends of lines, etc.
+          (lit-search-beg-s (c-semi-pp-to-literal lit-search-beg))
+          (beg-literal-beg (car (cddr lit-search-beg-s)))
+          (lit-search-end-s (c-semi-pp-to-literal lit-search-end))
+          (end-literal-beg (car (cddr lit-search-end-s)))
+          (beg-literal-end (c-end-of-literal lit-search-beg-s beg))
+          (end-literal-end (c-end-of-literal lit-search-end-s end))
+          new-beg new-end search-region)
+
+      ;; Determine any new end of literal resulting from the 
insertion/deletion.
+      (setq search-region
+           (if (and (eq beg-literal-beg end-literal-beg)
+                    (eq beg-literal-end end-literal-end))
+               (if beg-literal-beg
+                   nil
+                 (cons beg
+                       (max end
+                            (or beg-literal-end (point-min))
+                            (or end-literal-end (point-min)))))
+             (cons (or beg-literal-beg beg)
+                   (max end
+                        (or beg-literal-end (point-min))
+                        (or end-literal-end (point-min))))))
+
+      (when search-region
+       ;; If we've just inserted text, mask its syntaxes temporarily so that
+       ;; they won't interfere with the undoing of the properties on the <s
+       ;; and >s.
+       (c-save-buffer-state (syn-tab-settings syn-tab-value
+                                              swap-open-string-ends)
+         (unwind-protect
+             (progn
+               (when old-len
+                 ;; Special case: If a \ has just been inserted into a
+                 ;; string, escaping or unescaping a LF, temporarily swap
+                 ;; the LF's syntax-table text property with that of the
+                 ;; former end of the open string.
+                 (goto-char end)
+                 (when (and (eq (cadr lit-search-beg-s) 'string)
+                            (not (eq beg-literal-end end-literal-end))
+                            (skip-chars-forward "\\\\")
+                            (eq (char-after) ?\n)
+                            (not (zerop (skip-chars-backward "\\\\"))))
+                   (setq swap-open-string-ends t)
+                   (if (c-get-char-property (1- beg-literal-end)
+                                            'syntax-table)
+                       (progn
+                         (c-clear-char-property (1- beg-literal-end)
+                                                'syntax-table)
+                         (c-put-char-property (1- end-literal-end)
+                                              'syntax-table '(15)))
+                     (c-put-char-property (1- beg-literal-end)
+                                          'syntax-table '(15))
+                     (c-clear-char-property (1- end-literal-end)
+                                            'syntax-table)))
+
+                 ;; Save current settings of the 'syntax-table property in
+                 ;; (BEG END), then splat these with the punctuation value.
+                 (goto-char beg)
+                 (while (progn (skip-syntax-forward "" end)
+                               (< (point) end))
+                   (setq syn-tab-value
+                         (c-get-char-property (point) 'syntax-table))
+                   (when (not (c-get-char-property (point) 'category))
+                     (push (cons (point) syn-tab-value) syn-tab-settings))
+                   (forward-char))
+
+                 (c-put-char-properties beg end 'syntax-table '(1))
+                 ;; If an open string's opener has just been neutralized,
+                 ;; do the same to the terminating LF.
+                 (when (and end-literal-end
+                            (eq (char-before end-literal-end) ?\n)
+                            (equal (c-get-char-property
+                                    (1- end-literal-end) 'syntax-table)
+                                   '(15)))
+                   (push (cons (1- end-literal-end) '(15)) syn-tab-settings)
+                   (c-put-char-property (1- end-literal-end) 'syntax-table
+                                        '(1))))
+
+               (let
+                   ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
+                    beg-limit end-limit <>-pos)
+                 ;; Locate the earliest < after the barrier before the
+                 ;; changed region, which isn't already marked as a paren.
+                 (goto-char (or beg-lit-start beg))
+                 (setq beg-limit (c-determine-limit 5000))
+
+                 ;; Remove the syntax-table/category properties from each 
pertinent <...>
+                 ;; pair.  Firstly, the ones with the < before beg and > after 
beg....
+                 (goto-char (cdr search-region))
+                 (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
+                               (eq (char-before) ?<))
+                   (c-backward-token-2)
+                   (when (eq (char-after) ?<)
+                     (when (setq <>-pos (c-clear-<-pair-props-if-match-after
+                                         (car search-region)))
+                       (setq new-end <>-pos))
+                     (setq new-beg (point))))
+
+                 ;; ...Then the ones with < before end and > after end.
+                 (goto-char (car search-region))
+                 (setq end-limit (c-determine-+ve-limit 5000))
+                 (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 
'end)
+                             (eq (char-before) ?>))
+                   (when (eq (char-before) ?>)
+                     (if (and (looking-at c->-op-cont-regexp)
+                              (not (eq (char-after) ?>)))
+                         (goto-char (match-end 0))
+                       (when
+                           (and (setq <>-pos
+                                      (c-clear->-pair-props-if-match-before
+                                       (cdr search-region)
+                                       (1- (point))))
+                                (or (not new-beg)
+                                    (< <>-pos new-beg)))
+                         (setq new-beg <>-pos))
+                       (when (or (not new-end) (> (point) new-end))
+                         (setq new-end (point))))))))
+
+           (when old-len
+             (c-clear-char-properties beg end 'syntax-table)
+             (dolist (elt syn-tab-settings)
+               (if (cdr elt)
+                   (c-put-char-property (car elt) 'syntax-table (cdr elt)))))
+           ;; Swap the '(15) syntax-table property on open string LFs back
+           ;; again.
+           (when swap-open-string-ends
+             (if (c-get-char-property (1- beg-literal-end)
+                                      'syntax-table)
+                 (progn
+                   (c-clear-char-property (1- beg-literal-end)
+                                          'syntax-table)
+                   (c-put-char-property (1- end-literal-end)
+                                        'syntax-table '(15)))
+               (c-put-char-property (1- beg-literal-end)
+                                    'syntax-table '(15))
+               (c-clear-char-property (1- end-literal-end)
+                                      'syntax-table)))))
+         ;; Extend the fontification region, if needed.
+         (and new-beg
+              (< new-beg c-new-BEG)
+              (setq c-new-BEG new-beg))
+         (and new-end
+              (> new-end c-new-END)
+              (setq c-new-END new-end))))))
+
+(defun c-before-change-check-<>-operators (beg end)
+  ;; When we're deleting text, unmark certain pairs of "< .... >" which are
+  ;; currently marked as template/generic delimiters.  (This marking is via
+  ;; syntax-table text properties), and expand the (c-new-BEG c-new-END)
+  ;; region to include all unmarked < and > operators within the certain
+  ;; bounds (see below).
+  ;;
+  ;; These pairs are those which are in the current "statement" (i.e.,
+  ;; the region between the {, }, or ; before BEG and the one after
+  ;; END), and which enclose any part of the interval (BEG END).
+  ;; Also unmark a < or > which is about to become part of a multi-character
+  ;; operator, e.g. <=.
+  ;;
+  ;; Note that in C++ (?and Java), template/generic parens cannot
+  ;; enclose a brace or semicolon, so we use these as bounds on the
+  ;; region we must work on.
+  ;;
   ;; This function is called from before-change-functions (via
   ;; c-get-state-before-change-functions).  Thus the buffer is widened,
   ;; and point is undefined, both at entry and exit.
   ;;
   ;; FIXME!!!  This routine ignores the possibility of macros entirely.
   ;; 2010-01-29.
-  (when (and (or (> end beg)
-                (and (> c-<-pseudo-digraph-cont-len 0)
-                     (goto-char beg)
-                     (progn
-                       (skip-chars-backward
-                        "^<" (max (- (point) c-<-pseudo-digraph-cont-len)
-                                  (point-min)))
-                       (eq (char-before) ?<))
-                     (looking-at c-<-pseudo-digraph-cont-regexp)))
-            (or
-             (progn
-               (goto-char beg)
-               (search-backward "<" (max (- (point) 1024) (point-min)) t))
-             (progn
-               (goto-char end)
-               (search-forward ">" (min (+ (point) 1024) (point-max)) t))))
-    (save-excursion
-      (c-save-buffer-state
-         ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
-          (end-lit-limits (progn (goto-char end) (c-literal-limits)))
-          new-beg new-end beg-limit end-limit)
-       ;; Locate the earliest < after the barrier before the changed region,
-       ;; which isn't already marked as a paren.
-       (goto-char (or beg-lit-start beg))
-       (setq beg-limit (c-determine-limit 512))
-
-       ;; Remove the syntax-table/category properties from each pertinent <...>
-       ;; pair.  Firstly, the ones with the < before beg and > after beg....
-       (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
-                     (eq (char-before) ?<))
-         (c-backward-token-2)
-         (when (eq (char-after) ?<)
-           (c-clear-<-pair-props-if-match-after beg)
-           (setq new-beg (point))))
-       (c-forward-syntactic-ws)
-
-       ;; ...Then the ones with < before end and > after end.
-       (goto-char (if end-lit-limits (cdr end-lit-limits) end))
-       (setq end-limit (c-determine-+ve-limit 512))
-       (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 'end)
-                   (eq (char-before) ?>))
-         (c-end-of-current-token)
-         (when (eq (char-before) ?>)
-           (c-clear->-pair-props-if-match-before end (1- (point)))
-           (setq new-end (point))))
-       (c-backward-syntactic-ws)
-
-       ;; Extend the fontification region, if needed.
-       (and new-beg
-            (< new-beg c-new-BEG)
-            (setq c-new-BEG new-beg))
-       (and new-end
-            (> new-end c-new-END)
-            (setq c-new-END new-end))))))
+  (when (> end beg)
+  ;; Cope with removing (beg end) coalescing a < or > with, say, an = sign.
+    (goto-char beg)
+    (let ((ch (char-before)))
+      (if (and (memq ch '(?< ?>))
+              (c-get-char-property (1- (point)) 'syntax-table)
+              (progn
+                (goto-char end)
+                (looking-at (if (eq ch ?<)
+                                c-<-op-cont-regexp
+                              c->-op-cont-regexp)))
+              (or (eq ch ?<)
+                  (not (eq (char-after) ?>))))
+         (c-unmark-<>-around-region (1- beg) beg)))))
 
 (defun c-after-change-check-<>-operators (beg end)
   ;; This is called from `after-change-functions' when
@@ -7198,29 +7375,38 @@ comment at the start of cc-engine.el for more info."
            (c-clear-<>-pair-props)
            (forward-char)))))))
 
+(defun c-<>-get-restricted ()
+  ;; With point at the < at the start of the purported <>-arglist, determine
+  ;; the value of `c-restricted-<>-arglists' to use for the call of
+  ;; `c-forward-<>-arglist' starting there.
+  (save-excursion
+    (c-backward-token-2)
+    (and (not (looking-at c-opt-<>-sexp-key))
+        (progn (c-backward-syntactic-ws)                 ; to ( or ,
+               (and (memq (char-before) '(?\( ?,))       ; what about <?
+                    (not (eq (c-get-char-property (point) 'c-type)
+                             'c-decl-arg-start)))))))
+
 (defun c-restore-<>-properties (_beg _end _old-len)
   ;; This function is called as an after-change function.  It restores the
   ;; category/syntax-table properties on template/generic <..> pairs between
   ;; c-new-BEG and c-new-END.  It may do hidden buffer changes.
-  (c-save-buffer-state ((c-parse-and-markup-<>-arglists t)
-                       c-restricted-<>-arglists lit-limits)
+  (c-save-buffer-state ((c-parse-and-markup-<>-arglists t) lit-limits)
     (goto-char c-new-BEG)
     (if (setq lit-limits (c-literal-limits))
        (goto-char (cdr lit-limits)))
     (while (and (< (point) c-new-END)
-               (c-syntactic-re-search-forward "<" c-new-END 'bound))
-      (backward-char)
-      (save-excursion
-       (c-backward-token-2)
-       (setq c-restricted-<>-arglists
-            (and (not (looking-at c-opt-<>-sexp-key))
-                 (progn (c-backward-syntactic-ws) ; to ( or ,
-                        (and (memq (char-before) '(?\( ?,)) ; what about <?
-                             (not (eq (c-get-char-property (point) 'c-type)
-                                      'c-decl-arg-start)))))))
-      (or (c-forward-<>-arglist nil)
-         (c-forward-over-token-and-ws)
-         (goto-char c-new-END)))))
+               (c-syntactic-re-search-forward "[<>]" c-new-END 'bound))
+      (if (eq (char-before) ?<)
+         (progn
+           (backward-char)
+           (let ((c-restricted-<>-arglists (c-<>-get-restricted)))
+             (or (c-forward-<>-arglist nil)
+                 (c-forward-over-token-and-ws)
+                 (goto-char c-new-END))))
+       (save-excursion
+         (when (c-backward-<>-arglist nil nil #'c-<>-get-restricted)
+           (setq c-new-BEG (min c-new-BEG (point)))))))))
 
 
 ;; Handling of CC Mode multi-line strings.
@@ -7372,13 +7558,13 @@ multi-line strings (but not C++, for example)."
 
 (defun c-ml-string-opener-intersects-region (&optional start finish)
   ;; If any part of the region [START FINISH] is inside an ml-string opener,
-  ;; return a dotted list of the start, end and double-quote position of that
-  ;; opener.  That list will not include any "context characters" before or
-  ;; after the opener.  If an opener is found, the match-data will indicate
-  ;; it, with (match-string 1) being the entire delimiter, and (match-string
-  ;; 2) the "main" double-quote.  Otherwise, the match-data is undefined.
-  ;; Both START and FINISH default to point.  FINISH may not be at an earlier
-  ;; buffer position than START.
+  ;; return a dotted list of the start, end and double-quote position of the
+  ;; first such opener.  That list wlll not include any "context characters"
+  ;; before or after the opener.  If an opener is found, the match-data will
+  ;; indicate it, with (match-string 1) being the entire delimiter, and
+  ;; (match-string 2) the "main" double-quote.  Otherwise, the match-data is
+  ;; undefined.  Both START and FINISH default to point.  FINISH may not be at
+  ;; an earlier buffer position than START.
   (let ((here (point)) found)
     (or finish (setq finish (point)))
     (or start (setq start (point)))
@@ -7402,7 +7588,10 @@ multi-line strings (but not C++, for example)."
   ;; If POSITION (default point) is at or inside an ml string opener, return a
   ;; dotted list of the start and end of that opener, and the position of the
   ;; double-quote in it.  That list will not include any "context characters"
-  ;; before or after the opener.
+  ;; before or after the opener.  If an opener is found, the match-data will
+  ;; indicate it, with (match-string 1) being the entire delimiter, and
+  ;; (match-string 2) the "main" double-quote.  Otherwise, the match-data is
+  ;; undefined.
   (let ((here (point))
        found)
     (or position (setq position (point)))
@@ -7414,7 +7603,7 @@ multi-line strings (but not C++, for example)."
                c-ml-string-opener-re
                (min (+ position c-ml-string-max-opener-len) (point-max))
                'bound))
-        (<= (match-end 1) position)))
+        (< (match-end 1) position)))
     (prog1
        (and found
             (<= (match-beginning 1) position)
@@ -8821,7 +9010,7 @@ multi-line strings (but not C++, for example)."
       (if res
          (or c-record-found-types t)))))
 
-(defun c-backward-<>-arglist (all-types &optional limit)
+(defun c-backward-<>-arglist (all-types &optional limit restricted-function)
   ;; The point is assumed to be directly after a ">".  Try to treat it
   ;; as the close paren of an angle bracket arglist and move back to
   ;; the corresponding "<".  If successful, the point is left at
@@ -8830,7 +9019,12 @@ multi-line strings (but not C++, for example)."
   ;; `c-forward-<>-arglist'.
   ;;
   ;; If the optional LIMIT is given, it bounds the backward search.
-  ;; It's then assumed to be at a syntactically relevant position.
+  ;; It's then assumed to be at a syntactically relevant position.  If
+  ;; RESTRICTED-FUNCTION is non-nil, it should be a function taking no
+  ;; arguments, called with point at a < at the start of a purported
+  ;; <>-arglist, which will return the value of
+  ;; `c-restricted-<>-arglists' to be used in the `c-forward-<>-arglist'
+  ;; call starting at that <.
   ;;
   ;; This is a wrapper around `c-forward-<>-arglist'.  See that
   ;; function for more details.
@@ -8866,7 +9060,11 @@ multi-line strings (but not C++, for example)."
                   t
 
                 (backward-char)
-                (let ((beg-pos (point)))
+                (let ((beg-pos (point))
+                      (c-restricted-<>-arglists
+                       (if restricted-function
+                           (funcall restricted-function)
+                         c-restricted-<>-arglists)))
                   (if (c-forward-<>-arglist all-types)
                       (cond ((= (point) start)
                              ;; Matched the arglist.  Break the while.
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 9118e3253c2..d220af2ab0e 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -2659,7 +2659,9 @@ need for `c-font-lock-extra-types'.")
   ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
   ;; fontification".
   (let (pos)
-    (while (c-syntactic-re-search-forward c-using-key limit 'end)
+    (while 
+       (and (< (point) limit)
+            (c-syntactic-re-search-forward c-using-key limit 'end))
       (while  ; Do one declarator of a comma separated list, each time around.
          (progn
            (c-forward-syntactic-ws)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index ffb8c5c7b16..d56366e1755 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -455,6 +455,7 @@ so that all identifiers are recognized as words.")
   c++ '(c-extend-region-for-CPP
        c-depropertize-CPP
        c-before-change-check-ml-strings
+       c-unmark-<>-around-region
        c-before-change-check-<>-operators
        c-before-after-change-check-c++-modules
        c-truncate-bs-cache
@@ -468,6 +469,7 @@ so that all identifiers are recognized as words.")
             c-parse-quotes-before-change
             c-before-change-fix-comment-escapes)
   java '(c-parse-quotes-before-change
+        c-unmark-<>-around-region
         c-before-change-check-unbalanced-strings
         c-before-change-check-<>-operators)
   pike '(c-before-change-check-ml-strings
@@ -516,6 +518,7 @@ parameters \(point-min) and \(point-max).")
        c-after-change-unmark-ml-strings
        c-parse-quotes-after-change
        c-after-change-mark-abnormal-strings
+       c-unmark-<>-around-region
        c-extend-font-lock-region-for-macros
        c-before-after-change-check-c++-modules
        c-neutralize-syntax-in-CPP
@@ -524,6 +527,7 @@ parameters \(point-min) and \(point-max).")
   java '(c-depropertize-new-text
         c-after-change-escape-NL-in-string
         c-parse-quotes-after-change
+        c-unmark-<>-around-region
         c-after-change-mark-abnormal-strings
         c-restore-<>-properties
         c-change-expand-fl-region)
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 2c5596e65c4..968ccd7ace9 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1371,7 +1371,9 @@ Note that the style variables are always made local to 
the buffer."
                      (and              ;(< (point) end)
                       (not (nth 3 s))
                       (c-get-char-property (1- (point)) 'c-fl-syn-tab))
-                   (c-put-char-property pos 'syntax-table '(1)))
+                   (c-put-char-property pos 'syntax-table '(1))
+                   (c-put-char-properties (1+ pos) (c-point 'eol pos)
+                                          'syntax-table '(1)))
                  (setq pos (point)))
              (setq pos (1+ pos)))))))))
 
@@ -1388,6 +1390,9 @@ Note that the style variables are always made local to 
the buffer."
           (setq pos
                 (c-min-property-position pos c-max-syn-tab-mkr 'c-fl-syn-tab))
           (< pos c-max-syn-tab-mkr))
+       (when (and (equal (c-get-char-property pos 'syntax-table) '(1))
+                  (equal (c-get-char-property pos 'c-fl-syn-tab) '(15)))
+         (c-clear-char-properties (1+ pos) (c-point 'eol pos) 'syntax-table))
        (c-put-char-property pos 'syntax-table
                             (c-get-char-property pos 'c-fl-syn-tab))
        (setq pos (1+ pos))))))
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 72d4b93ee59..286d569aaca 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1219,7 +1219,8 @@ can always override the use of `c-default-style' by 
making calls to
        (incomposition         . +)
        ;; Anchor pos: At the extern/namespace/etc block open brace if
        ;; it's at boi, otherwise boi at the keyword.
-       (template-args-cont    . (c-lineup-template-args +))
+       (template-args-cont    . (c-lineup-template-args
+                                c-lineup-template-args-indented-from-margin))
        ;; Anchor pos: Boi at the decl start.  This might be changed;
        ;; the logical position is clearly the opening '<'.
        (inlambda              . 0)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 759b1ab4baf..955b708aee9 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -254,6 +254,9 @@ Comments in the form will be lost."
       ;; Empty symbol.
       ("##" (0 (unless (nth 8 (syntax-ppss))
                  (string-to-syntax "_"))))
+      ;; Prevent the @ from becoming part of a following symbol.
+      (",@" (0 (unless (nth 8 (syntax-ppss))
+                 (string-to-syntax "'"))))
       ;; Unicode character names.  (The longest name is 88 characters
       ;; long.)
       ("\\?\\\\N{[-A-Za-z0-9 ]\\{,100\\}}"
diff --git a/lisp/startup.el b/lisp/startup.el
index acfa4eb657b..2ba84a471af 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1054,11 +1054,17 @@ init-file, or to a default value if loading is not 
possible."
               ;; `user-init-file'.
               (setq user-init-file t)
              (when init-file-name
-               (load (if (equal (file-name-extension init-file-name)
-                                "el")
-                         (file-name-sans-extension init-file-name)
-                       init-file-name)
-                     'noerror 'nomessage))
+                ;; If they specified --debug-init, enter the debugger
+                ;; on any error whatsoever.
+                (let ((debug-ignored-errors
+                       (if (and init-file-debug (not noninteractive))
+                           nil
+                         debug-ignored-errors)))
+                 (load (if (equal (file-name-extension init-file-name)
+                                  "el")
+                           (file-name-sans-extension init-file-name)
+                         init-file-name)
+                       'noerror 'nomessage)))
 
               (when (and (eq user-init-file t) alternate-filename-function)
                 (let ((alt-file (funcall alternate-filename-function)))
@@ -1066,7 +1072,11 @@ init-file, or to a default value if loading is not 
possible."
                    (setq init-file-name alt-file))
                   (and (equal (file-name-extension alt-file) "el")
                        (setq alt-file (file-name-sans-extension alt-file)))
-                  (load alt-file 'noerror 'nomessage)))
+                  (let ((debug-ignored-errors
+                         (if (and init-file-debug (not noninteractive))
+                             nil
+                           debug-ignored-errors)))
+                    (load alt-file 'noerror 'nomessage))))
 
               ;; If we did not find the user's init file, set
               ;; user-init-file conclusively.  Don't let it be
@@ -1105,7 +1115,11 @@ init-file, or to a default value if loading is not 
possible."
                        (not inhibit-default-init))
               ;; Prevent default.el from changing the value of
               ;; `inhibit-startup-screen'.
-              (let ((inhibit-startup-screen nil))
+              (let ((inhibit-startup-screen nil)
+                    (debug-ignored-errors
+                     (if (and init-file-debug (not noninteractive))
+                         nil
+                       debug-ignored-errors)))
                 (load "default" 'noerror 'nomessage))))
         (error
          (display-warning
diff --git a/src/nsterm.m b/src/nsterm.m
index 8c72bb25df1..78089906752 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1624,7 +1624,7 @@ ns_free_frame_resources (struct frame *f)
     [f->output_data.ns->miniimage release];
 
   [[view window] close];
-  [view release];
+  [view removeFromSuperview];
 
   xfree (f->output_data.ns);
   f->output_data.ns = NULL;
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9cec7243515..c154d37f47f 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -3451,7 +3451,6 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
   tab_bar_height = FRAME_TAB_BAR_HEIGHT (f);
   tab_bar_width = (tab_bar_height
                   ? native_width - 2 * internal_border_width : 0);
-  inner_top += tab_bar_height;
 
   /* Construct list.  */
   if (EQ (attribute, Qouter_edges))
@@ -3464,10 +3463,12 @@ frame_geometry (Lisp_Object frame, Lisp_Object 
attribute)
   else if (EQ (attribute, Qinner_edges))
     return list4 (make_fixnum (native_left + internal_border_width),
                  make_fixnum (native_top
-                              + tool_bar_height
+                              + tab_bar_height
+                              + FRAME_TOOL_BAR_TOP_HEIGHT (f)
                               + internal_border_width),
                  make_fixnum (native_right - internal_border_width),
-                 make_fixnum (native_bottom - internal_border_width));
+                 make_fixnum (native_bottom - internal_border_width
+                              - FRAME_TOOL_BAR_BOTTOM_HEIGHT (f)));
   else
     return
       list (Fcons (Qouter_position,
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index fea34df991b..9e298b81ebb 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -1716,7 +1716,8 @@ regex_compile (re_char *pattern, ptrdiff_t size,
 
   /* Address of start of the most recently finished expression.
      This tells, e.g., postfix * where to find the start of its
-     operand.  Reset at the beginning of groups and alternatives.  */
+     operand.  Reset at the beginning of groups and alternatives,
+     and after ^ and \` for dusty-deck compatibility.  */
   unsigned char *laststart = 0;
 
   /* Address of beginning of regexp, or inside of last group.  */
@@ -1847,12 +1848,16 @@ regex_compile (re_char *pattern, ptrdiff_t size,
        case '^':
          if (! (p == pattern + 1 || at_begline_loc_p (pattern, p)))
            goto normal_char;
+         /* Special case for compatibility: postfix ops after ^ become
+            literals.  */
+         laststart = 0;
          BUF_PUSH (begline);
          break;
 
        case '$':
          if (! (p == pend || at_endline_loc_p (p, pend)))
            goto normal_char;
+         laststart = b;
          BUF_PUSH (endline);
          break;
 
@@ -1892,7 +1897,7 @@ regex_compile (re_char *pattern, ptrdiff_t size,
 
            /* Star, etc. applied to an empty pattern is equivalent
               to an empty pattern.  */
-           if (!laststart || laststart == b)
+           if (laststart == b)
              break;
 
            /* Now we know whether or not zero matches is allowed
@@ -2544,18 +2549,24 @@ regex_compile (re_char *pattern, ptrdiff_t size,
               break;
 
            case 'b':
+             laststart = b;
              BUF_PUSH (wordbound);
              break;
 
            case 'B':
+             laststart = b;
              BUF_PUSH (notwordbound);
              break;
 
            case '`':
+             /* Special case for compatibility: postfix ops after \` become
+                literals, as for ^ (see above).  */
+             laststart = 0;
              BUF_PUSH (begbuf);
              break;
 
            case '\'':
+             laststart = b;
              BUF_PUSH (endbuf);
              break;
 
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index 963ea9abe0c..278496f5259 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -776,6 +776,10 @@ inner loops respectively."
       (nconc x nil nil))
     (let ((x (cons 1 (cons 2 (cons 3 4)))))
       (nconc nil x nil (list 5 6) nil))
+
+    ;; (+ 0 -0.0) etc
+    (let ((x (bytecomp-test-identity -0.0)))
+      (list x (+ x) (+ 0 x) (+ x 0) (+ 1 2 -3 x) (+ 0 x 0)))
     )
   "List of expressions for cross-testing interpreted and compiled code.")
 
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index de2fff5ef19..28a7f38c576 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -116,6 +116,7 @@ back to the top level.")
               (with-current-buffer (find-file edebug-tests-temp-file)
                 (read-only-mode)
                 (setq lexical-binding t)
+                (syntax-ppss)
                 (eval-buffer)
                 ,@body
                 (when edebug-tests-failure-in-post-command
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 0b01c13470a..a2e57e468c1 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -521,6 +521,7 @@ is greater than 10.
        tramp-default-method-alist
        tramp-default-user-alist
        tramp-default-host-alist
+       tramp-default-proxies-alist
        ;; Suppress method name check.
        (non-essential t)
        ;; Suppress check for multihops.
@@ -847,154 +848,203 @@ is greater than 10.
                   "/path/to/file"))
 
          ;; Multihop.
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file")
-           "/method2:user2@host2:"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file" 'method)
-           "method2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file" 'user)
-           "user2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file" 'host)
-           "host2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file"
-            'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/method1:user1@host1|method2:user2@host2:/path/to/file" 'hop)
-           (format "%s:%s@%s|"
-                   "method1" "user1" "host1")))
+         (dolist (tramp-show-ad-hoc-proxies '(nil t))
 
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file"))
-           "/method3:user3@host3:"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file")
-            'method)
-           "method3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file")
-            'user)
-           "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file")
-            'host)
-           "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file")
-            'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@host2"
-             "|method3:user3@host3:/path/to/file")
-            'hop)
-           (format "%s:%s@%s|%s:%s@%s|"
-                   "method1" "user1" "host1" "method2" "user2" "host2")))
-
-         ;; Expand `tramp-default-method-alist'.
-         (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
-         (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
-         (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/-:user1@host1"
-             "|-:user2@host2"
-             "|-:user3@host3:/path/to/file"))
-           "/method3:user3@host3:"))
-
-         ;; Expand `tramp-default-user-alist'.
-         (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
-         (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
-         (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:host1"
-             "|method2:host2"
-             "|method3:host3:/path/to/file"))
-           "/method3:user3@host3:"))
-
-         ;; Expand `tramp-default-host-alist'.
-         (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
-         (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
-         (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@"
-             "|method2:user2@"
-             "|method3:user3@:/path/to/file"))
-           "/method3:user3@host3:"))
-
-         ;; Ad-hoc user name and host name expansion.
-         (setq tramp-default-method-alist nil
-               tramp-default-user-alist nil
-               tramp-default-host-alist nil)
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:user1@host1"
-             "|method2:user2@"
-             "|method3:user3@:/path/to/file"))
-           "/method3:user3@host1:"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/method1:%u@%h"
-             "|method2:user2@host2"
-             "|method3:%u@%h"
-             "|method4:user4%domain4@host4#1234:/path/to/file"))
-           "/method4:user4%domain4@host4#1234:")))
+           ;; Explicit settings in `tramp-default-proxies-alist'
+           ;; shouldn't show hops.
+           (setq tramp-default-proxies-alist
+                 '(("^host2$" "^user2$" "/method1:user1@host1:")))
+           (should
+            (string-equal
+             (file-remote-p "/method2:user2@host2:/path/to/file")
+             "/method2:user2@host2:"))
+           (setq tramp-default-proxies-alist nil)
+
+           ;; Ad-hoc settings.
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file")
+             (if tramp-show-ad-hoc-proxies
+                 "/method1:user1@host1|method2:user2@host2:"
+               "/method2:user2@host2:")))
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file" 'method)
+             "method2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file" 'user)
+             "user2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file" 'host)
+             "host2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file"
+              'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/method1:user1@host1|method2:user2@host2:/path/to/file" 'hop)
+             (format "%s:%s@%s|"
+                     "method1" "user1" "host1")))
+
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user1@host1"
+                  "|method2:user2@host2"
+                  "|method3:user3@host3:")
+               "/method3:user3@host3:")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file")
+              'method)
+             "method3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file")
+              'user)
+             "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file")
+              'host)
+             "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file")
+              'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@host2"
+               "|method3:user3@host3:/path/to/file")
+              'hop)
+             (format "%s:%s@%s|%s:%s@%s|"
+                     "method1" "user1" "host1" "method2" "user2" "host2")))
+
+           ;; Expand `tramp-default-method-alist'.
+           (add-to-list
+            'tramp-default-method-alist '("host1" "user1" "method1"))
+           (add-to-list
+            'tramp-default-method-alist '("host2" "user2" "method2"))
+           (add-to-list
+            'tramp-default-method-alist '("host3" "user3" "method3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/-:user1@host1"
+               "|-:user2@host2"
+               "|-:user3@host3:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user1@host1"
+                  "|method2:user2@host2"
+                  "|method3:user3@host3:")
+               "/method3:user3@host3:")))
+
+           ;; Expand `tramp-default-user-alist'.
+           (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+           (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+           (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:host1"
+               "|method2:host2"
+               "|method3:host3:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user1@host1"
+                  "|method2:user2@host2"
+                  "|method3:user3@host3:")
+               "/method3:user3@host3:")))
+
+           ;; Expand `tramp-default-host-alist'.
+           (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+           (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+           (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@"
+               "|method2:user2@"
+               "|method3:user3@:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user1@host1"
+                  "|method2:user2@host2"
+                  "|method3:user3@host3:")
+               "/method3:user3@host3:")))
+
+           ;; Ad-hoc user name and host name expansion.
+           (setq tramp-default-method-alist nil
+                 tramp-default-user-alist nil
+                 tramp-default-host-alist nil)
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:user1@host1"
+               "|method2:user2@"
+               "|method3:user3@:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user1@host1"
+                  "|method2:user2@host1"
+                  "|method3:user3@host1:")
+               "/method3:user3@host1:")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/method1:%u@%h"
+               "|method2:user2@host2"
+               "|method3:%u@%h"
+               "|method4:user4%domain4@host4#1234:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/method1:user2@host2"
+                  "|method2:user2@host2"
+                  "|method3:user4@host4"
+                  "|method4:user4%domain4@host4#1234:")
+               "/method4:user4%domain4@host4#1234:")))))
 
       ;; Exit.
       (tramp-change-syntax syntax))))
@@ -1007,6 +1057,7 @@ is greater than 10.
        (tramp-default-host "default-host")
        tramp-default-user-alist
        tramp-default-host-alist
+       tramp-default-proxies-alist
        ;; Suppress method name check.
        (non-essential t)
        ;; Suppress check for multihops.
@@ -1178,137 +1229,178 @@ is greater than 10.
                   "/path/to/file"))
 
          ;; Multihop.
-         (should
-          (string-equal
-           (file-remote-p "/user1@host1|user2@host2:/path/to/file")
-           "/user2@host2:"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/user1@host1|user2@host2:/path/to/file" 'method)
-           "default-method"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/user1@host1|user2@host2:/path/to/file" 'user)
-           "user2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/user1@host1|user2@host2:/path/to/file" 'host)
-           "host2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/user1@host1|user2@host2:/path/to/file" 'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/user1@host1|user2@host2:/path/to/file" 'hop)
-           (format "%s@%s|" "user1" "host1")))
+         (dolist (tramp-show-ad-hoc-proxies '(nil t))
 
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file"))
-           "/user3@host3:"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file")
-            'method)
-           "default-method"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file")
-            'user)
-           "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file")
-            'host)
-           "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file")
-            'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@host2"
-             "|user3@host3:/path/to/file")
-            'hop)
-           (format "%s@%s|%s@%s|"
-                   "user1" "host1" "user2" "host2")))
-
-         ;; Expand `tramp-default-user-alist'.
-         (add-to-list 'tramp-default-user-alist '(nil "host1" "user1"))
-         (add-to-list 'tramp-default-user-alist '(nil "host2" "user2"))
-         (add-to-list 'tramp-default-user-alist '(nil "host3" "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/host1"
-             "|host2"
-             "|host3:/path/to/file"))
-           "/user3@host3:"))
-
-         ;; Expand `tramp-default-host-alist'.
-         (add-to-list 'tramp-default-host-alist '(nil "user1" "host1"))
-         (add-to-list 'tramp-default-host-alist '(nil "user2" "host2"))
-         (add-to-list 'tramp-default-host-alist '(nil "user3" "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@"
-             "|user2@"
-             "|user3@:/path/to/file"))
-           "/user3@host3:"))
-
-         ;; Ad-hoc user name and host name expansion.
-         (setq tramp-default-user-alist nil
-               tramp-default-host-alist nil)
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/user1@host1"
-             "|user2@"
-             "|user3@:/path/to/file"))
-           "/user3@host1:"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/%u@%h"
-             "|user2@host2"
-             "|%u@%h"
-             "|user4%domain4@host4#1234:/path/to/file"))
-           "/user4%domain4@host4#1234:")))
+           ;; Explicit settings in `tramp-default-proxies-alist'
+           ;; shouldn't show hops.
+           (setq tramp-default-proxies-alist
+                 '(("^host2$" "^user2$" "/user1@host1:")))
+           (should
+            (string-equal
+             (file-remote-p "/user2@host2:/path/to/file")
+             "/user2@host2:"))
+           (setq tramp-default-proxies-alist nil)
+
+           ;; Ad-hoc settings.
+           (should
+            (string-equal
+             (file-remote-p "/user1@host1|user2@host2:/path/to/file")
+             (if tramp-show-ad-hoc-proxies
+                 "/user1@host1|user2@host2:"
+               "/user2@host2:")))
+           (should
+            (string-equal
+             (file-remote-p
+              "/user1@host1|user2@host2:/path/to/file" 'method)
+             "default-method"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/user1@host1|user2@host2:/path/to/file" 'user)
+             "user2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/user1@host1|user2@host2:/path/to/file" 'host)
+             "host2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/user1@host1|user2@host2:/path/to/file" 'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/user1@host1|user2@host2:/path/to/file" 'hop)
+             (format "%s@%s|" "user1" "host1")))
+
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/user1@host1"
+                  "|user2@host2"
+                  "|user3@host3:")
+               "/user3@host3:")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file")
+              'method)
+             "default-method"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file")
+              'user)
+             "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file")
+              'host)
+             "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file")
+              'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@host2"
+               "|user3@host3:/path/to/file")
+              'hop)
+             (format "%s@%s|%s@%s|"
+                     "user1" "host1" "user2" "host2")))
+
+           ;; Expand `tramp-default-user-alist'.
+           (add-to-list 'tramp-default-user-alist '(nil "host1" "user1"))
+           (add-to-list 'tramp-default-user-alist '(nil "host2" "user2"))
+           (add-to-list 'tramp-default-user-alist '(nil "host3" "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/host1"
+               "|host2"
+               "|host3:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/user1@host1"
+                  "|user2@host2"
+                  "|user3@host3:")
+               "/user3@host3:")))
+
+           ;; Expand `tramp-default-host-alist'.
+           (add-to-list 'tramp-default-host-alist '(nil "user1" "host1"))
+           (add-to-list 'tramp-default-host-alist '(nil "user2" "host2"))
+           (add-to-list 'tramp-default-host-alist '(nil "user3" "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@"
+               "|user2@"
+               "|user3@:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/user1@host1"
+                  "|user2@host2"
+                  "|user3@host3:")
+               "/user3@host3:")))
+
+           ;; Ad-hoc user name and host name expansion.
+           (setq tramp-default-user-alist nil
+                 tramp-default-host-alist nil)
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/user1@host1"
+               "|user2@"
+               "|user3@:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/user1@host1"
+                  "|user2@host1"
+                  "|user3@host1:")
+               "/user3@host1:")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/%u@%h"
+               "|user2@host2"
+               "|%u@%h"
+               "|user4%domain4@host4#1234:/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/user2@host2"
+                  "|user2@host2"
+                  "|user4@host4"
+                  "|user4%domain4@host4#1234:")
+               "/user4%domain4@host4#1234:")))))
 
       ;; Exit.
       (tramp-change-syntax syntax))))
@@ -1322,6 +1414,7 @@ is greater than 10.
        tramp-default-method-alist
        tramp-default-user-alist
        tramp-default-host-alist
+       tramp-default-proxies-alist
        ;; Suppress method name check.
        (non-essential t)
        ;; Suppress check for multihops.
@@ -1794,154 +1887,203 @@ is greater than 10.
                   "/path/to/file"))
 
          ;; Multihop.
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file")
-           "/[method2/user2@host2]"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'method)
-           "method2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'user)
-           "user2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'host)
-           "host2"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file"
-            'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'hop)
-           (format "%s/%s@%s|"
-                   "method1" "user1" "host1")))
+         (dolist (tramp-show-ad-hoc-proxies '(nil t))
 
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file"))
-           "/[method3/user3@host3]"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file")
-            'method)
-           "method3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file")
-            'user)
-           "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file")
-            'host)
-           "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file")
-            'localname)
-           "/path/to/file"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@host2"
-             "|method3/user3@host3]/path/to/file")
-            'hop)
-           (format "%s/%s@%s|%s/%s@%s|"
-                   "method1" "user1" "host1" "method2" "user2" "host2")))
-
-         ;; Expand `tramp-default-method-alist'.
-         (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
-         (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
-         (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[/user1@host1"
-             "|/user2@host2"
-             "|/user3@host3]/path/to/file"))
-           "/[method3/user3@host3]"))
-
-         ;; Expand `tramp-default-user-alist'.
-         (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
-         (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
-         (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/host1"
-             "|method2/host2"
-             "|method3/host3]/path/to/file"))
-           "/[method3/user3@host3]"))
-
-         ;; Expand `tramp-default-host-alist'.
-         (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
-         (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
-         (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@"
-             "|method2/user2@"
-             "|method3/user3@]/path/to/file"))
-           "/[method3/user3@host3]"))
-
-         ;; Ad-hoc user name and host name expansion.
-         (setq tramp-default-method-alist nil
-               tramp-default-user-alist nil
-               tramp-default-host-alist nil)
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/user1@host1"
-             "|method2/user2@"
-             "|method3/user3@]/path/to/file"))
-           "/[method3/user3@host1]"))
-         (should
-          (string-equal
-           (file-remote-p
-            (concat
-             "/[method1/%u@%h"
-             "|method2/user2@host2"
-             "|method3/%u@%h"
-             "|method4/user4%domain4@host4#1234]/path/to/file"))
-           "/[method4/user4%domain4@host4#1234]")))
+           ;; Explicit settings in `tramp-default-proxies-alist'
+           ;; shouldn't show hops.
+           (setq tramp-default-proxies-alist
+                 '(("^host2$" "^user2$" "/[method1/user1@host1]")))
+           (should
+            (string-equal
+             (file-remote-p "/[method2/user2@host2]/path/to/file")
+             "/[method2/user2@host2]"))
+           (setq tramp-default-proxies-alist nil)
+
+           ;; Ad-hoc settings.
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file")
+             (if tramp-show-ad-hoc-proxies
+                 "/[method1/user1@host1|method2/user2@host2]"
+               "/[method2/user2@host2]")))
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file" 
'method)
+             "method2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'user)
+             "user2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'host)
+             "host2"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file"
+              'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              "/[method1/user1@host1|method2/user2@host2]/path/to/file" 'hop)
+             (format "%s/%s@%s|"
+                     "method1" "user1" "host1")))
+
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user1@host1"
+                  "|method2/user2@host2"
+                  "|method3/user3@host3]")
+               "/[method3/user3@host3]")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file")
+              'method)
+             "method3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file")
+              'user)
+             "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file")
+              'host)
+             "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file")
+              'localname)
+             "/path/to/file"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@host2"
+               "|method3/user3@host3]/path/to/file")
+              'hop)
+             (format "%s/%s@%s|%s/%s@%s|"
+                     "method1" "user1" "host1" "method2" "user2" "host2")))
+
+           ;; Expand `tramp-default-method-alist'.
+           (add-to-list
+            'tramp-default-method-alist '("host1" "user1" "method1"))
+           (add-to-list
+            'tramp-default-method-alist '("host2" "user2" "method2"))
+           (add-to-list
+            'tramp-default-method-alist '("host3" "user3" "method3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[/user1@host1"
+               "|/user2@host2"
+               "|/user3@host3]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user1@host1"
+                  "|method2/user2@host2"
+                  "|method3/user3@host3]")
+               "/[method3/user3@host3]")))
+
+           ;; Expand `tramp-default-user-alist'.
+           (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+           (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+           (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/host1"
+               "|method2/host2"
+               "|method3/host3]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user1@host1"
+                  "|method2/user2@host2"
+                  "|method3/user3@host3]")
+               "/[method3/user3@host3]")))
+
+           ;; Expand `tramp-default-host-alist'.
+           (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+           (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+           (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@"
+               "|method2/user2@"
+               "|method3/user3@]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user1@host1"
+                  "|method2/user2@host2"
+                  "|method3/user3@host3]")
+               "/[method3/user3@host3]")))
+
+           ;; Ad-hoc user name and host name expansion.
+           (setq tramp-default-method-alist nil
+                 tramp-default-user-alist nil
+                 tramp-default-host-alist nil)
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/user1@host1"
+               "|method2/user2@"
+               "|method3/user3@]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user1@host1"
+                  "|method2/user2@host1"
+                  "|method3/user3@host1]")
+               "/[method3/user3@host1]")))
+           (should
+            (string-equal
+             (file-remote-p
+              (concat
+               "/[method1/%u@%h"
+               "|method2/user2@host2"
+               "|method3/%u@%h"
+               "|method4/user4%domain4@host4#1234]/path/to/file"))
+             (if tramp-show-ad-hoc-proxies
+                 (concat
+                  "/[method1/user2@host2"
+                  "|method2/user2@host2"
+                  "|method3/user4@host4"
+                  "|method4/user4%domain4@host4#1234]")
+               "/[method4/user4%domain4@host4#1234]")))))
 
       ;; Exit.
       (tramp-change-syntax syntax))))
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index 52d43775b8e..08a93dbf30e 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -883,4 +883,70 @@ This evaluates the TESTS test cases from glibc."
     (should (looking-at "x*\\(=\\|:\\)*"))
     (should (looking-at "x*=*?"))))
 
+(ert-deftest regexp-tests-zero-width-assertion-repetition ()
+  ;; Check compatibility behaviour with repetition operators after
+  ;; certain zero-width assertions (bug#64128).
+
+  ;; This function is just to hide ugly regexps from relint so that it
+  ;; doesn't complain about them.
+  (cl-flet ((smatch (re str) (string-match re str)))
+    ;; Postfix operators after ^ and \` become literals, for historical
+    ;; compatibility.  Only the first character of a lazy operator (like *?)
+    ;; becomes a literal.
+    (should (equal (smatch "^*a" "x\n*a") 2))
+    (should (equal (smatch "^*?a" "x\n*a") 2))
+    (should (equal (smatch "^*?a" "x\na") 2))
+    (should (equal (smatch "^*?a" "x\n**a") nil))
+
+    (should (equal (smatch "\\`*a" "*a") 0))
+    (should (equal (smatch "\\`*?a" "*a") 0))
+    (should (equal (smatch "\\`*?a" "a") 0))
+    (should (equal (smatch "\\`*?a" "**a") nil))
+
+    ;; Other zero-width assertions are treated as normal elements, so postfix
+    ;; operators apply to them alone (which is pointless but valid).
+    (should (equal (smatch "\\b*!" "*!") 1))
+    (should (equal (smatch "!\\b+;" "!;") nil))
+    (should (equal (smatch "!\\b+a" "!a") 0))
+
+    (should (equal (smatch "\\B*!" "*!") 1))
+    (should (equal (smatch "!\\B+;" "!;") 0))
+    (should (equal (smatch "!\\B+a" "!a") nil))
+
+    (should (equal (smatch "\\<*b" "*b") 1))
+    (should (equal (smatch "a\\<*b" "ab") 0))
+    (should (equal (smatch ";\\<*b" ";b") 0))
+    (should (equal (smatch "a\\<+b" "ab") nil))
+    (should (equal (smatch ";\\<+b" ";b") 0))
+
+    (should (equal (smatch "\\>*;" "*;") 1))
+    (should (equal (smatch "a\\>*b" "ab") 0))
+    (should (equal (smatch "a\\>*;" "a;") 0))
+    (should (equal (smatch "a\\>+b" "ab") nil))
+    (should (equal (smatch "a\\>+;" "a;") 0))
+
+    (should (equal (smatch "a\\'" "ab") nil))
+    (should (equal (smatch "b\\'" "ab") 1))
+    (should (equal (smatch "a\\'*b" "ab") 0))
+    (should (equal (smatch "a\\'+" "ab") nil))
+    (should (equal (smatch "b\\'+" "ab") 1))
+    (should (equal (smatch "\\'+" "+") 1))
+
+    (should (equal (smatch "\\_<*b" "*b") 1))
+    (should (equal (smatch "a\\_<*b" "ab") 0))
+    (should (equal (smatch " \\_<*b" " b") 0))
+    (should (equal (smatch "a\\_<+b" "ab") nil))
+    (should (equal (smatch " \\_<+b" " b") 0))
+
+    (should (equal (smatch "\\_>*;" "*;") 1))
+    (should (equal (smatch "a\\_>*b" "ab") 0))
+    (should (equal (smatch "a\\_>* " "a ") 0))
+    (should (equal (smatch "a\\_>+b" "ab") nil))
+    (should (equal (smatch "a\\_>+ " "a ") 0))
+
+    (should (equal (smatch "\\=*b" "*b") 1))
+    (should (equal (smatch "a\\=*b" "a*b") nil))
+    (should (equal (smatch "a\\=*b" "ab") 0))
+    ))
+
 ;;; regex-emacs-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]